aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.mk21
-rw-r--r--java/AndroidManifest.xml28
-rw-r--r--java/proguard.flags45
-rw-r--r--java/res/anim/alt_code_key_while_typing_fadein.xml27
-rw-r--r--java/res/anim/alt_code_key_while_typing_fadeout.xml27
-rw-r--r--java/res/anim/language_on_spacebar_fadeout.xml28
-rw-r--r--java/res/anim/more_keys_keyboard_fadein.xml (renamed from java/res/anim/mini_keyboard_fadein.xml)2
-rw-r--r--java/res/anim/more_keys_keyboard_fadeout.xml (renamed from java/res/anim/mini_keyboard_fadeout.xml)2
-rw-r--r--java/res/drawable-hdpi/btn_close_candidates_pane.9.pngbin1110 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_expand_candidates_pane.9.pngbin1123 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_active_holo.9.pngbin0 -> 462 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.pngbin472 -> 506 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.pngbin564 -> 435 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.pngbin649 -> 657 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.pngbin648 -> 547 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.pngbin944 -> 1048 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.pngbin721 -> 587 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.pngbin663 -> 972 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.pngbin684 -> 553 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.pngbin869 -> 1082 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.pngbin721 -> 668 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1119 -> 1440 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.pngbin838 -> 707 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.pngbin1370 -> 1785 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.pngbin1696 -> 1701 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.pngbin448 -> 505 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.pngbin583 -> 468 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.pngbin126 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.pngbin453 -> 301 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.pngbin649 -> 835 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.pngbin652 -> 547 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal.9.pngbin904 -> 1134 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.pngbin1076 -> 1243 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.pngbin2389 -> 2389 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.pngbin1137 -> 1307 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.pngbin2408 -> 2409 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.pngbin2213 -> 2211 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_popup_background_holo.9.pngbin894 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_popup_selected_holo.9.pngbin339 -> 282 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_pressed.9.pngbin831 -> 1088 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.pngbin1041 -> 1233 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.pngbin1086 -> 1271 bytes
-rw-r--r--java/res/drawable-hdpi/btn_suggestion_pressed.9.png (renamed from java/res/drawable-hdpi/btn_candidate_pressed.9.png)bin1234 -> 1234 bytes
-rw-r--r--java/res/drawable-hdpi/caution.pngbin2451 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/hint_popup.9.pngbin242 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/hint_popup_holo.9.pngbin324 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/ic_dialog_keyboard.pngbin1157 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/ic_ime_settings.pngbin0 -> 1570 bytes
-rw-r--r--java/res/drawable-hdpi/ic_mic_dialog.pngbin4083 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/ic_subtype_mic.pngbin892 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/ic_suggest_strip_microphone.pngbin970 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.pngbin795 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_background_holo.9.pngbin255 -> 227 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_background.9.pngbin937 -> 843 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.pngbin2150 -> 2080 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_left_background_holo.9.pngbin2066 -> 1990 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_holo.9.pngbin2223 -> 2152 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.pngbin1099 -> 1056 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_more_background_holo.9.pngbin2307 -> 2256 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_right_background_holo.9.pngbin2077 -> 1993 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_holo.9.pngbin2239 -> 2163 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_popup_panel_background_holo.9.pngbin4047 -> 856 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_suggest_strip_divider.pngbin2946 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/keyboard_suggest_strip_holo.9.pngbin168 -> 160 bytes
-rw-r--r--java/res/drawable-hdpi/mic_base.pngbin4347 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/mic_full.pngbin5013 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/mic_slash.pngbin12569 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/more_keys_divider.pngbin0 -> 1034 bytes
-rw-r--r--java/res/drawable-hdpi/more_suggestions_divider.pngbin0 -> 1034 bytes
-rw-r--r--java/res/drawable-hdpi/suggestion_feedback_background.9.png (renamed from java/res/drawable-hdpi/candidate_feedback_background.9.png)bin1607 -> 1607 bytes
-rw-r--r--java/res/drawable-hdpi/suggestions_strip_divider.pngbin0 -> 73 bytes
-rw-r--r--java/res/drawable-hdpi/sym_bkeyboard_123_mic.pngbin2576 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_bkeyboard_label_mic.pngbin0 -> 905 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_123_mic.pngbin2510 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_123_mic_holo.pngbin2510 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_delete_holo.pngbin4003 -> 1248 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_123_mic.pngbin6061 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_delete.pngbin4019 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.pngbin3397 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.pngbin3388 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_mic.pngbin4637 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_numalt.pngbin5931 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_return.pngbin4346 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_search.pngbin4658 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_settings.pngbin4641 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_shift.pngbin3865 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_feedback_space.pngbin3908 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_label_mic.pngbin0 -> 1417 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_label_mic_holo.pngbin0 -> 905 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_language_arrows_left.pngbin3220 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_language_arrows_right.pngbin3286 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_language_switch.pngbin0 -> 1788 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_return_holo.pngbin4024 -> 1216 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_search_holo.pngbin0 -> 1607 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_settings_holo.pngbin4015 -> 787 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_shift_holo.pngbin3740 -> 1290 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_shift_locked_holo.pngbin3686 -> 1036 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_space_holo.pngbin3331 -> 630 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_space_led_holo.9.pngbin0 -> 322 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_tab_holo.pngbin3792 -> 1142 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_voice_holo.pngbin3893 -> 1889 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_voice_off_holo.pngbin1180 -> 1741 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_zwj_holo.pngbin0 -> 973 bytes
-rw-r--r--java/res/drawable-hdpi/sym_keyboard_zwnj_holo.pngbin0 -> 961 bytes
-rw-r--r--java/res/drawable-hdpi/vs_dialog_blue.9.pngbin11064 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/vs_dialog_red.9.pngbin10976 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/vs_dialog_yellow.9.pngbin10518 -> 0 bytes
-rw-r--r--java/res/drawable-hdpi/vs_popup_mic_edge.pngbin3685 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_normal.9.pngbin737 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.pngbin941 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_normal_off_stone.9.pngbin2691 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.pngbin1076 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_normal_on_stone.9.pngbin2720 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_normal_stone.9.pngbin2517 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.pngbin733 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.pngbin964 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.pngbin1055 -> 0 bytes
-rw-r--r--java/res/drawable-land-hdpi/hint_popup_holo.9.pngbin321 -> 0 bytes
-rw-r--r--java/res/drawable-land-mdpi/hint_popup_holo.9.pngbin1180 -> 0 bytes
-rw-r--r--java/res/drawable-land-xhdpi/hint_popup_holo.9.pngbin373 -> 0 bytes
-rw-r--r--java/res/drawable-land/btn_keyboard_key.xml38
-rw-r--r--java/res/drawable-large-hdpi/btn_keyboard_key_popup_selected_holo.9.pngbin250 -> 0 bytes
-rw-r--r--java/res/drawable-large-hdpi/hint_popup_holo.9.pngbin333 -> 0 bytes
-rw-r--r--java/res/drawable-large-hdpi/sym_keyboard_numsymbol_holo.pngbin4137 -> 0 bytes
-rw-r--r--java/res/drawable-large-hdpi/sym_keyboard_tab_holo.pngbin1361 -> 0 bytes
-rw-r--r--java/res/drawable-large-land-hdpi/hint_popup_holo.9.pngbin333 -> 0 bytes
-rw-r--r--java/res/drawable-large-land-mdpi/hint_popup_holo.9.pngbin206 -> 0 bytes
-rw-r--r--java/res/drawable-large-land-xhdpi/hint_popup_holo.9.pngbin379 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_holo.9.pngbin268 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_off_holo.9.pngbin597 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_on_holo.9.pngbin751 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_holo.9.pngbin295 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.pngbin626 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.pngbin739 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_light_normal_holo.9.pngbin268 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_light_pressed_holo.9.pngbin233 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/btn_keyboard_key_popup_selected_holo.9.pngbin151 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/hint_popup_holo.9.pngbin206 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/keyboard_background_holo.9.pngbin1108 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/keyboard_popup_panel_background_holo.9.pngbin3730 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/keyboard_suggest_strip_holo.9.pngbin1003 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_delete_holo.pngbin1419 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num0_holo.pngbin1759 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num1_holo.pngbin1324 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num2_holo.pngbin2397 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num3_holo.pngbin2143 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num4_holo.pngbin2063 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num5_holo.pngbin2021 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num6_holo.pngbin2502 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num7_holo.pngbin2540 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num8_holo.pngbin2226 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_num9_holo.pngbin2699 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_numbpound_holo.pngbin1548 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_numbstar_holo.pngbin1414 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_numsymbol_holo.pngbin830 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_return_holo.pngbin1391 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_settings_holo.pngbin1865 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_shift_holo.pngbin1683 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_shift_locked_holo.pngbin1480 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_space_holo.pngbin1195 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_tab_holo.pngbin387 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_voice_holo.pngbin1678 -> 0 bytes
-rw-r--r--java/res/drawable-large-mdpi/sym_keyboard_voice_off_holo.pngbin1587 -> 0 bytes
-rw-r--r--java/res/drawable-large-xhdpi/btn_keyboard_key_popup_selected_holo.9.pngbin248 -> 0 bytes
-rw-r--r--java/res/drawable-large-xhdpi/hint_popup_holo.9.pngbin379 -> 0 bytes
-rw-r--r--java/res/drawable-large-xhdpi/sym_keyboard_numsymbol_holo.pngbin6242 -> 0 bytes
-rw-r--r--java/res/drawable-large-xhdpi/sym_keyboard_tab_holo.pngbin1803 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_close_candidates_pane.9.pngbin713 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_expand_candidates_pane.9.pngbin681 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_active_holo.9.pngbin0 -> 345 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.pngbin377 -> 458 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.pngbin402 -> 334 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.pngbin545 -> 588 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.pngbin446 -> 407 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.pngbin806 -> 960 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.pngbin498 -> 411 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.pngbin514 -> 849 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.pngbin460 -> 394 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.pngbin687 -> 957 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.pngbin496 -> 505 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.pngbin940 -> 1293 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.pngbin571 -> 489 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.pngbin1068 -> 1553 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.pngbin1021 -> 1461 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.pngbin355 -> 454 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.pngbin394 -> 332 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.pngbin999 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.pngbin389 -> 258 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.pngbin526 -> 717 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.pngbin436 -> 381 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal.9.pngbin726 -> 991 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.pngbin860 -> 1083 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.pngbin2389 -> 2389 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.pngbin926 -> 1151 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.pngbin2408 -> 2409 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.pngbin2213 -> 2212 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_popup_background_holo.9.pngbin612 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.pngbin270 -> 236 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_pressed.9.pngbin664 -> 956 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.pngbin836 -> 1078 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.pngbin886 -> 1119 bytes
-rw-r--r--java/res/drawable-mdpi/btn_suggestion_pressed.9.png (renamed from java/res/drawable-mdpi/btn_candidate_pressed.9.png)bin11006 -> 11006 bytes
-rw-r--r--java/res/drawable-mdpi/caution.pngbin1100 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/hint_popup.9.pngbin202 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/hint_popup_holo.9.pngbin273 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/ic_dialog_keyboard.pngbin528 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/ic_ime_settings.pngbin0 -> 1292 bytes
-rw-r--r--java/res/drawable-mdpi/ic_mic_dialog.pngbin3312 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/ic_subtype_mic.pngbin648 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/ic_suggest_strip_microphone.pngbin398 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.pngbin309 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_background_holo.9.pngbin211 -> 204 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_background.9.pngbin764 -> 747 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.pngbin1371 -> 1313 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_left_background_holo.9.pngbin1349 -> 1297 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_holo.9.pngbin1446 -> 1437 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_more_background.9.pngbin850 -> 853 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.pngbin1473 -> 1457 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_right_background_holo.9.pngbin1339 -> 1288 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_holo.9.pngbin1443 -> 1423 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.pngbin3730 -> 571 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_suggest_strip_divider.pngbin2812 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/keyboard_suggest_strip_holo.9.pngbin162 -> 151 bytes
-rw-r--r--java/res/drawable-mdpi/mic_base.pngbin2957 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/mic_full.pngbin2935 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/mic_slash.pngbin7595 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/more_keys_divider.pngbin0 -> 2940 bytes
-rw-r--r--java/res/drawable-mdpi/more_suggestions_divider.pngbin0 -> 2940 bytes
-rw-r--r--java/res/drawable-mdpi/suggestion_feedback_background.9.png (renamed from java/res/drawable-mdpi/candidate_feedback_background.9.png)bin1182 -> 1182 bytes
-rw-r--r--java/res/drawable-mdpi/suggestions_strip_divider.pngbin0 -> 264 bytes
-rw-r--r--java/res/drawable-mdpi/sym_bkeyboard_123_mic.pngbin1520 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_bkeyboard_label_mic.pngbin0 -> 539 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_123_mic.pngbin1540 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_delete_holo.pngbin819 -> 813 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_123_mic.pngbin4640 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_delete.pngbin3414 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.pngbin3126 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.pngbin3121 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_mic.pngbin3803 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_numalt.pngbin4679 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_return.pngbin3613 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_search.pngbin3793 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_settings.pngbin3839 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_shift.pngbin3320 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_feedback_space.pngbin3222 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_label_mic.pngbin0 -> 542 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_label_mic_holo.pngbin0 -> 658 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_language_arrows_left.pngbin3001 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_language_arrows_right.pngbin3032 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_language_switch.pngbin0 -> 1113 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_return_holo.pngbin710 -> 870 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_search_holo.pngbin0 -> 991 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_settings_holo.pngbin1061 -> 585 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_shift_holo.pngbin867 -> 940 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.pngbin738 -> 850 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_space_holo.pngbin397 -> 505 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_space_led_holo.9.pngbin0 -> 201 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_tab_holo.pngbin679 -> 801 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_voice_holo.pngbin841 -> 1166 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_voice_off_holo.pngbin801 -> 1105 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_zwj_holo.pngbin0 -> 733 bytes
-rw-r--r--java/res/drawable-mdpi/sym_keyboard_zwnj_holo.pngbin0 -> 704 bytes
-rw-r--r--java/res/drawable-mdpi/vs_dialog_blue.9.pngbin8275 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/vs_dialog_red.9.pngbin8607 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/vs_dialog_yellow.9.pngbin8151 -> 0 bytes
-rw-r--r--java/res/drawable-mdpi/vs_popup_mic_edge.pngbin3685 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_close_candidates_pane.9.pngbin1027 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_expand_candidates_pane.9.pngbin1350 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_active_holo.9.pngbin0 -> 601 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.pngbin546 -> 571 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.pngbin759 -> 568 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off.9.pngbin735 -> 727 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.pngbin856 -> 722 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on.9.pngbin1069 -> 1110 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.pngbin987 -> 745 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.pngbin709 -> 1007 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.pngbin932 -> 737 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off.9.pngbin924 -> 1128 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.pngbin961 -> 953 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.pngbin1244 -> 1486 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.pngbin1177 -> 945 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.pngbin1389 -> 1869 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.pngbin529 -> 548 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.pngbin795 -> 591 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_popup_normal.9.pngbin126 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.pngbin535 -> 359 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.pngbin722 -> 860 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.pngbin867 -> 668 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal.9.pngbin1004 -> 1172 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.pngbin1176 -> 1278 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_off_stone.9.pngbin2117 -> 2833 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.pngbin1271 -> 1345 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_on_stone.9.pngbin2131 -> 2867 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_stone.9.pngbin1787 -> 2658 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_popup_background_holo.9.pngbin1287 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_holo.9.pngbin422 -> 351 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.pngbin921 -> 1131 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.pngbin1131 -> 1273 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.pngbin1197 -> 1312 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_suggestion_pressed.9.png (renamed from java/res/drawable-xhdpi/btn_candidate_pressed.9.png)bin1266 -> 1266 bytes
-rw-r--r--java/res/drawable-xhdpi/caution.pngbin3207 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/hint_popup.9.pngbin292 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/hint_popup_holo.9.pngbin410 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_dialog_keyboard.pngbin1589 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_ime_settings.pngbin0 -> 2065 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_mic_dialog.pngbin4755 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_subtype_mic.pngbin1099 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_suggest_strip_microphone.pngbin1334 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.pngbin982 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_background_holo.9.pngbin297 -> 267 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_background.9.pngbin1028 -> 949 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.pngbin3062 -> 2916 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_left_background_holo.9.pngbin2907 -> 2873 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_holo.9.pngbin3122 -> 3176 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.pngbin1161 -> 1088 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_more_background_holo.9.pngbin3275 -> 3184 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_right_background_holo.9.pngbin2904 -> 2818 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_holo.9.pngbin3119 -> 3102 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_popup_panel_background_holo.9.pngbin0 -> 1178 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_suggest_strip_divider.pngbin2951 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/keyboard_suggest_strip_holo.9.pngbin181 -> 168 bytes
-rw-r--r--java/res/drawable-xhdpi/mic_base.pngbin6497 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/mic_full.pngbin7100 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/mic_slash.pngbin17757 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/more_keys_divider.pngbin0 -> 1053 bytes
-rw-r--r--java/res/drawable-xhdpi/more_suggestions_divider.pngbin0 -> 1053 bytes
-rw-r--r--java/res/drawable-xhdpi/suggestion_feedback_background.9.png (renamed from java/res/drawable-xhdpi/candidate_feedback_background.9.png)bin1676 -> 1676 bytes
-rw-r--r--java/res/drawable-xhdpi/suggestions_strip_divider.pngbin0 -> 267 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_bkeyboard_123_mic.pngbin3765 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_bkeyboard_label_mic.pngbin0 -> 2112 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_123_mic.pngbin3682 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_delete_holo.pngbin1608 -> 1584 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_123_mic.pngbin7767 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_delete.pngbin4645 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_left.pngbin3624 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_right.pngbin3602 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_mic.pngbin5610 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_numalt.pngbin7559 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_return.pngbin5070 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_search.pngbin5742 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_settings.pngbin5616 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_shift.pngbin4380 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_feedback_space.pngbin4446 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_label_mic.pngbin0 -> 2086 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_label_mic_holo.pngbin0 -> 1222 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_language_arrows_left.pngbin3356 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_language_arrows_right.pngbin3461 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_language_switch.pngbin0 -> 2512 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_return_holo.pngbin1346 -> 1452 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_search_holo.pngbin0 -> 2070 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_settings_holo.pngbin2351 -> 1062 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_shift_holo.pngbin1814 -> 1592 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_shift_locked_holo.pngbin1435 -> 1295 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_space_holo.pngbin551 -> 675 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_space_led_holo.9.pngbin0 -> 381 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_tab_holo.pngbin1223 -> 1336 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_voice_holo.pngbin1703 -> 2393 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_voice_off_holo.pngbin1561 -> 2196 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_zwj_holo.pngbin0 -> 1185 bytes
-rw-r--r--java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.pngbin0 -> 1148 bytes
-rw-r--r--java/res/drawable-xhdpi/vs_dialog_blue.9.pngbin11547 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/vs_dialog_red.9.pngbin11400 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/vs_dialog_yellow.9.pngbin10921 -> 0 bytes
-rw-r--r--java/res/drawable-xhdpi/vs_popup_mic_edge.pngbin4670 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-hdpi/btn_keyboard_key_popup_selected_holo.9.pngbin250 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-hdpi/hint_popup_holo.9.pngbin333 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-land-hdpi/hint_popup_holo.9.pngbin321 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-land-mdpi/hint_popup_holo.9.pngbin1180 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-land-xhdpi/hint_popup_holo.9.pngbin373 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_holo.9.pngbin268 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_off_holo.9.pngbin597 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_on_holo.9.pngbin751 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_holo.9.pngbin295 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.pngbin626 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.pngbin739 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_normal_holo.9.pngbin268 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_pressed_holo.9.pngbin233 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/btn_keyboard_key_popup_selected_holo.9.pngbin151 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/hint_popup_holo.9.pngbin1168 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/keyboard_background_holo.9.pngbin1108 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/keyboard_popup_panel_background_holo.9.pngbin3730 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/keyboard_suggest_strip_holo.9.pngbin1003 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.pngbin1419 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num0_holo.pngbin1759 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num1_holo.pngbin1324 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num2_holo.pngbin2397 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num3_holo.pngbin2143 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num4_holo.pngbin2063 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num5_holo.pngbin2021 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num6_holo.pngbin2502 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num7_holo.pngbin2540 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num8_holo.pngbin2226 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_num9_holo.pngbin2699 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_numbpound_holo.pngbin1548 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_numbstar_holo.pngbin1414 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_return_holo.pngbin1391 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_settings_holo.pngbin1865 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_shift_holo.pngbin1683 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked_holo.pngbin1480 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_space_holo.pngbin1195 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_voice_holo.pngbin1678 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-mdpi/sym_keyboard_voice_off_holo.pngbin1587 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-xhdpi/btn_keyboard_key_popup_selected_holo.9.pngbin248 -> 0 bytes
-rw-r--r--java/res/drawable-xlarge-xhdpi/hint_popup_holo.9.pngbin379 -> 0 bytes
-rw-r--r--java/res/drawable/btn_center.xml3
-rw-r--r--java/res/drawable/btn_keyboard_key_gingerbread.xml9
-rw-r--r--java/res/drawable/btn_keyboard_key_ics.xml9
-rw-r--r--java/res/drawable/btn_keyboard_key_popup.xml2
-rw-r--r--java/res/drawable/btn_keyboard_key_popup_ics.xml2
-rw-r--r--java/res/drawable/btn_keyboard_key_stone.xml9
-rw-r--r--java/res/drawable/btn_suggestion.xml (renamed from java/res/drawable/btn_candidate.xml)4
-rw-r--r--java/res/drawable/btn_suggestion_ics.xml (renamed from java/res/drawable/btn_candidate_ics.xml)0
-rw-r--r--java/res/drawable/keyboard_key_feedback_left_ics.xml (renamed from java/res/drawable/btn_keyboard_key_fulltrans.xml)13
-rw-r--r--java/res/drawable/keyboard_key_feedback_right_ics.xml21
-rw-r--r--java/res/layout-xlarge/recognition_status.xml101
-rw-r--r--java/res/layout/additional_subtype_dialog.xml56
-rw-r--r--java/res/layout/candidates_strip.xml124
-rw-r--r--java/res/layout/hint_add_to_dictionary.xml (renamed from java/res/layout/candidate_word.xml)15
-rw-r--r--java/res/layout/input_view.xml58
-rw-r--r--java/res/layout/key_preview.xml6
-rw-r--r--java/res/layout/more_keys_keyboard.xml (renamed from java/res/layout/keyboard_popup.xml)7
-rw-r--r--java/res/layout/more_suggestions.xml37
-rw-r--r--java/res/layout/recognition_status.xml102
-rw-r--r--java/res/layout/sound_effect_volume_dialog.xml44
-rw-r--r--java/res/layout/suggestion_divider.xml (renamed from java/res/layout/candidate_divider.xml)8
-rw-r--r--java/res/layout/suggestion_info.xml (renamed from java/res/layout/candidate_info.xml)3
-rw-r--r--java/res/layout/suggestion_preview.xml (renamed from java/res/layout/candidate_preview.xml)24
-rw-r--r--java/res/layout/suggestion_word.xml36
-rw-r--r--java/res/layout/suggestions_strip.xml30
-rw-r--r--java/res/layout/vibration_settings_dialog.xml49
-rw-r--r--java/res/layout/voice_punctuation_hint.xml49
-rw-r--r--java/res/layout/voice_swipe_hint.xml56
-rw-r--r--java/res/raw/main_de.dictbin0 -> 1605732 bytes
-rw-r--r--java/res/raw/main_en.dictbin0 -> 1068816 bytes
-rw-r--r--java/res/raw/main_es.dictbin0 -> 1138855 bytes
-rw-r--r--java/res/raw/main_fr.dictbin0 -> 1328007 bytes
-rw-r--r--java/res/raw/main_it.dictbin0 -> 1143310 bytes
-rw-r--r--java/res/raw/main_pt_br.dictbin0 -> 1091964 bytes
-rw-r--r--java/res/values-af/strings.xml168
-rw-r--r--java/res/values-am/strings.xml168
-rw-r--r--java/res/values-ar/donottranslate.xml (renamed from java/res/values-ru/donottranslate-altchars.xml)8
-rw-r--r--java/res/values-ar/strings.xml168
-rw-r--r--java/res/values-be/strings.xml170
-rw-r--r--java/res/values-bg/strings.xml168
-rw-r--r--java/res/values-ca/donottranslate-altchars.xml29
-rw-r--r--java/res/values-ca/strings.xml168
-rw-r--r--java/res/values-cs/donottranslate-altchars.xml34
-rw-r--r--java/res/values-cs/strings.xml180
-rw-r--r--java/res/values-da/donottranslate-altchars.xml35
-rw-r--r--java/res/values-da/strings.xml170
-rw-r--r--java/res/values-de-rZZ/donottranslate-altchars.xml29
-rw-r--r--java/res/values-de/donottranslate-altchars.xml29
-rw-r--r--java/res/values-de/strings.xml168
-rw-r--r--java/res/values-el/strings.xml168
-rw-r--r--java/res/values-en-rGB/strings.xml172
-rw-r--r--java/res/values-en/donottranslate-altchars.xml29
-rw-r--r--java/res/values-en/whitelist.xml377
-rw-r--r--java/res/values-es-rUS/strings.xml168
-rw-r--r--java/res/values-es/donottranslate-altchars.xml30
-rw-r--r--java/res/values-es/strings.xml184
-rw-r--r--java/res/values-et/strings.xml168
-rw-r--r--java/res/values-fa/donottranslate.xml (renamed from java/res/values-ro/donottranslate-altchars.xml)10
-rw-r--r--java/res/values-fa/strings.xml170
-rw-r--r--java/res/values-fi/donottranslate-altchars.xml30
-rw-r--r--java/res/values-fi/strings.xml168
-rw-r--r--java/res/values-fr/donottranslate-altchars.xml31
-rw-r--r--java/res/values-fr/donottranslate.xml8
-rw-r--r--java/res/values-fr/strings.xml168
-rw-r--r--java/res/values-hdpi/config.xml8
-rw-r--r--java/res/values-hi/strings.xml170
-rw-r--r--java/res/values-hr/strings.xml168
-rw-r--r--java/res/values-hu/donottranslate-altchars.xml28
-rw-r--r--java/res/values-hu/strings.xml168
-rw-r--r--java/res/values-in/strings.xml176
-rw-r--r--java/res/values-it/donottranslate-altchars.xml26
-rw-r--r--java/res/values-it/donottranslate.xml2
-rw-r--r--java/res/values-it/strings.xml172
-rw-r--r--java/res/values-iw/donottranslate.xml25
-rw-r--r--java/res/values-iw/strings.xml168
-rw-r--r--java/res/values-ja/strings.xml168
-rw-r--r--java/res/values-ko/strings.xml170
-rw-r--r--java/res/values-ky/strings.xml221
-rw-r--r--java/res/values-land/config.xml (renamed from java/res/values-de/config.xml)2
-rw-r--r--java/res/values-land/dimens.xml61
-rw-r--r--java/res/values-land/keyboard-heights.xml37
-rw-r--r--java/res/values-large-land/dimens.xml48
-rw-r--r--java/res/values-large/dimens.xml65
-rw-r--r--java/res/values-lt/donottranslate-altchars.xml28
-rw-r--r--java/res/values-lt/strings.xml168
-rw-r--r--java/res/values-lv/donottranslate-altchars.xml33
-rw-r--r--java/res/values-lv/strings.xml168
-rw-r--r--java/res/values-ms/strings.xml168
-rw-r--r--java/res/values-nb/donottranslate-altchars.xml29
-rw-r--r--java/res/values-nb/strings.xml170
-rw-r--r--java/res/values-nl/donottranslate-altchars.xml27
-rw-r--r--java/res/values-nl/strings.xml168
-rw-r--r--java/res/values-pl/donottranslate-altchars.xml29
-rw-r--r--java/res/values-pl/strings.xml168
-rw-r--r--java/res/values-pt-rPT/strings.xml168
-rw-r--r--java/res/values-pt/donottranslate-altchars.xml27
-rw-r--r--java/res/values-pt/strings.xml168
-rw-r--r--java/res/values-rm/strings.xml226
-rw-r--r--java/res/values-ro/strings.xml170
-rw-r--r--java/res/values-ru/strings.xml168
-rw-r--r--java/res/values-sk/donottranslate-altchars.xml35
-rw-r--r--java/res/values-sk/strings.xml170
-rw-r--r--java/res/values-sl/strings.xml168
-rw-r--r--java/res/values-sr/strings.xml170
-rw-r--r--java/res/values-sv/donottranslate-altchars.xml29
-rw-r--r--java/res/values-sv/strings.xml168
-rw-r--r--java/res/values-sw/strings.xml168
-rw-r--r--java/res/values-sw600dp-land/config.xml (renamed from java/res/values-rm/donottranslate-altchars.xml)7
-rw-r--r--java/res/values-sw600dp-land/dimens.xml59
-rw-r--r--java/res/values-sw600dp/config.xml (renamed from java/res/values-large/config.xml)21
-rw-r--r--java/res/values-sw600dp/dimens.xml82
-rw-r--r--java/res/values-sw768dp-land/config.xml (renamed from java/res/drawable/background_voice.xml)10
-rw-r--r--java/res/values-sw768dp-land/dimens.xml62
-rw-r--r--java/res/values-sw768dp/config.xml (renamed from java/res/values-xlarge/config.xml)30
-rw-r--r--java/res/values-sw768dp/dimens.xml83
-rw-r--r--java/res/values-th/strings.xml170
-rw-r--r--java/res/values-tl/strings.xml168
-rw-r--r--java/res/values-tr/donottranslate-altchars.xml28
-rw-r--r--java/res/values-tr/strings.xml176
-rw-r--r--java/res/values-uk/strings.xml178
-rw-r--r--java/res/values-vi/strings.xml168
-rw-r--r--java/res/values-xlarge-land/dimens.xml53
-rw-r--r--java/res/values-xlarge/dimens.xml70
-rw-r--r--java/res/values-zh-rCN/strings.xml182
-rw-r--r--java/res/values-zh-rTW/strings.xml176
-rw-r--r--java/res/values-zu/strings.xml168
-rw-r--r--java/res/values/attrs.xml362
-rw-r--r--java/res/values/config.xml93
-rw-r--r--java/res/values/dimens.xml110
-rw-r--r--java/res/values/donottranslate-altchars.xml56
-rw-r--r--java/res/values/donottranslate.xml112
-rw-r--r--java/res/values/keyboard-heights.xml37
-rw-r--r--java/res/values/keyboard-icons-black.xml31
-rw-r--r--java/res/values/keyboard-icons-ics.xml44
-rw-r--r--java/res/values/keyboard-icons-white.xml27
-rw-r--r--java/res/values/keycodes.xml31
-rw-r--r--java/res/values/keypress-vibration-durations.xml (renamed from java/res/values-large/donottranslate.xml)9
-rw-r--r--java/res/values/keypress-volumes.xml28
-rw-r--r--java/res/values/phantom_sudden_move_event_device_list.xml26
-rw-r--r--java/res/values/predefined-subtypes.xml (renamed from java/res/values-xlarge/donottranslate.xml)6
-rw-r--r--java/res/values/strings.xml402
-rw-r--r--java/res/values/styles.xml355
-rw-r--r--java/res/values/sudden-jumping-touch-event-device-list.xml (renamed from java/res/values-hr/donottranslate-altchars.xml)14
-rw-r--r--java/res/values/themes-basic-highcontrast.xml12
-rw-r--r--java/res/values/themes-basic.xml10
-rw-r--r--java/res/values/themes-gingerbread.xml12
-rw-r--r--java/res/values/themes-ics.xml10
-rw-r--r--java/res/values/themes-stone-bold.xml12
-rw-r--r--java/res/values/themes-stone.xml10
-rw-r--r--java/res/values/touch-position-correction.xml74
-rw-r--r--java/res/xml-fi/kbd_qwerty.xml27
-rw-r--r--java/res/xml-fr-rCH/kbd_qwerty.xml27
-rw-r--r--java/res/xml-fr/kbd_qwerty.xml27
-rw-r--r--java/res/xml-hr/kbd_qwerty.xml28
-rw-r--r--java/res/xml-land/kbd_number.xml28
-rw-r--r--java/res/xml-land/kbd_phone.xml28
-rw-r--r--java/res/xml-land/kbd_phone_symbols.xml (renamed from java/res/xml-de/kbd_qwerty.xml)5
-rw-r--r--java/res/xml-large/kbd_key_styles.xml137
-rw-r--r--java/res/xml-large/kbd_number.xml204
-rw-r--r--java/res/xml-large/kbd_phone_symbols.xml134
-rw-r--r--java/res/xml-large/kbd_qwerty_f2.xml77
-rw-r--r--java/res/xml-large/kbd_qwerty_row1.xml65
-rw-r--r--java/res/xml-large/kbd_qwerty_row2.xml59
-rw-r--r--java/res/xml-large/kbd_qwerty_row3.xml74
-rw-r--r--java/res/xml-large/kbd_qwerty_row4.xml163
-rw-r--r--java/res/xml-large/kbd_rows_arabic.xml134
-rw-r--r--java/res/xml-large/kbd_rows_azerty.xml156
-rw-r--r--java/res/xml-large/kbd_rows_hebrew.xml122
-rw-r--r--java/res/xml-large/kbd_rows_qwertz.xml121
-rw-r--r--java/res/xml-large/kbd_rows_russian.xml129
-rw-r--r--java/res/xml-large/kbd_rows_scandinavian.xml166
-rw-r--r--java/res/xml-large/kbd_rows_serbian.xml144
-rw-r--r--java/res/xml-large/kbd_rows_spanish.xml69
-rw-r--r--java/res/xml-large/kbd_symbols.xml218
-rw-r--r--java/res/xml-large/kbd_symbols_shift.xml156
-rw-r--r--java/res/xml-pl/kbd_qwerty.xml27
-rw-r--r--java/res/xml-pt/kbd_qwerty.xml27
-rw-r--r--java/res/xml-ru/kbd_qwerty.xml27
-rw-r--r--java/res/xml-sr/kbd_qwerty.xml27
-rw-r--r--java/res/xml-sv/kbd_qwerty.xml27
-rw-r--r--java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml (renamed from java/res/xml-large-land/kbd_popup_template.xml)3
-rw-r--r--java/res/xml-sw600dp-land/kbd_number.xml28
-rw-r--r--java/res/xml-sw600dp-land/kbd_phone.xml (renamed from java/res/xml-es/kbd_qwerty.xml)5
-rw-r--r--java/res/xml-sw600dp-land/kbd_phone_symbols.xml29
-rw-r--r--java/res/xml-sw600dp-land/kbd_thai.xml29
-rw-r--r--java/res/xml-sw600dp/kbd_10_10_7_symbols.xml26
-rw-r--r--java/res/xml-sw600dp/kbd_10_10_7_symbols_shift.xml26
-rw-r--r--java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml (renamed from java/res/xml-large/kbd_popup_template.xml)3
-rw-r--r--java/res/xml-sw600dp/kbd_number.xml (renamed from java/res/xml-de-rZZ/kbd_qwerty.xml)4
-rw-r--r--java/res/xml-sw600dp/kbd_phone.xml (renamed from java/res/xml-cs/kbd_qwerty.xml)4
-rw-r--r--java/res/xml-sw600dp/kbd_phone_symbols.xml28
-rw-r--r--java/res/xml-sw600dp/kbd_thai.xml29
-rw-r--r--java/res/xml-sw600dp/key_apostrophe.xml49
-rw-r--r--java/res/xml-sw600dp/key_azerty_quote.xml29
-rw-r--r--java/res/xml-sw600dp/key_colemak_colon.xml29
-rw-r--r--java/res/xml-sw600dp/key_dash.xml49
-rw-r--r--java/res/xml-sw600dp/key_f1.xml62
-rw-r--r--java/res/xml-sw600dp/key_f2.xml45
-rw-r--r--java/res/xml-sw600dp/key_greek_semicolon.xml29
-rw-r--r--java/res/xml-sw600dp/key_question_exclamation.xml39
-rw-r--r--java/res/xml-sw600dp/key_shortcut.xml53
-rw-r--r--java/res/xml-sw600dp/key_space.xml63
-rw-r--r--java/res/xml-sw600dp/key_styles_common.xml177
-rw-r--r--java/res/xml-sw600dp/keys_comma_period.xml (renamed from java/res/xml-xlarge/kbd_row3_right2.xml)16
-rw-r--r--java/res/xml-sw600dp/keys_dvorak_123.xml40
-rw-r--r--java/res/xml-sw600dp/keys_pcqwerty2_right3.xml58
-rw-r--r--java/res/xml-sw600dp/keys_pcqwerty3_right2.xml68
-rw-r--r--java/res/xml-sw600dp/keys_pcqwerty4_right3.xml76
-rw-r--r--java/res/xml-sw600dp/row_dvorak4.xml46
-rw-r--r--java/res/xml-sw600dp/row_hebrew4.xml44
-rw-r--r--java/res/xml-sw600dp/row_pcqwerty5.xml46
-rw-r--r--java/res/xml-sw600dp/row_qwerty4.xml46
-rw-r--r--java/res/xml-sw600dp/row_symbols4.xml46
-rw-r--r--java/res/xml-sw600dp/row_symbols_shift4.xml38
-rw-r--r--java/res/xml-sw600dp/rowkeys_arabic1.xml71
-rw-r--r--java/res/xml-sw600dp/rowkeys_arabic2.xml83
-rw-r--r--java/res/xml-sw600dp/rowkeys_arabic3.xml59
-rw-r--r--java/res/xml-sw600dp/rowkeys_dvorak3.xml47
-rw-r--r--java/res/xml-sw600dp/rowkeys_farsi1.xml65
-rw-r--r--java/res/xml-sw600dp/rowkeys_farsi2.xml73
-rw-r--r--java/res/xml-sw600dp/rowkeys_farsi3.xml56
-rw-r--r--java/res/xml-sw600dp/rowkeys_pcqwerty1.xml113
-rw-r--r--java/res/xml-sw600dp/rowkeys_symbols2.xml74
-rw-r--r--java/res/xml-sw600dp/rowkeys_symbols3.xml57
-rw-r--r--java/res/xml-sw600dp/rowkeys_symbols_shift1.xml56
-rw-r--r--java/res/xml-sw600dp/rowkeys_symbols_shift2.xml52
-rw-r--r--java/res/xml-sw600dp/rowkeys_symbols_shift3.xml46
-rw-r--r--java/res/xml-sw600dp/rowkeys_thai1.xml97
-rw-r--r--java/res/xml-sw600dp/rowkeys_thai2.xml108
-rw-r--r--java/res/xml-sw600dp/rowkeys_thai3.xml97
-rw-r--r--java/res/xml-sw600dp/rowkeys_thai4.xml89
-rw-r--r--java/res/xml-sw600dp/rows_10_10_7_symbols.xml60
-rw-r--r--java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml60
-rw-r--r--java/res/xml-sw600dp/rows_arabic.xml53
-rw-r--r--java/res/xml-sw600dp/rows_azerty.xml61
-rw-r--r--java/res/xml-sw600dp/rows_bulgarian.xml61
-rw-r--r--java/res/xml-sw600dp/rows_bulgarian_bds.xml58
-rw-r--r--java/res/xml-sw600dp/rows_colemak.xml63
-rw-r--r--java/res/xml-sw600dp/rows_dvorak.xml61
-rw-r--r--java/res/xml-sw600dp/rows_east_slavic.xml58
-rw-r--r--java/res/xml-sw600dp/rows_farsi.xml53
-rw-r--r--java/res/xml-sw600dp/rows_georgian.xml62
-rw-r--r--java/res/xml-sw600dp/rows_greek.xml64
-rw-r--r--java/res/xml-sw600dp/rows_hebrew.xml57
-rw-r--r--java/res/xml-sw600dp/rows_hindi.xml58
-rw-r--r--java/res/xml-sw600dp/rows_nordic.xml64
-rw-r--r--java/res/xml-sw600dp/rows_number_normal.xml157
-rw-r--r--java/res/xml-sw600dp/rows_number_password.xml80
-rw-r--r--java/res/xml-sw600dp/rows_pcqwerty.xml72
-rw-r--r--java/res/xml-sw600dp/rows_pcqwerty_symbols.xml67
-rw-r--r--java/res/xml-sw600dp/rows_phone.xml (renamed from java/res/xml-large/kbd_phone.xml)90
-rw-r--r--java/res/xml-sw600dp/rows_qwerty.xml62
-rw-r--r--java/res/xml-sw600dp/rows_qwertz.xml62
-rw-r--r--java/res/xml-sw600dp/rows_south_slavic.xml58
-rw-r--r--java/res/xml-sw600dp/rows_spanish.xml61
-rw-r--r--java/res/xml-sw600dp/rows_symbols.xml61
-rw-r--r--java/res/xml-sw600dp/rows_symbols_shift.xml61
-rw-r--r--java/res/xml-sw600dp/rows_thai.xml66
-rw-r--r--java/res/xml-sw768dp-land/kbd_more_keys_keyboard_template.xml (renamed from java/res/xml-xlarge-land/kbd_popup_template.xml)3
-rw-r--r--java/res/xml-sw768dp-land/kbd_number.xml28
-rw-r--r--java/res/xml-sw768dp-land/kbd_phone.xml28
-rw-r--r--java/res/xml-sw768dp-land/kbd_phone_symbols.xml29
-rw-r--r--java/res/xml-sw768dp-land/kbd_thai.xml29
-rw-r--r--java/res/xml-sw768dp-land/kbd_thai_symbols.xml29
-rw-r--r--java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml29
-rw-r--r--java/res/xml-sw768dp/kbd_more_keys_keyboard_template.xml (renamed from java/res/xml-xlarge/kbd_popup_template.xml)3
-rw-r--r--java/res/xml-sw768dp/kbd_number.xml (renamed from java/res/xml-iw/kbd_qwerty.xml)4
-rw-r--r--java/res/xml-sw768dp/kbd_phone.xml (renamed from java/res/xml-nb/kbd_qwerty.xml)4
-rw-r--r--java/res/xml-sw768dp/kbd_phone_symbols.xml (renamed from java/res/xml-da/kbd_qwerty.xml)5
-rw-r--r--java/res/xml-sw768dp/kbd_thai.xml29
-rw-r--r--java/res/xml-sw768dp/kbd_thai_symbols.xml29
-rw-r--r--java/res/xml-sw768dp/kbd_thai_symbols_shift.xml29
-rw-r--r--java/res/xml-sw768dp/key_settings.xml35
-rw-r--r--java/res/xml-sw768dp/key_shortcut.xml36
-rw-r--r--java/res/xml-sw768dp/key_space.xml42
-rw-r--r--java/res/xml-sw768dp/key_styles_common.xml163
-rw-r--r--java/res/xml-sw768dp/row_dvorak4.xml46
-rw-r--r--java/res/xml-sw768dp/row_hebrew4.xml44
-rw-r--r--java/res/xml-sw768dp/row_pcqwerty5.xml59
-rw-r--r--java/res/xml-sw768dp/row_qwerty4.xml46
-rw-r--r--java/res/xml-sw768dp/row_symbols4.xml44
-rw-r--r--java/res/xml-sw768dp/row_symbols_shift4.xml (renamed from java/res/xml-xlarge/kbd_rows_qwerty.xml)23
-rw-r--r--java/res/xml-sw768dp/rowkeys_thai_digits.xml54
-rw-r--r--java/res/xml-sw768dp/rows_10_10_7_symbols.xml69
-rw-r--r--java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml69
-rw-r--r--java/res/xml-sw768dp/rows_arabic.xml61
-rw-r--r--java/res/xml-sw768dp/rows_azerty.xml69
-rw-r--r--java/res/xml-sw768dp/rows_bulgarian.xml69
-rw-r--r--java/res/xml-sw768dp/rows_bulgarian_bds.xml69
-rw-r--r--java/res/xml-sw768dp/rows_colemak.xml71
-rw-r--r--java/res/xml-sw768dp/rows_dvorak.xml69
-rw-r--r--java/res/xml-sw768dp/rows_east_slavic.xml72
-rw-r--r--java/res/xml-sw768dp/rows_farsi.xml61
-rw-r--r--java/res/xml-sw768dp/rows_georgian.xml69
-rw-r--r--java/res/xml-sw768dp/rows_greek.xml71
-rw-r--r--java/res/xml-sw768dp/rows_hebrew.xml65
-rw-r--r--java/res/xml-sw768dp/rows_hindi.xml69
-rw-r--r--java/res/xml-sw768dp/rows_nordic.xml72
-rw-r--r--java/res/xml-sw768dp/rows_number_normal.xml172
-rw-r--r--java/res/xml-sw768dp/rows_number_password.xml79
-rw-r--r--java/res/xml-sw768dp/rows_pcqwerty.xml71
-rw-r--r--java/res/xml-sw768dp/rows_pcqwerty_symbols.xml67
-rw-r--r--java/res/xml-sw768dp/rows_phone.xml (renamed from java/res/xml-xlarge/kbd_phone_symbols.xml)107
-rw-r--r--java/res/xml-sw768dp/rows_qwerty.xml69
-rw-r--r--java/res/xml-sw768dp/rows_qwertz.xml69
-rw-r--r--java/res/xml-sw768dp/rows_south_slavic.xml69
-rw-r--r--java/res/xml-sw768dp/rows_spanish.xml70
-rw-r--r--java/res/xml-sw768dp/rows_symbols.xml68
-rw-r--r--java/res/xml-sw768dp/rows_symbols_shift.xml68
-rw-r--r--java/res/xml-sw768dp/rows_thai.xml72
-rw-r--r--java/res/xml-sw768dp/rows_thai_symbols.xml76
-rw-r--r--java/res/xml-sw768dp/rows_thai_symbols_shift.xml76
-rw-r--r--java/res/xml-tr/kbd_qwerty.xml27
-rw-r--r--java/res/xml-xlarge/kbd_key_styles.xml119
-rw-r--r--java/res/xml-xlarge/kbd_number.xml223
-rw-r--r--java/res/xml-xlarge/kbd_phone.xml139
-rw-r--r--java/res/xml-xlarge/kbd_qwerty_row1.xml69
-rw-r--r--java/res/xml-xlarge/kbd_qwerty_row2.xml62
-rw-r--r--java/res/xml-xlarge/kbd_qwerty_row3.xml57
-rw-r--r--java/res/xml-xlarge/kbd_qwerty_row4.xml141
-rw-r--r--java/res/xml-xlarge/kbd_rows_arabic.xml140
-rw-r--r--java/res/xml-xlarge/kbd_rows_azerty.xml169
-rw-r--r--java/res/xml-xlarge/kbd_rows_hebrew.xml127
-rw-r--r--java/res/xml-xlarge/kbd_rows_qwertz.xml127
-rw-r--r--java/res/xml-xlarge/kbd_rows_russian.xml134
-rw-r--r--java/res/xml-xlarge/kbd_rows_scandinavian.xml151
-rw-r--r--java/res/xml-xlarge/kbd_rows_serbian.xml130
-rw-r--r--java/res/xml-xlarge/kbd_rows_spanish.xml72
-rw-r--r--java/res/xml-xlarge/kbd_symbols.xml195
-rw-r--r--java/res/xml-xlarge/kbd_symbols_shift.xml175
-rw-r--r--java/res/xml/additional_subtype_settings.xml (renamed from java/res/xml/language_prefs.xml)10
-rw-r--r--java/res/xml/kbd_10_10_7_symbols.xml26
-rw-r--r--java/res/xml/kbd_10_10_7_symbols_shift.xml26
-rw-r--r--java/res/xml/kbd_arabic.xml (renamed from java/res/xml-hu/kbd_qwerty.xml)3
-rw-r--r--java/res/xml/kbd_azerty.xml (renamed from java/res/xml-ar/kbd_qwerty.xml)3
-rw-r--r--java/res/xml/kbd_bulgarian.xml26
-rw-r--r--java/res/xml/kbd_bulgarian_bds.xml26
-rw-r--r--java/res/xml/kbd_colemak.xml26
-rw-r--r--java/res/xml/kbd_currency_key_styles.xml99
-rw-r--r--java/res/xml/kbd_dvorak.xml26
-rw-r--r--java/res/xml/kbd_east_slavic.xml26
-rw-r--r--java/res/xml/kbd_farsi.xml26
-rw-r--r--java/res/xml/kbd_georgian.xml26
-rw-r--r--java/res/xml/kbd_greek.xml26
-rw-r--r--java/res/xml/kbd_hebrew.xml26
-rw-r--r--java/res/xml/kbd_hindi.xml26
-rw-r--r--java/res/xml/kbd_key_styles.xml216
-rw-r--r--java/res/xml/kbd_more_keys_keyboard_template.xml (renamed from java/res/xml/kbd_popup_template.xml)3
-rw-r--r--java/res/xml/kbd_nordic.xml26
-rw-r--r--java/res/xml/kbd_number.xml127
-rw-r--r--java/res/xml/kbd_pcqwerty.xml29
-rw-r--r--java/res/xml/kbd_pcqwerty_symbols.xml29
-rw-r--r--java/res/xml/kbd_phone.xml80
-rw-r--r--java/res/xml/kbd_phone_symbols.xml93
-rw-r--r--java/res/xml/kbd_qwerty.xml3
-rw-r--r--java/res/xml/kbd_qwerty_f1.xml116
-rw-r--r--java/res/xml/kbd_qwerty_row1.xml72
-rw-r--r--java/res/xml/kbd_qwerty_row2.xml56
-rw-r--r--java/res/xml/kbd_qwerty_row4.xml115
-rw-r--r--java/res/xml/kbd_qwertz.xml26
-rw-r--r--java/res/xml/kbd_rows_arabic.xml122
-rw-r--r--java/res/xml/kbd_rows_azerty.xml143
-rw-r--r--java/res/xml/kbd_rows_hebrew.xml111
-rw-r--r--java/res/xml/kbd_rows_qwertz.xml110
-rw-r--r--java/res/xml/kbd_rows_russian.xml140
-rw-r--r--java/res/xml/kbd_rows_scandinavian.xml119
-rw-r--r--java/res/xml/kbd_rows_serbian.xml136
-rw-r--r--java/res/xml/kbd_rows_spanish.xml64
-rw-r--r--java/res/xml/kbd_south_slavic.xml26
-rw-r--r--java/res/xml/kbd_spanish.xml26
-rw-r--r--java/res/xml/kbd_suggestions_pane_template.xml25
-rw-r--r--java/res/xml/kbd_symbols.xml122
-rw-r--r--java/res/xml/kbd_symbols_f1.xml63
-rw-r--r--java/res/xml/kbd_symbols_row4.xml88
-rw-r--r--java/res/xml/kbd_symbols_shift.xml121
-rw-r--r--java/res/xml/kbd_symbols_shift_row4.xml87
-rw-r--r--java/res/xml/kbd_thai.xml26
-rw-r--r--java/res/xml/kbd_thai_symbols.xml26
-rw-r--r--java/res/xml/kbd_thai_symbols_shift.xml26
-rw-r--r--java/res/xml/key_azerty_quote.xml (renamed from java/res/xml/kbd_rows_qwerty.xml)25
-rw-r--r--java/res/xml/key_colemak_colon.xml41
-rw-r--r--java/res/xml/key_f1.xml (renamed from java/res/xml-large/kbd_row3_right.xml)40
-rw-r--r--java/res/xml/key_greek_semicolon.xml42
-rw-r--r--java/res/xml/key_space.xml63
-rw-r--r--java/res/xml/key_styles_common.xml189
-rw-r--r--java/res/xml/key_styles_currency.xml162
-rw-r--r--java/res/xml/key_styles_currency_dollar.xml42
-rw-r--r--java/res/xml/key_styles_currency_euro.xml43
-rw-r--r--java/res/xml/key_styles_enter.xml180
-rw-r--r--java/res/xml/key_styles_f1.xml43
-rw-r--r--java/res/xml/key_styles_number.xml (renamed from java/res/xml/kbd_numkey_styles.xml)72
-rw-r--r--java/res/xml/keyboard_layout_set_arabic.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_azerty.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_bulgarian.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_bulgarian_bds.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_colemak.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_dvorak.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_east_slavic.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_farsi.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_georgian.xml58
-rw-r--r--java/res/xml/keyboard_layout_set_greek.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_hebrew.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_hindi.xml58
-rw-r--r--java/res/xml/keyboard_layout_set_nordic.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_pcqwerty.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_qwerty.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_qwertz.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_south_slavic.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_spanish.xml42
-rw-r--r--java/res/xml/keyboard_layout_set_thai.xml58
-rw-r--r--java/res/xml/keys_curly_brackets.xml30
-rw-r--r--java/res/xml/keys_dvorak_123.xml84
-rw-r--r--java/res/xml/keys_less_greater.xml50
-rw-r--r--java/res/xml/keys_parentheses.xml32
-rw-r--r--java/res/xml/keys_pcqwerty2_right3.xml51
-rw-r--r--java/res/xml/keys_pcqwerty3_right2.xml54
-rw-r--r--java/res/xml/keys_pcqwerty4_right3.xml59
-rw-r--r--java/res/xml/keys_pcqwerty_symbols1.xml57
-rw-r--r--java/res/xml/keys_pcqwerty_symbols2.xml59
-rw-r--r--java/res/xml/keys_pcqwerty_symbols3.xml54
-rw-r--r--java/res/xml/keys_pcqwerty_symbols4.xml49
-rw-r--r--java/res/xml/keys_square_brackets.xml30
-rw-r--r--java/res/xml/method.xml327
-rw-r--r--java/res/xml/prefs.xml131
-rw-r--r--java/res/xml/prefs_for_debug.xml13
-rw-r--r--java/res/xml/row_dvorak4.xml76
-rw-r--r--java/res/xml/row_pcqwerty5.xml81
-rw-r--r--java/res/xml/row_qwerty4.xml54
-rw-r--r--java/res/xml/row_symbols4.xml55
-rw-r--r--java/res/xml/row_symbols_shift4.xml49
-rw-r--r--java/res/xml/rowkeys_arabic1.xml98
-rw-r--r--java/res/xml/rowkeys_arabic2.xml83
-rw-r--r--java/res/xml/rowkeys_arabic3.xml52
-rw-r--r--java/res/xml/rowkeys_azerty1.xml73
-rw-r--r--java/res/xml/rowkeys_azerty2.xml51
-rw-r--r--java/res/xml/rowkeys_azerty3.xml42
-rw-r--r--java/res/xml/rowkeys_bulgarian1.xml79
-rw-r--r--java/res/xml/rowkeys_bulgarian2.xml57
-rw-r--r--java/res/xml/rowkeys_bulgarian3.xml48
-rw-r--r--java/res/xml/rowkeys_bulgarian_bds1.xml79
-rw-r--r--java/res/xml/rowkeys_bulgarian_bds2.xml57
-rw-r--r--java/res/xml/rowkeys_bulgarian_bds3.xml51
-rw-r--r--java/res/xml/rowkeys_colemak1.xml66
-rw-r--r--java/res/xml/rowkeys_colemak2.xml54
-rw-r--r--java/res/xml/rowkeys_colemak3.xml42
-rw-r--r--java/res/xml/rowkeys_dvorak1.xml57
-rw-r--r--java/res/xml/rowkeys_dvorak2.xml54
-rw-r--r--java/res/xml/rowkeys_dvorak3.xml42
-rw-r--r--java/res/xml/rowkeys_east_slavic1.xml80
-rw-r--r--java/res/xml/rowkeys_east_slavic2.xml58
-rw-r--r--java/res/xml/rowkeys_east_slavic3.xml51
-rw-r--r--java/res/xml/rowkeys_farsi1.xml91
-rw-r--r--java/res/xml/rowkeys_farsi2.xml72
-rw-r--r--java/res/xml/rowkeys_farsi3.xml54
-rw-r--r--java/res/xml/rowkeys_georgian1.xml131
-rw-r--r--java/res/xml/rowkeys_georgian2.xml89
-rw-r--r--java/res/xml/rowkeys_georgian3.xml75
-rw-r--r--java/res/xml/rowkeys_greek1.xml100
-rw-r--r--java/res/xml/rowkeys_greek2.xml55
-rw-r--r--java/res/xml/rowkeys_greek3.xml47
-rw-r--r--java/res/xml/rowkeys_hebrew1.xml48
-rw-r--r--java/res/xml/rowkeys_hebrew2.xml60
-rw-r--r--java/res/xml/rowkeys_hebrew3.xml59
-rw-r--r--java/res/xml/rowkeys_hindi1.xml167
-rw-r--r--java/res/xml/rowkeys_hindi2.xml142
-rw-r--r--java/res/xml/rowkeys_hindi3.xml107
-rw-r--r--java/res/xml/rowkeys_nordic1.xml28
-rw-r--r--java/res/xml/rowkeys_nordic2.xml (renamed from java/res/xml-large/kbd_rows_qwerty.xml)18
-rw-r--r--java/res/xml/rowkeys_pcqwerty1.xml87
-rw-r--r--java/res/xml/rowkeys_pcqwerty2.xml41
-rw-r--r--java/res/xml/rowkeys_pcqwerty3.xml40
-rw-r--r--java/res/xml/rowkeys_pcqwerty4.xml40
-rw-r--r--java/res/xml/rowkeys_qwerty1.xml72
-rw-r--r--java/res/xml/rowkeys_qwerty2.xml50
-rw-r--r--java/res/xml/rowkeys_qwerty3.xml42
-rw-r--r--java/res/xml/rowkeys_qwertz1.xml72
-rw-r--r--java/res/xml/rowkeys_qwertz3.xml42
-rw-r--r--java/res/xml/rowkeys_south_slavic1.xml78
-rw-r--r--java/res/xml/rowkeys_south_slavic2.xml56
-rw-r--r--java/res/xml/rowkeys_south_slavic3.xml49
-rw-r--r--java/res/xml/rowkeys_spanish2.xml29
-rw-r--r--java/res/xml/rowkeys_symbols1.xml64
-rw-r--r--java/res/xml/rowkeys_symbols2.xml66
-rw-r--r--java/res/xml/rowkeys_symbols3.xml61
-rw-r--r--java/res/xml/rowkeys_symbols_shift1.xml50
-rw-r--r--java/res/xml/rowkeys_symbols_shift2.xml55
-rw-r--r--java/res/xml/rowkeys_symbols_shift3.xml42
-rw-r--r--java/res/xml/rowkeys_thai1.xml124
-rw-r--r--java/res/xml/rowkeys_thai2.xml107
-rw-r--r--java/res/xml/rowkeys_thai3.xml83
-rw-r--r--java/res/xml/rows_arabic.xml51
-rw-r--r--java/res/xml/rows_azerty.xml (renamed from java/res/xml/kbd_qwerty_row3.xml)44
-rw-r--r--java/res/xml/rows_bulgarian.xml52
-rw-r--r--java/res/xml/rows_bulgarian_bds.xml52
-rw-r--r--java/res/xml/rows_colemak.xml56
-rw-r--r--java/res/xml/rows_dvorak.xml56
-rw-r--r--java/res/xml/rows_east_slavic.xml52
-rw-r--r--java/res/xml/rows_farsi.xml51
-rw-r--r--java/res/xml/rows_georgian.xml55
-rw-r--r--java/res/xml/rows_greek.xml57
-rw-r--r--java/res/xml/rows_hebrew.xml52
-rw-r--r--java/res/xml/rows_hindi.xml52
-rw-r--r--java/res/xml/rows_nordic.xml57
-rw-r--r--java/res/xml/rows_number.xml (renamed from java/res/xml-fr-rCA/kbd_qwerty.xml)21
-rw-r--r--java/res/xml/rows_number_normal.xml131
-rw-r--r--java/res/xml/rows_number_password.xml80
-rw-r--r--java/res/xml/rows_pcqwerty.xml65
-rw-r--r--java/res/xml/rows_pcqwerty_symbols.xml60
-rw-r--r--java/res/xml/rows_phone.xml78
-rw-r--r--java/res/xml/rows_phone_symbols.xml84
-rw-r--r--java/res/xml/rows_qwerty.xml55
-rw-r--r--java/res/xml/rows_qwertz.xml55
-rw-r--r--java/res/xml/rows_south_slavic.xml52
-rw-r--r--java/res/xml/rows_spanish.xml54
-rw-r--r--java/res/xml/rows_symbols.xml56
-rw-r--r--java/res/xml/rows_symbols_shift.xml56
-rw-r--r--java/res/xml/rows_thai.xml55
-rw-r--r--java/res/xml/spell_checker_settings.xml26
-rw-r--r--java/res/xml/spellchecker.xml74
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java342
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java96
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java131
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java37
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java334
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java222
-rw-r--r--java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java39
-rw-r--r--java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java42
-rw-r--r--java/src/com/android/inputmethod/compat/ArraysCompatUtils.java50
-rw-r--r--java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java54
-rw-r--r--java/src/com/android/inputmethod/compat/CompatUtils.java40
-rw-r--r--java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java111
-rw-r--r--java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java80
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java59
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java188
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java84
-rw-r--r--java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java161
-rw-r--r--java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java118
-rw-r--r--java/src/com/android/inputmethod/compat/LinearLayoutCompatUtils.java55
-rw-r--r--java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java (renamed from java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java)27
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java71
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java44
-rw-r--r--java/src/com/android/inputmethod/deprecated/LanguageSwitcherProxy.java90
-rw-r--r--java/src/com/android/inputmethod/deprecated/VoiceProxy.java842
-rw-r--r--java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java36
-rw-r--r--java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java255
-rw-r--r--java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java234
-rw-r--r--java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java287
-rw-r--r--java/src/com/android/inputmethod/deprecated/recorrection/RecorrectionSuggestionEntries.java62
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/FieldContext.java104
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/Hints.java188
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java354
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java110
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java155
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java692
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java266
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java92
-rw-r--r--java/src/com/android/inputmethod/deprecated/voice/Whitelist.java68
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java866
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyDetector.java177
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java1520
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java47
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java278
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java406
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java884
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java1565
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboard.java433
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java1103
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java52
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java59
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java51
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java371
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java178
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java57
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java874
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java112
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupPanel.java45
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java219
-rw-r--r--java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java153
-rw-r--r--java/src/com/android/inputmethod/keyboard/ViewLayoutUtils.java (renamed from java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java)19
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java (renamed from java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java)62
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java498
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java297
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java151
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java159
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java726
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java617
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java2511
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java250
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java18
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java101
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java85
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java185
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/Row.java73
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java164
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java157
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtype.java106
-rw-r--r--java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java599
-rw-r--r--java/src/com/android/inputmethod/latin/AssetFileAddress.java8
-rw-r--r--java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java104
-rw-r--r--java/src/com/android/inputmethod/latin/AutoCorrection.java145
-rw-r--r--java/src/com/android/inputmethod/latin/AutoDictionary.java250
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java152
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java301
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java362
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java633
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java127
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java293
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsDictionary.java162
-rw-r--r--java/src/com/android/inputmethod/latin/DebugSettings.java29
-rw-r--r--java/src/com/android/inputmethod/latin/DebugSettingsActivity.java36
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java49
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java56
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java148
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java2
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtils.java293
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java473
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableDictionary.java672
-rw-r--r--java/src/com/android/inputmethod/latin/FileTransforms.java38
-rw-r--r--java/src/com/android/inputmethod/latin/Flag.java64
-rw-r--r--java/src/com/android/inputmethod/latin/ImfUtils.java179
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java176
-rw-r--r--java/src/com/android/inputmethod/latin/InputTypeUtils.java90
-rw-r--r--java/src/com/android/inputmethod/latin/InputView.java112
-rw-r--r--java/src/com/android/inputmethod/latin/JniUtils.java41
-rw-r--r--java/src/com/android/inputmethod/latin/LastComposedWord.java86
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java2754
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java22
-rw-r--r--java/src/com/android/inputmethod/latin/LocaleUtils.java222
-rw-r--r--java/src/com/android/inputmethod/latin/NativeUtils.java (renamed from java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java)21
-rw-r--r--java/src/com/android/inputmethod/latin/ResearchLogger.java1043
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java429
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java712
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsActivity.java34
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java418
-rw-r--r--java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java53
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java197
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeLocale.java180
-rw-r--r--java/src/com/android/inputmethod/latin/SubtypeSwitcher.java577
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java672
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java255
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java55
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java47
-rw-r--r--java/src/com/android/inputmethod/latin/TargetApplicationGetter.java70
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java236
-rw-r--r--java/src/com/android/inputmethod/latin/UserBigramDictionary.java399
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java224
-rw-r--r--java/src/com/android/inputmethod/latin/UserDictionary.java158
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictionary.java586
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java120
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java222
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java566
-rw-r--r--java/src/com/android/inputmethod/latin/VibratorUtils.java (renamed from java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java)33
-rw-r--r--java/src/com/android/inputmethod/latin/WhitelistDictionary.java61
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java308
-rw-r--r--java/src/com/android/inputmethod/latin/WordListInfo.java (renamed from java/src/com/android/inputmethod/latin/PrivateBinaryDictionaryGetter.java)20
-rw-r--r--java/src/com/android/inputmethod/latin/XmlParseUtils.java80
-rw-r--r--java/src/com/android/inputmethod/latin/define/JniLibName.java25
-rw-r--r--java/src/com/android/inputmethod/latin/define/ProductionFlag.java25
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java1413
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java50
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java767
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/MakedictLog.java47
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java32
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java26
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Word.java91
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java837
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java32
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java86
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java115
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java214
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java39
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java39
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java231
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java221
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java889
1080 files changed, 48777 insertions, 32176 deletions
diff --git a/java/Android.mk b/java/Android.mk
index 1bbcd5315..52cc18b26 100644
--- a/java/Android.mk
+++ b/java/Android.mk
@@ -1,3 +1,17 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -9,9 +23,14 @@ LOCAL_PACKAGE_NAME := LatinIME
LOCAL_CERTIFICATE := shared
-LOCAL_JNI_SHARED_LIBRARIES := libjni_latinime2
+# We want to package libjni_latinime.so into the apk.
+LOCAL_JNI_SHARED_LIBRARIES := libjni_latinime
+# We want to install libjni_latinime.so to the system partition if LatinIME gets installed.
+LOCAL_REQUIRED_MODULES := libjni_latinime
LOCAL_STATIC_JAVA_LIBRARIES := android-common
+LOCAL_STATIC_JAVA_LIBRARIES += inputmethod-common
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
# Do not compress dictionary files to mmap dict data runtime
LOCAL_AAPT_FLAGS := -0 .dict
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index cb0a9a2e1..06d852bb0 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -1,19 +1,19 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ coreApp="true"
package="com.android.inputmethod.latin">
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
- <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
- <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
- <application android:label="@string/english_ime_name"
+ <application android:label="@string/aosp_android_keyboard_ime_name"
+ android:icon="@drawable/ic_ime_settings"
android:backupAgent="BackupAgent"
android:killAfterRestore="false">
<service android:name="LatinIME"
- android:label="@string/english_ime_name"
+ android:label="@string/aosp_android_keyboard_ime_name"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
@@ -21,24 +21,32 @@
<meta-data android:name="android.view.im" android:resource="@xml/method" />
</service>
- <activity android:name="Settings" android:label="@string/english_ime_settings">
+ <service android:name=".spellcheck.AndroidSpellCheckerService"
+ android:label="@string/spell_checker_service_name"
+ android:permission="android.permission.BIND_TEXT_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.textservice.SpellCheckerService" />
+ </intent-filter>
+ <meta-data android:name="android.view.textservice.scs" android:resource="@xml/spellchecker" />
+ </service>
+
+ <activity android:name="SettingsActivity" android:label="@string/english_ime_settings"
+ android:uiOptions="splitActionBarWhenNarrow">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
- <activity android:name="DebugSettings" android:label="@string/english_ime_debug_settings">
+ <activity android:name="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity"
+ android:label="@string/android_spell_checker_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
- <activity android:name="com.android.inputmethod.deprecated.languageswitcher.InputLanguageSelection"
- android:label="@string/language_selection_title">
+ <activity android:name="DebugSettingsActivity" android:label="@string/english_ime_debug_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
- <action android:name="com.android.inputmethod.latin.INPUT_LANGUAGE_SELECTION"/>
- <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/java/proguard.flags b/java/proguard.flags
index 9094be401..752ced3e3 100644
--- a/java/proguard.flags
+++ b/java/proguard.flags
@@ -1,6 +1,14 @@
-keep class com.android.inputmethod.latin.BinaryDictionary {
int mDictLength;
- <init>(...);
+ <init>(...);
+}
+
+-keep class com.android.inputmethod.latin.Flag {
+ *;
+}
+
+-keep class com.android.inputmethod.keyboard.ProximityInfo {
+ <init>(com.android.inputmethod.keyboard.ProximityInfo);
}
-keep class com.android.inputmethod.latin.Suggest {
@@ -8,13 +16,6 @@
com.android.inputmethod.latin.SuggestedWords getSuggestions(...);
}
--keep class com.android.inputmethod.latin.UserBigramDictionary {
- void setDatabaseMax(int);
- void setDatabaseDelete(int);
- void waitUntilUpdateDBDone();
- void waitForDictionaryLoading();
-}
-
-keep class com.android.inputmethod.latin.AutoCorrection {
java.lang.CharSequence getAutoCorrectionWord();
}
@@ -23,6 +24,32 @@
boolean equalsIgnoreCase(...);
}
--keep class com.android.inputmethod.latin.spellcheck.SpellChecker {
+-keep class com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment {
*;
}
+
+-keep class com.android.inputmethod.keyboard.LatinKeyboardView {
+ # Keep getter/setter methods for ObjectAnimator
+ int getLanguageOnSpacebarAnimAlpha();
+ void setLanguageOnSpacebarAnimAlpha(int);
+ int getAltCodeKeyWhileTypingAnimAlpha();
+ void setAltCodeKeyWhileTypingAnimAlpha(int);
+}
+
+-keep class com.android.inputmethod.keyboard.MoreKeysKeyboard$Builder$MoreKeysKeyboardParams {
+ <init>(...);
+}
+
+-keep class com.android.inputmethod.latin.ResearchLogger {
+ void flush();
+}
+
+-keep class com.android.inputmethod.keyboard.KeyboardLayoutSet$Builder {
+ void setTouchPositionCorrectionEnabled(...);
+}
+
+# The support library contains references to newer platform versions.
+# Don't warn about those in case this app is linking against an older
+# platform version. We know about them, and they are safe.
+-dontwarn android.support.v4.**
+-dontwarn android.support.v13.**
diff --git a/java/res/anim/alt_code_key_while_typing_fadein.xml b/java/res/anim/alt_code_key_while_typing_fadein.xml
new file mode 100644
index 000000000..079c98090
--- /dev/null
+++ b/java/res/anim/alt_code_key_while_typing_fadein.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:propertyName="altCodeKeyWhileTypingAnimAlpha"
+ android:valueType="intType"
+ android:duration="1000"
+ android:valueFrom="128"
+ android:valueTo="255" />
diff --git a/java/res/anim/alt_code_key_while_typing_fadeout.xml b/java/res/anim/alt_code_key_while_typing_fadeout.xml
new file mode 100644
index 000000000..511e13886
--- /dev/null
+++ b/java/res/anim/alt_code_key_while_typing_fadeout.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:propertyName="altCodeKeyWhileTypingAnimAlpha"
+ android:valueType="intType"
+ android:duration="3000"
+ android:valueFrom="255"
+ android:valueTo="128" />
diff --git a/java/res/anim/language_on_spacebar_fadeout.xml b/java/res/anim/language_on_spacebar_fadeout.xml
new file mode 100644
index 000000000..531f440cc
--- /dev/null
+++ b/java/res/anim/language_on_spacebar_fadeout.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:propertyName="languageOnSpacebarAnimAlpha"
+ android:valueType="intType"
+ android:startOffset="1200"
+ android:duration="200"
+ android:valueFrom="255"
+ android:valueTo="@integer/config_language_on_spacebar_final_alpha" />
diff --git a/java/res/anim/mini_keyboard_fadein.xml b/java/res/anim/more_keys_keyboard_fadein.xml
index f80e8b8de..c781f36ad 100644
--- a/java/res/anim/mini_keyboard_fadein.xml
+++ b/java/res/anim/more_keys_keyboard_fadein.xml
@@ -25,5 +25,5 @@
<alpha
android:fromAlpha="0.5"
android:toAlpha="1.0"
- android:duration="@integer/config_mini_keyboard_fadein_anim_time" />
+ android:duration="@integer/config_more_keys_keyboard_fadein_anim_time" />
</set>
diff --git a/java/res/anim/mini_keyboard_fadeout.xml b/java/res/anim/more_keys_keyboard_fadeout.xml
index 535b100ae..32fae6bd8 100644
--- a/java/res/anim/mini_keyboard_fadeout.xml
+++ b/java/res/anim/more_keys_keyboard_fadeout.xml
@@ -25,5 +25,5 @@
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
- android:duration="@integer/config_mini_keyboard_fadeout_anim_time" />
+ android:duration="@integer/config_more_keys_keyboard_fadeout_anim_time" />
</set>
diff --git a/java/res/drawable-hdpi/btn_close_candidates_pane.9.png b/java/res/drawable-hdpi/btn_close_candidates_pane.9.png
deleted file mode 100644
index 6df00f229..000000000
--- a/java/res/drawable-hdpi/btn_close_candidates_pane.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_expand_candidates_pane.9.png b/java/res/drawable-hdpi/btn_expand_candidates_pane.9.png
deleted file mode 100644
index 63015ec5b..000000000
--- a/java/res/drawable-hdpi/btn_expand_candidates_pane.9.png
+++ /dev/null
Binary files differ
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_holo.9.png
new file mode 100644
index 000000000..9aa8db60e
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_active_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
index 50cc49fdb..bc130cab6 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
index 2dc1bed5d..5e6a9d6a4 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png
index dabf77ec6..43099899c 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index 575781f07..a3ba2230d 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png
index 6e7d74c88..2d1acf22f 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png
Binary files differ
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_holo.9.png
index 6c5b42e5c..9f4587b4a 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
index ddb77c224..af5ea6bd2 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png
Binary files differ
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_holo.9.png
index 8c999f655..7ec33dd20 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png
index 1e9227e1c..3e25a9817 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png
Binary files differ
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_holo.9.png
index 8c7c2f3bc..655bc01b1 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
index 7207b2ece..fc7ba2aeb 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png
Binary files differ
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_holo.9.png
index 02497b472..138e915d9 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png
index a524168c9..116329016 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png
index 73a8cd1c3..207c90d6c 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
index 9d85c7b74..005c4e498 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
index a13b2003f..baff85873 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png
deleted file mode 100644
index 2ed1b3447..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
index 77e17dbae..9a07acd91 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
index a409639e7..be420a7af 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png
Binary files differ
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_holo.9.png
index 0b76855e6..5612c51a1 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png
index 6ec7e6592..3e25180f0 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png
index 995780cbf..bad360f77 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png
index fad0ec458..cdd6c8b79 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png
index 7215782eb..49f519860 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png
index 215f8157c..d8421746a 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png
index 88acdd748..671d4e5d6 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_popup_background_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_popup_background_holo.9.png
deleted file mode 100644
index 0b2758925..000000000
--- a/java/res/drawable-hdpi/btn_keyboard_key_popup_background_holo.9.png
+++ /dev/null
Binary files differ
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_holo.9.png
index 166de2a03..c2e8b3779 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png
index 0bd49a0e7..e784eddf8 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png
index 634419f1b..a4731cf1a 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png
index 8474f9f42..03e163c9c 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_candidate_pressed.9.png b/java/res/drawable-hdpi/btn_suggestion_pressed.9.png
index 7acceaee7..7acceaee7 100644
--- a/java/res/drawable-hdpi/btn_candidate_pressed.9.png
+++ b/java/res/drawable-hdpi/btn_suggestion_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/caution.png b/java/res/drawable-hdpi/caution.png
deleted file mode 100644
index 61eb4dd62..000000000
--- a/java/res/drawable-hdpi/caution.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/hint_popup.9.png b/java/res/drawable-hdpi/hint_popup.9.png
deleted file mode 100644
index 5b2ad5388..000000000
--- a/java/res/drawable-hdpi/hint_popup.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/hint_popup_holo.9.png b/java/res/drawable-hdpi/hint_popup_holo.9.png
deleted file mode 100644
index c44af8883..000000000
--- a/java/res/drawable-hdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_dialog_keyboard.png b/java/res/drawable-hdpi/ic_dialog_keyboard.png
deleted file mode 100644
index 305441633..000000000
--- a/java/res/drawable-hdpi/ic_dialog_keyboard.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_ime_settings.png b/java/res/drawable-hdpi/ic_ime_settings.png
new file mode 100644
index 000000000..f8f80732d
--- /dev/null
+++ b/java/res/drawable-hdpi/ic_ime_settings.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_mic_dialog.png b/java/res/drawable-hdpi/ic_mic_dialog.png
deleted file mode 100644
index 6107f876e..000000000
--- a/java/res/drawable-hdpi/ic_mic_dialog.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_subtype_mic.png b/java/res/drawable-hdpi/ic_subtype_mic.png
deleted file mode 100644
index 25c9ee2ab..000000000
--- a/java/res/drawable-hdpi/ic_subtype_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_suggest_strip_microphone.png b/java/res/drawable-hdpi/ic_suggest_strip_microphone.png
deleted file mode 100644
index 189a861fb..000000000
--- a/java/res/drawable-hdpi/ic_suggest_strip_microphone.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png b/java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png
deleted file mode 100644
index b4a6e373b..000000000
--- a/java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_background_holo.9.png b/java/res/drawable-hdpi/keyboard_background_holo.9.png
index 39746ffd2..73868751c 100644
--- a/java/res/drawable-hdpi/keyboard_background_holo.9.png
+++ b/java/res/drawable-hdpi/keyboard_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png
index 27d992375..21520178e 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.png
index fd7a56e17..28b406a5c 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.png
Binary files differ
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_holo.9.png
index 60d920315..e42cd88dc 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_left_background_holo.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_holo.9.png
Binary files differ
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_holo.9.png
index f694b796c..160344073 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png
index 33263b9d7..7ac82cffd 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png
Binary files differ
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_holo.9.png
index 3165d08aa..a40d4277c 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_holo.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_holo.9.png
Binary files differ
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_holo.9.png
index 3136073a2..1f6807376 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_right_background_holo.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_holo.9.png
Binary files differ
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_holo.9.png
index 13d5af9cb..ec53593d9 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_holo.9.png
Binary files differ
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
index 4002dbe65..53d7b6fb3 100644
--- 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 differ
diff --git a/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png
deleted file mode 100644
index a62daf90c..000000000
--- a/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_suggest_strip_holo.9.png b/java/res/drawable-hdpi/keyboard_suggest_strip_holo.9.png
index f25003405..e173beb73 100644
--- a/java/res/drawable-hdpi/keyboard_suggest_strip_holo.9.png
+++ b/java/res/drawable-hdpi/keyboard_suggest_strip_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/mic_base.png b/java/res/drawable-hdpi/mic_base.png
deleted file mode 100644
index 504a1aa2a..000000000
--- a/java/res/drawable-hdpi/mic_base.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/mic_full.png b/java/res/drawable-hdpi/mic_full.png
deleted file mode 100644
index 3f4a67657..000000000
--- a/java/res/drawable-hdpi/mic_full.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/mic_slash.png b/java/res/drawable-hdpi/mic_slash.png
deleted file mode 100644
index c3b10929b..000000000
--- a/java/res/drawable-hdpi/mic_slash.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/more_keys_divider.png b/java/res/drawable-hdpi/more_keys_divider.png
new file mode 100644
index 000000000..a5912f95c
--- /dev/null
+++ b/java/res/drawable-hdpi/more_keys_divider.png
Binary files differ
diff --git a/java/res/drawable-hdpi/more_suggestions_divider.png b/java/res/drawable-hdpi/more_suggestions_divider.png
new file mode 100644
index 000000000..a5912f95c
--- /dev/null
+++ b/java/res/drawable-hdpi/more_suggestions_divider.png
Binary files differ
diff --git a/java/res/drawable-hdpi/candidate_feedback_background.9.png b/java/res/drawable-hdpi/suggestion_feedback_background.9.png
index 16499002e..16499002e 100644
--- a/java/res/drawable-hdpi/candidate_feedback_background.9.png
+++ b/java/res/drawable-hdpi/suggestion_feedback_background.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/suggestions_strip_divider.png b/java/res/drawable-hdpi/suggestions_strip_divider.png
new file mode 100644
index 000000000..5d44d9ce5
--- /dev/null
+++ b/java/res/drawable-hdpi/suggestions_strip_divider.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_bkeyboard_123_mic.png b/java/res/drawable-hdpi/sym_bkeyboard_123_mic.png
deleted file mode 100644
index 3e4eff698..000000000
--- a/java/res/drawable-hdpi/sym_bkeyboard_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_bkeyboard_label_mic.png b/java/res/drawable-hdpi/sym_bkeyboard_label_mic.png
new file mode 100644
index 000000000..25702cf73
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_bkeyboard_label_mic.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_123_mic.png b/java/res/drawable-hdpi/sym_keyboard_123_mic.png
deleted file mode 100644
index 6f0aec24c..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_123_mic_holo.png b/java/res/drawable-hdpi/sym_keyboard_123_mic_holo.png
deleted file mode 100644
index 6f0aec24c..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_123_mic_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_delete_holo.png b/java/res/drawable-hdpi/sym_keyboard_delete_holo.png
index 0591b82cd..d3e108846 100644
--- a/java/res/drawable-hdpi/sym_keyboard_delete_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_delete_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_123_mic.png b/java/res/drawable-hdpi/sym_keyboard_feedback_123_mic.png
deleted file mode 100644
index e56799cdb..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_delete.png b/java/res/drawable-hdpi/sym_keyboard_feedback_delete.png
deleted file mode 100644
index 960bb4e8e..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_delete.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png b/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png
deleted file mode 100644
index 5d1cb7833..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png b/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png
deleted file mode 100644
index 3a56d4745..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png
deleted file mode 100644
index a88a19d0d..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_numalt.png b/java/res/drawable-hdpi/sym_keyboard_feedback_numalt.png
deleted file mode 100644
index 7d418d91d..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_numalt.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_return.png b/java/res/drawable-hdpi/sym_keyboard_feedback_return.png
deleted file mode 100644
index f73ff3cd9..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_return.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_search.png b/java/res/drawable-hdpi/sym_keyboard_feedback_search.png
deleted file mode 100644
index 0e69157d6..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_search.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png
deleted file mode 100644
index 6304b00ed..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_shift.png b/java/res/drawable-hdpi/sym_keyboard_feedback_shift.png
deleted file mode 100644
index fc858f220..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_shift.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_space.png b/java/res/drawable-hdpi/sym_keyboard_feedback_space.png
deleted file mode 100644
index 67311fc8f..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_feedback_space.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_label_mic.png b/java/res/drawable-hdpi/sym_keyboard_label_mic.png
new file mode 100644
index 000000000..4e0a8ed8e
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_label_mic.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_label_mic_holo.png b/java/res/drawable-hdpi/sym_keyboard_label_mic_holo.png
new file mode 100644
index 000000000..22802433e
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_label_mic_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_language_arrows_left.png b/java/res/drawable-hdpi/sym_keyboard_language_arrows_left.png
deleted file mode 100644
index 79f235f25..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_language_arrows_left.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png b/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png
deleted file mode 100644
index e1444e85b..000000000
--- a/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_language_switch.png b/java/res/drawable-hdpi/sym_keyboard_language_switch.png
new file mode 100644
index 000000000..7b980a0c8
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_language_switch.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_return_holo.png b/java/res/drawable-hdpi/sym_keyboard_return_holo.png
index 9743c7f2f..8978934b8 100644
--- a/java/res/drawable-hdpi/sym_keyboard_return_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_search_holo.png b/java/res/drawable-hdpi/sym_keyboard_search_holo.png
new file mode 100644
index 000000000..b987a20f1
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_search_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_settings_holo.png b/java/res/drawable-hdpi/sym_keyboard_settings_holo.png
index 1e5bf939e..5af09ad8c 100644
--- a/java/res/drawable-hdpi/sym_keyboard_settings_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_settings_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_shift_holo.png b/java/res/drawable-hdpi/sym_keyboard_shift_holo.png
index 8e3d0320c..c58f9ab5c 100644
--- a/java/res/drawable-hdpi/sym_keyboard_shift_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_shift_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-hdpi/sym_keyboard_shift_locked_holo.png
index d345634a6..7a5c03713 100644
--- a/java/res/drawable-hdpi/sym_keyboard_shift_locked_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_shift_locked_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_space_holo.png b/java/res/drawable-hdpi/sym_keyboard_space_holo.png
index 780733ec5..e8bc3902d 100644
--- a/java/res/drawable-hdpi/sym_keyboard_space_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_space_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_space_led_holo.9.png b/java/res/drawable-hdpi/sym_keyboard_space_led_holo.9.png
new file mode 100644
index 000000000..34a1ebde2
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_space_led_holo.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_tab_holo.png b/java/res/drawable-hdpi/sym_keyboard_tab_holo.png
index 3d1c5c0ea..8d10d057c 100644
--- a/java/res/drawable-hdpi/sym_keyboard_tab_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_tab_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_voice_holo.png b/java/res/drawable-hdpi/sym_keyboard_voice_holo.png
index 520a40f09..8a6336a57 100644
--- a/java/res/drawable-hdpi/sym_keyboard_voice_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_voice_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png
index 45e3e79c5..edf1379ab 100644
--- a/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png
+++ b/java/res/drawable-hdpi/sym_keyboard_voice_off_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_zwj_holo.png b/java/res/drawable-hdpi/sym_keyboard_zwj_holo.png
new file mode 100644
index 000000000..5fa30ceb8
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_zwj_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_zwnj_holo.png b/java/res/drawable-hdpi/sym_keyboard_zwnj_holo.png
new file mode 100644
index 000000000..91367f3d2
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_zwnj_holo.png
Binary files differ
diff --git a/java/res/drawable-hdpi/vs_dialog_blue.9.png b/java/res/drawable-hdpi/vs_dialog_blue.9.png
deleted file mode 100644
index 4f813ead3..000000000
--- a/java/res/drawable-hdpi/vs_dialog_blue.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/vs_dialog_red.9.png b/java/res/drawable-hdpi/vs_dialog_red.9.png
deleted file mode 100644
index a2055600e..000000000
--- a/java/res/drawable-hdpi/vs_dialog_red.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/vs_dialog_yellow.9.png b/java/res/drawable-hdpi/vs_dialog_yellow.9.png
deleted file mode 100644
index ce664b676..000000000
--- a/java/res/drawable-hdpi/vs_dialog_yellow.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/vs_popup_mic_edge.png b/java/res/drawable-hdpi/vs_popup_mic_edge.png
deleted file mode 100644
index 4ff6337a2..000000000
--- a/java/res/drawable-hdpi/vs_popup_mic_edge.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_normal.9.png
deleted file mode 100644
index 603bf0e15..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.png
deleted file mode 100644
index 6ddd516e7..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_off_stone.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_normal_off_stone.9.png
deleted file mode 100644
index 67a204f85..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_off_stone.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.png
deleted file mode 100644
index 65fdeb353..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_on_stone.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_normal_on_stone.9.png
deleted file mode 100644
index 63cbe60a3..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_on_stone.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_stone.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_normal_stone.9.png
deleted file mode 100644
index 0dd33b429..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_normal_stone.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.png
deleted file mode 100644
index 7ec915fe8..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.png
deleted file mode 100644
index 439271723..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.png
deleted file mode 100644
index c2cc32044..000000000
--- a/java/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-hdpi/hint_popup_holo.9.png b/java/res/drawable-land-hdpi/hint_popup_holo.9.png
deleted file mode 100644
index 2b93014e1..000000000
--- a/java/res/drawable-land-hdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-mdpi/hint_popup_holo.9.png b/java/res/drawable-land-mdpi/hint_popup_holo.9.png
deleted file mode 100644
index c409cea00..000000000
--- a/java/res/drawable-land-mdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-xhdpi/hint_popup_holo.9.png b/java/res/drawable-land-xhdpi/hint_popup_holo.9.png
deleted file mode 100644
index 3cd20d34f..000000000
--- a/java/res/drawable-land-xhdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land/btn_keyboard_key.xml b/java/res/drawable-land/btn_keyboard_key.xml
deleted file mode 100644
index 45578e582..000000000
--- a/java/res/drawable-land/btn_keyboard_key.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <!-- 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_pressed_on" />
- <item android:state_checkable="true" android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_pressed_off" />
- <item android:state_checkable="true" android:state_checked="true"
- android:drawable="@drawable/btn_keyboard_key_normal_on" />
- <item android:state_checkable="true"
- android:drawable="@drawable/btn_keyboard_key_normal_off" />
-
- <!-- Normal keys -->
-
- <item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_pressed" />
- <item
- android:drawable="@drawable/btn_keyboard_key_normal" />
-
-</selector>
diff --git a/java/res/drawable-large-hdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-large-hdpi/btn_keyboard_key_popup_selected_holo.9.png
deleted file mode 100644
index 544ed7f78..000000000
--- a/java/res/drawable-large-hdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-hdpi/hint_popup_holo.9.png b/java/res/drawable-large-hdpi/hint_popup_holo.9.png
deleted file mode 100644
index 2ffc6ea2b..000000000
--- a/java/res/drawable-large-hdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-hdpi/sym_keyboard_numsymbol_holo.png b/java/res/drawable-large-hdpi/sym_keyboard_numsymbol_holo.png
deleted file mode 100644
index 398eaea12..000000000
--- a/java/res/drawable-large-hdpi/sym_keyboard_numsymbol_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-hdpi/sym_keyboard_tab_holo.png b/java/res/drawable-large-hdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index 1780f682b..000000000
--- a/java/res/drawable-large-hdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-land-hdpi/hint_popup_holo.9.png b/java/res/drawable-large-land-hdpi/hint_popup_holo.9.png
deleted file mode 100644
index 2ffc6ea2b..000000000
--- a/java/res/drawable-large-land-hdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-land-mdpi/hint_popup_holo.9.png b/java/res/drawable-large-land-mdpi/hint_popup_holo.9.png
deleted file mode 100644
index f5d15b728..000000000
--- a/java/res/drawable-large-land-mdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-land-xhdpi/hint_popup_holo.9.png b/java/res/drawable-large-land-xhdpi/hint_popup_holo.9.png
deleted file mode 100644
index bc37fa844..000000000
--- a/java/res/drawable-large-land-xhdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_holo.9.png
deleted file mode 100644
index 2ad73041e..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
deleted file mode 100644
index fc21e79c4..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
deleted file mode 100644
index 76cfbb221..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
deleted file mode 100644
index 73748c2fb..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
deleted file mode 100644
index 059d4ac2e..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
deleted file mode 100644
index e5cfdec88..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_light_normal_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_light_normal_holo.9.png
deleted file mode 100644
index 060524a53..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_light_normal_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_light_pressed_holo.9.png
deleted file mode 100644
index f4b061e07..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-large-mdpi/btn_keyboard_key_popup_selected_holo.9.png
deleted file mode 100644
index ffa7386df..000000000
--- a/java/res/drawable-large-mdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/hint_popup_holo.9.png b/java/res/drawable-large-mdpi/hint_popup_holo.9.png
deleted file mode 100644
index f5d15b728..000000000
--- a/java/res/drawable-large-mdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/keyboard_background_holo.9.png b/java/res/drawable-large-mdpi/keyboard_background_holo.9.png
deleted file mode 100644
index a93966c92..000000000
--- a/java/res/drawable-large-mdpi/keyboard_background_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-large-mdpi/keyboard_popup_panel_background_holo.9.png
deleted file mode 100644
index 7be7ab7e2..000000000
--- a/java/res/drawable-large-mdpi/keyboard_popup_panel_background_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/keyboard_suggest_strip_holo.9.png b/java/res/drawable-large-mdpi/keyboard_suggest_strip_holo.9.png
deleted file mode 100644
index 1f87a68e9..000000000
--- a/java/res/drawable-large-mdpi/keyboard_suggest_strip_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_delete_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index 155579169..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num0_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num0_holo.png
deleted file mode 100644
index e1d395b45..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num0_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num1_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num1_holo.png
deleted file mode 100644
index 225436ac2..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num1_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num2_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num2_holo.png
deleted file mode 100644
index e513fa4a0..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num2_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num3_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num3_holo.png
deleted file mode 100644
index b91e005fc..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num3_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num4_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num4_holo.png
deleted file mode 100644
index 65f88245b..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num4_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num5_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num5_holo.png
deleted file mode 100644
index b89ef07eb..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num5_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num6_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num6_holo.png
deleted file mode 100644
index 931275a9e..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num6_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num7_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num7_holo.png
deleted file mode 100644
index 9396c4c8f..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num7_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num8_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num8_holo.png
deleted file mode 100644
index 12e3eef45..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num8_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_num9_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_num9_holo.png
deleted file mode 100644
index 6911c2b4f..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_num9_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_numbpound_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_numbpound_holo.png
deleted file mode 100644
index e3a8b4900..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_numbpound_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_numbstar_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_numbstar_holo.png
deleted file mode 100644
index e80e9345f..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_numbstar_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_numsymbol_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_numsymbol_holo.png
deleted file mode 100644
index 73153849c..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_numsymbol_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_return_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index d519ccecf..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_settings_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 784a45054..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_shift_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index 91d6e32f9..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index 2bd053656..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_space_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index 25e655d96..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_tab_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index 5acd12cc4..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_voice_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index c1116dc17..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-mdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-large-mdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index 081a13096..000000000
--- a/java/res/drawable-large-mdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-xhdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-large-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
deleted file mode 100644
index 8b5d1b098..000000000
--- a/java/res/drawable-large-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-xhdpi/hint_popup_holo.9.png b/java/res/drawable-large-xhdpi/hint_popup_holo.9.png
deleted file mode 100644
index bc37fa844..000000000
--- a/java/res/drawable-large-xhdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-xhdpi/sym_keyboard_numsymbol_holo.png b/java/res/drawable-large-xhdpi/sym_keyboard_numsymbol_holo.png
deleted file mode 100644
index c7a8b286a..000000000
--- a/java/res/drawable-large-xhdpi/sym_keyboard_numsymbol_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-large-xhdpi/sym_keyboard_tab_holo.png b/java/res/drawable-large-xhdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index fd9f8cce6..000000000
--- a/java/res/drawable-large-xhdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_close_candidates_pane.9.png b/java/res/drawable-mdpi/btn_close_candidates_pane.9.png
deleted file mode 100644
index 5ea56925d..000000000
--- a/java/res/drawable-mdpi/btn_close_candidates_pane.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_expand_candidates_pane.9.png b/java/res/drawable-mdpi/btn_expand_candidates_pane.9.png
deleted file mode 100644
index 83cb65305..000000000
--- a/java/res/drawable-mdpi/btn_expand_candidates_pane.9.png
+++ /dev/null
Binary files differ
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_holo.9.png
new file mode 100644
index 000000000..e810c7789
--- /dev/null
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_active_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
index 4e337fa08..49329f094 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
index 034d63870..d449d7600 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png
index fe18497d8..46e9db092 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index 0cb53d506..fa24d5987 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png
index 00aab3d5a..ee60e4864 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png
Binary files differ
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_holo.9.png
index 0050a0110..f3fc64114 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
index ac0bfd3c1..c6876f76e 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png
Binary files differ
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_holo.9.png
index 27f8fdac6..8f340d355 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png
index ea2f35789..1f8f318d1 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png
Binary files differ
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_holo.9.png
index b8ce95235..53ea5f894 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
index 6195ac0d4..2bb7b64f4 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png
Binary files differ
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_holo.9.png
index 4d4d1a748..69c84e7ec 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png
index 20f3d5087..4b1a78cfb 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
index 1ed3065c5..697683e29 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
index 50cd06ae3..f5ce40cf6 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
index 90f471f48..976083fdf 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png
deleted file mode 100644
index 0e828a6cf..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
index 125ff1335..ca73b9249 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
index 7ce52f0f5..73f2006d4 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png
Binary files differ
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_holo.9.png
index c850768cd..c39dd4a94 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png
index 7ba18dd25..12bc97928 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png
index bda9b8394..44bd414a1 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png
index fad0ec458..cdd6c8b79 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png
index 0c16ed509..43fdf5b88 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png
index 215f8157c..d8421746a 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png
index 88acdd748..73cf35df0 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_popup_background_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_popup_background_holo.9.png
deleted file mode 100644
index e9186b7bb..000000000
--- a/java/res/drawable-mdpi/btn_keyboard_key_popup_background_holo.9.png
+++ /dev/null
Binary files differ
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_holo.9.png
index e96c8c5db..93a6e7921 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png
index 39b9314a1..1c1f3d711 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png
index bdcf06e1b..dacb675a9 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png
index 79621a9e6..3daa69f31 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_candidate_pressed.9.png b/java/res/drawable-mdpi/btn_suggestion_pressed.9.png
index 02b4e9a53..02b4e9a53 100644
--- a/java/res/drawable-mdpi/btn_candidate_pressed.9.png
+++ b/java/res/drawable-mdpi/btn_suggestion_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/caution.png b/java/res/drawable-mdpi/caution.png
deleted file mode 100644
index eaef53425..000000000
--- a/java/res/drawable-mdpi/caution.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/hint_popup.9.png b/java/res/drawable-mdpi/hint_popup.9.png
deleted file mode 100644
index 444cc26ee..000000000
--- a/java/res/drawable-mdpi/hint_popup.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/hint_popup_holo.9.png b/java/res/drawable-mdpi/hint_popup_holo.9.png
deleted file mode 100644
index e9e131c54..000000000
--- a/java/res/drawable-mdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_dialog_keyboard.png b/java/res/drawable-mdpi/ic_dialog_keyboard.png
deleted file mode 100644
index 9a5aada8b..000000000
--- a/java/res/drawable-mdpi/ic_dialog_keyboard.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_ime_settings.png b/java/res/drawable-mdpi/ic_ime_settings.png
new file mode 100644
index 000000000..060e8620e
--- /dev/null
+++ b/java/res/drawable-mdpi/ic_ime_settings.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_mic_dialog.png b/java/res/drawable-mdpi/ic_mic_dialog.png
deleted file mode 100644
index 77613ca05..000000000
--- a/java/res/drawable-mdpi/ic_mic_dialog.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_subtype_mic.png b/java/res/drawable-mdpi/ic_subtype_mic.png
deleted file mode 100644
index 0b6aca802..000000000
--- a/java/res/drawable-mdpi/ic_subtype_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_suggest_strip_microphone.png b/java/res/drawable-mdpi/ic_suggest_strip_microphone.png
deleted file mode 100644
index 18f314a61..000000000
--- a/java/res/drawable-mdpi/ic_suggest_strip_microphone.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png b/java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png
deleted file mode 100644
index ff629b674..000000000
--- a/java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_background_holo.9.png b/java/res/drawable-mdpi/keyboard_background_holo.9.png
index f1d55c6dd..fbe97f7a2 100644
--- a/java/res/drawable-mdpi/keyboard_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background.9.png
index a84c19c39..1745cecbe 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_background.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.png
index 9a1b7aadd..7a9f640d1 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.png
Binary files differ
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_holo.9.png
index cb222b0f9..5b06f09bb 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_left_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_holo.9.png
Binary files differ
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_holo.9.png
index 07d980083..fd992d6f4 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png
index 82513aadd..cdfa6804b 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png
Binary files differ
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_holo.9.png
index 05a332b8e..128dcd6ad 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png
Binary files differ
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_holo.9.png
index fd1675512..0b08d1747 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_right_background_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_holo.9.png
Binary files differ
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_holo.9.png
index 1acbd8268..cf0b33c1d 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_holo.9.png
Binary files differ
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
index 7be7ab7e2..61988a8e1 100644
--- 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 differ
diff --git a/java/res/drawable-mdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-mdpi/keyboard_suggest_strip_divider.png
deleted file mode 100644
index 363936362..000000000
--- a/java/res/drawable-mdpi/keyboard_suggest_strip_divider.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_suggest_strip_holo.9.png b/java/res/drawable-mdpi/keyboard_suggest_strip_holo.9.png
index 17faf86d0..b1c18b412 100644
--- a/java/res/drawable-mdpi/keyboard_suggest_strip_holo.9.png
+++ b/java/res/drawable-mdpi/keyboard_suggest_strip_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/mic_base.png b/java/res/drawable-mdpi/mic_base.png
deleted file mode 100644
index 53e29ff4b..000000000
--- a/java/res/drawable-mdpi/mic_base.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/mic_full.png b/java/res/drawable-mdpi/mic_full.png
deleted file mode 100644
index e3e3dfac3..000000000
--- a/java/res/drawable-mdpi/mic_full.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/mic_slash.png b/java/res/drawable-mdpi/mic_slash.png
deleted file mode 100644
index d04b56344..000000000
--- a/java/res/drawable-mdpi/mic_slash.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/more_keys_divider.png b/java/res/drawable-mdpi/more_keys_divider.png
new file mode 100644
index 000000000..a46284f21
--- /dev/null
+++ b/java/res/drawable-mdpi/more_keys_divider.png
Binary files differ
diff --git a/java/res/drawable-mdpi/more_suggestions_divider.png b/java/res/drawable-mdpi/more_suggestions_divider.png
new file mode 100644
index 000000000..a46284f21
--- /dev/null
+++ b/java/res/drawable-mdpi/more_suggestions_divider.png
Binary files differ
diff --git a/java/res/drawable-mdpi/candidate_feedback_background.9.png b/java/res/drawable-mdpi/suggestion_feedback_background.9.png
index 2a80f096d..2a80f096d 100644
--- a/java/res/drawable-mdpi/candidate_feedback_background.9.png
+++ b/java/res/drawable-mdpi/suggestion_feedback_background.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/suggestions_strip_divider.png b/java/res/drawable-mdpi/suggestions_strip_divider.png
new file mode 100644
index 000000000..2dbe2f94b
--- /dev/null
+++ b/java/res/drawable-mdpi/suggestions_strip_divider.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_bkeyboard_123_mic.png b/java/res/drawable-mdpi/sym_bkeyboard_123_mic.png
deleted file mode 100644
index 0749b5fc6..000000000
--- a/java/res/drawable-mdpi/sym_bkeyboard_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_bkeyboard_label_mic.png b/java/res/drawable-mdpi/sym_bkeyboard_label_mic.png
new file mode 100644
index 000000000..7f0b1355f
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_bkeyboard_label_mic.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_123_mic.png b/java/res/drawable-mdpi/sym_keyboard_123_mic.png
deleted file mode 100644
index 35afe0821..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_delete_holo.png b/java/res/drawable-mdpi/sym_keyboard_delete_holo.png
index f8f6e6a80..86be35185 100644
--- a/java/res/drawable-mdpi/sym_keyboard_delete_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_delete_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_123_mic.png b/java/res/drawable-mdpi/sym_keyboard_feedback_123_mic.png
deleted file mode 100644
index c556c35cb..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_delete.png b/java/res/drawable-mdpi/sym_keyboard_feedback_delete.png
deleted file mode 100644
index a79f15852..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_delete.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.png b/java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.png
deleted file mode 100644
index eecb02694..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.png b/java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.png
deleted file mode 100644
index 7e10ae3af..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-mdpi/sym_keyboard_feedback_mic.png
deleted file mode 100644
index 3ed0782d3..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_numalt.png b/java/res/drawable-mdpi/sym_keyboard_feedback_numalt.png
deleted file mode 100644
index bc8f1cfc3..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_numalt.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_return.png b/java/res/drawable-mdpi/sym_keyboard_feedback_return.png
deleted file mode 100644
index dd99ff381..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_return.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_search.png b/java/res/drawable-mdpi/sym_keyboard_feedback_search.png
deleted file mode 100644
index 6b8e01d90..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_search.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-mdpi/sym_keyboard_feedback_settings.png
deleted file mode 100644
index 03bad1843..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_settings.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_shift.png b/java/res/drawable-mdpi/sym_keyboard_feedback_shift.png
deleted file mode 100644
index d56357559..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_shift.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_feedback_space.png b/java/res/drawable-mdpi/sym_keyboard_feedback_space.png
deleted file mode 100644
index 36eb60c13..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_feedback_space.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_label_mic.png b/java/res/drawable-mdpi/sym_keyboard_label_mic.png
new file mode 100644
index 000000000..a354d5321
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_label_mic.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_label_mic_holo.png b/java/res/drawable-mdpi/sym_keyboard_label_mic_holo.png
new file mode 100644
index 000000000..d51adbe2f
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_label_mic_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_language_arrows_left.png b/java/res/drawable-mdpi/sym_keyboard_language_arrows_left.png
deleted file mode 100644
index 7067a8bf5..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_language_arrows_left.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_language_arrows_right.png b/java/res/drawable-mdpi/sym_keyboard_language_arrows_right.png
deleted file mode 100644
index f7a133d9e..000000000
--- a/java/res/drawable-mdpi/sym_keyboard_language_arrows_right.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_language_switch.png b/java/res/drawable-mdpi/sym_keyboard_language_switch.png
new file mode 100644
index 000000000..f840a631d
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_language_switch.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_return_holo.png b/java/res/drawable-mdpi/sym_keyboard_return_holo.png
index abbce5234..bfcb91328 100644
--- a/java/res/drawable-mdpi/sym_keyboard_return_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_search_holo.png b/java/res/drawable-mdpi/sym_keyboard_search_holo.png
new file mode 100644
index 000000000..dd3c83a84
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_search_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_settings_holo.png b/java/res/drawable-mdpi/sym_keyboard_settings_holo.png
index 82df90376..36c8c9623 100644
--- a/java/res/drawable-mdpi/sym_keyboard_settings_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_settings_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_shift_holo.png b/java/res/drawable-mdpi/sym_keyboard_shift_holo.png
index 49b9fc088..621946455 100644
--- a/java/res/drawable-mdpi/sym_keyboard_shift_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_shift_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png
index 5375beb4e..fb3a020d8 100644
--- a/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_shift_locked_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_space_holo.png b/java/res/drawable-mdpi/sym_keyboard_space_holo.png
index e413ddf2e..1f787d573 100644
--- a/java/res/drawable-mdpi/sym_keyboard_space_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_space_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_space_led_holo.9.png b/java/res/drawable-mdpi/sym_keyboard_space_led_holo.9.png
new file mode 100644
index 000000000..abd8b742e
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_space_led_holo.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_tab_holo.png b/java/res/drawable-mdpi/sym_keyboard_tab_holo.png
index c41af7b89..8d20153ee 100644
--- a/java/res/drawable-mdpi/sym_keyboard_tab_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_tab_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_voice_holo.png b/java/res/drawable-mdpi/sym_keyboard_voice_holo.png
index 158439a9f..0795fcc9b 100644
--- a/java/res/drawable-mdpi/sym_keyboard_voice_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_voice_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png
index 79026f1ab..f76da5797 100644
--- a/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png
+++ b/java/res/drawable-mdpi/sym_keyboard_voice_off_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_zwj_holo.png b/java/res/drawable-mdpi/sym_keyboard_zwj_holo.png
new file mode 100644
index 000000000..70370d83d
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_zwj_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_zwnj_holo.png b/java/res/drawable-mdpi/sym_keyboard_zwnj_holo.png
new file mode 100644
index 000000000..a69eade17
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_zwnj_holo.png
Binary files differ
diff --git a/java/res/drawable-mdpi/vs_dialog_blue.9.png b/java/res/drawable-mdpi/vs_dialog_blue.9.png
deleted file mode 100644
index cf27e8f43..000000000
--- a/java/res/drawable-mdpi/vs_dialog_blue.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/vs_dialog_red.9.png b/java/res/drawable-mdpi/vs_dialog_red.9.png
deleted file mode 100644
index 6c08d5a30..000000000
--- a/java/res/drawable-mdpi/vs_dialog_red.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/vs_dialog_yellow.9.png b/java/res/drawable-mdpi/vs_dialog_yellow.9.png
deleted file mode 100644
index 2fb06c263..000000000
--- a/java/res/drawable-mdpi/vs_dialog_yellow.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-mdpi/vs_popup_mic_edge.png b/java/res/drawable-mdpi/vs_popup_mic_edge.png
deleted file mode 100644
index 4ff6337a2..000000000
--- a/java/res/drawable-mdpi/vs_popup_mic_edge.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_close_candidates_pane.9.png b/java/res/drawable-xhdpi/btn_close_candidates_pane.9.png
deleted file mode 100644
index 9d797ed0d..000000000
--- a/java/res/drawable-xhdpi/btn_close_candidates_pane.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_expand_candidates_pane.9.png b/java/res/drawable-xhdpi/btn_expand_candidates_pane.9.png
deleted file mode 100644
index 88d01c9c8..000000000
--- a/java/res/drawable-xhdpi/btn_expand_candidates_pane.9.png
+++ /dev/null
Binary files differ
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_holo.9.png
new file mode 100644
index 000000000..d990c0258
--- /dev/null
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
index eae1e3a54..d0090a305 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
index b9667be13..d2cd029bb 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off.9.png
index 13bad8f1a..2baf7d90c 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index 1719992e1..bca39cf17 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on.9.png
index 853b8bc6e..6812f9e8f 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on.9.png
Binary files differ
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_holo.9.png
index 0eb9c9f93..ab8fb2e86 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
index 1edfd64fe..a932249a8 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed.9.png
Binary files differ
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_holo.9.png
index 5114bf5f1..3871689ef 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off.9.png
index dfdbfadd3..16416f000 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off.9.png
Binary files differ
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_holo.9.png
index 992395039..912506368 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
index 0e2733e17..3ca93fdb3 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on.9.png
Binary files differ
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_holo.9.png
index 474951c1d..35ce67fdc 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png
index 00c447604..df3b5ba2d 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
index ea13a7fdf..aa4f44fdd 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_normal.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
index 4a255f7fb..b26f1d27a 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_normal.9.png
deleted file mode 100644
index 2ed1b3447..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
index 057c5716e..4539255c2 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_popup_selected.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
index 5d8e46de0..568392444 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed.9.png
Binary files differ
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_holo.9.png
index 5bcd1c9c2..c23a4b225 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png
index f53b40419..026005d6f 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png
index 3c6ae6be8..38c5f244b 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_stone.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_stone.9.png
index eebe7d391..dec219304 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_stone.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_stone.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png
index 655bfb2c6..f1223e50e 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_stone.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_stone.9.png
index 336248aae..3c77b3ccd 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_stone.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_stone.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_stone.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_stone.9.png
index bb1c72bb3..5cdfc4201 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_stone.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_stone.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_popup_background_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_popup_background_holo.9.png
deleted file mode 100644
index 10d788dfb..000000000
--- a/java/res/drawable-xhdpi/btn_keyboard_key_popup_background_holo.9.png
+++ /dev/null
Binary files differ
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_holo.9.png
index 0a9a9e44d..0c7bfdace 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png
index f73911674..ec35db54d 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png
index 34a948f4e..bd30464d6 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png
index 520f12d3f..a3ff5d1bb 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_candidate_pressed.9.png b/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png
index 41e126a73..41e126a73 100644
--- a/java/res/drawable-xhdpi/btn_candidate_pressed.9.png
+++ b/java/res/drawable-xhdpi/btn_suggestion_pressed.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/caution.png b/java/res/drawable-xhdpi/caution.png
deleted file mode 100644
index cfc3f7547..000000000
--- a/java/res/drawable-xhdpi/caution.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/hint_popup.9.png b/java/res/drawable-xhdpi/hint_popup.9.png
deleted file mode 100644
index add474337..000000000
--- a/java/res/drawable-xhdpi/hint_popup.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/hint_popup_holo.9.png b/java/res/drawable-xhdpi/hint_popup_holo.9.png
deleted file mode 100644
index a2b114e14..000000000
--- a/java/res/drawable-xhdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_dialog_keyboard.png b/java/res/drawable-xhdpi/ic_dialog_keyboard.png
deleted file mode 100644
index f114c93b6..000000000
--- a/java/res/drawable-xhdpi/ic_dialog_keyboard.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_ime_settings.png b/java/res/drawable-xhdpi/ic_ime_settings.png
new file mode 100644
index 000000000..d674be06e
--- /dev/null
+++ b/java/res/drawable-xhdpi/ic_ime_settings.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_mic_dialog.png b/java/res/drawable-xhdpi/ic_mic_dialog.png
deleted file mode 100644
index 5d6399c0a..000000000
--- a/java/res/drawable-xhdpi/ic_mic_dialog.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_subtype_mic.png b/java/res/drawable-xhdpi/ic_subtype_mic.png
deleted file mode 100644
index fc8d18cc2..000000000
--- a/java/res/drawable-xhdpi/ic_subtype_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_suggest_strip_microphone.png b/java/res/drawable-xhdpi/ic_suggest_strip_microphone.png
deleted file mode 100644
index d65d28708..000000000
--- a/java/res/drawable-xhdpi/ic_suggest_strip_microphone.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.png b/java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.png
deleted file mode 100644
index 889378a6a..000000000
--- a/java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_background_holo.9.png
index 58d15142b..f5c9df3e5 100644
--- a/java/res/drawable-xhdpi/keyboard_background_holo.9.png
+++ b/java/res/drawable-xhdpi/keyboard_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background.9.png
index 16c76106c..5ef12a776 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_background.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.png
index 44675ba00..d999127f2 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.png
Binary files differ
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_holo.9.png
index cfd1f5242..c4d694136 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_holo.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_holo.9.png
Binary files differ
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_holo.9.png
index a01c1733d..5429c1785 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_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png
index e020e34b1..70cef569b 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png
Binary files differ
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_holo.9.png
index 1d2abc26b..5135a0869 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_holo.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_holo.9.png
Binary files differ
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_holo.9.png
index 5616d1988..19a77a29f 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_holo.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_holo.9.png
Binary files differ
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_holo.9.png
index ecf9c2cbc..ae2ffff8e 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_holo.9.png
Binary files differ
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
new file mode 100644
index 000000000..1dee699f4
--- /dev/null
+++ b/java/res/drawable-xhdpi/keyboard_popup_panel_background_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-xhdpi/keyboard_suggest_strip_divider.png
deleted file mode 100644
index cd7c2c7a2..000000000
--- a/java/res/drawable-xhdpi/keyboard_suggest_strip_divider.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_suggest_strip_holo.9.png b/java/res/drawable-xhdpi/keyboard_suggest_strip_holo.9.png
index f4ff7dc1c..4c27072e9 100644
--- a/java/res/drawable-xhdpi/keyboard_suggest_strip_holo.9.png
+++ b/java/res/drawable-xhdpi/keyboard_suggest_strip_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/mic_base.png b/java/res/drawable-xhdpi/mic_base.png
deleted file mode 100644
index 5c060bec9..000000000
--- a/java/res/drawable-xhdpi/mic_base.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/mic_full.png b/java/res/drawable-xhdpi/mic_full.png
deleted file mode 100644
index 32ffe124e..000000000
--- a/java/res/drawable-xhdpi/mic_full.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/mic_slash.png b/java/res/drawable-xhdpi/mic_slash.png
deleted file mode 100644
index 18b22542b..000000000
--- a/java/res/drawable-xhdpi/mic_slash.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/more_keys_divider.png b/java/res/drawable-xhdpi/more_keys_divider.png
new file mode 100644
index 000000000..178594bf0
--- /dev/null
+++ b/java/res/drawable-xhdpi/more_keys_divider.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/more_suggestions_divider.png b/java/res/drawable-xhdpi/more_suggestions_divider.png
new file mode 100644
index 000000000..178594bf0
--- /dev/null
+++ b/java/res/drawable-xhdpi/more_suggestions_divider.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/candidate_feedback_background.9.png b/java/res/drawable-xhdpi/suggestion_feedback_background.9.png
index 0ec90e5ea..0ec90e5ea 100644
--- a/java/res/drawable-xhdpi/candidate_feedback_background.9.png
+++ b/java/res/drawable-xhdpi/suggestion_feedback_background.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/suggestions_strip_divider.png b/java/res/drawable-xhdpi/suggestions_strip_divider.png
new file mode 100644
index 000000000..0d8b98437
--- /dev/null
+++ b/java/res/drawable-xhdpi/suggestions_strip_divider.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_bkeyboard_123_mic.png b/java/res/drawable-xhdpi/sym_bkeyboard_123_mic.png
deleted file mode 100644
index 0aefaa1c3..000000000
--- a/java/res/drawable-xhdpi/sym_bkeyboard_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_bkeyboard_label_mic.png b/java/res/drawable-xhdpi/sym_bkeyboard_label_mic.png
new file mode 100644
index 000000000..9bd1d65b4
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_bkeyboard_label_mic.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_123_mic.png b/java/res/drawable-xhdpi/sym_keyboard_123_mic.png
deleted file mode 100644
index bcb097967..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_delete_holo.png b/java/res/drawable-xhdpi/sym_keyboard_delete_holo.png
index 5150073b8..354c09ee6 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_delete_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_delete_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_123_mic.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_123_mic.png
deleted file mode 100644
index 5238c16d2..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_123_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_delete.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_delete.png
deleted file mode 100644
index f0c29e7c8..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_delete.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_left.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_left.png
deleted file mode 100644
index a90b8dacf..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_left.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_right.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_right.png
deleted file mode 100644
index 1123bf36e..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_language_arrows_right.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_mic.png
deleted file mode 100644
index 5ac27ebad..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_mic.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_numalt.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_numalt.png
deleted file mode 100644
index b68e6066a..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_numalt.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_return.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_return.png
deleted file mode 100644
index c777d00d6..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_return.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_search.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_search.png
deleted file mode 100644
index 32e0789dd..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_search.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_settings.png
deleted file mode 100644
index 021cafacb..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_settings.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_shift.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_shift.png
deleted file mode 100644
index d8c0325c4..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_shift.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_feedback_space.png b/java/res/drawable-xhdpi/sym_keyboard_feedback_space.png
deleted file mode 100644
index cee10568d..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_feedback_space.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_label_mic.png b/java/res/drawable-xhdpi/sym_keyboard_label_mic.png
new file mode 100644
index 000000000..49810a02f
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_label_mic.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_label_mic_holo.png b/java/res/drawable-xhdpi/sym_keyboard_label_mic_holo.png
new file mode 100644
index 000000000..a7d3eaa0a
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_label_mic_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_language_arrows_left.png b/java/res/drawable-xhdpi/sym_keyboard_language_arrows_left.png
deleted file mode 100644
index 226f2e617..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_language_arrows_left.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_language_arrows_right.png b/java/res/drawable-xhdpi/sym_keyboard_language_arrows_right.png
deleted file mode 100644
index 1e02e7e46..000000000
--- a/java/res/drawable-xhdpi/sym_keyboard_language_arrows_right.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_language_switch.png b/java/res/drawable-xhdpi/sym_keyboard_language_switch.png
new file mode 100644
index 000000000..6c2fb53ec
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_language_switch.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_return_holo.png b/java/res/drawable-xhdpi/sym_keyboard_return_holo.png
index 6e2e1c0b9..ba424adfd 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_return_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_search_holo.png b/java/res/drawable-xhdpi/sym_keyboard_search_holo.png
new file mode 100644
index 000000000..f2fb2a2b5
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_search_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_settings_holo.png b/java/res/drawable-xhdpi/sym_keyboard_settings_holo.png
index 018e45d9e..99ee97dbf 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_settings_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_settings_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_shift_holo.png b/java/res/drawable-xhdpi/sym_keyboard_shift_holo.png
index 41d4ca176..1046b4545 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_shift_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_shift_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-xhdpi/sym_keyboard_shift_locked_holo.png
index b811b7464..6acb565d9 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_shift_locked_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_shift_locked_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_space_holo.png b/java/res/drawable-xhdpi/sym_keyboard_space_holo.png
index da8926496..504a3ed45 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_space_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_space_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_space_led_holo.9.png b/java/res/drawable-xhdpi/sym_keyboard_space_led_holo.9.png
new file mode 100644
index 000000000..ba4e9ec49
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_space_led_holo.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_tab_holo.png b/java/res/drawable-xhdpi/sym_keyboard_tab_holo.png
index dd207ca3f..ff380eeab 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_tab_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_tab_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_voice_holo.png b/java/res/drawable-xhdpi/sym_keyboard_voice_holo.png
index d73e49910..b2bb9b803 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_voice_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_voice_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-xhdpi/sym_keyboard_voice_off_holo.png
index 8d34a5ada..23e75bfe7 100644
--- a/java/res/drawable-xhdpi/sym_keyboard_voice_off_holo.png
+++ b/java/res/drawable-xhdpi/sym_keyboard_voice_off_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_zwj_holo.png b/java/res/drawable-xhdpi/sym_keyboard_zwj_holo.png
new file mode 100644
index 000000000..26694274e
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_zwj_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.png b/java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.png
new file mode 100644
index 000000000..75a22b65f
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/vs_dialog_blue.9.png b/java/res/drawable-xhdpi/vs_dialog_blue.9.png
deleted file mode 100644
index 3284d78ef..000000000
--- a/java/res/drawable-xhdpi/vs_dialog_blue.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/vs_dialog_red.9.png b/java/res/drawable-xhdpi/vs_dialog_red.9.png
deleted file mode 100644
index 5af2465b5..000000000
--- a/java/res/drawable-xhdpi/vs_dialog_red.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/vs_dialog_yellow.9.png b/java/res/drawable-xhdpi/vs_dialog_yellow.9.png
deleted file mode 100644
index 4f50439de..000000000
--- a/java/res/drawable-xhdpi/vs_dialog_yellow.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xhdpi/vs_popup_mic_edge.png b/java/res/drawable-xhdpi/vs_popup_mic_edge.png
deleted file mode 100644
index 1063cb464..000000000
--- a/java/res/drawable-xhdpi/vs_popup_mic_edge.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-hdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-xlarge-hdpi/btn_keyboard_key_popup_selected_holo.9.png
deleted file mode 100644
index 544ed7f78..000000000
--- a/java/res/drawable-xlarge-hdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-hdpi/hint_popup_holo.9.png b/java/res/drawable-xlarge-hdpi/hint_popup_holo.9.png
deleted file mode 100644
index 2ffc6ea2b..000000000
--- a/java/res/drawable-xlarge-hdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-land-hdpi/hint_popup_holo.9.png b/java/res/drawable-xlarge-land-hdpi/hint_popup_holo.9.png
deleted file mode 100644
index 2b93014e1..000000000
--- a/java/res/drawable-xlarge-land-hdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-land-mdpi/hint_popup_holo.9.png b/java/res/drawable-xlarge-land-mdpi/hint_popup_holo.9.png
deleted file mode 100644
index c409cea00..000000000
--- a/java/res/drawable-xlarge-land-mdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-land-xhdpi/hint_popup_holo.9.png b/java/res/drawable-xlarge-land-xhdpi/hint_popup_holo.9.png
deleted file mode 100644
index 3cd20d34f..000000000
--- a/java/res/drawable-xlarge-land-xhdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_holo.9.png
deleted file mode 100644
index 2ad73041e..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
deleted file mode 100644
index fc21e79c4..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
deleted file mode 100644
index 76cfbb221..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
deleted file mode 100644
index 73748c2fb..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
deleted file mode 100644
index 059d4ac2e..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
deleted file mode 100644
index e5cfdec88..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_normal_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_normal_holo.9.png
deleted file mode 100644
index 060524a53..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_normal_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_pressed_holo.9.png
deleted file mode 100644
index f4b061e07..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-xlarge-mdpi/btn_keyboard_key_popup_selected_holo.9.png
deleted file mode 100644
index ffa7386df..000000000
--- a/java/res/drawable-xlarge-mdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/hint_popup_holo.9.png b/java/res/drawable-xlarge-mdpi/hint_popup_holo.9.png
deleted file mode 100644
index 01d1139d8..000000000
--- a/java/res/drawable-xlarge-mdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/keyboard_background_holo.9.png b/java/res/drawable-xlarge-mdpi/keyboard_background_holo.9.png
deleted file mode 100644
index a93966c92..000000000
--- a/java/res/drawable-xlarge-mdpi/keyboard_background_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-xlarge-mdpi/keyboard_popup_panel_background_holo.9.png
deleted file mode 100644
index 7be7ab7e2..000000000
--- a/java/res/drawable-xlarge-mdpi/keyboard_popup_panel_background_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/keyboard_suggest_strip_holo.9.png b/java/res/drawable-xlarge-mdpi/keyboard_suggest_strip_holo.9.png
deleted file mode 100644
index 1f87a68e9..000000000
--- a/java/res/drawable-xlarge-mdpi/keyboard_suggest_strip_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index 155579169..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num0_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num0_holo.png
deleted file mode 100644
index e1d395b45..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num0_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num1_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num1_holo.png
deleted file mode 100644
index 225436ac2..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num1_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num2_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num2_holo.png
deleted file mode 100644
index e513fa4a0..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num2_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num3_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num3_holo.png
deleted file mode 100644
index b91e005fc..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num3_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num4_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num4_holo.png
deleted file mode 100644
index 65f88245b..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num4_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num5_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num5_holo.png
deleted file mode 100644
index b89ef07eb..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num5_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num6_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num6_holo.png
deleted file mode 100644
index 931275a9e..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num6_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num7_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num7_holo.png
deleted file mode 100644
index 9396c4c8f..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num7_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num8_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num8_holo.png
deleted file mode 100644
index 12e3eef45..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num8_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_num9_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_num9_holo.png
deleted file mode 100644
index 6911c2b4f..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_num9_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_numbpound_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_numbpound_holo.png
deleted file mode 100644
index e3a8b4900..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_numbpound_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_numbstar_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_numbstar_holo.png
deleted file mode 100644
index e80e9345f..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_numbstar_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_return_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index d519ccecf..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_settings_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 784a45054..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_shift_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index 91d6e32f9..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index 2bd053656..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_space_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index 25e655d96..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_voice_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index c1116dc17..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-mdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-xlarge-mdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index 081a13096..000000000
--- a/java/res/drawable-xlarge-mdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-xhdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-xlarge-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
deleted file mode 100644
index 8b5d1b098..000000000
--- a/java/res/drawable-xlarge-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-xlarge-xhdpi/hint_popup_holo.9.png b/java/res/drawable-xlarge-xhdpi/hint_popup_holo.9.png
deleted file mode 100644
index bc37fa844..000000000
--- a/java/res/drawable-xlarge-xhdpi/hint_popup_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable/btn_center.xml b/java/res/drawable/btn_center.xml
index 19b298f75..3ac21297c 100644
--- a/java/res/drawable/btn_center.xml
+++ b/java/res/drawable/btn_center.xml
@@ -19,7 +19,8 @@
-->
<selector
- xmlns:android="http://schemas.android.com/apk/res/android">
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<item
android:state_window_focused="false"
android:state_enabled="true"
diff --git a/java/res/drawable/btn_keyboard_key_gingerbread.xml b/java/res/drawable/btn_keyboard_key_gingerbread.xml
index 4a113a8a1..5b4399e1b 100644
--- a/java/res/drawable/btn_keyboard_key_gingerbread.xml
+++ b/java/res/drawable/btn_keyboard_key_gingerbread.xml
@@ -23,6 +23,13 @@
<item android:state_single="true"
android:drawable="@drawable/btn_keyboard_key_dark_normal" />
+ <!-- Action keys. -->
+
+ <item android:state_active="true" android:state_pressed="true"
+ android:drawable="@drawable/btn_keyboard_key_dark_pressed" />
+ <item android:state_active="true"
+ android:drawable="@drawable/btn_keyboard_key_dark_normal" />
+
<!-- Toggle keys. Use checkable/checked state. -->
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
@@ -34,7 +41,7 @@
<item android:state_checkable="true"
android:drawable="@drawable/btn_keyboard_key_dark_normal_off" />
- <!-- Normal keys -->
+ <!-- Normal keys. -->
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_light_pressed" />
diff --git a/java/res/drawable/btn_keyboard_key_ics.xml b/java/res/drawable/btn_keyboard_key_ics.xml
index 7335cc299..e893da133 100644
--- a/java/res/drawable/btn_keyboard_key_ics.xml
+++ b/java/res/drawable/btn_keyboard_key_ics.xml
@@ -23,6 +23,13 @@
<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" />
+ <item android:state_active="true"
+ android:drawable="@drawable/btn_keyboard_key_dark_active_holo" />
+
<!-- Toggle keys. Use checkable/checked state. -->
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
@@ -34,7 +41,7 @@
<item android:state_checkable="true"
android:drawable="@drawable/btn_keyboard_key_dark_normal_off_holo" />
- <!-- Normal keys -->
+ <!-- Normal keys. -->
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_light_pressed_holo" />
diff --git a/java/res/drawable/btn_keyboard_key_popup.xml b/java/res/drawable/btn_keyboard_key_popup.xml
index 860cfd5d5..9e3670d22 100644
--- a/java/res/drawable/btn_keyboard_key_popup.xml
+++ b/java/res/drawable/btn_keyboard_key_popup.xml
@@ -17,5 +17,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_light_popup_selected" />
- <item android:drawable="@drawable/btn_keyboard_key_light_popup_normal" />
+ <item android:drawable="@drawable/transparent" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_key_popup_ics.xml b/java/res/drawable/btn_keyboard_key_popup_ics.xml
index 8f797ac3c..b99679ba1 100644
--- a/java/res/drawable/btn_keyboard_key_popup_ics.xml
+++ b/java/res/drawable/btn_keyboard_key_popup_ics.xml
@@ -17,5 +17,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_popup_selected_holo" />
- <item android:drawable="@drawable/btn_keyboard_key_popup_background_holo" />
+ <item android:drawable="@drawable/transparent" />
</selector>
diff --git a/java/res/drawable/btn_keyboard_key_stone.xml b/java/res/drawable/btn_keyboard_key_stone.xml
index 27932e8da..9bc3f18d6 100644
--- a/java/res/drawable/btn_keyboard_key_stone.xml
+++ b/java/res/drawable/btn_keyboard_key_stone.xml
@@ -23,6 +23,13 @@
<item android:state_single="true"
android:drawable="@drawable/btn_keyboard_key_normal_stone" />
+ <!-- Action keys. -->
+
+ <item android:state_active="true" android:state_pressed="true"
+ android:drawable="@drawable/btn_keyboard_key_fulltrans_pressed" />
+ <item android:state_active="true"
+ android:drawable="@drawable/btn_keyboard_key_normal_stone" />
+
<!-- Toggle keys. Use checkable/checked state. -->
<item android:state_checkable="true" android:state_checked="true"
@@ -35,7 +42,7 @@
<item android:state_checkable="true"
android:drawable="@drawable/btn_keyboard_key_normal_off_stone" />
- <!-- Normal keys -->
+ <!-- Normal keys. -->
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_fulltrans_pressed" />
diff --git a/java/res/drawable/btn_candidate.xml b/java/res/drawable/btn_suggestion.xml
index efcee9f54..cde12fe55 100644
--- a/java/res/drawable/btn_candidate.xml
+++ b/java/res/drawable/btn_suggestion.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -23,5 +23,5 @@
>
<item
android:state_pressed="true"
- android:drawable="@drawable/btn_candidate_pressed" />
+ android:drawable="@drawable/btn_suggestion_pressed" />
</selector>
diff --git a/java/res/drawable/btn_candidate_ics.xml b/java/res/drawable/btn_suggestion_ics.xml
index e4257e327..e4257e327 100644
--- a/java/res/drawable/btn_candidate_ics.xml
+++ b/java/res/drawable/btn_suggestion_ics.xml
diff --git a/java/res/drawable/btn_keyboard_key_fulltrans.xml b/java/res/drawable/keyboard_key_feedback_left_ics.xml
index bad2a931d..b68b37f6b 100644
--- a/java/res/drawable/btn_keyboard_key_fulltrans.xml
+++ b/java/res/drawable/keyboard_key_feedback_left_ics.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,12 +15,7 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <!-- Normal keys -->
-
- <item android:state_pressed="true"
- android:drawable="@drawable/btn_keyboard_key_fulltrans_pressed" />
- <item
- android:drawable="@drawable/btn_keyboard_key_fulltrans_normal" />
-
+ <item android:state_long_pressable="true"
+ android:drawable="@drawable/keyboard_key_feedback_left_more_background_holo" />
+ <item android:drawable="@drawable/keyboard_key_feedback_left_background_holo" />
</selector>
diff --git a/java/res/drawable/keyboard_key_feedback_right_ics.xml b/java/res/drawable/keyboard_key_feedback_right_ics.xml
new file mode 100644
index 000000000..830678a5a
--- /dev/null
+++ b/java/res/drawable/keyboard_key_feedback_right_ics.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_long_pressable="true"
+ android:drawable="@drawable/keyboard_key_feedback_right_more_background_holo" />
+ <item android:drawable="@drawable/keyboard_key_feedback_right_background_holo" />
+</selector>
diff --git a/java/res/layout-xlarge/recognition_status.xml b/java/res/layout-xlarge/recognition_status.xml
deleted file mode 100644
index 40bc09823..000000000
--- a/java/res/layout-xlarge/recognition_status.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="@drawable/background_voice">
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/popup_layout"
- android:orientation="vertical"
- android:layout_height="371dip"
- android:layout_width="500dip"
- android:layout_centerInParent="true"
- android:background="@drawable/vs_dialog_red">
- <TextView
- android:id="@+id/text"
- android:text="@string/voice_error"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:singleLine="true"
- android:layout_marginTop="10dip"
- android:textSize="28sp"
- android:textColor="#ffffff"
- android:layout_gravity="center"
- android:visibility="invisible"/>
- <RelativeLayout
- android:layout_height="0dip"
- android:layout_width="match_parent"
- android:layout_weight="1.0">
- <com.android.inputmethod.deprecated.voice.SoundIndicator
- android:id="@+id/sound_indicator"
- android:src="@drawable/mic_full"
- android:background="@drawable/mic_base"
- android:adjustViewBounds="true"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_centerInParent="true"
- android:visibility="gone"/>
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/mic_slash"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_centerInParent="true"
- android:visibility="visible"/>
- <ProgressBar
- android:id="@+id/progress"
- android:indeterminate="true"
- android:indeterminateOnly="false"
- android:layout_height="60dip"
- android:layout_width="60dip"
- android:layout_centerInParent="true"
- android:visibility="gone"/>
- </RelativeLayout>
- <!--
- The text is set by the code. We specify a random text (voice_error), so the
- text view does not have a zero height. This is necessary to keep the slash
- mic and the recording mic is the same position
- -->
- <TextView
- android:id="@+id/language"
- android:text="@string/voice_error"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:singleLine="true"
- android:textSize="14sp"
- android:layout_marginBottom="3dip"
- android:layout_gravity="center"
- android:textColor="#ffffff"
- android:visibility="invisible"/>
- <Button
- android:id="@+id/button"
- android:layout_width="match_parent"
- android:layout_height="54dip"
- android:singleLine="true"
- android:focusable="true"
- android:text="@string/cancel"
- android:layout_gravity="center_horizontal"
- android:background="@drawable/btn_center"
- android:textColor="#ffffff"
- android:textSize="19sp" />
- </LinearLayout>
-</RelativeLayout>
diff --git a/java/res/layout/additional_subtype_dialog.xml b/java/res/layout/additional_subtype_dialog.xml
new file mode 100644
index 000000000..f97c006d6
--- /dev/null
+++ b/java/res/layout/additional_subtype_dialog.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:columnCount="2"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
+ android:padding="8dip">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left|center_vertical"
+ style="?android:attr/textAppearanceSmall"
+ android:text="@string/subtype_locale" />
+ <Spinner
+ android:id="@+id/subtype_locale_spinner"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="8dip"
+ android:layout_marginBottom="8dip"
+ android:layout_marginTop="8dip"
+ android:layout_gravity="fill_horizontal|center_vertical"
+ android:prompt="@string/subtype_locale" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left|center_vertical"
+ style="?android:attr/textAppearanceSmall"
+ android:text="@string/keyboard_layout_set" />
+ <Spinner
+ android:id="@+id/keyboard_layout_set_spinner"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="8dip"
+ android:layout_marginBottom="8dip"
+ android:layout_marginTop="8dip"
+ android:layout_gravity="fill_horizontal|center_vertical"
+ android:prompt="@string/keyboard_layout_set" />
+</GridLayout>
diff --git a/java/res/layout/candidates_strip.xml b/java/res/layout/candidates_strip.xml
deleted file mode 100644
index ea6708ee7..000000000
--- a/java/res/layout/candidates_strip.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <LinearLayout
- android:id="@+id/candidates_strip"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <RelativeLayout
- android:layout_weight="1.0"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:gravity="center"
- >
- <include
- android:id="@+id/word_left"
- layout="@layout/candidate_word" />
- <include
- android:id="@+id/info_left"
- layout="@layout/candidate_info" />
- </RelativeLayout>
- <include
- layout="@layout/candidate_divider" />
- <RelativeLayout
- android:layout_weight="1.0"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:gravity="center"
- >
- <include
- android:id="@+id/word_center"
- layout="@layout/candidate_word" />
- <include
- android:id="@+id/info_center"
- layout="@layout/candidate_info" />
- </RelativeLayout>
- <include
- layout="@layout/candidate_divider" />
- <LinearLayout
- android:orientation="horizontal"
- android:layout_weight="1.0"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- >
- <RelativeLayout
- android:layout_weight="1.0"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:gravity="center"
- >
- <include
- android:id="@+id/word_right"
- layout="@layout/candidate_word" />
- <include
- android:id="@+id/info_right"
- layout="@layout/candidate_info" />
- </RelativeLayout>
- <!-- Image drawables are set in CandidateView constructor -->
- <ImageButton
- android:id="@+id/expand_candidates_pane"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:background="@null" />
- <ImageButton
- android:id="@+id/close_candidates_pane"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:background="@null" />
- </LinearLayout>
- </LinearLayout>
- <LinearLayout
- android:id="@+id/touch_to_save"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone"
- >
- <Button
- android:id="@+id/word_to_save"
- android:layout_weight="1.0"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center_vertical"
- android:textSize="@dimen/candidate_text_size"
- android:singleLine="true"
- android:ellipsize="middle"
- style="?attr/suggestionBackgroundStyle" />
- <include
- layout="@layout/candidate_divider" />
- <TextView
- android:layout_weight="2.0"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:gravity="left|center_vertical"
- android:text="@string/hint_add_to_dictionary"
- android:textSize="@dimen/candidate_text_size"
- android:background="@null" />
- </LinearLayout>
-</merge>
diff --git a/java/res/layout/candidate_word.xml b/java/res/layout/hint_add_to_dictionary.xml
index 7b6db2fe8..73de44fae 100644
--- a/java/res/layout/candidate_word.xml
+++ b/java/res/layout/hint_add_to_dictionary.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -18,16 +18,19 @@
*/
-->
-<Button
+<!-- This is derived from suggestion_word.xml without minWidth attribute and padding -->
+<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:minWidth="@dimen/candidate_min_width"
- android:textSize="@dimen/candidate_text_size"
- android:paddingLeft="@dimen/candidate_padding"
+ android:textSize="@dimen/suggestion_text_size"
+ android:gravity="center"
+ android:paddingLeft="0dp"
android:paddingTop="0dp"
- android:paddingRight="@dimen/candidate_padding"
+ android:paddingRight="0dp"
android:paddingBottom="0dp"
+ android:focusable="false"
+ android:clickable="false"
android:singleLine="true"
android:ellipsize="none"
style="?attr/suggestionBackgroundStyle" />
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index 821082f91..3863534be 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -18,65 +18,47 @@
*/
-->
-<LinearLayout
+<com.android.inputmethod.latin.InputView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
- <!-- On tablets, the candidate strip is centered with horizontal paddings on both sides because
- width of the landscape mode is too long for the candidate strip. This LinearLayout is
- required to hold the paddings. -->
+ <!-- The height of key_preview_backing view will automatically be determined by code. -->
+ <View
+ android:id="@+id/key_preview_backing"
+ android:layout_width="match_parent"
+ android:layout_height="0dp" />
+
+ <!-- On tablets, the suggestions strip is centered with horizontal paddings on both sides
+ because width of the landscape mode is too long for the suggestions strip. This
+ LinearLayout is required to hold the paddings. -->
<LinearLayout
- android:id="@+id/candidates_container"
+ android:id="@+id/suggestions_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="@dimen/candidate_strip_minimum_height"
- android:gravity="bottom"
>
<View
- android:layout_width="@dimen/candidate_strip_padding"
- android:layout_height="@dimen/candidate_strip_height"
+ android:layout_width="@dimen/suggestions_strip_padding"
+ android:layout_height="@dimen/suggestions_strip_height"
style="?attr/suggestionsStripBackgroundStyle" />
- <com.android.inputmethod.latin.CandidateView
- android:id="@+id/candidates"
+ <com.android.inputmethod.latin.suggestions.SuggestionsView
+ android:id="@+id/suggestions_view"
android:layout_weight="1.0"
android:layout_width="0dp"
- android:layout_height="@dimen/candidate_strip_height"
+ android:layout_height="@dimen/suggestions_strip_height"
android:gravity="center_vertical"
- style="?attr/candidateViewStyle" />
+ style="?attr/suggestionsViewStyle" />
<View
- android:layout_width="@dimen/candidate_strip_padding"
- android:layout_height="@dimen/candidate_strip_height"
+ android:layout_width="@dimen/suggestions_strip_padding"
+ android:layout_height="@dimen/suggestions_strip_height"
style="?attr/suggestionsStripBackgroundStyle" />
</LinearLayout>
- <LinearLayout
- android:id="@+id/candidates_pane_container"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- style="?attr/suggestionsStripBackgroundStyle"
- >
- <View
- android:layout_width="@dimen/candidate_strip_padding"
- android:layout_height="@dimen/candidate_strip_height" />
- <FrameLayout
- android:id="@+id/candidates_pane"
- android:layout_weight="1.0"
- android:layout_width="0dp"
- android:layout_height="match_parent" />
- <View
- android:layout_width="@dimen/candidate_strip_padding"
- android:layout_height="@dimen/candidate_strip_height" />
- </LinearLayout>
-
<com.android.inputmethod.keyboard.LatinKeyboardView
android:id="@+id/keyboard_view"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
-</LinearLayout>
+</com.android.inputmethod.latin.InputView>
diff --git a/java/res/layout/key_preview.xml b/java/res/layout/key_preview.xml
index b620d07d8..6ed892e28 100644
--- a/java/res/layout/key_preview.xml
+++ b/java/res/layout/key_preview.xml
@@ -20,8 +20,8 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
- android:layout_height="80sp"
- android:textSize="40sp"
- android:minWidth="32dip"
+ android:layout_height="80dp"
+ android:textSize="40dp"
+ android:minWidth="32dp"
android:gravity="center"
/>
diff --git a/java/res/layout/keyboard_popup.xml b/java/res/layout/more_keys_keyboard.xml
index e2508da78..6b2464b99 100644
--- a/java/res/layout/keyboard_popup.xml
+++ b/java/res/layout/more_keys_keyboard.xml
@@ -22,12 +22,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
- style="?attr/popupMiniKeyboardPanelStyle"
+ style="?attr/moreKeysKeyboardPanelStyle"
>
- <com.android.inputmethod.keyboard.PopupMiniKeyboardView
+ <com.android.inputmethod.keyboard.MoreKeysKeyboardView
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- android:id="@+id/mini_keyboard_view"
- android:layout_alignParentBottom="true"
+ android:id="@+id/more_keys_keyboard_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
diff --git a/java/res/layout/more_suggestions.xml b/java/res/layout/more_suggestions.xml
new file mode 100644
index 000000000..b41bb8aa4
--- /dev/null
+++ b/java/res/layout/more_suggestions.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ style="?attr/moreKeysKeyboardPanelStyle"
+ >
+ <com.android.inputmethod.latin.suggestions.MoreSuggestionsView
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ android:id="@+id/more_suggestions_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ latin:keyLetterSize="@dimen/suggestion_text_size"
+ latin:keyLabelSize="@dimen/suggestion_text_size"
+ latin:keyHintLetterRatio="@fraction/more_suggestions_info_ratio"
+ latin:keyHintLetterColor="@android:color/white"
+ />
+</LinearLayout>
diff --git a/java/res/layout/recognition_status.xml b/java/res/layout/recognition_status.xml
deleted file mode 100644
index a2ddb7c50..000000000
--- a/java/res/layout/recognition_status.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="@drawable/background_voice">
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/popup_layout"
- android:orientation="vertical"
- android:layout_height="371dip"
- android:layout_width="500dip"
- android:layout_centerInParent="true"
- android:background="@drawable/vs_dialog_red">
- <TextView
- android:id="@+id/text"
- android:text="@string/voice_error"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:singleLine="true"
- android:layout_marginTop="10dip"
- android:textSize="20sp"
- android:textColor="#ffffff"
- android:layout_gravity="center"
- android:visibility="invisible"/>
- <RelativeLayout
- android:layout_height="0dip"
- android:layout_width="match_parent"
- android:layout_weight="1.0">
- <com.android.inputmethod.deprecated.voice.SoundIndicator
- android:id="@+id/sound_indicator"
- android:src="@drawable/mic_full"
- android:background="@drawable/mic_base"
- android:adjustViewBounds="true"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_centerInParent="true"
- android:visibility="gone"/>
- <ImageView
- android:id="@+id/image"
- android:src="@drawable/mic_slash"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_centerInParent="true"
- android:visibility="visible"/>
- <ProgressBar
- android:id="@+id/progress"
- android:indeterminate="true"
- android:indeterminateOnly="false"
- android:layout_height="60dip"
- android:layout_width="60dip"
- android:layout_centerInParent="true"
- android:visibility="gone"/>
- </RelativeLayout>
- <!--
- The text is set by the code. We specify a random text (voice_error), so the
- text view does not have a zero height. This is necessary to keep the slash
- mic and the recording mic is the same position
- -->
- <TextView
- android:id="@+id/language"
- android:text="@string/voice_error"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:singleLine="true"
- android:textSize="15sp"
- android:layout_marginTop="3dip"
- android:layout_marginBottom="3dip"
- android:layout_gravity="center"
- android:textColor="#ffffff"
- android:visibility="invisible"/>
- <Button
- android:id="@+id/button"
- android:layout_width="match_parent"
- android:layout_height="30dip"
- android:singleLine="true"
- android:focusable="true"
- android:text="@string/cancel"
- android:layout_gravity="center_horizontal"
- android:background="@drawable/btn_center"
- android:textColor="#ffffff"
- android:textSize="15sp" />
- </LinearLayout>
-</RelativeLayout>
diff --git a/java/res/layout/sound_effect_volume_dialog.xml b/java/res/layout/sound_effect_volume_dialog.xml
new file mode 100644
index 000000000..294663006
--- /dev/null
+++ b/java/res/layout/sound_effect_volume_dialog.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_margin="10dp">
+ <TextView android:id="@+id/sound_effect_volume_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20dp"/>
+ </LinearLayout>
+ <SeekBar
+ android:id="@+id/sound_effect_volume_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:max="100"
+ android:layout_margin="10dp"/>
+</LinearLayout>
diff --git a/java/res/layout/candidate_divider.xml b/java/res/layout/suggestion_divider.xml
index 748163074..a8b78c082 100644
--- a/java/res/layout/candidate_divider.xml
+++ b/java/res/layout/suggestion_divider.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -22,8 +22,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:src="@drawable/keyboard_suggest_strip_divider"
+ android:src="@drawable/suggestions_strip_divider"
android:padding="0dp"
- android:focusable="false"
- android:clickable="false"
- android:gravity="center_vertical|center_horizontal" />
+ android:gravity="center" />
diff --git a/java/res/layout/candidate_info.xml b/java/res/layout/suggestion_info.xml
index f3557289c..a4ad6df25 100644
--- a/java/res/layout/candidate_info.xml
+++ b/java/res/layout/suggestion_info.xml
@@ -22,7 +22,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textSize="6sp"
+ android:textSize="6dp"
android:textColor="@android:color/white"
- android:visibility="gone"
style="?attr/suggestionBackgroundStyle" />
diff --git a/java/res/layout/candidate_preview.xml b/java/res/layout/suggestion_preview.xml
index 32705c996..856447bba 100644
--- a/java/res/layout/candidate_preview.xml
+++ b/java/res/layout/suggestion_preview.xml
@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/*
+/*
**
-** Copyright 2008, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** 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
+** 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
+** 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.
*/
-->
@@ -21,8 +21,8 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textSize="18sp"
+ android:textSize="18dp"
android:textColor="?android:attr/textColorPrimaryInverse"
- android:minWidth="32dip"
+ android:minWidth="32dp"
android:gravity="center"
style="?attr/suggestionPreviewBackgroundStyle" />
diff --git a/java/res/layout/suggestion_word.xml b/java/res/layout/suggestion_word.xml
new file mode 100644
index 000000000..d64cacf04
--- /dev/null
+++ b/java/res/layout/suggestion_word.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:minWidth="@dimen/suggestion_min_width"
+ android:textSize="@dimen/suggestion_text_size"
+ android:gravity="center"
+ android:paddingLeft="@dimen/suggestion_padding"
+ android:paddingTop="0dp"
+ android:paddingRight="@dimen/suggestion_padding"
+ android:paddingBottom="0dp"
+ android:focusable="false"
+ android:clickable="false"
+ android:singleLine="true"
+ android:ellipsize="none"
+ style="?attr/suggestionBackgroundStyle" />
diff --git a/java/res/layout/suggestions_strip.xml b/java/res/layout/suggestions_strip.xml
new file mode 100644
index 000000000..cbf31e6dc
--- /dev/null
+++ b/java/res/layout/suggestions_strip.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <LinearLayout
+ android:id="@+id/suggestions_strip"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</merge>
diff --git a/java/res/layout/vibration_settings_dialog.xml b/java/res/layout/vibration_settings_dialog.xml
new file mode 100644
index 000000000..c9fb6ec4e
--- /dev/null
+++ b/java/res/layout/vibration_settings_dialog.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_margin="10dp">
+ <TextView android:id="@+id/vibration_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20dp"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/settings_ms"
+ android:textSize="20dp"/>
+ </LinearLayout>
+ <SeekBar
+ android:id="@+id/vibration_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:max="250"
+ android:layout_margin="10dp"/>
+</LinearLayout>
diff --git a/java/res/layout/voice_punctuation_hint.xml b/java/res/layout/voice_punctuation_hint.xml
deleted file mode 100644
index 629a7f2b5..000000000
--- a/java/res/layout/voice_punctuation_hint.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/keyboard_suggest_strip">
-
- <!-- TODO: Use dark mic icon. -->
- <ImageView android:id="@+id/image"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:layout_gravity="center_horizontal"
- android:src="@drawable/ic_suggest_strip_microphone"
- />
-
- <TextView android:id="@+id/text"
- android:text="@string/voice_punctuation_hint"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:paddingTop="2dip"
- android:paddingRight="3dip"
- android:textSize="13sp"
- android:textColor="#888888"
- android:layout_gravity="center_horizontal"
- />
-
-</LinearLayout>
diff --git a/java/res/layout/voice_swipe_hint.xml b/java/res/layout/voice_swipe_hint.xml
deleted file mode 100644
index 4e8859a71..000000000
--- a/java/res/layout/voice_swipe_hint.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/keyboard_suggest_strip"
- android:gravity="center_horizontal"
- android:paddingTop="2dip">
-
- <TextView android:id="@+id/text"
- android:text="@string/voice_swipe_hint"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:paddingTop="10dip"
- android:paddingRight="6dip"
- android:textSize="13sp"
- android:textColor="#888888"
- android:layout_gravity="center_horizontal"
- />
-
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="center_horizontal"
- android:src="@drawable/ic_suggest_strip_microphone"
- />
-
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_gravity="center_horizontal"
- android:src="@drawable/ic_suggest_strip_microphone_swipe"
- />
-
-
-</LinearLayout>
diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict
new file mode 100644
index 000000000..6122cd3f0
--- /dev/null
+++ b/java/res/raw/main_de.dict
Binary files differ
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
new file mode 100644
index 000000000..98a9361b5
--- /dev/null
+++ b/java/res/raw/main_en.dict
Binary files differ
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
new file mode 100644
index 000000000..71370aac2
--- /dev/null
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
new file mode 100644
index 000000000..717078c93
--- /dev/null
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/raw/main_it.dict b/java/res/raw/main_it.dict
new file mode 100644
index 000000000..82579078c
--- /dev/null
+++ b/java/res/raw/main_it.dict
Binary files differ
diff --git a/java/res/raw/main_pt_br.dict b/java/res/raw/main_pt_br.dict
new file mode 100644
index 000000000..d31752e07
--- /dev/null
+++ b/java/res/raw/main_pt_br.dict
Binary files differ
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 184e87528..22543efe5 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -21,61 +21,69 @@
<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">"Android-sleutelbord"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-sleutelbord (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-sleutelbordinstellings"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Navorsing-loglêerbevele"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-speltoetser"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-speltoetser (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Speltoetser se instellings"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Soek kontakname op"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Speltoetser gebruik inskrywings uit jou kontaklys"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreer met sleuteldruk"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Klank met sleuteldruk"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Opspring met sleuteldruk"</string>
<string name="general_category" msgid="1859088467017573195">"Algemeen"</string>
<string name="correction_category" msgid="2236750915056607613">"Tekskorrigering"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Voorstelle gebaseer op vorige woorde"</string>
<string name="misc_category" msgid="6894192814868233453">"Ander opsies"</string>
<string name="advanced_settings" msgid="362895144495591463">"Gevorderde instellings"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opsies vir gevorderde gebruikers"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opsies vir kundiges"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skakel oor na die ander invoermetodes"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Taal-wisselsleutel dek ook ander invoermetodes"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Onderdruk taal-wisselsleutel"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Sleutelopspringer-wagperiode"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen wagperiode nie"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Verstek"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Stel kontakname voor"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gebruik name van kontakte vir voorstelle en korreksies"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Aktiveer herkorrigerings"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Stel voorstelle vir herkorrigerings"</string>
<string name="auto_cap" msgid="1719746674854628252">"Outohoofletters"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Stel woordeboeke op"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Vinnige oplossings"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Korrigeer algemene tikfoute"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Voeg woordeboeke by"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Hoofwoordeboek"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Wys voorstelle vir korrigering"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Wys voorgestelde woorde terwyl jy tik"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Wys altyd"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Wys in portretmodus"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Versteek altyd"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Gebruik die spasiebalk-taalwisselaar"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Wys instellingsleutel"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Outomaties"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Wys altyd"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Versteek altyd"</string>
<string name="auto_correction" msgid="4979925752001319458">"Outokorrigering"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Spasiebalk en leestekens korrigeer outomaties woorde wat verkeerd gespel is"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Af"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Matig"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressief"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Baie aggressief"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram-voorstelle"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Gebruik vorige woord om voorstel te verbeter"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram-voorspellings"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Volgendewoordvoorstelle"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gebruik vorige woord om voorstelle te verbeter"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Volgendewoordvoorspelling"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Gebruik vorige woord ook vir voorspelling"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Meer"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift geaktiveer"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bokas-slot geaktiveer"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aan (tik om te deaktiveer)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Kasslot aan (tik om te deaktiveer)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Vee uit"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simbole"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Letters"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Steminvoering"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Glimlag-gesiggie"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Tydperk"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Links-hakie"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Regs-hakie"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dubbelpunt"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Kommapunt"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uitroepteken"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Vraagteken"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dubbel-aanhalingsteken"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkel-aanhalingsteken"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Soek"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punt"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Vierkantswortel"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Handelsmerk"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Per adres"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Ster"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Pond"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellips"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Onderste dubbel-aanhalingsteken"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Steminvoering"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Steminvoering vir jou taal word nie tans ondersteun nie, maar werk wel in Engels."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Steminvoer gebruik Google se spraakherkenning. "<a href="http://m.google.com/privacy">"Die Mobiel-privaatheidsbeleid"</a>" is van toepassing."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Om steminvoer af te skakel, gaan na invoermetode-instellings."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Om steminvoer te gebruik, druk die mikrofoonknoppie."</string>
- <string name="voice_listening" msgid="467518160751321844">"Praat nou"</string>
- <string name="voice_working" msgid="6666937792815731889">"Werkend"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Fout. Probeer asseblief weer."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Kon nie koppel nie"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Fout, te veel spraak."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Oudioprobleem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Bedienerfout"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Geen spraak gehoor nie"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Geen passings gevind nie"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Stemsoek nie geïnstalleer nie"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Wenk:"</b>" Sleep oor die sleutelbord om te praat"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Wenk:"</b>" Probeer volgende keer om leestekens soos \"punt\", \"komma\" of \"vraagteken\" hardop te sê."</string>
- <string name="cancel" msgid="6830980399865683324">"Kanselleer"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Steminvoering"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift geaktiveer"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kasslot geaktiveer"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift gedeaktiveer"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Simboolmodus"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Lettermodus"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Foonmodus"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Foonsimbool-modus"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Steminvoerinstellings"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Op hoofsleutelbord"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Op simbolesleutelbord"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Af"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofoon op hoofsleutelbord"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofoon op simbolesleutelbord"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Steminvoer is gedeaktiveer"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Kies invoermetode"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Gly vinger op spasiebalk om taal te verander"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Raak weer om te stoor"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"let op die tydstempel in die loglêer"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Aangetekende tydstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Moenie hierdie sessie aanteken nie"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sessie se loglêer uitgevee"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sessie se loglêer uitgevee"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sessie se loglêer NIE uitgevee nie"</string>
+ <string name="select_language" msgid="3693815588777926848">"Invoertale"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak weer om te stoor"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Aktiveer gebruikerterugvoer"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Help hierdie invoermetode-redigeerder te verbeter deur gebruikstatistiek en omvalverslae outomaties na Google te stuur."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Raak om woorde reg te maak"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Raak ingevoerde woorde om hulle te korrigeer, net wanneer voorstelle sigbaar is"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Sleutelbordtema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tsjeggiese sleutelbord"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabiese sleutelbord"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Deense sleutelbord"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Duitse sleutelbord"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Duitse QWERTY-sleutelbord"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Engelse (VK) sleutelbord"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Engelse (VS) sleutelbord"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spaanse sleutelbord"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finse sleutelbord"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Franse sleutelbord"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Franse (Kanada) sleutelbord"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Franse (Switserland) sleutelbord"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatiese sleutelbord"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Hongaarse sleutelbord"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebreeuse sleutelbord"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italiaanse sleutelbord"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Noorweegse sleutelbord"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Nederlandse sleutelbord"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Poolse sleutelbord"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugese sleutelbord"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russiese sleutelbord"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serwiese sleutelbord"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Sweedse sleutelbord"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turkse sleutelbord"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaanse stem"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Tsjeggiese stem"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Duitse stem"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Engelse stem"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spaanse stem"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Franse stem"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italiaanse stem"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japannese stem"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Koreaanse stem"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Nederlandse stem"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Poolse stem"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugese stem"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russiese stem"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Turkse stem"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Chinese, Yuese-stem"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Chinese, Mandarynse stem"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Zoeloe-stem"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engels (VK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Engels (VK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Engels (VS) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Geen taal nie"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Geen taal (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Geen taal nie (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Geen taal nie (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Geen taal nie (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Geen taal nie (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Geen taal nie (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Gepasmaakte invoerstyle"</string>
+ <string name="add_style" msgid="6163126614514489951">"Voeg styl by"</string>
+ <string name="add" msgid="8299699805688017798">"Voeg by"</string>
+ <string name="remove" msgid="4486081658752944606">"Verwyder"</string>
+ <string name="save" msgid="7646738597196767214">"Stoor"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Taal"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Uitleg"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Jou gepasmaakte invoerstyl moet geaktiveer word voor gebruik. Aktiveer nou?"</string>
+ <string name="enable" msgid="5031294444630523247">"Aktiveer"</string>
+ <string name="not_now" msgid="6172462888202790482">"Nie nou nie"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Dieselfde invoerstyl bestaan ​​reeds: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruikbaarheidstudie-modus"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Sleuteldruk se vibrasie-tydsduurinstellings"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Sleuteldruk se klankvolume-instellings"</string>
</resources>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index adeb1d443..a1b168cb7 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -21,61 +21,69 @@
<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">"የAndroid ቁልፍሰሌዳ"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"የAndroid ቁልፍ ሰሌዳ (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"የAndroid ቁልፍሰሌዳ ቅንብሮች"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ግቤት አማራጮች"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"የጥናት የምዝግብ ማስታወሻ ትዕዛዞች"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android የፊደል ማረሚያ"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android የፊደል ማረሚያ (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"የፊደል አራሚ ቅንብሮች"</string>
+ <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="ngram_category" msgid="5337109164339320257">"በቀደሙ ቃላት የተመሰረቱ ጥቆማዎች"</string>
<string name="misc_category" msgid="6894192814868233453">"ሌሎች አማራጮች"</string>
<string name="advanced_settings" msgid="362895144495591463">"የላቁ ቅንብሮች"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"ለብቁ ተጠቃሚዎች አማራጮች"</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="suppress_language_switch_key" msgid="8003788410354806368">"የቋንቋ መቀየሪያ ቁልፍ አፍን"</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="use_contacts_dict" msgid="4435317977804180815">"የዕውቂያ ስም ጠቁም"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ከዕውቂያዎች ለጥቆማዎች እና ማስተካከያዎች ስሞች ተጠቀም"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"ድጋሚ ለማስተካከል አንቃ"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"ድጋሚ ለማስተካከል ጥቆማዎችን አዘጋጅ"</string>
<string name="auto_cap" msgid="1719746674854628252">"ራስ-ሰር አቢይ ማድረግ"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"መዝገበ ቃላት አዋቅር"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"ፈጣንጥገና"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">" የተለመዱ የትየባ ስህተቶችንያስተካክላል"</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="3551821800439659812">"በቁመት ሁነታ አሳይ"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"ሁልጊዜ ደብቅ"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"የባዶ ቦታ አሞሌ ቋንቋ መቀየሪያ ተጠቀም"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"የቅንብሮች ቁልፍ አሳይ"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"ራስ ሰር"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"ሁልጊዜ አሳይ"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"ሁልጊዜ ደብቅ"</string>
<string name="auto_correction" msgid="4979925752001319458">"በራስ ማስተካከል"</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_aggeressive" msgid="3524029103734923819">"ኃይለኛ"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"በጣም ቁጡ"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"የቢግራም ምክሮች"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"ምክርን ለማሻሻል የቀደመ ቃልን ተጠቀም"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"የቢግራም ትንበያዎች"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"የቀጣይ ቃል አስተያየቶች"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ምክሮችን ለማሻሻል ቀዳሚ ቃል ተጠቀም"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"የቀጣይ ቃል ግምት"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"ለትንበያ የቀደመ ቃል እንዲሁ ተጠቀም"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"ተጨማሪ"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"ላፍታ አቁም"</string>
<string name="label_wait_key" msgid="6402152600878093134">"ቆይ"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"የይለፍቃል ቁልፎች ጮክ በለው ሲነገሩ ለመስማት የጆሮ ማዳመጫ ሰካ::"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"የአሁኑ ፅሁፍ %s ነው"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"ምንም ፅሁፍ አልገባም"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"የቁልፍ ኮድ%d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"ቀይር"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"መቀያየሪያ ቁልፍ ነቅቷል"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"አቢያት ማርጊያነቅቷል"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"ቅያር በርቷል (ለማሰናክል ንካ)"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"ነጠላ ሰረዝ"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"ክፍለ ጊዜ"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"የግራ ቅንፍ"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"የቀኝ ቅንፍ"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"ሁለት ነጥብ"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"ድርብ ሰረዝ"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"ቃል አጋኖ"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"ጥያቄ ምልክት"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"ድርብ ጥቅስ"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"ነጠላ ትምህርተ ጥቅስ"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"ፍለጋ"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"ነጥብ"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"ስክዌር ሩት"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"ዴልታ"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"የንግድምልክት"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"መጠንቀቅ"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"ኮከብ"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"ፓውንድ"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"ዝቅ ያለ ድርብ ትምህርተ ጥቅስ"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"የድምፅ ግቤ ት"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"የድምፅ ግቤት በአሁኑ ጊዜ ለእርስዎን ቋንቋ አይደግፍም፣ ግን በእንግሊዘኛ ይሰራል።"</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"የድምፅ ግቤት የGoogleን ንግግር ለይቶ ማወቂያ ይጠቀማል።"<a href="http://m.google.com/privacy">"የተንቀሳቃሽ ስልክ ግላዊ ፖሊሲ"</a>" ይተገበራል።"</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"የድምፅ ግቤት ለማጥፋት፣ወደ ግቤት ሜተድ ቅንብሮች ሂድ።"</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"የድምፅግቤት ለመጠቀም፣ የማይክራፎንየድምፅ ማጉያ አዝራር ተጫን።"</string>
- <string name="voice_listening" msgid="467518160751321844">"አሁን ተናገር"</string>
- <string name="voice_working" msgid="6666937792815731889">"ሥራ ላይ"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"ስህተት፣ እባክዎ እንደገና ይሞክሩ።"</string>
- <string name="voice_network_error" msgid="6649556447401862563">"ማያያዝ አልተቻለም"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"ስህተት፣ በጣም ብዙ ንግግር።"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"የድምፅ ችግር"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"የአገልጋይ ስህተት"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"ምንም ንግግር አልተሰማም"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"ምንም ተመሳሳይ አልተገኘም።"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"የድምፅ ፍለጋአልተጫነም"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"ምክር፡"</b>" ለመናገር በቁልፍሰሌዳ ላይ አንሸራት"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"ምክር፡"</b>" ሌላ ጊዜ፣ እንደ \"period\", \"comma\", ወይም \"question mark\" ያሉ ስርዓተ ነጥቦችን ለመናገር ሞክር።"</string>
- <string name="cancel" msgid="6830980399865683324">"ይቅር"</string>
- <string name="ok" msgid="7898366843681727667">"እሺ"</string>
- <string name="voice_input" msgid="2466640768843347841">"የድምፅ ግቤት"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"ቅያር ቁልፍ ነቅቷል"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"አቢያት ማድረጊያ ነቅቷል"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"ቅያር ተሰናክሏል"</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="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="selectInputMethod" msgid="315076553378705821">"የግቤት ሜተድ ምረጥ"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"ግቤት ሜተዶችን አዋቀር"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ቋንቋዎች አግቤት"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"ቋንቋ ለመለወጥ የቦታ ቁልፍ ላይ ጣትዎን ያንሸራቱ"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← ለማስቀመጥ ድጋሚ ንካ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"የምዝግብ ማስታወሻ ጊዜ ማህተም ማስታወሻ"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"የጊዜ ማህተም ተመዝግቧል"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ይህን ክፍለ ጊዜ እንዳትመዘግበው"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"የክፍለጊዜ ምዝግብ ማስታወሻ በመሰረዝ ላይ"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"የክፍለ ጊዜ ምዝግብ ማስታወሻ ተሰርዟል"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"የክፍለጊዜ ምዝግብ ማስታወሻ አልተሰረዘም"</string>
+ <string name="select_language" msgid="3693815588777926848">"ቋንቋዎች አግቤት"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"ለማስቀመጥ እንደገና ንካ"</string>
<string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላት አለ"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"የተጠቃሚ ግብረ ምላሽ አንቃ"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"ወደ Google የተሰናከለ ሪፖርቶች እና አጠቃቀም ስታስቲክስ በራስ ሰር በመላክ ይህን ግቤት ሜተድ አርትኢ እገዛ ያሻሽላል።"</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"ቃላትን ለማስተካከል ንካ"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"የገቡ ቃላትን ለማስተካከል ንካ፣ አማራጮች ሲታዩብቻ"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"የቁልፍ ሰሌዳ ገጽታ"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"የቼክ ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"የአረብኛ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"የዳኒሽኛ ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"የጀርመንኛ ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"የጀርመንኛ QWERTY ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"የእንግሊዘኛ(ዩኬ) ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"የእንግሊዘኛ(ዩኤስ) ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"የስፖኒሽኛቁልፍ ሰሌዳ"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"የፊኒሽ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"የፈረንሳይኛ ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"የፈረንሳይኛ(ካናዳ) ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"የፈረንሳይኛ(ስዊዘርላንድ) ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"የክሮሺያ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"የሃንጋሪ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"የዕብራይስጥ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"የጣሊያንኛ ቁልፍ ሰሌዳ"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"የኖርዌጂኛ ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"የደች ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"የፖላንድኛ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"የፖርቹጋልኛ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"የራሽኛቁልፍ ሰሌዳ"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"የሩሲኪኛቁልፍ ሰሌዳ"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"የሲውድናዊ ቁልፍሰሌዳ"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"የቱርክ ሰሌዳ ቁልፍ"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"የአፍሪካንስ ድምፅ"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"የቼክ ድምፅ"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"የጀርመናዊ ድምፅ"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"የእንግሊዘኛ ድምፅ"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"የስፔናዊ ድምፅ"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"የፈረንሳዊ ድምፅ"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"የጣሊያንኛ ድምፅ"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"የጃፓናዊ ድምፅ"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"የኮሪያዊ ድምፅ"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"የደች ድምፅ"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"የፖሊሽኛ ድምፅ"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"የፖርቹጊኛ ድምፅ"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"የራሽኛድምፅ"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"የቱርካዊ ድምፅ"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"የቻይንኛ፣ ዩ ድምፅ"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"የቻይንኛ፣ማንድሪን ድምፅ"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"የኢዚዙሉ ድምፅ"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"እንግሊዘኛ (የታላቋ ብሪታንያ)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"እንግሊዘኛ (ዩ.ኤስ)"</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_no_language" msgid="141420857808801746">"ምንም ቋንቋ"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"ቋንቋ አልባ (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"ቋንቋ አልባ (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"ቋንቋ አልባ (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"ቋንቋ አልባ (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"ቋንቋ አልባ (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"ቋንቋ አልባ (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"ቁልፍ ተጫን በቅንጅቶች ወቅት ንዝረት"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"ቁልፍ ተጫን የድምጽ መጠን ቅንብሮች"</string>
</resources>
diff --git a/java/res/values-ru/donottranslate-altchars.xml b/java/res/values-ar/donottranslate.xml
index 2da8b8469..57de2538b 100644
--- a/java/res/values-ru/donottranslate-altchars.xml
+++ b/java/res/values-ar/donottranslate.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_cyrillic_e">5,ё</string>
- <string name="alternates_for_cyrillic_soft_sign">ъ</string>
+ <!-- The all letters need to be mirrored are found at
+ http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt -->
+ <!-- Symbols that are suggested between words -->
+ <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string>
</resources>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index e2764e9bf..2a2207447 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -21,61 +21,69 @@
<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">"لوحة مفاتيح Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"لوحة مفاتيح Android ‏(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"إعدادات لوحة مفاتيح Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"خيارات الإرسال"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"أوامر سجلات البحث"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"التدقيق الإملائي في Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"التدقيق الإملائي في Android‏ (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"إعدادات التدقيق الإملائي"</string>
+ <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="ngram_category" msgid="5337109164339320257">"الاقتراحات بناءً على الكلمات السابقة"</string>
<string name="misc_category" msgid="6894192814868233453">"خيارات أخرى"</string>
<string name="advanced_settings" msgid="362895144495591463">"الإعدادات المتقدمة"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"خيارات للمستخدمين الخبراء"</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="suppress_language_switch_key" msgid="8003788410354806368">"إيقاف مفتاح تبديل اللغات"</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="use_contacts_dict" msgid="4435317977804180815">"اقتراح أسماء جهات الاتصال"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"استخدام الأسماء من جهات الاتصال للاقتراحات والتصحيحات"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"تمكين عمليات إعادة التصحيح"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"تعيين اقتراحات لعمليات إعادة التصحيح"</string>
<string name="auto_cap" msgid="1719746674854628252">"أحرف كبيرة تلقائيًا"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"تهيئة القواميس"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"إصلاحات سريعة"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"تصحيح الأخطاء المكتوبة الشائعة"</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="3551821800439659812">"عرض في وضع رأسي"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"إخفاء دومًا"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"استخدام مفتاح المسافة لتبديل اللغة"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"عرض مفتاح الإعدادات"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"تلقائي"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"إظهار بشكل دائم"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"إخفاء دومًا"</string>
<string name="auto_correction" msgid="4979925752001319458">"التصحيح التلقائي"</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_aggeressive" msgid="3524029103734923819">"حاد"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"شديد الصرامة"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"اقتراحات ثنائية"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"استخدام الكلمة السابقة لتحسين الاقتراح"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"التنبؤ الثنائي"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"اقتراحات الكلمات التالية"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"استخدام الكلمة السابقة لتحسين الاقتراحات"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"تنبؤ الكلمات التالية"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"استخدام الكلمة السابقة أيضًا للتنبؤ"</string>
<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_to_alpha_key" msgid="4793983863798817523">"أ ب ج"</string>
- <string name="label_more_key" msgid="3760239494604948502">"المزيد"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"٣٢١؟"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"٣٢١"</string>
<string name="label_pause_key" msgid="181098308428035340">"توقف مؤقت"</string>
<string name="label_wait_key" msgid="6402152600878093134">"انتظار"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"يمكنك توصيل سماعة رأس لسماع مفاتيح كلمة المرور منطوقة بصوت عالٍ."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"النص الحالي هو %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"لم يتم إدخال نص"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"رمز المفتاح %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"العالي"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"تم تمكين العالي"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"تمكين 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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"فاصلة"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"نقطة"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"قوس أيسر"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"قوس أيمن"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"نقطتان"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"فاصلة منقوطة"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"علامة التعجب"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"علامة استفهام"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"علامة الاقتباس المزدوجة"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"علامة الاقتباس المفردة"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"بحث"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"نقطة"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"جذر تربيعي"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"باي"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"دلتا"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"علامة تجارية"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"رعاية"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"نجمة"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"جنيه"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"علامة حذف"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"علامة الاقتباس المزدوجة السفلية"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"الإدخال الصوتي"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"الإدخال الصوتي غير معتمد حاليًا للغتك، ولكنه يعمل باللغة الإنجليزية."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"يستخدم الإدخال الصوتي خاصية التعرف على الكلام من Google. تنطبق "<a href="http://m.google.com/privacy">"سياسة خصوصية الجوال"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"لإيقاف الإدخال الصوتي، انتقل إلى إعدادات طريقة الإدخال."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"لاستخدام الإدخال الصوتي، اضغط على زر الميكروفون."</string>
- <string name="voice_listening" msgid="467518160751321844">"تحدث الآن"</string>
- <string name="voice_working" msgid="6666937792815731889">"العمل"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"خطأ. الرجاء المحاولة مرة أخرى."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"تعذر الاتصال"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"خطأ، كلام أكثر مما ينبغي."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"مشكلة بالإعدادات الصوتية"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"خطأ في الخادم"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"لم يتم سماع كلام"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"لم يتمّ العثور على أية تطابقات"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"لم يتم تثبيت البحث الصوتي"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"تلميح:"</b>" مرر عبر لوحة المفاتيح للتحدث"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"تلميح:"</b>" جرب في المرة التالية نطق الترقيم مثل \"نقطة\" أو \"فاصلة\" أو \"علامة استفهام\"."</string>
- <string name="cancel" msgid="6830980399865683324">"إلغاء"</string>
- <string name="ok" msgid="7898366843681727667">"موافق"</string>
- <string name="voice_input" msgid="2466640768843347841">"الإدخال الصوتي"</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="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="selectInputMethod" msgid="315076553378705821">"تحديد طريقة الإرسال"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"تهيئة طرق الإدخال"</string>
<string name="language_selection_title" msgid="1651299598555326750">"لغات الإدخال"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"مرر إصبعك على مفتاح المسافة لتغيير اللغة"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← المس مرة أخرى للحفظ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ملاحظة طابع زمني في سجل"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"تم تسجيل الطابع الزمني"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"عدم تسجيل هذه الجلسة"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"جارٍ حذف سجل الجلسة"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"تم حذف سجل الجلسة"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"لم يتم حذف سجل الجلسة"</string>
+ <string name="select_language" msgid="3693815588777926848">"لغات الإدخال"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"المس مرة أخرى للحفظ"</string>
<string name="has_dictionary" msgid="6071847973466625007">"القاموس متاح"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"تمكين ملاحظات المستخدم"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"المساعدة في تحسين محرر طريقة الإرسال هذا من خلال إرسال إحصاءات الاستخدام وتقارير الأعطال تلقائيًا إلى Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"المس لتصحيح الكلمات"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"المس الكلمات التي تم إدخالها لتصحيحها، وذلك فقط عندما تكون الاقتراحات مرئية."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"مظهر لوحة المفاتيح"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"لوحة مفاتيح تشيكية"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"لوحة المفاتيح العربية"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"لوحة مفاتيح دانماركية"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"لوحة مفاتيح ألمانية"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"لوحة مفاتيح QWERTY ألمانية"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"لوحة مفاتيح إنجليزية (بريطانيا)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"لوحة مفاتيح إنجليزية (الولايات المتحدة)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"لوحة مفاتيح إسبانية"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"لوحة المفاتيح الفنلندية"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"لوحة مفاتيح فرنسية"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"لوحة مفاتيح فرنسية (كندا)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"لوحة مفاتيح فرنسية (سويسرا)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"لوحة المفاتيح الكرواتية"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"لوحة المفاتيح المجرية"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"لوحة المفاتيح العبرية"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"لوحة مفاتيح إيطالية"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"لوحة مفاتيح نرويجية"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"لوحة مفاتيح بولندية"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"لوحة المفاتيح البولندية"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"لوحة المفاتيح البرتغالية"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"لوحة مفاتيح روسية"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"لوحة مفاتيح صربية"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"لوحة مفاتيح سويدية"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"لوحة المفاتيح التركية"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"صوت أفريقاني"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"صوت تشيكي"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"صوت ألماني"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"صوت إنجليزي"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"صوت إسباني"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"صوت فرنسي"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"صوت إيطالي"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"صوت ياباني"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"صوت كوري"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"صوت هولندي"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"صوت بولندي"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"صوت برتغالي"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"صوت روسي"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"صوت تركي"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"صوت صيني، يوي"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"صوت صيني، الماندارين"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"صوت زولوي"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"الإنجليزية (المملكة المتحدة)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"الإنجليزية (الولايات المتحدة)"</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_no_language" msgid="141420857808801746">"بدون لغة"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"بدون لغة (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"بدون لغة (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"بدون لغة (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"بدون لغة (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"بدون لغة (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"بدون لغة (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"إعدادات مدة اهتزاز الضغط على المفاتيح"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"إعدادات مستوى صوت الضغط على المفاتيح"</string>
</resources>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index 961d3d3ef..ff3213ad6 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -21,61 +21,69 @@
<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">"Клавіятура Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавіятура Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Налады клавіятуры Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ўводу"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Каманды гiсторыя даследаванняў"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Iнструмент праверкi правапiсу для Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Iнструмент праверкi правапiсу для Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Налады праверкі арфаграфіі"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Прапановы на аснове папярэдніх слоў"</string>
<string name="misc_category" msgid="6894192814868233453">"Іншыя параметры"</string>
<string name="advanced_settings" msgid="362895144495591463">"Адмысловыя налады"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Парам. для дасведч. карыст."</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Функцыi для спецыялістаў"</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">"Кнопка пераключэння мовы звязана i з iншымi спосабамi ўводу"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Забаранiць кнопку пераключэння мовы"</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="use_contacts_dict" msgid="4435317977804180815">"Прапан. імёны кантактаў"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Выкарыстоўваць імёны са спісу кантактаў для прапаноў і выпраўл."</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Уключыць карэкцiроўкі"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Задаць прапановы для карэкцiроўкі"</string>
<string name="auto_cap" msgid="1719746674854628252">"Аўтаматычна рабіць вялікія літары"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Налада слоўнікаў"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Хуткія выпраўленні"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Выпраўленне звычайных памылак"</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="3551821800439659812">"Паказаць у партрэтным рэжыме"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Заўседы хаваць"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Перакл. мовы праб."</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Паказаць умоўныя азначэнні налад"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Аўтаматычна"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Заўсёды паказваць"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Заўседы хаваць"</string>
<string name="auto_correction" msgid="4979925752001319458">"Аўтамат. выпраўленне"</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_aggeressive" msgid="3524029103734923819">"Агрэсіўны"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Вельмі агрэсіўны"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Біграмныя падказкi"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Выкарыстаць папярэдняе слова, каб палепшыць прапанову"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Бiграмныя падказкi"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Падказкi для наступнага слова"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Выкарыстаць папярэдняе слова, каб палепшыць прапановы"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Падказка наступнага слова"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Выкарыстанне папярэдняга слова для падказак"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Яшчэ"</string>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"АБВ"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Клавішны код %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Зрух"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Зрух уключаны"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock уключаны"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift уключаны (націснiце, каб адключыць)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock уключаны (націснiце, каб адключыць)"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"Коска"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Кропка"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Адчыняючая дужка"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Дужка, якая зачыняе"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Двукроп\'е"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Кропка з коскай"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Клічнік"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Пытальнік"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Двукоссі"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Паўдвукоссі"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Пошук"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Кропка"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратны корань"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Пі"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Дэльта"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Гандлёвая марка"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Працэнт"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Пазначыць"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Фунт"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Шматкроп\'е"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Нізкія падвойныя двукоссі"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Галасавы ўвод"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Галасавы ўвод пакуль не падтрымліваецца для вашай мовы, але працуе на англійскай мове."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Галасавы набор выкарыстоўвае распазнанне гаворкі Google. Ужываецца "<a href="http://m.google.com/privacy">"палiтыка прыватнасцi для мабiльных прылад"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Каб адключыць галасавы ўвод, перайдзіце ў налады метаду ўводу."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Каб выкарыстоўваць галасавы ўвод, націсніце кнопку мікрафона."</string>
- <string name="voice_listening" msgid="467518160751321844">"Гаварыце"</string>
- <string name="voice_working" msgid="6666937792815731889">"Апрацоўка"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Памылка. Паспрабуйце яшчэ."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Не атрымалася ўсталяваць падключэнне"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Памылка, зашмат гаворкі."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Праблема з гукам"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Памылка сервера"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Не чуваць гаворку"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Няма супадзенняў"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Галасавы пошук не ўсталяваны"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Падказка:"</b>" Правядзіце пальцам праз клавіятуру, каб казаць"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Падказка:"</b>" У наступны раз паспрабуйце прагаворваць такiя знакі пунктуацыі, як \"кропка\", \"коска\" або \"пытальнік\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Адмяніць"</string>
- <string name="ok" msgid="7898366843681727667">"ОК"</string>
- <string name="voice_input" msgid="2466640768843347841">"Галасавы ўвод"</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">"Рэжым лiтар"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Рэжым тэлефона"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Рэжым тэлефонных знакаў"</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="selectInputMethod" msgid="315076553378705821">"Выберыце метад уводу"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Налада метадаў уводу"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Мовы ўводу"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Правядзіце пальцам на клавішы прабелу, каб змяніць мову"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"... Дакраніцеся яшчэ раз, каб захаваць"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Пазначыць час у гiсторыi"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Запiсаныя пазнакі"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Не рэгістраваць гэты сеанс"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Выдаленне гiсторыi сеанса"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Гiсторыя сеанса выдалена"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Гiсторыя сеанса НЕ выдалена"</string>
+ <string name="select_language" msgid="3693815588777926848">"Мовы ўводу"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Дакраніцеся зноў, каб захаваць"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Слоўнік даступны"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Уключыць зваротную сувязь з карыстальнікамі"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Дапамажыце палепшыць гэты рэдактар ​​метаду ўводу, аўтаматычна адпраўляючы статыстыку выкарыстання і справаздачы аб збоях Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Дакр., каб выправіць словы"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Дакранайцеся да ўведзеных слоў, каб выправіць іх, толькі тады, калі бачыце прапановы"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Тэма клавіятуры"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Чэшская раскладка клавіятуры"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Арабская раскладка"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Дацкая раскладка клавіятуры"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Нямецкая раскладка клавіятуры"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Нямецкая раскладка QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Англ. рас. клав. (Велікабрытанія)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Англійская раскл. клав. (ЗША)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Іспанская раскладка клавіятуры"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Фінская раскладка"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Французская раскладка клавіятуры"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Французская раскл. клав. (Канада)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Французская рас. клав. (Швейцарыя)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Харвацкая раскладка"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Венгерская раскладка"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Габрэйская раскладка"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Італьянская раскладка клавіятуры"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Нарвежская раскладка клавіятуры"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Нідэрландская раскладка клавіятуры"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Польская раскладка"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Партугальская раскладка"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Руская раскладка клавіятуры"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Сербская раскладка клавіятуры"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Шведская раскладка клавіятуры"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Турэцкая раскладка"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Афрыкаанс, Afrikaans Voice"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Гал. ўвод: чэшская мова"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Гал. квод: нямецкая мова"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Англійская, English Voice"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Гал. ўвод: іспанская мова"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Гал. ўвод: французская мова"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Гал. ўвод: італьянская мова"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Гал. ўвод: японская мова"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Гал. ўвод: карэйская мова"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Галасавы ўвод: нідэрландская мова"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Гал. ўвод: польская мова"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Гал. уквод: партугальская мова"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Гал. увод: руская мова"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Гал. ўвод: турэцкая мова"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Кітайская, юэ Voice"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Кітайская, Mandarin Voice"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Зулу"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Англійская (ЗК)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Англійская (ЗША)"</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_no_language" msgid="141420857808801746">"Мова не выбрана"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Мова не выбрана (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Няма мовы (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Няма мовы (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Няма мовы (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Няма мовы (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Няма мовы (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Налады працягласцi вiбрацыi пры нацiску"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Налады гучнасцi пры нацiску"</string>
</resources>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 301d484d4..5e916cef0 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -21,61 +21,69 @@
<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">"Клавиатура на Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавиатура на Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Настройки на клавиатурата на Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Опции за въвеждане"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Команди за рег. файл за проучвания"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Програма за правописна проверка за Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Програма за правописна проверка за Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Настройки за проверка на правописа"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Предложения въз основа на предишни думи"</string>
<string name="misc_category" msgid="6894192814868233453">"Други опции"</string>
<string name="advanced_settings" msgid="362895144495591463">"Разширени настройки"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Опции за потребителите експерти"</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="suppress_language_switch_key" msgid="8003788410354806368">"Потискане"</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="use_contacts_dict" msgid="4435317977804180815">"Предложения за контакти"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Използване на имена от „Контакти“ за предложения и поправки"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Повторни поправки: Актив."</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Задаване на предложения за повторни поправки"</string>
<string name="auto_cap" msgid="1719746674854628252">"Автоматично поставяне на главни букви"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Конфигуриране на речници"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Бързи корекции"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Коригира най-честите грешки при въвеждане"</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="3551821800439659812">"Показване с вертикална ориентация"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Винаги да се скрива"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Смяна на езика: интервал"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Показване на клавиша за настройки"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Автоматично"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Да се показва винаги"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Да се скрива винаги"</string>
<string name="auto_correction" msgid="4979925752001319458">"Автоко"</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_aggeressive" msgid="3524029103734923819">"Агресивно"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Много агресивно"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Предложения за биграми"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Използване на предишната дума за подобряване на предложението"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Предвиждане за биграми"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Предложения за следващата дума"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Използване на предишната дума за подобряване на предложенията"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Предвиждане на следващата дума"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Използване на предишната дума и за предвиждане"</string>
<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_to_alpha_key" msgid="4793983863798817523">"АБВ"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Още"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Пауза"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Чака"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Включете слушалки, за да чуете клавишите за паролата на висок глас."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Текущият текст е %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Няма въведен текст"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Код на клавишa %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"„Shift“ е активиран"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"„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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"Запетая"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Точка"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Лява кръгла скоба"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Дясна кръгла скоба"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Двоеточие"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Точка и запетая"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Удивителен знак"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Въпросителен знак"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Двойни кавички"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Единични кавички"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Търсене"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Точка"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Корен квадратен"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Пи"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Делта"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Запазена марка"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"По адрес"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Звездичка"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Диез"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Многоточие"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Долни двойни кавички"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Гласово въвеждане"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"За вашия език понастоящем не се поддържа гласово въвеждане, но можете да го използвате на английски."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Гласовото въвеждане използва функцията на Google за разпознаване на говор. В сила е "<a href="http://m.google.com/privacy">"Декларацията за поверителност за мобилни устройства"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"За да изключите гласовото въвеждане, отворете настройките за метода за въвеждане."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"За да използвате гласово въвеждане, натиснете бутона на микрофона."</string>
- <string name="voice_listening" msgid="467518160751321844">"Говорете сега"</string>
- <string name="voice_working" msgid="6666937792815731889">"Обработва се"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Грешка. Моля, опитайте отново."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Не можа да се свърже"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Грешка, твърде много речева информация."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Аудиопроблем"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Грешка в сървъра"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Не се чува реч"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Нямаше съответствия"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Не е инсталирано гласово търсене"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Съвет:"</b>" Прокарайте палец през клавиатурата, за да говорите"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Съвет:"</b>" Следващия път опитайте да произнесете знаците за пунктуация, напр. „точка“, „запетая“ или „въпросителен знак“."</string>
- <string name="cancel" msgid="6830980399865683324">"Отказ"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Гласово въвеждане"</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="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="selectInputMethod" msgid="315076553378705821">"Избор на метод на въвеждане"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Конфигуриране на въвеждането"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Входни езици"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Плъзнете пръст по клавиша за интервал за промяна на езика"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Докоснете отново, за да запазите"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Отбелязване на часа в рег. файл"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Часът е записан"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Без регистр. на сесията"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Рег. файл на сесията се изтрива"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Рег. файл на сесията е изтрит"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Рег. файл на сесията НЕ Е изтрит"</string>
+ <string name="select_language" msgid="3693815588777926848">"Езици за въвеждане"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Докоснете отново, за да запазите"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Има достъп до речник"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Активиране на отзивите от потребителите"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Помогнете за подобряването на този редактор за въвеждане чрез автоматично изпращане до Google на статистически данни за употребата и сигнали за сривове."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Докоснете, за да поправите думите"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Докоснете въведените думи, за да ги поправите – само когато предложенията са видими"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Тема на клавиатурата"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"чешка клавиатура"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"клавиатура на арабски"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"датска клавиатура"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"немска клавиатура"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"клавиатура „QWERTY“ на немски"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"английска (Великобрит.) клавиатура"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"английска (САЩ) клавиатура"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"испанска клавиатура"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"клавиатура на финландски"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"френска клавиатура"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"френска (Канада) клавиатура"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"френска (Швейцария) клавиатура"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"клавиатура на хърватски"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"клавиатура на унгарски"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"клавиатура на иврит"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"италианска клавиатура"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"норвежка клавиатура"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"нидерландска клавиатура"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"клавиатура на полски"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"клавиатура на португалски"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"руска клавиатура"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"сръбска клавиатура"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"шведска клавиатура"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"клавиатура на турски"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"африкаанс, гласово"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"чешки, гласово"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"немски, гласово"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"английски, гласово"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"испански, гласово"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"френски, гласово"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"италиански, гласово"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"японски, гласово"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"корейски, гласово"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"нидерландски, гласово"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"полски, гласово"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"португалски, гласово"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"руски, гласово"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"турски, гласово"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"китайски, кантонски, гласово"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"китайски, мандарин, гласово"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"зулуски, гласово"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"английски (Великобритания)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"английски (САЩ)"</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_no_language" msgid="141420857808801746">"Без език"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Без език („QWERTY“)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Без език (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Без език (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Без език (Дворак)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Без език (Коулмак)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Без език (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки за продължителност на вибрирането при натискане на клавиш"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки за силата на звука при натискане на клавиш"</string>
</resources>
diff --git a/java/res/values-ca/donottranslate-altchars.xml b/java/res/values-ca/donottranslate-altchars.xml
deleted file mode 100644
index 336057be0..000000000
--- a/java/res/values-ca/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">à,á,ä,â,ã,å,ą,æ,ā,ª</string>
- <string name="alternates_for_e">3,è,é,ë,ê,ę,ė,ē</string>
- <string name="alternates_for_i">8,í,ï,ì,î,į,ī</string>
- <string name="alternates_for_o">9,ò,ó,ö,ô,õ,ø,œ,ō,º</string>
- <string name="alternates_for_u">7,ú,ü,ù,û,ū</string>
- <string name="alternates_for_n">ñ,ń</string>
- <string name="alternates_for_c">ç,ć,č</string>
- <string name="alternates_for_l">ŀ,ł</string>
-</resources>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 977d30166..1b7cfc255 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -21,61 +21,69 @@
<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">"Teclat Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclat d\'Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Configuració del teclat d\'Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Recerca d\'ordres de reg."</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortogràfic d\'Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortogràfic d\'Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Configuració de la correcció ortogràfica"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca noms de contactes"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortogràfic utilitza entrades de la llista de cont."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibra en prémer tecles"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"So en prémer una tecla"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Finestra emergent en prémer un botó"</string>
<string name="general_category" msgid="1859088467017573195">"General"</string>
<string name="correction_category" msgid="2236750915056607613">"Correcció de text"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Suggeriments basats en paraules anteriors"</string>
<string name="misc_category" msgid="6894192814868233453">"Altres opcions"</string>
<string name="advanced_settings" msgid="362895144495591463">"Configuració avançada"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcions per a usuaris experts"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcions per a experts"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Canvia mètode d\'entrada"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de canvi d\'idioma també cobreix altres mètodes d\'entrada"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suprimeix tecla d\'idioma"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retard d\'om. em. de tecla"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sense retard"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminat"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggereix noms contactes"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilitza els noms de Contactes per a suggeriments i correccions"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Activa la capacitat de tornar a corregir"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Estableix suggeriments per tornar a corregir"</string>
<string name="auto_cap" msgid="1719746674854628252">"Majúscules automàtiques"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configura diccionaris"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Correccions ràpides"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corregeix els errors d\'ortografia habituals"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionaris complementaris"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Diccionari principal"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostra els suggeriments de correcció"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Mostra paraules suggerides mentre s\'escriu"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostra sempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostra en mode vertical"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Amaga sempre"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Utilitza el canvi d\'idioma amb la barra espaiadora"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Mostra la tecla de configuració"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automàtic"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mostra sempre"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Amaga sempre"</string>
<string name="auto_correction" msgid="4979925752001319458">"Correcció automàtica"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Barra espaiadora i punt. correg. autom. paraules mal escrites"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactiva"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderada"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Molt agressiu"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Suggeriments Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utilitza la paraula anterior per millorar el suggeriment"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Predicció Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Suggeriments de paraula següent"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilitza la paraula anterior per millorar els suggeriments"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Predicció de paraula següent"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilitza també la paraula anterior per a la predicció"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Més"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Maj activat"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bloq Maj activat"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Maj activat (pica per desactivar)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Bloq Maj activat (pica per desactivar)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Supr"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbols"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Lletres"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Entrada de veu"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Cara somrient"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Retorn"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Coma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punt"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parèntesi esquerre"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parèntesi dret"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Coma"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Punt i coma"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Signe d\'admiració"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Signe d\'interrogació"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Cometes dobles"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Cometes simples"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Cerca"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punt"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Arrel quadrada"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marca comercial"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Percentatge"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Destaca"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Coixinet"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Punts suspensius"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Cometes angulars"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Entrada de veu"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualment, l\'entrada de veu no és compatible amb el vostre idioma, però funciona en anglès."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"L\'entrada de veu utilitza el reconeixement de veu de Google. S\'hi aplica la "<a href="http://m.google.com/privacy">"Política de privadesa de Google per a mòbils"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Per desactivar l\'entada de veu, vés a la configuració del mètode d\'entrada."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Per utilitzar l\'entrada de veu, prem el botó del micròfon."</string>
- <string name="voice_listening" msgid="467518160751321844">"Parleu ara"</string>
- <string name="voice_working" msgid="6666937792815731889">"S\'està treballant"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Error. Torneu-ho a provar."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"No s\'ha pogut connectar"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Error; s\'ha parlat massa."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema d\'àudio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"No s\'escolten paraules"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"No hi ha resultats"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Cerca per veu no instal·lada"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Consell:"</b>" Feu lliscar el dit pel teclat per parlar"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Suggeriment:"</b>" La propera vegada, proveu de dir la puntuació, com ara \"punt\", \"coma\" o \"interrogant\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Cancel·la"</string>
- <string name="ok" msgid="7898366843681727667">"D\'acord"</string>
- <string name="voice_input" msgid="2466640768843347841">"Entrada de veu"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maj activat"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Bloq Maj activat"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Maj desactivat"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode de símbols"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode de lletres"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode de telèfon"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode de símbols de telèfon"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Clau de l\'entrada de veu"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Al teclat principal"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Al tecl. de símb."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivada"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micro en tecl. princ."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro en tecl. símb."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. veu desactiv."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Selecciona el mètode d\'entrada"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomes d\'entrada"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Feu lliscar el dit a la barra espaiadora per canviar l\'idioma"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Torna a tocar per desar"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Indica m. horària al reg."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marca horària enregistrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"No enregistris la sessió"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Suprimint registre de ses."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registre de ses. suprimit"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Registre de ses. NO sup."</string>
+ <string name="select_language" msgid="3693815588777926848">"Idiomes d\'entrada"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Activa els comentaris de l\'usuari"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Ajuda a millorar aquest editor de mètodes d\'entrada enviant automàticament estadístiques d\'ús i informes de bloqueigs a Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Toca per corregir paraules"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Toca les paraules introduïdes per corregir-les, només quan els suggeriments siguin visibles"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclat"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Teclat txec"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Teclat àrab"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Teclat danès"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Teclat alemany"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Teclat alemany QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Teclat anglès (Regne Unit)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Teclat anglès (Estats Units)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Teclat espanyol"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Teclat finès"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Teclat francès"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Teclat francès (Canadà)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Teclat francès (Suïssa)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Teclat croat"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Teclat hongarès"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Teclat hebreu"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Teclat italià"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Teclat noruec"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Teclat holandès"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Teclat polonès"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Teclat portuguès"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Teclat rus"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Teclat serbi"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Teclat suec"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Teclat turc"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Veu en afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Veu txeca"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Veu alemanya"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Veu anglesa"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Veu espanyola"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Veu francesa"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Veu italiana"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Veu japonesa"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Veu coreana"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Veu holandesa"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Veu polonesa"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Veu portuguesa"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Veu russa"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Veu turca"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Veu xinesa (Yue)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Veu xinesa (mandarí)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Veu en zulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Anglès (Regne Unit)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Anglès (EUA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Anglès (Regne Unit) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Anglès (Estats Units) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Cap idioma"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Cap idioma (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Cap idioma (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Cap idioma (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Cap idioma (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Cap idioma (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Cap idioma (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Estils d\'entrada pers."</string>
+ <string name="add_style" msgid="6163126614514489951">"Afeg. estil"</string>
+ <string name="add" msgid="8299699805688017798">"Afegeix"</string>
+ <string name="remove" msgid="4486081658752944606">"Elimina"</string>
+ <string name="save" msgid="7646738597196767214">"Desa"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Disseny"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"El teu estil d\'entrada personalitzat ha d\'estar activat per poder fer-lo servir. Vols activar-lo ara?"</string>
+ <string name="enable" msgid="5031294444630523247">"Activa"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ara no"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ja existeix aquest estil d\'entrada: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'estudi d\'usabilitat"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Configuració de la durada de les vibracions per pulsació de tecla"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Configuració del volum de so de pulsació de tecla"</string>
</resources>
diff --git a/java/res/values-cs/donottranslate-altchars.xml b/java/res/values-cs/donottranslate-altchars.xml
deleted file mode 100644
index 541cd2154..000000000
--- a/java/res/values-cs/donottranslate-altchars.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">á,à,â,ä,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,é,ě,è,ê,ë,ę,ė,ē</string>
- <string name="alternates_for_i">8,í,î,ï,ì,į,ī</string>
- <string name="alternates_for_o">9,ó,ö,ô,ò,õ,œ,ø,ō</string>
- <string name="alternates_for_u">7,ú,ů,û,ü,ù,ū</string>
- <string name="alternates_for_s">š,ß,ś</string>
- <string name="alternates_for_n">ň,ñ,ń</string>
- <string name="alternates_for_c">č,ç,ć</string>
- <string name="alternates_for_y">ý,ÿ</string>
- <string name="alternates_for_d">ď</string>
- <string name="alternates_for_r">4,ř</string>
- <string name="alternates_for_t">5,ť</string>
- <string name="alternates_for_z">6,ž,ź,ż</string>
-</resources>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index ab5ef66ea..7e6ee0b4a 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -21,61 +21,69 @@
<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">"Klávesnice Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klávesnice Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Nastavení klávesnice Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávání textu a dat"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Příkazy vývoj. protokolu"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Kontrola pravopisu Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavení kontroly pravopisu"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhledat kontakty"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používá záznamy z vašeho seznamu kontaktů."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Při stisku klávesy vibrovat"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk při stisku klávesy"</string>
- <string name="popup_on_keypress" msgid="123894815723512944">"Zobrazit znaky při stisku klávesy"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"Detail znaku při stisku klávesy"</string>
<string name="general_category" msgid="1859088467017573195">"Obecné"</string>
<string name="correction_category" msgid="2236750915056607613">"Oprava textu"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Návrhy na základě předchozích slov"</string>
<string name="misc_category" msgid="6894192814868233453">"Další možnosti"</string>
<string name="advanced_settings" msgid="362895144495591463">"Pokročilá nastavení"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Možnosti pro zkušené uživatele"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna kláv."</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti pro odborníky"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Přepínat metody zadávání"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klávesa pro přepínání jazyka ovládá i další metody zadávání"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Zakázat kl. přepínání jazyka"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna klávesnice"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez prodlevy"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Výchozí"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Navrhovat jména kontaktů"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Použít jména ze seznamu kontaktů k návrhům a opravám"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Povolit opětovné opravy"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastavit návrhy pro opětovné opravy"</string>
<string name="auto_cap" msgid="1719746674854628252">"Velká písmena automaticky"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurovat slovníky"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Rychlé opravy"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Opravuje nejčastější chyby při psaní"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Doplňkové slovníky"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Hlavní slovník"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Zobrazit návrhy oprav"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Zobrazovat navržená slova během psaní"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vždy zobrazovat"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Zobrazit v režimu na výšku"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vždy skrývat"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Přepínání jazyků mezerníkem"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Zobrazit klávesu Nastavení"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automaticky"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Vždy zobrazovat"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Vždy skrývat"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automatické opravy"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Stisknutím mezerníku a interpunkce se automaticky opravují chybně napsaná slova"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Vypnuto"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mírné"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivní"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Velmi agresivní"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Návrhy Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Použít předchozí slovo ke zlepšení návrhu"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Odhady Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Návrh dalšího slova"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Použít předchozí slovo ke zlepšení návrhů"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Odhad dalšího slova"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Použít předchozí slovo také pro odhad"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Další"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Klávesa Shift je aktivní"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Klávesa Caps Lock je aktivní"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Klávesa Shift je zapnutá (vypnete ji klepnutím)."</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Klávesa Caps Lock je zapnutá (vypnete ji klepnutím)."</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboly"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Písmena"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Hlasový vstup"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smajlík"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Čárka"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Tečka"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Levá závorka"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Pravá závorka"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dvojtečka"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Středník"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Vykřičník"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Otazník"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Uvozovky"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Apostrof"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"vyhledávací tlačítko"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Tečka"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Odmocnina"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pí"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Ochranná známka"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Procento"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Hvězdička"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Libra"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tři tečky"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Uvozovky dole"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Hlasový vstup"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Pro váš jazyk aktuálně není hlasový vstup podporován, ale funguje v angličtině."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Hlasový vstup používá rozpoznávání hlasu Google a vztahují se na něj "<a href="http://m.google.com/privacy">"Zásady ochrany osobních údajů pro mobilní služby"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Chcete-li vypnout hlasový vstup, přejděte do nastavení metod vstupu."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Chcete-li použít hlasový vstup, stiskněte tlačítko mikrofonu."</string>
- <string name="voice_listening" msgid="467518160751321844">"Mluvte"</string>
- <string name="voice_working" msgid="6666937792815731889">"Probíhá zpracování"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Chyba. Zkuste to prosím znovu."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Připojení se nezdařilo."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Chyba, řeč je příliš dlouhá."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problém se zvukem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Chyba serveru"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nebyla detekována žádná řeč."</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nebyly nalezeny žádné shody"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Hlasové vyhledávání není nainstalováno"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Nápověda:"</b>" Chcete-li aktivovat hlasový vstup, přejeďte prstem přes klávesnici."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Nápověda:"</b>" Příště zkuste vyslovit interpunkci, například „tečka“, „čárka“ nebo „otazník“."</string>
- <string name="cancel" msgid="6830980399865683324">"Zrušit"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Hlasový vstup"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Klávesa Shift je aktivní"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Klávesa Caps Lock je aktivní"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Klávesa Shift je neaktivní"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Režim symbolů"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Režim písmen"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Režim telefonu"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Režim telefonních symbolů"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Klávesa hlasového vstupu"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavní klávesnici"</string>
- <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici se symb."</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici se symboly"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Vypnuto"</string>
- <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. na hlav. kláv."</string>
- <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. na kláv. se symb."</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na hlavní klávesnici"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon na klávesnici se symboly"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup vypnut"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Výběr metody zadávání dat"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod zadávání"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Jazyk můžete změnit posunutím prstu po mezerníku."</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Dalším dotykem slovo uložíte"</string>
- <string name="has_dictionary" msgid="6071847973466625007">"K dispozici je slovník"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Uložit čas do protokolu"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Časové razítko vloženo"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Neprotokolovat relaci"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Mazání protokolu relace"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Protokol relace smazán"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Protokol relace nesmazán"</string>
+ <string name="select_language" msgid="3693815588777926848">"Vstupní jazyky"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opětovným dotykem provedete uložení"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"Slovník k dispozici"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Aktivovat zasílání statistik užívání a zpráv o selhání"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Automatickým zasíláním statistik o užívání editoru zadávání dat a zpráv o jeho selhání do Googlu můžete přispět k vylepšení tohoto nástroje."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Dotykem aktivovat opravy"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Klepnutím na zadaná slova tato slova opravíte, musí však být viditelné návrhy."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Motiv klávesnice"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Klávesnice – čeština"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabská klávesnice"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Klávesnice – dánština"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Klávesnice – němčina"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Německá klávesnice QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Klávesnice – angličtina (VB)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Klávesnice – angličtina (USA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Klávesnice – španělština"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finská klávesnice"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Klávesnice – francouzština"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Klávesnice – francouzština (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Klávesnice – francouzština (Švýc.)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Chorvatská klávesnice"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Maďarská klávesnice"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebrejská klávesnice"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Klávesnice – italština"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Klávesnice – norština"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Klávesnice – holandština"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polská klávesnice"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugalská klávesnice"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Klávesnice – ruština"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Klávesnice – srbština"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Klávesnice – švédština"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turecká klávesnice"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voice – afrikánština"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voice – čeština"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voice – němčina"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voice – angličtina"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voice – španělština"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voice – francouzština"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Hlasový vstup – italština"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voice – japonština"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voice – korejština"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Hlasový vstup – holandština"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voice – polština"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voice – portugalština"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voice – ruština"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voice – turečtina"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voice – čínština, kantonština"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voice – čínština, mandarínština"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voice – zulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"angličtina (Velká Británie)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"angličtina (USA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"angličtina (VB) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"angličtina (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Žádný jazyk"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Žádný jazyk (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Žádný jazyk (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Žádný jazyk (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Žádný jazyk (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Žádný jazyk (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Žádný jazyk (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Vlastní styl zadávání"</string>
+ <string name="add_style" msgid="6163126614514489951">"Přidat styl"</string>
+ <string name="add" msgid="8299699805688017798">"Přidat"</string>
+ <string name="remove" msgid="4486081658752944606">"Odebrat"</string>
+ <string name="save" msgid="7646738597196767214">"Uložit"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Jazyk"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Rozvržení"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Vlastní styl zadávání musíte nejdříve povolit. Povolit?"</string>
+ <string name="enable" msgid="5031294444630523247">"Povolit"</string>
+ <string name="not_now" msgid="6172462888202790482">"Teď ne"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Tento styl zadávání již existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim studie použitelnosti"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Délka vibrace při stisku klávesy"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Hlasitost při stisknutí klávesy"</string>
</resources>
diff --git a/java/res/values-da/donottranslate-altchars.xml b/java/res/values-da/donottranslate-altchars.xml
deleted file mode 100644
index 46f1644ad..000000000
--- a/java/res/values-da/donottranslate-altchars.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">á,ä,à,â,ã,ā</string>
- <string name="alternates_for_e">3,é,ë</string>
- <string name="alternates_for_i">8,í,ï</string>
- <string name="alternates_for_o">9,ó,ô,ò,õ,œ,ō</string>
- <string name="alternates_for_u">7,ú,ü,û,ù,ū</string>
- <string name="alternates_for_s">ß,ś,š</string>
- <string name="alternates_for_n">ñ,ń</string>
- <string name="alternates_for_y">6,ý,ÿ</string>
- <string name="alternates_for_d">ð</string>
- <string name="alternates_for_l">ł</string>
- <string name="keylabel_for_scandinavia_row2_10">æ</string>
- <string name="keylabel_for_scandinavia_row2_11">ø</string>
- <string name="alternates_for_scandinavia_row2_10">ä</string>
- <string name="alternates_for_scandinavia_row2_11">ö</string>
-</resources>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 6bc9f62ad..c6800a952 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -21,61 +21,69 @@
<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">"Android-tastatur"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-tastatur-indstillinger"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Forskningslogkommandoer"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-stavekontrol"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontrol (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Indstillinger for stavekontrol"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå kontaktnavne op"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruger poster fra listen over kontaktpersoner"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibration ved tastetryk"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetryk"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop op ved tastetryk"</string>
<string name="general_category" msgid="1859088467017573195">"Generelt"</string>
<string name="correction_category" msgid="2236750915056607613">"Tekstkorrigering"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Forslag baseret på tidligere ord"</string>
<string name="misc_category" msgid="6894192814868233453">"Andre valgmuligheder"</string>
<string name="advanced_settings" msgid="362895144495591463">"Avancerede indstillinger"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Muligheder for ekspertbrugere"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Muligheder for eksperter"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skift inputmetode"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasten til sprogskift gælder også for andre inputmetoder"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Ignorer sprogskifttast"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Forsink. afvis. af taste-pop op"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ingen forsink."</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå navne på kontakter"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Brug navne fra Kontaktpersoner til forslag og rettelser"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Aktivér fornyet rettelse"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angiv forslag til fornyet rettelse"</string>
<string name="auto_cap" msgid="1719746674854628252">"Skriv aut. med stort"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurer ordbøger"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Hurtige løsninger"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Retter almindelige stavefejl"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tillægsordbøger"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Hovedordbog"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Vis rettelsesforslag"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Vis ordforslag under indtastning"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vis altid"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Vis i portrættilstand"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Skjul altid"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Brug mellemrumst. som sprogskifter"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Vis indstillingsnøgle"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatisk"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Vis altid"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Skjul altid"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automatisk retning"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Mellemrumstast og tegnsætning retter automatisk forkerte ord"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Fra"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressiv"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Meget aggressiv"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram-forslag"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Brug forrige ord for at forbedre forslag"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram-forudsigelse"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Forslag til næste ord"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Brug forrige ord til at forbedre forslag"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Forudsigelse af næste ord"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Brug også tidligere ord til forudsigelse"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mere"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift-tasten er aktiveret"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock er aktiveret"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Skift er slået til (tryk for at deaktivere)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock er slået til (tryk for at deaktivere)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Slet"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboler"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Bogstaver"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Stemmeinput"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Tilbage"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punktum"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Venstre parentes"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Højre parentes"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Kolon"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Udråbstegn"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Spørgsmålstegn"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dobbelt anførselstegn"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkelt anførselstegn"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Søg"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punktum"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratrod"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Varemærke"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"De bedste hilsner"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Stjerne"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Pund"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipse"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Lave dobbelte anførelsestegn"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Stemmeinput"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Stemmeinput understøttes i øjeblikket ikke for dit sprog, men fungerer på engelsk."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Stemmeinput anvender Googles stemmegenkendelse. "<a href="http://m.google.com/privacy">"Fortrolighedspolitikken for mobilenheder"</a>" gælder."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Slå stemmeinput fra i indstillingerne for inputmetode."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Brug stemmeinput ved at trykke på mikrofonknappen."</string>
- <string name="voice_listening" msgid="467518160751321844">"Tal nu"</string>
- <string name="voice_working" msgid="6666937792815731889">"Arbejder"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Fejl. Prøv igen."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke oprette forbindelse"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Fejl. For meget tale."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Lydproblem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Serverfejl"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Der høres ingen tale"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Der blev ikke fundet nogen matches"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Stemmesøgning er ikke installeret"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tip:"</b>" Glid hen over tastaturet for at tale"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tip:"</b>" Næste gang kan du forsøge at sige tegnsætning, f.eks. \"punktum\", \"komma\" eller \"spørgsmålstegn\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Annuller"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Stemmeinput"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift er aktiveret"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock er aktiveret"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Skift er deaktiveret"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symboltilstand"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Bogstavtilstand"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefontilstand"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefonsymboltilstand"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Nøgle til stemmeinput"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På hovedtastatur"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På symboltastatur"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Fra"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. på hovedtastatur"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. på symboltastatur"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Stemmeinput deaktiveret"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Vælg inputmetode"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Træk fingeren på mellemrumstasten for at skifte sprog"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tryk igen for at gemme"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Notér tidsstempel i log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Noteret tidsstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Logfør ikke denne session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sletter sessionslogfil"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sessionslogfil slettet"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sessionslog IKKE slettet"</string>
+ <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
- <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiver brugerfeedback"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivér brugerfeedback"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Vær med til at forbedre denne inputmetode ved at sende anvendelsesstatistikker og rapporter om nedbrud til Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tryk for at rette ord"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Tryk på de indtastede ord for at rette dem. Kun når der er synlige forslag."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tjekkisk tastatur"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabisk tastatur"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Dansk tastatur"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Tysk tastatur"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Tysk QWERTY-tastatur"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Engelsk tastatur (Storbritannien)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Engelsk tastatur (USA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spansk tastatur"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finsk tastatur"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Fransk tastatur"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Fransk tastatur (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Fransk tastatur (Schweiz)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatisk tastatur"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ungarsk tastatur"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebraisk tastatur"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italiensk tastatur"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norsk tastatur"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Hollandsk tastatur"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polsk tastatur"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugisisk tastatur"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russisk tastatur"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbisk tastatur"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Svensk tastatur"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Tyrkisk tastatur"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaans stemme"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Tjekkisk stemme"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Tysk stemme"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Engelsk stemme"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spansk stemme"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Fransk stemme"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italiensk stemme"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japansk stemme"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Koreansk stemme"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Hollandsk stemme"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Polsk stemme"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugisisk stemme"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russisk stemme"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Tyrkisk stemme"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Kinesisk, Yue stemme"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Kinesisk, mandarin stemme"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu stemme"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannien)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Engelsk (Storbritannien) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Engelsk (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Intet sprog"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Ingen sprog (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Intet sprog (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Intet sprog (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Intet sprog (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Intet sprog (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Intet sprog (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Tilpasset inputtypografi"</string>
+ <string name="add_style" msgid="6163126614514489951">"Tilføj typografi"</string>
+ <string name="add" msgid="8299699805688017798">"Tilføj"</string>
+ <string name="remove" msgid="4486081658752944606">"Fjern"</string>
+ <string name="save" msgid="7646738597196767214">"Gem"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Sprog"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Din tilpassede indtastningsmetode skal være aktiveret, før du begynder at bruge den. Vil du gøre det nu?"</string>
+ <string name="enable" msgid="5031294444630523247">"Aktivér"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ikke nu"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Denne inputstil findes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tilstand for brugsstudie"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Indstillinger for varighed af vibration ved tastetryk"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Indstillinger for lydstyrke ved tastetryk"</string>
</resources>
diff --git a/java/res/values-de-rZZ/donottranslate-altchars.xml b/java/res/values-de-rZZ/donottranslate-altchars.xml
deleted file mode 100644
index a6f8fc810..000000000
--- a/java/res/values-de-rZZ/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">ä,â,à,á,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,ė</string>
- <string name="alternates_for_o">9,ö,ô,ò,ó,õ,œ,ø,ō</string>
- <string name="alternates_for_u">7,ü,û,ù,ú,ū</string>
- <string name="alternates_for_s">ß,ś,š</string>
- <string name="alternates_for_n">ñ,ń</string>
- <string name="alternates_for_y">6</string>
- <string name="alternates_for_z"></string>
-</resources>
diff --git a/java/res/values-de/donottranslate-altchars.xml b/java/res/values-de/donottranslate-altchars.xml
deleted file mode 100644
index 8b8b6aed7..000000000
--- a/java/res/values-de/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">ä,â,à,á,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,ė</string>
- <string name="alternates_for_o">9,ö,ô,ò,ó,õ,œ,ø,ō</string>
- <string name="alternates_for_u">7,ü,û,ù,ú,ū</string>
- <string name="alternates_for_s">ß,ś,š</string>
- <string name="alternates_for_n">ñ,ń</string>
- <string name="alternates_for_y"></string>
- <string name="alternates_for_z">6</string>
-</resources>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 52fc575c0..cd2d78e4a 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -21,61 +21,69 @@
<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">"Android-Tastatur"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-Tastatur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-Tastatureinstellungen"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Forschungsprotokollbefehle"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-Rechtschreibprüfung"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-Rechtschreibprüfung (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Einstellungen für Rechtschreibprüfung"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktnamen prüfen"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rechtschreibprüfung verwendet Einträge aus Ihrer Kontaktliste."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Bei Tastendruck vibrieren"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Ton bei Tastendruck"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bei Tastendruck"</string>
<string name="general_category" msgid="1859088467017573195">"Allgemein"</string>
<string name="correction_category" msgid="2236750915056607613">"Textkorrektur"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Vorschläge basieren auf bisherigen Wörtern"</string>
<string name="misc_category" msgid="6894192814868233453">"Sonstige Optionen"</string>
<string name="advanced_settings" msgid="362895144495591463">"Erweiterte Einstellungen"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Optionen für Experten"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Optionen für Experten"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Eingabemethoden wechseln"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Sprachwechseltaste umfasst auch andere Eingabemethoden."</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Sprachwechsel unterdrücken"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tasten-Pop-up"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Keine Verzögerung"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Kontakte vorschlagen"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen aus \"Kontakte\" als Vorschläge und Korrekturmöglichkeiten anzeigen"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Korrekturen aktivieren"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Vorschläge für Korrekturen festlegen"</string>
<string name="auto_cap" msgid="1719746674854628252">"Autom. Groß-/Kleinschr."</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Wörterbücher konfigurieren"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Quick Fixes"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Korrigiert gängige Tippfehler"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Erweiterte Wörterbücher"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Allgemeines Wörterbuch"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Änderungsvorschläge"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Vorgeschlagene Wörter während des Tippens anzeigen"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Immer anzeigen"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Im Hochformat anzeigen"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Nie anzeigen"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Sprache mit Leertaste ändern"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Taste für Einstellungen"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatisch"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Immer anzeigen"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Nie anzeigen"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autokorrektur"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Korrektur fehlerhafter Wörter durch Leertaste und Satzzeichen"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Aus"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mäßig"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Stark"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sehr stark"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigramm-Vorschläge"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Zur Verbesserung des Vorschlags vorheriges Wort verwenden"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigramm-Vervollständigung"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Vorschläge für nächstes Wort"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Zur Verbesserung von Vorschlägen vorheriges Wort verwenden"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Vervollständigung für nächstes Wort"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Vorheriges Wort auch für Vervollständigung verwenden"</string>
<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">"Vorh."</string>
<string name="label_done_key" msgid="2441578748772529288">"Fertig"</string>
<string name="label_send_key" msgid="2815056534433717444">"Senden"</string>
<string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mehr"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Umschalttaste aktiviert"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Feststelltaste aktiviert"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Umschalttaste aktiviert (zum Deaktivieren berühren)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Feststelltaste aktiviert (zum Deaktivieren berühren)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Entf"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbole"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Buchstaben"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Spracheingabe"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Eingabe"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punkt"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Öffnende Klammer"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Schließende Klammer"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Doppelpunkt"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ausrufezeichen"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Fragezeichen"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Anführungszeichen"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Einfaches Anführungszeichen"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Suchen"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Aufzählungspunkt"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Quadratwurzel"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"c/o"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Sternchen"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Raute"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Auslassungszeichen"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Anführungszeichen unten"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Spracheingabe"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Spracheingaben werden zurzeit nicht für Ihre Sprache unterstützt, funktionieren jedoch in Englisch."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Die Spracheingabe verwendet die Spracherkennung von Google. Es gelten die "<a href="http://m.google.com/privacy">"Google Mobile-Datenschutzbestimmungen"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Rufen Sie zum Deaktivieren der Spracheingabe die Einstellungen für die Eingabemethode auf."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Drücken Sie zur Verwendung der Spracheingabe die Mikrofonschaltfläche."</string>
- <string name="voice_listening" msgid="467518160751321844">"Jetzt sprechen"</string>
- <string name="voice_working" msgid="6666937792815731889">"Vorgang läuft"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Fehler. Versuchen Sie es erneut.."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Keine Verbindung"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Fehler – Text zu lang"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Audio-Problem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Serverfehler"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Keine Sprache zu hören"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Keine Treffer gefunden"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Sprachsuche nicht installiert"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hinweis:"</b>" Ziehen Sie zum Sprechen den Finger über die Tastatur."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hinweis:"</b>" Versuchen Sie beim nächsten Mal, Satzzeichen wie \"Punkt\", \"Komma\" oder \"Fragezeichen\" per Sprachbefehl einzugeben."</string>
- <string name="cancel" msgid="6830980399865683324">"Abbrechen"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Spracheingabe"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Umschalttaste aktiviert"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Feststelltaste aktiviert"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Umschalttaste deaktiviert"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolmodus"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Buchstabenmodus"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonmodus"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefon-Symbolmodus"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Taste für Spracheingabe"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Auf Haupttastatur"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Auf Symboltastatur"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Aus"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikro auf Haupttastatur"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikro auf Symboltastatur"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spracheingabe deaktiviert"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Eingabemethode auswählen"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Finger über die Leertaste bewegen, um die Eingabesprache zu wechseln"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Zum Speichern erneut berühren"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Zeitstempel im Protokoll"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zeitstempel aufgenommen"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nicht protokollieren"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Protokoll wird gelöscht..."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Protokoll gelöscht"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Protokoll NICHT gelöscht"</string>
+ <string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berühren"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Nutzer-Feedback aktivieren"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Tragen Sie zur Verbesserung dieses Eingabemethodeneditors bei, indem Sie automatisch Nutzungsstatistiken und Absturzberichte an Google senden."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Wortkorrektur"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Tippen Sie zum Korrigieren auf eingegebene Wörter (nur, wenn Vorschläge angezeigt werden)."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tastaturdesign"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tschechische Tastatur"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabische Tastatur"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Dänische Tastatur"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Deutsche Tastatur"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Deutsche QWERTY-Tastatur"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Englische Tastatur (GB)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Englische Tastatur (USA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spanische Tastatur"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finnische Tastatur"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Französische Tastatur"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Französische Tastatur (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Französische Tastatur (Schweiz)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatische Tastatur"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ungarische Tastatur"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebräische Tastatur"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italienische Tastatur"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norwegische Tastatur"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Niederländische Tastatur"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polnische Tastatur"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugiesische Tastatur"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russische Tastatur"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbische Tastatur"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Schwedische Tastatur"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Türkische Tastatur"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Stimme in Afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Tschechische Sprache"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Deutsche Sprache"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Englische Stimme"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spanische Sprache"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Französische Sprache"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italienisch"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japanische Sprache"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Koreanische Sprache"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Niederländisch"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Polnische Sprache"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugiesische Sprache"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russische Sprache"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Türkische Sprache"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Chinesische Stimme (Yue)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Chinesische Stimme (Mandarin)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Stimme in isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Englisch (Großbritannien)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Englisch (USA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Englisch (GB) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Englisch (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Keine Sprache"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Keine Sprache (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Keine Sprache (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Keine Sprache (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Keine Sprache (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Keine Sprache (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Keine Sprache (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Benutzerdefinierte Eingabestile"</string>
+ <string name="add_style" msgid="6163126614514489951">"Stil hinzufügen"</string>
+ <string name="add" msgid="8299699805688017798">"Hinzufügen"</string>
+ <string name="remove" msgid="4486081658752944606">"Entfernen"</string>
+ <string name="save" msgid="7646738597196767214">"Speichern"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Sprache"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Ihr benutzerdefinierter Eingabestil muss vor der Verwendung aktiviert werden. Möchten Sie ihn jetzt aktivieren?"</string>
+ <string name="enable" msgid="5031294444630523247">"Aktivieren"</string>
+ <string name="not_now" msgid="6172462888202790482">"Später"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Der gleiche Eingabestil ist bereits vorhanden: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus der Studie zur Benutzerfreundlichkeit"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Einstellungen für Vibrationsdauer bei Tastendruck"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Einstellungen für Tonlautstärke bei Tastendruck"</string>
</resources>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 888dcee46..5dcbf43ba 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -21,61 +21,69 @@
<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">"Πληκτρολόγιο Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Πληκτρολόγιο Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ρυθμίσεις πληκτρολογίου Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Επιλογές εισόδου"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Έρευνα εντολών καταγραφής"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Ορθογραφικός έλεγχος Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Ορθογραφικός έλεγχος Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ρυθμίσεις ορθογραφικού ελέγχου"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Προτάσεις που βασίζονται σε προηγούμενες λέξεις"</string>
<string name="misc_category" msgid="6894192814868233453">"Άλλες επιλογές"</string>
<string name="advanced_settings" msgid="362895144495591463">"Σύνθετες ρυθμίσεις"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Επιλογές για έμπειρους χρήστες"</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="suppress_language_switch_key" msgid="8003788410354806368">"Κατάργ. κλειδιού γλώσσας"</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="use_contacts_dict" msgid="4435317977804180815">"Πρόταση ονομάτων επαφών"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Χρησιμοποιήστε ονόματα από τις Επαφές για προτάσεις και διορθ."</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Ενεργ. επανάλ. διορθώσεων"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ορισμός προτάσεων για επαναλήψεις διορθώσεων"</string>
<string name="auto_cap" msgid="1719746674854628252">"Αυτόματη χρήση κεφαλαίων"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Διαμόρφωση λεξικών"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Γρήγορες διορθώσεις"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Διορθώνει συνηθισμένα λάθη πληκτρολόγησης"</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="3551821800439659812">"Εμφάνιση σε λειτουργία κατακόρυφης προβολής"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Πάντα απόκρυψη"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Αλλαγή γλώσ με space"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Εμφάνιση πλήκτρου ρυθμίσεων"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Αυτόματο"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Να εμφανίζεται πάντα"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Πάντα απόκρυψη"</string>
<string name="auto_correction" msgid="4979925752001319458">"Αυτόματη διόρθωση"</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_aggeressive" msgid="3524029103734923819">"Υψηλή"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Πολύ επιθετική"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Προτάσεις bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Χρήση προηγούμενης λέξης για τη βελτίωση πρότασης"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Πρόβλεψη bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Προτάσεις επόμενων λέξεων"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Χρήση προηγούμενης λέξης για τη βελτίωση προτάσεων"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Πρόβλεψη επόμενης λέξης"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Χρησιμοποιήστε, επίσης, την προηγούμενη λέξη για πρόβλεψη"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ΑΒΓ"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Περισσότερα"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Παύση"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Αναμ."</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Συνδέστε ένα σετ ακουστικών για να ακούσετε τα πλήκτρα του κωδικού πρόσβασης να εκφωνούνται δυνατά."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Το τρέχον κείμενο είναι %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Δεν υπάρχει κείμενο"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Κωδικός πλήκτρου %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift ενεργοποιημένο"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Μικρόφωνο"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Πλήκτρο Return"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Κόμμα"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Τελεία"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Αριστερή παρένθεση"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Δεξιά παρένθεση"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Άνω και κάτω τελεία"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Ερωτηματικό"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Θαυμαστικό"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Ερωτηματικό"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Διπλά εισαγωγικά"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Μονό εισαγωγικό"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Αναζήτηση"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Κουκκίδα"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Τετραγωνική ρίζα"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"πι"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Δέλτα"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Εμπορικό σήμα"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Υπεύθυνος"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Αστερίσκος"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Δίεση"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Αποσιωπητικά"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Χαμηλό διπλό εισαγωγικό"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Φωνητική είσοδος"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Η φωνητική είσοδος δεν υποστηρίζεται αυτή τη στιγμή για τη γλώσσα σας, ωστόσο λειτουργεί στα Αγγλικά."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Οι φωνητικές εντολές χρησιμοποιούν την τεχνολογία αναγνώρισης φωνής της Google. Ισχύει "<a href="http://m.google.com/privacy">"η Πολιτική Απορρήτου για κινητά"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Για να απενεργοποιήσετε τις φωνητικές εντολές, μεταβείτε στις ρυθμίσεις της μεθόδου εισαγωγής."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Για τη χρήση φωνητικών εντολών, πατήστε το κουμπί του μικροφώνου."</string>
- <string name="voice_listening" msgid="467518160751321844">"Μιλήστε τώρα"</string>
- <string name="voice_working" msgid="6666937792815731889">"Σε λειτουργία"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Σφάλμα. Δοκιμάστε ξανά."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Δεν ήταν δυνατή η σύνδεση"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Σφάλμα, πολλές λέξεις."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Πρόβλημα ήχου"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Σφάλμα διακομιστή"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Δεν ακούγεται ομιλία"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Δεν βρέθηκε καμία αντιστοίχιση"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Η Φωνητική αναζήτηση δεν εγκαταστάθηκε"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Υπόδειξη:"</b>" Σύρετε κατά μήκος του πληκτρολογίου για να μιλήσετε"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Υπόδειξη:"</b>" Την επόμενη φορά, προσπαθήστε να προφέρετε σημεία στίξης, όπως \"τελεία\", \"κόμμα\" ή \"ερωτηματικό\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Ακύρωση"</string>
- <string name="ok" msgid="7898366843681727667">"ΟΚ"</string>
- <string name="voice_input" msgid="2466640768843347841">"Φωνητική είσοδος"</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="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="selectInputMethod" msgid="315076553378705821">"Επιλογή μεθόδου εισόδου"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Διαμόρφωση μεθόδων εισαγωγής"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Γλώσσες εισόδου"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Σύρετε το δάχτυλο στο πλήκτρο διαστήματος για να αλλάξετε γλώσσα"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Αγγίξτε ξανά για αποθήκευση"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Χρόνος στο αρχείο καταγρ."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Καταγεγραμμένος χρόνος"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Χωρίς αρχείο καταγραφής"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Διαγραφή αρχείου σύνδεσης"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Αρχείο καταγρ. διαγράφηκε"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Αρχείο καταγρ. ΔΕΝ διαγρ."</string>
+ <string name="select_language" msgid="3693815588777926848">"Γλώσσες εισόδου"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Αγγίξτε ξανά για αποθήκευση"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Ενεργοποίηση σχολίων χρηστών"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Βοηθήστε μας να βελτιώσουμε αυτό το πρόγραμμα επεξεργασίας μεθόδου εισόδου στέλνοντας αυτόματα στατιστικά στοιχεία και αναφορές σφαλμάτων στην Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Αγγίξτε για διόρθωση λέξεων"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Αγγίξτε τις λέξες για να τις διορθώσετε, μόνο όταν οι προτάσεις είναι ορατές"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Θέμα πληκτρολογίου"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Τσεχικό πληκτρολόγιο"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Πληκτρολ. με αραβικούς χαρακτήρες"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Δανικό πληκτρολόγιο"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Γερμανικό πληκτρολόγιο"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Γερμανικό πληκτρολόγιο QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Αγγλικό (ΗΒ) πληκτρολόγιο"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Αγγλικό (ΗΠΑ) πληκτρολόγιο"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Ισπανικό πληκτρολόγιο"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Πληκτρ. με φινλανδικούς χαρακτήρες"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Γαλλικό πληκτρολόγιο"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Γαλλικό (Καναδάς) πληκτρολόγιο"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Γαλλικό (Ελβετία) πληκτρολόγιο"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Πληκτρολ. με κροατικούς χαρακτήρες"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Πληκτρολ. με ουγγρικούς χαρακτήρες"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Πληκτρολ. με εβραϊκούς χαρακτήρες"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Ιταλικό πληκτρολόγιο"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Νορβηγικό πληκτρολόγιο"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Ολλανδικό πληκτρολόγιο"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Πληκτρολ. με πολωνικούς χαρακτήρες"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Πληκτρολ. με πορτογαλικούς χαρακτ."</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Ρωσικό πληκτρολόγιο"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Σερβικό πληκτρολόγιο"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Σουηδικό πληκτρολόγιο"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Πληκτρολ. με τουρκικούς χαρακτήρες"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Αφρικάανς"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Τσεχικά"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Γερμανικά"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Αγγλικά"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Ισπανικά"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Γαλλικά"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Φωνητικές εντολές στα Ιταλικά"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Ιαπωνικά"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Κορεατικά"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Φωνητικές εντολές στα Ολλανδικά"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Πολωνικά"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Πορτογαλικά"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Ρωσικά"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Τουρκικά"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Κινεζικά, Γιούε"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Κινεζικά, Μανδαρινικά"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Ζουλού"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Αγγλικά (Η.Β.)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Αγγλικά (Η.Π.Α)"</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_no_language" msgid="141420857808801746">"Καμία γλώσσα"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Καμία γλώσσα (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Καμία γλώσσα (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Καμία γλώσσα (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Καμία γλώσσα (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Καμία γλώσσα (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Καμία γλώσσα (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Ρυθμίσεις διάρκειας δόνησης κατά το πάτημα πλήκτρων"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Ρυθμίσεις έντασης ήχου κατά το πάτημα πλήκτρων"</string>
</resources>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 3249bd406..cd9b218e7 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -21,61 +21,69 @@
<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">"Android keyboard"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android keyboard settings"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android spell checker"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android spell checker (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Spellchecking settings"</string>
+ <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 key-press"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sound on key-press"</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="ngram_category" msgid="5337109164339320257">"Suggestions based on previous words"</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="5193513161106637254">"Options for expert users"</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="suppress_language_switch_key" msgid="8003788410354806368">"Suppress language switch key"</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="use_contacts_dict" msgid="4435317977804180815">"Suggest Contact names"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Use names from Contacts for suggestions and corrections"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Enable recorrections"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Set suggestions for recorrections"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalisation"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configure dictionaries"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Quick fixes"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrects commonly typed mistakes"</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="3551821800439659812">"Show on portrait mode"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Show in portrait mode"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Always hide"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Use the space bar language switcher"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Show settings key"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatic"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Always show"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Always hide"</string>
<string name="auto_correction" msgid="4979925752001319458">"Auto-correction"</string>
- <string name="auto_correction_summary" msgid="5625751551134658006">"Spacebar and punctuation correct mistyped words automatically"</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_aggeressive" msgid="3524029103734923819">"Aggressive"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Very aggressive"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram Suggestions"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Use previous word to improve suggestion"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram prediction"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Next word suggestions"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Use previous word to improve suggestion"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Next word prediction"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Use previous word also for prediction"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"More"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Pause"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Wait"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Plug in a headset to hear password keys spoken aloud."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Current text is %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"No text entered"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Key code %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift enabled"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock enabled"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"Comma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Full stop"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Left parenthesis"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Right parenthesis"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Colon"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semi-colon"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Exclamation mark"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Question mark"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Double quote"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Single quote"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Search"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Dot"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Square root"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Star"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Pound"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Low double quote"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Voice input"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Voice input is not currently supported for your language, but does work in English."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Voice input uses Google\'s speech recognition. "<a href="http://m.google.com/privacy">"The Mobile Privacy Policy"</a>" applies."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"To turn off voice input, go to input method settings."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"To use voice input, press the microphone button."</string>
- <string name="voice_listening" msgid="467518160751321844">"Speak now"</string>
- <string name="voice_working" msgid="6666937792815731889">"Working"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Error: Please try again."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Couldn\'t connect"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, too much speech."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Audio problem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Server error"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"No speech heard"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"No matches found"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Voice search not installed"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hint:"</b>" Swipe across keyboard to speak"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" Next time, try speaking punctuation marks, like \"full stop\", \"comma\" or \"question mark\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Cancel"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Voice input"</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="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="selectInputMethod" msgid="315076553378705821">"Select input method"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Slide finger on spacebar to change language"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Touch again to save"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Note timestamp in log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Recorded timestamp"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Do not log this session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Deleting session log"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Session log deleted"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Session log NOT deleted"</string>
+ <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Enable user feedback"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Help improve this input method editor by sending usage statistics and crash reports automatically to Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Touch to correct words"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Touch words entered to correct them, only when suggestions are visible"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Czech Keyboard"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabic Keyboard"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Danish Keyboard"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"German Keyboard"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"German QWERTY Keyboard"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"English (UK) Keyboard"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"English (US) Keyboard"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spanish Keyboard"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finnish Keyboard"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"French Keyboard"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"French (Canada) Keyboard"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"French (Switzerland) Keyboard"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Croatian Keyboard"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Hungarian Keyboard"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebrew Keyboard"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italian Keyboard"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norwegian Keyboard"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Dutch Keyboard"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polish Keyboard"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portuguese Keyboard"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russian Keyboard"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbian Keyboard"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Swedish Keyboard"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turkish Keyboard"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaans Voice"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Czech Voice"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"German Voice"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"English Voice"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spanish Voice"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"French Voice"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italian Voice"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japanese Voice"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Korean Voice"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Dutch Voice"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Polish Voice"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portuguese Voice"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russian Voice"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Turkish Voice"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Chinese, Yue Voice"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Chinese, Mandarin Voice"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu Voice"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"English (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_no_language" msgid="141420857808801746">"No language"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"No language (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"No language (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"No language (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"No language (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"No language (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"No language (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Custom 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 custom 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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Key-press vibration duration settings"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Key-press sound volume settings"</string>
</resources>
diff --git a/java/res/values-en/donottranslate-altchars.xml b/java/res/values-en/donottranslate-altchars.xml
deleted file mode 100644
index 29582c950..000000000
--- a/java/res/values-en/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">à,á,â,ä,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,è,é,ê,ë,ē</string>
- <string name="alternates_for_i">8,î,ï,í,ī,ì</string>
- <string name="alternates_for_o">9,ô,ö,ò,ó,œ,ø,ō,õ</string>
- <string name="alternates_for_s">ß</string>
- <string name="alternates_for_u">7,û,ü,ù,ú,ū</string>
- <string name="alternates_for_n">ñ</string>
- <string name="alternates_for_c">ç</string>
-</resources>
diff --git a/java/res/values-en/whitelist.xml b/java/res/values-en/whitelist.xml
index 9395f4c88..262017916 100644
--- a/java/res/values-en/whitelist.xml
+++ b/java/res/values-en/whitelist.xml
@@ -30,9 +30,382 @@
<item>ill</item>
<item>I\'ll</item>
+ <!-- TODO: Trim down more entries by removing ones that get auto-corrected by the
+ Android keyboard's own typing error correction algorithms. -->
+
+ <item>255</item>
+ <item>acomodate</item>
+ <item>accommodate</item>
+
+ <item>255</item>
+ <item>aint</item>
+ <item>ain\'t</item>
+
+ <item>255</item>
+ <item>alot</item>
+ <item>a lot</item>
+
+ <item>255</item>
+ <item>andteh</item>
+ <item>and the</item>
+
+ <item>255</item>
+ <item>arent</item>
+ <item>aren\'t</item>
+
+ <item>255</item>
+ <item>bot</item>
+ <item>not</item>
+
+ <item>255</item>
+ <item>bern</item>
+ <item>been</item>
+
+ <item>255</item>
+ <item>bot</item>
+ <item>not</item>
+
+ <item>255</item>
+ <item>bur</item>
+ <item>but</item>
+
+ <item>255</item>
+ <item>cam</item>
+ <item>can</item>
+
+ <item>255</item>
+ <item>cant</item>
+ <item>can\'t</item>
+
+ <item>255</item>
+ <item>dame</item>
+ <item>same</item>
+
+ <item>255</item>
+ <item>didint</item>
+ <item>didn\'t</item>
+
+ <item>255</item>
+ <item>dormer</item>
+ <item>former</item>
+
+ <item>255</item>
+ <item>dud</item>
+ <item>did</item>
+
+ <item>255</item>
+ <item>fay</item>
+ <item>day</item>
+
+ <item>255</item>
+ <item>fife</item>
+ <item>five</item>
+
+ <item>255</item>
+ <item>foo</item>
+ <item>for</item>
+
+ <item>255</item>
+ <item>fora</item>
+ <item>for a</item>
+
+ <item>255</item>
+ <item>galled</item>
+ <item>called</item>
+
+ <item>255</item>
+ <item>goo</item>
+ <item>too</item>
+
+ <item>255</item>
+ <item>hed</item>
+ <item>he\'d</item>
+
+ <item>255</item>
+ <item>hel</item>
+ <item>he\'ll</item>
+
+ <item>255</item>
+ <item>heres</item>
+ <item>here\'s</item>
+
+ <item>255</item>
+ <item>hew</item>
+ <item>new</item>
+
+ <item>255</item>
+ <item>hoe</item>
+ <item>how</item>
+
+ <item>255</item>
+ <item>hoes</item>
+ <item>how\'s</item>
+
+ <item>255</item>
+ <item>howd</item>
+ <item>how\'d</item>
+
+ <item>255</item>
+ <item>howll</item>
+ <item>how\'ll</item>
+
+ <item>255</item>
+ <item>hows</item>
+ <item>how\'s</item>
+
+ <item>255</item>
+ <item>howve</item>
+ <item>how\'ve</item>
+
+ <item>255</item>
+ <item>hum</item>
+ <item>him</item>
+
+ <item>255</item>
+ <item>i</item>
+ <item>I</item>
+
+ <item>255</item>
+ <item>ifs</item>
+ <item>its</item>
+
+ <item>255</item>
+ <item>il</item>
+ <item>I\'ll</item>
+
+ <item>255</item>
+ <item>im</item>
+ <item>I\'m</item>
+
+ <item>255</item>
+ <item>inteh</item>
+ <item>in the</item>
+
+ <item>255</item>
+ <item>itd</item>
+ <item>it\'d</item>
+
+ <item>255</item>
+ <item>itsa</item>
+ <item>it\'s a</item>
+
+ <item>255</item>
+ <item>lets</item>
+ <item>let\'s</item>
+
+ <item>255</item>
+ <item>maam</item>
+ <item>ma\'am</item>
+
+ <item>255</item>
+ <item>manu</item>
+ <item>many</item>
+
+ <item>255</item>
+ <item>mare</item>
+ <item>made</item>
+
+ <item>255</item>
+ <item>mew</item>
+ <item>new</item>
+
+ <item>255</item>
+ <item>mire</item>
+ <item>more</item>
+
+ <item>255</item>
+ <item>moat</item>
+ <item>most</item>
+
+ <item>255</item>
+ <item>mot</item>
+ <item>not</item>
+
+ <item>255</item>
+ <item>mote</item>
+ <item>note</item>
+
+ <item>255</item>
+ <item>motes</item>
+ <item>notes</item>
+
+ <item>255</item>
+ <item>mow</item>
+ <item>now</item>
+
+ <item>255</item>
+ <item>namer</item>
+ <item>named</item>
+
+ <item>255</item>
+ <item>nave</item>
+ <item>have</item>
+
+ <item>255</item>
+ <item>nee</item>
+ <item>new</item>
+
+ <item>255</item>
+ <item>nigh</item>
+ <item>high</item>
+
+ <item>255</item>
+ <item>nit</item>
+ <item>not</item>
+
+ <item>255</item>
+ <item>oft</item>
+ <item>off</item>
+
+ <item>255</item>
+ <item>os</item>
+ <item>is</item>
+
+ <item>255</item>
+ <item>pater</item>
+ <item>later</item>
+
+ <item>255</item>
+ <item>rook</item>
+ <item>took</item>
+
+ <item>255</item>
+ <item>shel</item>
+ <item>she\'ll</item>
+
+ <item>255</item>
+ <item>shouldent</item>
+ <item>shouldn\'t</item>
+
+ <item>255</item>
+ <item>sill</item>
+ <item>will</item>
+
+ <item>255</item>
+ <item>sown</item>
+ <item>down</item>
+
+ <item>255</item>
+ <item>thatd</item>
+ <item>that\'d</item>
+
+ <item>255</item>
+ <item>tine</item>
+ <item>time</item>
+
+ <item>255</item>
+ <item>thong</item>
+ <item>thing</item>
+
+ <item>255</item>
+ <item>tome</item>
+ <item>time</item>
+
+ <!-- through additional proximity, 'uf' becomes 'of'. 'o' is not next to 'u' so anyone
+ typing 'uf' probably meant 'if', but 'of' is much more common and should be left
+ higher than 'if', hence the need for this entry. -->
+ <item>255</item>
+ <item>uf</item>
+ <item>if</item>
+
+ <!-- 'un' becomes 'UN' because of perfect match ; even if we remove 'UN', then 'un'
+ will become 'on' for the same reason as above. So list this here. -->
+ <item>255</item>
+ <item>un</item>
+ <item>in</item>
+
+ <!-- does it really make any sense to have the following here? -->
+ <item>255</item>
+ <item>UnitedStates</item>
+ <item>United States</item>
+
+ <item>255</item>
+ <item>unitedstates</item>
+ <item>United States</item>
+
+ <item>255</item>
+ <item>visavis</item>
+ <item>vis-a-vis</item>
+
+ <item>255</item>
+ <item>wierd</item>
+ <item>weird</item>
+
+ <item>255</item>
+ <item>wel</item>
+ <item>we\'ll</item>
+
+ <item>255</item>
+ <item>wer</item>
+ <item>we\'re</item>
+
+ <item>255</item>
+ <item>whatd</item>
+ <item>what\'d</item>
+
+ <item>255</item>
+ <item>whatm</item>
+ <item>what\'m</item>
+
+ <item>255</item>
+ <item>whatre</item>
+ <item>what\'re</item>
+
+ <item>255</item>
+ <item>whats</item>
+ <item>what\'s</item>
+
+ <item>255</item>
+ <item>whens</item>
+ <item>when\'s</item>
+
+ <item>255</item>
+ <item>whered</item>
+ <item>where\'d</item>
+
+ <item>255</item>
+ <item>wherell</item>
+ <item>where\'ll</item>
+
+ <item>255</item>
+ <item>wheres</item>
+ <item>where\'s</item>
+
+ <item>255</item>
+ <item>wholl</item>
+ <item>who\'ll</item>
+
+ <item>255</item>
+ <item>whove</item>
+ <item>who\'ve</item>
+
+ <item>255</item>
+ <item>whyd</item>
+ <item>why\'d</item>
+
+ <item>255</item>
+ <item>whyll</item>
+ <item>why\'ll</item>
+
+ <item>255</item>
+ <item>whys</item>
+ <item>why\'s</item>
+
+ <item>255</item>
+ <item>whyve</item>
+ <item>why\'ve</item>
+
+ <item>255</item>
+ <item>wont</item>
+ <item>won\'t</item>
+
+ <item>255</item>
+ <item>yall</item>
+ <item>y\'all</item>
+
<item>255</item>
- <item>thisd</item>
- <item>this\'d</item>
+ <item>youd</item>
+ <item>you\'d</item>
</string-array>
</resources>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 713632c85..39ca40903 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -21,61 +21,69 @@
<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">"Teclado de Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado de Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Configuración de teclado de Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro invest."</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortográfico de Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortográfico de Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Configuración del corrector ortográfico"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres contactos"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar teclas"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sonar al pulsar las teclas"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Aviso emergente al pulsar tecla"</string>
<string name="general_category" msgid="1859088467017573195">"General"</string>
<string name="correction_category" msgid="2236750915056607613">"Corrección de texto"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Sugerencias sobre la base de palabras anteriores"</string>
<string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string>
<string name="advanced_settings" msgid="362895144495591463">"Configuración avanzada"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opciones para usuarios expertos"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de entrada"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma abarca otros métodos de entrada."</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Elim. tecla cambio de idioma"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso en rechazo de alerta de tecla"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin demora"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres de contacto"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nombres de los contactos para sugerencias y correcciones"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Activar correcciones"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para realizar correcciones"</string>
<string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configurar diccionarios"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Arreglos rápidos"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige errores de escritura comunes"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugerencias de correcciones"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Mostrar palabras sugeridas al escribir"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar en modo retrato"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar siempre"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Espac cambia idioma"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla de configuración"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automático"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mostrar siempre"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Ocultar siempre"</string>
<string name="auto_correction" msgid="4979925752001319458">"Corrección automática"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"La barra espaciadora y las teclas de puntuación insertan automáticamente la palabra corregida"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactivado"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresivo"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Sugerencias de bigramas"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utiliza la palabra anterior para mejorar la sugerencia"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Predicción de biagramas"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerencias para la palabra siguiente"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar la palabra anterior para mejorar las sugerencias"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Predicción de la palabra siguiente"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Usar la palabra anterior también para predicción."</string>
<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">"Hecho"</string>
<string name="label_send_key" msgid="2815056534433717444">"Enviar"</string>
<string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Más"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Mayús habilitada"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bloqueo de mayúsculas habilitado"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Se activó el modo Mayúscula (toca para desactivarlo)."</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Se activó el bloqueo de mayúsculas (toca para desactivarlo)."</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Borrar"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Carita sonriente"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Volver"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Coma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punto"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Paréntesis de apertura"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paréntesis de cierre"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dos puntos"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Punto y coma"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Signo de admiración"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Signo de interrogación"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Comillas dobles"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Comillas simples"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Buscar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punto"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Raíz cuadrada"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marca registrada"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"En atención de"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Destacar"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Numeral"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Elipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Comillas bajas"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Entrada por voz"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"La entrada por voz no está admitida en tu idioma, pero sí funciona en inglés."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"La entrada de voz usa el reconocimiento de voz de Google. "<a href="http://m.google.com/privacy">"Se aplica la política de privacidad para"</a>" celulares."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desactivar la entrada de voz, ve a la configuración de métodos de entrada."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para utilizar entrada de voz, presiona el botón micrófono."</string>
- <string name="voice_listening" msgid="467518160751321844">"Habla ahora"</string>
- <string name="voice_working" msgid="6666937792815731889">"Procesando"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Error. Vuelve a intentarlo."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"No se pudo establecer la conexión."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, demasiado discurso."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema de audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"No se oyó la voz"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"No se encontraron coincidencias"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Búsqueda por voz no instalada"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugerencia:"</b>" Deslizar en el teclado para hablar"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugerencia:"</b>" La próxima vez intenta decir la puntuación como \"punto\", \"coma\" o \"signo de pregunta\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
- <string name="ok" msgid="7898366843681727667">"Aceptar"</string>
- <string name="voice_input" msgid="2466640768843347841">"Entrada por voz"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Se activó el modo Mayúscula."</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Se activó el bloqueo de mayúsculas."</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Se desactivó el modo Mayúscula"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo Símbolos"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo Letras"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo Teléfono"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo Símbolos del teléfono"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada por voz"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"En el teclado principal"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En el teclado de símbolos"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivado"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en el teclado principal"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en el teclado de símbolos"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"La entrada por voz está inhabilitada"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Seleccionar método de entrada"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Deslizarse manualmente por la barra espaciadora para cambiar el idioma"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tocar de nuevo para guardar"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Marcar tiempo en registro"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marca tiempo registrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"No registrar esta sesión"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Eliminando registro"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registro sesión eliminado"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"NO se eliminó el registro"</string>
+ <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Vuelve a tocar para guardar."</string>
<string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Activar los comentarios del usuario"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de introducción de texto al enviar las estadísticas de uso y los informes de error a Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tocar para corregir palabras"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Toca las palabras ingresadas que desees corregir solo cuando las sugerencias estén visibles."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclado"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Teclado en checo"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Teclado en árabe"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Teclado en danés"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Teclado en alemán"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Teclado QWERTY en alemán"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Teclado en inglés (Reino Unido)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Teclado en inglés (EE.UU.)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Teclado en español"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Teclado en finlandés"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Teclado en francés"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Teclado en francés (Canadá)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Teclado en francés (Suiza)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Teclado en croata"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Teclado en húngaro"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Teclado en hebreo"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Teclado en italiano"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Teclado en noruego"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Teclado en holandés"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Teclado en polaco"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Teclado en portugués"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Teclado en ruso"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Teclado en serbio"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Teclado en sueco"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Teclado en turco"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voz en Afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voz en checo"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voz en alemán"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voz en inglés"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voz en español"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voz en francés"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voz italiana"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voz en japonés"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voz en coreano"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voz holandesa"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voz en polaco"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voz en portugués"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voz en ruso"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voz en turco"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voz en Yue, chino"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voz en mandarín, chino"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voz en isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EE.UU.)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglés (Reino Unido) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglés (EE.UU.) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Ningún idioma"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Ningún idioma (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Sin idioma (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Sin idioma (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Sin idioma (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Sin idioma (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Sin idioma (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
+ <string name="add_style" msgid="6163126614514489951">"Agr. estilo"</string>
+ <string name="add" msgid="8299699805688017798">"Agregar"</string>
+ <string name="remove" msgid="4486081658752944606">"Eliminar"</string>
+ <string name="save" msgid="7646738597196767214">"Guardar"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Diseño"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Debes activar estilo de entrada personalizado para utilizarlo."</string>
+ <string name="enable" msgid="5031294444630523247">"Activar"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Duración de vibración al presionar teclas"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volumen de sonido al presionar teclas"</string>
</resources>
diff --git a/java/res/values-es/donottranslate-altchars.xml b/java/res/values-es/donottranslate-altchars.xml
deleted file mode 100644
index 16111ec42..000000000
--- a/java/res/values-es/donottranslate-altchars.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">á,à,ä,â,ã,å,ą,æ,ā,ª</string>
- <string name="alternates_for_e">3,é,è,ë,ê,ę,ė,ē</string>
- <string name="alternates_for_i">8,í,ï,ì,î,į,ī</string>
- <string name="alternates_for_o">9,ó,ò,ö,ô,õ,ø,œ,ō,º</string>
- <string name="alternates_for_u">7,ú,ü,ù,û,ū</string>
- <string name="alternates_for_n">ñ,ń</string>
- <string name="alternates_for_c">ç,ć,č</string>
- <string name="alternates_for_punctuation">"\\,,\?,!,¿,¡,:,-,\',\",),(,/,;,+,&amp;,\@"</string>
- <string name="alternates_for_web_tab_punctuation">".,\\,,\?,!,¿,¡,:,-,\',\",),(,/,;,+,&amp;,\@"</string>
-</resources>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 889b9a28b..79a36cccd 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -21,61 +21,69 @@
<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">"Teclado de Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ajustes del teclado de Android"</string>
- <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones introducción texto"</string>
+ <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones entrada texto"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro investigación"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector de Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector de Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ajustes del corrector ortográfico"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Nombres de contactos"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Añadir nombres de tu lista de contactos al corrector"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar tecla"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sonido al pulsar tecla"</string>
- <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up al pulsar tecla"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"Ampliar al pulsar tecla"</string>
<string name="general_category" msgid="1859088467017573195">"General"</string>
<string name="correction_category" msgid="2236750915056607613">"Corrección ortográfica"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Sugerencias basadas en palabras anteriores"</string>
<string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string>
<string name="advanced_settings" msgid="362895144495591463">"Ajustes avanzados"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opciones para usuarios expertos"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso de rechazo"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de entrada"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma sirve también para otros métodos"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Quitar tecla de idioma"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso al ampliar tecla"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin retraso"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
- <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres contactos"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir contactos"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nombres de contactos para sugerencias y correcciones"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Activar nuevas correcciones"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para nuevas correcciones"</string>
<string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configurar diccionarios"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Correcciones rápidas"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige los errores tipográficos que se cometen con más frecuencia."</string>
- <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugerencias de correcciones"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"Sugerencias de correcciones"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Muestra las palabras sugeridas mientras se escribe."</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar en modo vertical"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar siempre"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Espacio para cambiar idioma"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla de ajustes"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automáticamente"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mostrar siempre"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Ocultar siempre"</string>
<string name="auto_correction" msgid="4979925752001319458">"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_modest" msgid="8788366690620799097">"Parcial"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresiva"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Sugerencias de bigramas"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Usar palabra anterior para mejorar sugerencias"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Predicción de bigramas"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerir siguiente palabra"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palabra anterior para mejorar las sugerencias"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Predecir siguiente palabra"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar también la palabra anterior para realizar la predicción"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Más"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Tecla Mayús habilitada"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bloq Mayús habilitado"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Mayúsculas activadas (tocar para inhabilitar)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Bloqueo de mayúsculas activado (tocar para inhabilitar)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Suprimir"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Emoticono"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Tecla Intro"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Coma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punto"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Paréntesis de apertura"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paréntesis de cierre"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dos puntos"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Punto y coma"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Signo de exclamación"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Signo de interrogación"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Comillas dobles"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Comillas simples"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Buscar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punto"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Raíz cuadrada"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marca comercial"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Porcentaje"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Asterisco"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Almohadilla"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Puntos suspensivos"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Comillas dobles bajas"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Introducción de voz"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualmente la introducción de voz no está disponible en tu idioma, pero se puede utilizar en inglés."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"La entrada de voz utiliza el reconocimiento de voz de Google. Se aplica la "<a href="http://m.google.com/privacy">"Política de privacidad de Google para móviles"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desactivar la función de entrada de voz, accede a los ajustes del método de introducción de texto."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para utilizar la entrada de voz, pulsa el botón de micrófono."</string>
- <string name="voice_listening" msgid="467518160751321844">"Habla ahora"</string>
- <string name="voice_working" msgid="6666937792815731889">"En curso"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Se ha producido un error. Inténtalo de nuevo."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"No se ha podido establecer conexión."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Se ha producido un error debido a un exceso de introducción de datos de voz."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema de audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Ninguna conversación escuchada"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"No se ha encontrado ninguna coincidencia."</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"La búsqueda por voz no está instalada."</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugerencia:"</b>" muévete por el teclado para hablar."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugerencia:"</b>" la próxima vez, prueba a indicar signos de puntuación como, por ejemplo, \"punto\", \"coma\" o \"signo de interrogación\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
- <string name="ok" msgid="7898366843681727667">"Aceptar"</string>
- <string name="voice_input" msgid="2466640768843347841">"Introducción de voz"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Mayúsculas habilitadas"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Bloqueo de mayúsculas habilitado"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Mayúsculas inhabilitadas"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo de símbolos"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo de letras"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo de teléfono"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo de símbolos de teléfono"</string>
+ <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_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en teclado principal"</string>
- <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro en teclado de símbolos"</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>
- <string name="selectInputMethod" msgid="315076553378705821">"Selecciona un método de introducción de texto"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Deslizar el dedo por la barra espaciadora para cambiar el idioma"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Volver a tocar para guardar"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Anotar marca tiempo en registro"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marca de tiempo registrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"No registrar esta sesión"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Eliminando registro..."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registro eliminado"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Registro no eliminado"</string>
+ <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar."</string>
<string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Habilitar comentarios de usuarios"</string>
- <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de introducción de texto enviando estadísticas de uso e informes de error a Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tocar para corregir palabras"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Toca las palabras introducidas para corregirlas, solo cuando las sugerencias sean visibles."</string>
+ <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de entrada de texto enviando estadísticas de uso e informes de error a Google."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema de teclado"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Teclado checo"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Teclado árabe"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Teclado danés"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Teclado alemán"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Teclado QWERTY alemán"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Teclado inglés (Reino Unido)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Teclado de inglés (EE.UU.)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Teclado español"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Teclado finlandés"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Teclado francés"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Teclado francés (Canadá)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Teclado francés (Suiza)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Teclado croata"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Teclado húngaro"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Teclado hebreo"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Teclado italiano"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Teclado noruego"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Teclado holandés"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Teclado polaco"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Teclado portugués"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Teclado ruso"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Teclado serbio"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Teclado sueco"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Teclado turco"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voz afrikáans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Google Voice en checo"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Google Voice en alemán"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voz inglesa"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Google Voice en español"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Google Voice en francés"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voz italiana"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Google Voice en japonés"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Google Voice en coreano"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voz holandesa"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Google Voice en polaco"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Google Voice en portugués"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Google Voice en ruso"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Google Voice en turco"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voz china (cantonés)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voz china (mandarín)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voz zulú"</string>
- <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"inglés (Reino Unido)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglés (Reino Unido) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglés (EE.UU.) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"ningún idioma"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"ningún idioma (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"ningún idioma (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"ningún idioma (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"ningún idioma (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"ningún idioma (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"ningún idioma (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
+ <string name="add_style" msgid="6163126614514489951">"Añadir estilo"</string>
+ <string name="add" msgid="8299699805688017798">"Añadir"</string>
+ <string name="remove" msgid="4486081658752944606">"Eliminar"</string>
+ <string name="save" msgid="7646738597196767214">"Guardar"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Tipo"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Debes habilitar los estilos de entrada personalizados para usar un estilo personalizado. ¿Quieres hacerlo ahora?"</string>
+ <string name="enable" msgid="5031294444630523247">"Habilitar"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Estudiar usabilidad"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Duración de la vibración al pulsar tecla"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volumen sonido al pulsar tecla"</string>
</resources>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index b0c13efa1..45870d3a9 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -21,61 +21,69 @@
<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">"Androidi klaviatuur"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-klaviatuur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Androidi klaviatuuriseaded"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Sisestusvalikud"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Uuringulogi käsud"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidi õigekirjakontroll"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidi õigekirjakontroll (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Õigekirjakontrolli seaded"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontakti nimede kontroll."</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Õigekirjakontroll kasutab teie kontaktisikute loendi sissekandeid"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreeri klahvivajutusel"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Heli klahvivajutusel"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Klahvivajutusel kuva hüpik"</string>
<string name="general_category" msgid="1859088467017573195">"Üldine"</string>
<string name="correction_category" msgid="2236750915056607613">"Teksti parandamine"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Eelmistel sõnadel põhinevad soovitused"</string>
<string name="misc_category" msgid="6894192814868233453">"Muud valikud"</string>
<string name="advanced_settings" msgid="362895144495591463">"Täpsemad seaded"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Valikud ekspertkasutajatele"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Valikud ekspertidele"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Vaheta sisestusmeetodit"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Keelevahetuse võti hõlmab ka muid sisestusmeetodeid"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Keela keelevahetuse võti"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Hüpiku loobumisviivitus"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Viivituseta"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Vaikeseade"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Soovita kontaktkirjeid"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Kasuta soovitusteks ja parandusteks nimesid kontaktiloendist"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Uute paranduste lubamine"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Soovituste seadmine uute paranduste jaoks"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automaatne suurtähtede kasutamine"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Sõnastike seadistamine"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Kiirparandused"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Parandab üldlevinud trükivigu"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Pistiksõnaraamatud"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Peamine sõnaraamat"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Kuva parandussoovitusi"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Kuva sisestamise ajal sõnasoovitusi"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Kuva alati"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Kuva portreerežiimis"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Peida alati"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Kasutage keele vahetamiseks tühikuklahvi"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Kuva seadete võti"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automaatne"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Kuva alati"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Peida alati"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automaatparandus"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Tühik ja kirjavahemärgid parand. autom. kirjavigadega sõnad"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Väljas"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mõõdukas"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressiivne"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Väga agressiivne"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigrammi soovitused"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Kasutage eelmist sõna soovituse parandamiseks"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigrammi ennustus"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Järgmise sõna soovitused"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Kasuta soovituste täiustamiseks eelmist sõna"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Järgmise sõna ennustus"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Kasuta ennustuseks ka eelmist sõna"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Rohkem"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Tõstuklahv on lubatud"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Suurtähelukk on lubatud"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Tõstuklahv sees (puudutage keelamiseks)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Suurtähelukk on sees (puudutage keelamiseks)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Kustuta"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Sümbolid"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Tähed"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Kõnesisend"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Naerunägu"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Tagasi"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punkt"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Vasaksulg"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paremsulg"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Koolon"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikoolon"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Hüüumärk"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Küsimärk"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Jutumärgid"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Üksikjutumärgid"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Otsing"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Ruutjuur"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pii"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Kaubamärk"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Vahendaja"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Tärn"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Nael"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Kolmikpunkt"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Alumised jutumärgid"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Kõnesisend"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Kõnesisendit ei toetata praegu teie keeles, kuid see töötab inglise keeles."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Kõnesisend kasutab Google\'i kõnetuvastust. Kehtivad "<a href="http://m.google.com/privacy">"Mobile\'i privaatsuseeskirjad"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Kõnesisendi väljalülitamiseks minge sisestusmeetodi seadete juurde."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Kõnesisendi kasutamiseks vajutage mikrofoni nuppu."</string>
- <string name="voice_listening" msgid="467518160751321844">"Alustage rääkimist"</string>
- <string name="voice_working" msgid="6666937792815731889">"Töötab"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Viga. Proovige uuesti."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Ühendamine nurjus."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Viga. Liiga palju kõnet."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Heli probleem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Serveri viga"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Kõne pole kuuldav"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Ühtki vastet ei leitud"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Hääleotsing pole installitud"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Vihje:"</b>" rääkimiseks libistage sõrme üle ekraani"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Vihje:"</b>" proovige järgmine kord kirjavahemärkide ütlemist, nt „punkt”, „koma” või „küsimärk”."</string>
- <string name="cancel" msgid="6830980399865683324">"Tühista"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Kõnesisend"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Tõstuklahv on lubatud"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Suurtähelukk on lubatud"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Tõstuklahv on keelatud"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Sümbolite režiim"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Tähtede režiim"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonirežiim"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefoni sümbolite režiim"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Häälesisendi klahv"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Peamisel klaviatuuril"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sümbol. klaviatuuril"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Väljas"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. peam. klaviat."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. sümb. klaviat."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Kõnesisend on keelatud"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Sisestusmeet. valim."</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Keele muutmiseks libistage sõrmega üle tühiku"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"←Salvestamiseks puudutage uuesti"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Märgi ajatempel logisse"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Salvestatud ajatemplid"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ära logi seda seanssi"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Seansi logi kustutamine"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Seansi logi kustutatud"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Seansi logi EI kustutatud"</string>
+ <string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Salvestamiseks puudutage uuesti"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Sõnastik saadaval"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Luba kasutaja tagasiside"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Saatke Google\'ile automaatselt kasutusstatistikat ja krahhiaruandeid ning aidake seda sisestusmeetodi redigeerijat parandada."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Puudutage sõnade parandamiseks"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Puudutage sisestatud sõnu nende parandamiseks; ainult juhul, kui soovitusi on näha"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Klaviatuuri teema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tšehhi klaviatuur"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Araabia klaviatuur"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Taani klaviatuur"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Saksa klaviatuur"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Saksa QWERTY klaviatuur"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Inglise (UK) klaviatuur"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Inglise (USA) klaviatuur"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Hispaania klaviatuur"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Soome klaviatuur"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Prantsuse klaviatuur"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Prantsuse (Kanada) klaviatuur"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Prantsuse (Šveits) klaviatuur"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Horvaatia klaviatuur"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ungari klaviatuur"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Heebrea klaviatuur"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Itaalia klaviatuur"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norra klaviatuur"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Hollandi klaviatuur"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Poola klaviatuur"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugali klaviatuur"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Vene klaviatuur"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbia klaviatuur"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Rootsi klaviatuur"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Türgi klaviatuur"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaani kõne"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Tšehhi kõne"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Saksa kõne"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Inglise kõne"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Hispaania kõne"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Prantsuse kõne"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Itaalia kõne"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Jaapani kõne"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Korea kõne"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Hollandi kõne"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Poola kõne"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugali kõne"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Vene kõne"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Türgi kõne"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Hiina, Yue\'i kõne"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Hiina, mandariini kõne"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu kõne"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Inglise (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Inglise (USA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglise (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglise (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Keel puudub"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Keel puudub (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Keel puudub (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Keel puudub (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Keel puudub (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Keel puudub (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Keel puudub (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Kohandage sisendlaadid"</string>
+ <string name="add_style" msgid="6163126614514489951">"Lisage laad"</string>
+ <string name="add" msgid="8299699805688017798">"Lisa"</string>
+ <string name="remove" msgid="4486081658752944606">"Eemalda"</string>
+ <string name="save" msgid="7646738597196767214">"Salvesta"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Keel"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Paigutus"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kohandatud sisendi laad tuleb enne kasutamist lubada. Lubada?"</string>
+ <string name="enable" msgid="5031294444630523247">"Luba"</string>
+ <string name="not_now" msgid="6172462888202790482">"Mitte kohe"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sama sisendstiil on juba olemas: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kasutatavuse uurimisrežiim"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Klahvivajutuse vibratsiooni kestuse seaded"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Klahvivajutuse helitugevuse seaded"</string>
</resources>
diff --git a/java/res/values-ro/donottranslate-altchars.xml b/java/res/values-fa/donottranslate.xml
index 728ead472..57de2538b 100644
--- a/java/res/values-ro/donottranslate-altchars.xml
+++ b/java/res/values-fa/donottranslate.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2011, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -18,8 +18,8 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">ă,â,à,á,ä,æ,ã,å,ā</string>
- <string name="alternates_for_i">8,î,ï,ì,í,į,ī</string>
- <string name="alternates_for_s">ș,ß,ś,š</string>
- <string name="alternates_for_t">5,ț</string>
+ <!-- The all letters need to be mirrored are found at
+ http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt -->
+ <!-- Symbols that are suggested between words -->
+ <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string>
</resources>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index fbf0a5b20..9f0e5aaa4 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -21,55 +21,63 @@
<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">"صفحه کلید Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"صفحه کلید (Android (AOSP"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"تنظیمات صفحه کلید Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"گزینه های ورودی"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"فرمان‌های گزارش‌گیری پژوهش"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"غلط‌گیر املای Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"غلط‌گیر املای Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"تنظیمات غلط گیری املایی"</string>
+ <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="ngram_category" msgid="5337109164339320257">"پیشنهادهایی بر اساس کلمه های قبلی"</string>
<string name="misc_category" msgid="6894192814868233453">"سایر گزینه ها"</string>
<string name="advanced_settings" msgid="362895144495591463">"تنظیمات پیشرفته"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"گزینه هایی برای کاربران حرفه ای"</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="suppress_language_switch_key" msgid="8003788410354806368">"کلید تغییر زبان را فشار دهید"</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="use_contacts_dict" msgid="4435317977804180815">"پیشنهاد نام های مخاطب"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"برای پیشنهاد و تصحیح از نام مخاطبین استفاده شود"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"فعال کردن تصحیح مجدد"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"تنظیم پیشنهادات برای تصحیح مجدد"</string>
<string name="auto_cap" msgid="1719746674854628252">"نوشتن با حروف بزرگ خودکار"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"پیکربندی لغت نامه ها"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"راه حل های سریع"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"تصحیح خطاهای تایپی رایج"</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="3551821800439659812">"نمایش در حالت عمودی"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"همیشه پنهان شود"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"از ویژگی تعویض زبان کلید فاصله استفاده شود"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"نمایش کلید تنظیمات"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"خودکار"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"همیشه نمایش"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"همیشه پنهان"</string>
<string name="auto_correction" msgid="4979925752001319458">"تصحیح خودکار"</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_aggeressive" msgid="3524029103734923819">"فعال"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"بسیار پرخاشگرانه"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"پیشنهادهای Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"برای بهبود پیشنهاد از کلمه قبلی استفاده شود"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"پیش بینی Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"پیشنهادات کلمه بعدی"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"برای بهبود پیشنهاد از کلمه قبلی استفاده شود"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"پیش‌بینی کلمه بعدی"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"استفاده از کلمه قبلی برای پیش بینی"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"بیشتر"</string>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"اب‌پ"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"۳۲۱؟"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"۳۲۱"</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 />
@@ -78,8 +86,8 @@
<!-- 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="954941524766465022">"Shift فعال است"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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>
@@ -90,103 +98,59 @@
<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_comma" msgid="4970844442999724586">"کاما"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"نقطه"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"پرانتز چپ"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"پرانتز راست"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"دو نقطه"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"نقطه ویرگول"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"علامت تعجب"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"علامت سؤال"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"علامت نقل قول"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"علامت نقل قول تکی"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"جستجو"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"نقطه"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"ریشه دوم"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"پی"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"دلتا"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"علامت تجاری"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"توسط"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"ستاره"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"پوند"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"سه نقطه"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"علامت نقل قول پایین"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"ورودی صوتی"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"ورودی صوتی در حال حاضر برای زبان شما پشتیبانی نمی شود اما برای زبان انگلیسی فعال است."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"ورودی صوتی از تشخیص صدای Google استفاده می کند. "<a href="http://m.google.com/privacy">"خط مشی رازداری Mobile "</a>" اعمال می شود."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"برای خاموش کردن ورودی صدا، به تنظیمات روش ورودی بروید."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"برای استفاده از ورودی صوتی، دکمه میکروفن را فشار دهید."</string>
- <string name="voice_listening" msgid="467518160751321844">"اکنون صحبت کنید"</string>
- <string name="voice_working" msgid="6666937792815731889">"در حال کار"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"خطا: لطفاً دوباره امتحان کنید."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"متصل نشد"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"خطا، گفتار بسیار زیاد است."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"مشکل صوتی"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"خطای سرور"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"گفتاری شنیده نشد"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"مورد منطبقی یافت نشد"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"جستجوی صوتی نصب نشده است"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"نکته: "</b>" برای صحبت روی صفحه کلید ضربه بزنید"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"نکته: دفعه دیگر، از نشانه گذاری های گفتاری مانند \"نقطه\"، \"کاما\" یا \"علامت سؤال\" استفاده کنید."</b></string>
- <string name="cancel" msgid="6830980399865683324">"لغو"</string>
- <string name="ok" msgid="7898366843681727667">"تأیید"</string>
- <string name="voice_input" msgid="2466640768843347841">"ورودی صوتی"</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="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="selectInputMethod" msgid="315076553378705821">"انتخاب روش ورودی"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"پیکربندی روش های ورودی"</string>
<string name="language_selection_title" msgid="1651299598555326750">"زبان های ورودی"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"برای تغییر زبان انگشت را روی کلید فاصله بلغزانید"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← جهت ذخیره دوباره لمس کنید"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"یادداشت مهر زمان در گزارش"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"مهر زمان ثبت شده"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"از این جلسه گزارش‌گیری نشود"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"در حال حذف گزارش جلسه"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"گزارش جلسه حذف شد"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"گزارش جلسه حذف نشد"</string>
+ <string name="select_language" msgid="3693815588777926848">"زبان‌های ورودی"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"برای ذخیره دوباره لمس کنید"</string>
<string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"فعال کردن بازخورد کاربر"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"با ارسال خودکار آمارهای کاربرد و گزارش های خرابی به Google، به بهبود این ویرایشگر روش ورودی کمک کنید."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"برای تصحیح کلمات لمس کنید"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"فقط هنگامی که پیشنهادات قابل مشاهده هستند، برای تصحیح کلمات وارد شده آنها را لمس کنید"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه کلید"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"صفحه کلید چک"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"صفحه کلید عربی"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"صفحه کلید دانمارکی"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"صفحه کلید آلمانی"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"صفحه کلید QWERTY آلمانی"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"صفحه کلید انگلیسی (بریتانیایی)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"صفحه کلید انگلیسی (آمریکایی)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"صفحه کلید اسپانیایی"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"صفحه کلید فنلاندی"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"صفحه کلید فرانسوی"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"صفحه کلید فرانسوی (کانادایی)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"صفحه کلید فرانسوی (سوئیس)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"صفحه کلید کرواتی"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"صفحه کلید مجارستانی"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"صفحه کلید عبری"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"صفحه کلید ایتالیایی"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"صفحه کلید نروژی"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"صفحه کلید هلندی"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"صفحه کلید لهستانی"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"صفحه کلید پرتغالی"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"صفحه کلید روسی"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"صفحه کلید صربی"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"صفحه کلید سوئدی"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"صفحه کلید ترکی"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"صدای آفریکانس"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"صدای چک"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"صدای آلمانی"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"صدای انگلیسی"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"صدای اسپانیایی"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"صدای فرانسوی"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"صدای ایتالیایی"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"صدای ژاپنی"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"صدای کره ای"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"صدای هلندی"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"صدای لهستانی"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"صدای پرتغالی"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"صدای روسی"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"صدای ترکی"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"صدای چینی، یوئه"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"صدای چینی، ماندارین"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"صدای ایزی زولو"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"انگیسی (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"انگیسی (US)"</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_no_language" msgid="141420857808801746">"زبانی موجود نیست"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"هیچ کدام از زبانها (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"هیچکدام از زبان‌ها (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"هیچکدام از زبان‌ها (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"هیچکدام از زبان‌ها (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"هیچکدام از زبان‌ها (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"هیچکدام از زبان‌ها (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"تنظیمات مدت زمان لرزش فشار کلید"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"تنظیمات میزان صدای فشار کلید"</string>
</resources>
diff --git a/java/res/values-fi/donottranslate-altchars.xml b/java/res/values-fi/donottranslate-altchars.xml
deleted file mode 100644
index ff87a3258..000000000
--- a/java/res/values-fi/donottranslate-altchars.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">æ,à,á,â,ã,ā</string>
- <string name="alternates_for_o">9,ø,ô,ò,ó,õ,œ,ō</string>
- <string name="alternates_for_u">7,ü</string>
- <string name="alternates_for_s">š,ß,ś</string>
- <string name="alternates_for_z">ž,ź,ż</string>
- <string name="keylabel_for_scandinavia_row2_10">ö</string>
- <string name="keylabel_for_scandinavia_row2_11">ä</string>
- <string name="alternates_for_scandinavia_row2_10">ø</string>
- <string name="alternates_for_scandinavia_row2_11">æ</string>
-</resources>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index ef38b14c0..f4dff35b9 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -21,61 +21,69 @@
<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">"Android-näppäimistö"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-näppäimistö (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-näppäimistön asetukset"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Tutkimuslokin komennot"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-oikoluku"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-oikoluku (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Oikoluvun asetukset"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Hae kontaktien nimiä"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Oikeinkirjoituksen tarkistus käyttää kontaktiluettelosi tietoja."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Käytä värinää näppäimiä painettaessa"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Toista ääni näppäimiä painettaessa"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Ponnahdusikkuna painalluksella"</string>
<string name="general_category" msgid="1859088467017573195">"Yleinen"</string>
<string name="correction_category" msgid="2236750915056607613">"Tekstin korjaus"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Aiempiin sanoihin perustuvat ehdotukset"</string>
<string name="misc_category" msgid="6894192814868233453">"Muut vaihtoehdot"</string>
<string name="advanced_settings" msgid="362895144495591463">"Lisäasetukset"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Valinnat kokeneille käyttäjille"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Valinnat asiantuntijoille"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Käytä toista syöttötapaa"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kielenvaihtonäppäin kattaa myös muut syöttötavat"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Piilota kielenvaihtonäpp."</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Näppäimen hylkäysviive"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ei viivettä"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Ehdota yhteystietojen nimiä"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Käytä yhteystietojen nimiä ehdotuksissa ja korjauksissa"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Ota korjaukset käyttöön"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Aseta korjausehdotuksia"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automaattiset isot kirjaimet"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Määritä sanakirjat"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Pikakorjaukset"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Korjaa yleiset kirjoitusvirheet"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Lisäsanakirjat"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Pääsanakirja"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Näytä korjausehdotukset"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Näytä sanaehdotukset kirjoitettaessa"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Näytä aina"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Näytä pystysuunnassa"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Piilota aina"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Vaihda kieli välil."</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Näytä asetukset-näppäin"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automaattinen"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Näytä aina"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Piilota aina"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autom. korjaus"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Välilyönnit ja välimerkit korjaavat väärinkirjoitetut sanat automaattisesti"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Älä käytä"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Osittainen"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Täysi"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Hyvin aggressiivinen"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram-ehdotukset"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Paranna ehdotusta aiemman sanan avulla"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram-ennakointi"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Seuraavan sanan ehdotukset"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Paranna ehdotuksia aiempien sanojen avulla"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Seuraavan sanan ennakointi"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Käytä edellistä sanaa myös ennakointiin"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Tallennettu"</string>
<string name="label_go_key" msgid="1635148082137219148">"Siirry"</string>
<string name="label_next_key" msgid="362972844525672568">"Seur."</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"Edell"</string>
<string name="label_done_key" msgid="2441578748772529288">"Valmis"</string>
<string name="label_send_key" msgid="2815056534433717444">"Lähetä"</string>
<string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Lisää"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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 kuullaksesi, 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>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Näppäimen koodi %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift päällä"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock päällä"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Vaihto päällä (napauta poistaaksesi käytöstä)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock päällä (napauta poistaaksesi käytöstä)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Poisto"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbolit"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Kirjaimet"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Puheohjaus"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Hymiö"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Pilkku"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Piste"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Vasen sulkumerkki"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Oikea sulkumerkki"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Kaksoispiste"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Puolipiste"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Huutomerkki"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Kysymysmerkki"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Lainausmerkki"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Puolilainausmerkki"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Haku"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Piste"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Neliöjuuri"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pii"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Tavaramerkki"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"C/O"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Tähti"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Punta"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsi"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Rivinalinen lainausmerkki"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Äänisyöte"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Äänisyötettä ei vielä tueta kielelläsi, mutta voit käyttää sitä englanniksi."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Äänisyöte käyttää Googlen puheentunnistusta. "<a href="http://m.google.com/privacy">"Mobile-tietosuojakäytäntö"</a>" on voimassa."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Siirry syöttöasetuksiin poistaaksesi äänisyötteen käytöstä."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ota äänisyöte käyttöön painamalla mikrofonikuvaketta."</string>
- <string name="voice_listening" msgid="467518160751321844">"Puhu nyt"</string>
- <string name="voice_working" msgid="6666937792815731889">"Työstetään"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Virhe. Yritä uudelleen."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Ei yhteyttä"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Virhe, liikaa puhetta."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Ääniongelma"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Palvelinvirhe"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Puhetta ei kuulu"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Ei vastineita"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Äänihakua ei asennettu"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Vihje:"</b>" liu\'uta sormea näppäimistöllä ja puhu"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Vihje:"</b>" kokeile seuraavalla kerralla puhua välimerkit, kuten \"period\" (piste), \"comma\" (pilkku) tai \"question mark\" (kysymysmerkki)."</string>
- <string name="cancel" msgid="6830980399865683324">"Peruuta"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Äänisyöte"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Vaihto päällä"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock päällä"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Vaihto pois käytöstä"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolit-tila"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Näppäimistötila"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Puhelintila"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Puhelinsymbolit-tila"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Ääniohjausavain"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Päänäppäimistössä"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Symbolinäppäimistössä"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Älä näytä"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. päänäppäim."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. symbolinäppäim."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ääniohjaus on pois käytöstä"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Valitse syöttötapa"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Vaihda kieltä liu\'uttamalla sormea välilyöntinäppäimellä"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tallenna koskettamalla uudelleen"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Merkitse aikaleima lokiin"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Merkitty aikaleima"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Älä tallenna tätä käyttök."</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Poistetaan lokia"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Käyttökertaloki poistettu"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Lokia EI poistettu"</string>
+ <string name="select_language" msgid="3693815588777926848">"Syöttökielet"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tallenna koskettamalla uudelleen"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Ota käyttäjäpalaute käyttöön"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Auta parantamaan tätä syöttötavan muokkausohjelmaa lähettämällä automaattisesti käyttötietoja ja kaatumisraportteja Googlelle."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Korjaa sanoja koskettamalla"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Korjaa annetut sanat napauttamalla. (Vain, kun ehdotuksia on näkyvillä.)"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Näppäimistöteema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Näppäimistö: tšekki"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabiankielinen näppäimistö"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Näppäimistö: tanska"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Näppäimistö: saksa"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Saksalainen QWERTY-näppäimistö"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Näppäimistö: englanti (UK)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Näppäimistö: englanti (US)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Näppäimistö: espanja"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Näppäimistö: suomi"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Näppäimistö: ranska"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Näppäimistö: ranska (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Näppäimistö: ranska (Sveitsi)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Näppäimistö: kroatia"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Näppäimistö: unkari"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hepreankielinen näppäimistö"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Näppäimistö: italia"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Näppäimistö: norja"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Näppäimistö: hollanti"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Näppäimistö: puola"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Näppäimistö: portugali"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Näppäimistö: venäjä"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Näppäimistö: serbia"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Näppäimistö: ruotsi"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Näppäimistö: turkki"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Ääni: afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Ääni: tšekki"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Ääni: saksa"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Ääni: englanti"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Ääni: espanja"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Ääni: ranska"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"italia (ääni)"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Ääni: japani"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Ääni: korea"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"hollanti (ääni)"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Ääni: puola"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Ääni: portugali"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Ääni: venäjä"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Ääni: turkki"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Ääni: kiina, yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Ääni: mandariinikiina"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Ääni: isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"englanti (Iso-Britannia)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"englanti (Yhdysvallat)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"englanti (Iso-Britannia) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"englanti (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Ei kieltä"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Ei kieltä (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Ei kieltä (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Ei kieltä (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Ei kieltä (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Ei kieltä (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Ei kieltä (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Muokatut syöttötyylit"</string>
+ <string name="add_style" msgid="6163126614514489951">"Lisää tyyli"</string>
+ <string name="add" msgid="8299699805688017798">"Lisää"</string>
+ <string name="remove" msgid="4486081658752944606">"Poista"</string>
+ <string name="save" msgid="7646738597196767214">"Tallenna"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Kieli"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Asettelu"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Ota muokattu syötetyyli käyttöön käyttääksesi sitä."</string>
+ <string name="enable" msgid="5031294444630523247">"Käyttöön"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ei nyt"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sama tulotyyli on jo olemassa: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Käytettävyystutkimustila"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Näppäimenpainalluksen värinän kestoasetukset"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Näppäimenpainalluksen äänenvoimakkuusasetukset"</string>
</resources>
diff --git a/java/res/values-fr/donottranslate-altchars.xml b/java/res/values-fr/donottranslate-altchars.xml
deleted file mode 100644
index ae9292f91..000000000
--- a/java/res/values-fr/donottranslate-altchars.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">à,â,1,æ,á,ä,ã,å,ā,ª</string>
- <string name="alternates_for_e">é,è,ê,ë,3,ę,ė,ē</string>
- <string name="alternates_for_i">î,8,ï,ì,í,į,ī</string>
- <string name="alternates_for_o">ô,œ,9,ö,ò,ó,õ,ø,ō,º</string>
- <string name="alternates_for_u">ù,û,7,ü,ú,ū</string>
- <string name="alternates_for_c">ç,ć,č</string>
- <string name="alternates_for_y">6,ÿ</string>
- <string name="alternates_for_q"></string>
- <string name="alternates_for_w"></string>
- <string name="alternates_for_z">2</string>
-</resources>
diff --git a/java/res/values-fr/donottranslate.xml b/java/res/values-fr/donottranslate.xml
index 09c37e31a..8cf2516a6 100644
--- a/java/res/values-fr/donottranslate.xml
+++ b/java/res/values-fr/donottranslate.xml
@@ -19,11 +19,11 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Symbols that should be swapped with a magic space -->
- <string name="magic_space_swapping_symbols">.,\u0022)]}</string>
+ <string name="weak_space_swapping_symbols">.,\")]}</string>
<!-- Symbols that should strip a magic space -->
- <string name="magic_space_stripping_symbols">\u0009\u0020\u0027\n-/_</string>
+ <string name="weak_space_stripping_symbols">"&#x0009;&#x0020;\'\n-/_"</string>
<!-- Symbols that should promote magic spaces into real space -->
- <string name="magic_space_promoting_symbols">;:!?([*&amp;@{&lt;&gt;+=|</string>
+ <string name="phantom_space_promoting_symbols">;:!?([*&amp;@{&lt;&gt;+=|</string>
<!-- Symbols that do NOT separate words -->
- <string name="non_word_separator_symbols">\u0027</string>
+ <string name="symbols_excluded_from_word_separators">\'</string>
</resources>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index daf14b32a..1094c4ac3 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -21,61 +21,69 @@
<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="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Clavier Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Paramètres du clavier Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Correcteur orthographique Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Correcteur orthographique Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Paramètre du correcteur orthographique"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Suggestions basées sur les mots précédents"</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="5193513161106637254">"Options destinées aux utilisateurs expérimenté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="suppress_language_switch_key" msgid="8003788410354806368">"Suppr. touche sélect. langue"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Masquer touche agrandie"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sans délai"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Proposer noms de contacts"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utiliser des noms de contacts pour les suggestions et corrections"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Activer la recorrection"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Définir des suggestions de recorrection"</string>
<string name="auto_cap" msgid="1719746674854628252">"Majuscules auto"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configurer les dictionnaires"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Corrections rapides"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige les fautes de frappe courantes"</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">"Afficher les 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="3551821800439659812">"Afficher en mode Portrait"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Toujours masquer"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Barre espace pour changer langue"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Afficher touche param."</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatique"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Toujours afficher"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Toujours masquer"</string>
<string name="auto_correction" msgid="4979925752001319458">"Correction automatique"</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_aggeressive" msgid="3524029103734923819">"Proactive"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Très exigeante"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Suggestions de type bigramme"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Améliorer la suggestion en fonction du mot précédent"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Prédiction bigramme"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Suggestions pour le mot suivant"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Améliorer les suggestions grâce au mot précédent"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Prédiction du mot suivant"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Utiliser le mot précédent pour la prédiction"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Plus"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Touche Maj activée"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Verrouillage des majuscules activé"</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>
@@ -86,103 +94,59 @@
<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">"Entrée"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Virgule"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Point"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parenthèse gauche"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parenthèse droite"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Deux-points"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Point-virgule"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Point d\'exclamation"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Point d\'interrogation"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Guillemets doubles"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Apostrophe"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Rechercher"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Point"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Racine carrée"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marque commerciale"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"à l\'attention de"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Étoile"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Dièse"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipse"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Guillemets bas doubles"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Saisie vocale"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"La saisie vocale n\'est pas encore prise en charge pour votre langue, mais elle fonctionne en anglais."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"La saisie vocale fait appel à la reconnaissance vocale de Google. Les "<a href="http://m.google.com/privacy">"Règles de confidentialité Google Mobile"</a>" s\'appliquent."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Pour désactiver la saisie vocale, accédez aux paramètres du mode de saisie."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Pour utiliser la saisie vocale, appuyez sur la touche du microphone."</string>
- <string name="voice_listening" msgid="467518160751321844">"Parlez maintenant"</string>
- <string name="voice_working" msgid="6666937792815731889">"Traitement en cours"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Erreur. Veuillez réessayer."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Connexion impossible"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Erreur, discours trop long."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problème audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Erreur serveur"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Aucune requête vocale détectée"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Aucune correspondance n\'a été trouvée."</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Recherche vocale non installée"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Astuce :"</b>" Faites glisser votre doigt sur le clavier pour parler."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Astuce :"</b>" La prochaine fois, essayez de prononcer la ponctuation, en énonçant des termes tels que \"point\", \"virgule\" ou \"point d\'interrogation\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Annuler"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Saisie vocale"</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="voice_input" msgid="3583258583521397548">"Touche de saisie vocale"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sur 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 clavier symboles"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Sélectionner un mode de saisie."</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="language_selection_summary" msgid="187110938289512256">"Faites glisser votre doigt sur la barre d\'espacement pour changer la langue."</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Appuyer de nouveau pour enregistrer"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Noter heure dans journal"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Heure enregistrée."</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ne pas enregistrer session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Suppr. journal session…"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Journal session supprimé."</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Journal session PAS suppr."</string>
+ <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Autoriser les commentaires des utilisateurs"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Contribuer à l\'amélioration de cet éditeur du mode de saisie grâce à l\'envoi automatique de statistiques d\'utilisation et de rapports d\'incident à Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Appuyer pour corriger"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Appuyer sur les mots saisis pour les corriger, uniquement lorsque des suggestions sont visibles"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Clavier tchèque"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Clavier arabe"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Clavier danois"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Clavier allemand"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Clavier QWERTY allemand"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Clavier anglais (Royaume-Uni)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Clavier anglais (États-Unis)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Clavier espagnol"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Clavier finnois"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Clavier français"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Clavier français (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Clavier français (Suisse)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Clavier croate"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Clavier hongrois"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Clavier hébreu"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Clavier italien"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Clavier norvégien"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Clavier néerlandais"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Clavier polonais"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Clavier portugais"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Clavier russe"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Clavier serbe"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Clavier suédois"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Clavier turc"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voix parlant afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voix tchèque"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voix allemande"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voix parlant anglais"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voix espagnole"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voix française"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voix parlant italien"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voix japonaise"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voix coréenne"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voix parlant néerlandais"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voix polonaise"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voix portugaise"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voix russe"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voix turque"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voix parlant chinois (cantonais)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voix parlant chinois (mandarin)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voix parlant zoulou"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (Royaume-Uni)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (É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_no_language" msgid="141420857808801746">"Aucune langue"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Pas de langue (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Aucune langue (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Aucune langue (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Aucune langue (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Aucune langue (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Aucune langue (PC)"</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">"Clavier"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Durée de vibration à chaque pression"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volume sonore à chaque pression"</string>
</resources>
diff --git a/java/res/values-hdpi/config.xml b/java/res/values-hdpi/config.xml
index 7333e9449..4cf3562fe 100644
--- a/java/res/values-hdpi/config.xml
+++ b/java/res/values-hdpi/config.xml
@@ -19,6 +19,12 @@
-->
<resources>
- <!-- Screen metrics for logging. 0 = "mdpi", 1 = "hdpi", 2 = "xlarge" -->
+ <!-- Screen metrics for logging.
+ 0 = "mdpi phone screen"
+ 1 = "hdpi phone screen"
+ 2 = "mdpi 11 inch tablet screen"
+ 3 = "xhdpi phone screen?"
+ 4 = ?
+ -->
<integer name="log_screen_metrics">1</integer>
</resources>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 9bcca1de5..c131e1278 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -21,61 +21,69 @@
<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">"Android कीबोर्ड"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android कीबोर्ड (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android कीबोर्ड सेटिंग"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्‍प"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"लॉग आदेशों का शोध करें"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android वर्तनी परीक्षक"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android वर्तनी परीक्षक (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"वर्तनी जांच सेटिंग"</string>
+ <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="ngram_category" msgid="5337109164339320257">"पिछले शब्दों के आधार पर सुझाव"</string>
<string name="misc_category" msgid="6894192814868233453">"अन्य विकल्प"</string>
<string name="advanced_settings" msgid="362895144495591463">"उन्नत सेटिंग"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"विशेषज्ञ उपयोगकर्ताओं के लिए विकल्‍प"</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="suppress_language_switch_key" msgid="8003788410354806368">"भाषा स्‍विच कुंजी रोकें"</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="use_contacts_dict" msgid="4435317977804180815">"संपर्क नाम सुझाएं"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"सुझाव और सुधार के लिए संपर्क से नामों का उपयोग करें"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"पुन: सुधार सक्षम करें"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"पुन: सुधार के लि‍ए सुझाव सेट करें"</string>
<string name="auto_cap" msgid="1719746674854628252">"स्‍वत: अक्षर बड़े करना"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"शब्दकोशों को कॉन्फ़िगर करें"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"त्‍वरित सुधार"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"लिखे जाने पर सामान्य गलतियों को सही करता है"</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="3551821800439659812">"र्पोट्रेट मोड पर प्रदर्शित करें"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"हमेशा छुपाएं"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"spacebar भाषा स्विचर का उपयोग करें"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"सेटिंग कुंजी प्रदर्शित करता है"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"स्वत:"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"हमेशा दिखाएं"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"हमेशा छुपाएं"</string>
<string name="auto_correction" msgid="4979925752001319458">"स्‍वत: सुधार"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Spacebar और विराम चिह्न गलत लिखे गए शब्‍दों को स्‍वचालित रूप से ठीक करते हैं"</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_aggeressive" msgid="3524029103734923819">"तीव्र"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"बहुत तीव्र"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"बाइग्राम सुझाव"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"सुझाव को सुधारने के लिए पिछले शब्‍द का उपयोग करें"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"बाइग्राम पूर्वानुमान"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"अगला शब्‍द सुझाव"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"सुझावों को बेहतर बनाने के लिए पिछले शब्‍द का उपयोग करें"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"अगला शब्‍द पूर्वानुमान"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"पूर्वानुमान के लिए पिछले शब्द का उपयोग करें"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"अधिक"</string>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"कखग"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?१२३"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"१२३"</string>
<string name="label_pause_key" msgid="181098308428035340">"रोकें"</string>
<string name="label_wait_key" msgid="6402152600878093134">"प्रतीक्षा करें"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"ज़ोर से बोली गई पासवर्ड कुंजियां सुनने के लिए हेडसेट प्‍लग इन करें."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"वर्तमान पाठ %s है"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"कोई पाठ दर्ज नहीं किया गया"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"कुंजी कोड %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"शिफ़्ट"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"शिफ़्ट सक्षम किया गया है"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"कैप्स लॉक सक्षम किया गया है"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"अल्पविराम"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"पूर्णविराम"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"बायां कोष्ठक"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"दायां कोष्ठक"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"अपूर्ण विराम"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"अर्द्धविराम"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"विस्मयादिबोधक चिह्न"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"प्रश्नचिह्न"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"दोहरा उद्धरण"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"एकल उद्धरण"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"खोजें"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"बिंदु"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"वर्गमूल"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"पाइ"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"डेल्टा"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"ट्रेडमार्क"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"संरक्षक"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"तारा"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"पाउंड"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"पदलोप चिह्न"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"निम्न दोहरा उद्धरण"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"ध्‍वनि इनपुट"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"ध्‍वनि इनपुट आपकी भाषा के लिए अभी समर्थित नहीं है, पर अंग्रेज़ी में कार्य करता है."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"ध्‍वनि इनपुट Google की वाक् पहचान का उपयोग करता है. "<a href="http://m.google.com/privacy">"मोबाइल गोपनीयता नीति"</a>" लागू होती है."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"ध्‍वनि इनपुट बंद करने के लिए, इनपुट पद्धति सेटिंग पर जाएं."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"ध्‍वनि इनपुट का उपयोग करने के लिए, माइक्रोफ़ोन बटन दबाएं."</string>
- <string name="voice_listening" msgid="467518160751321844">"अब बोलें"</string>
- <string name="voice_working" msgid="6666937792815731889">"कार्य कर रहा है"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"त्रुटि. कृपया पुन: प्रयास करें."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"कनेक्‍ट नहीं कर सका"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"त्रुटि, बहुत अधिक बातचीत."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"ऑडियो समस्या"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"सर्वर त्रुटि"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"कोई बातचीत नहीं सुनाई दी"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"कोई मिलान नहीं मिले"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"ध्‍वनि खोज इंस्टॉल नहीं है"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"संकेत:"</b>" बोलने के लिए कीबोर्ड पर स्‍वाइप करें"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"संकेत:"</b>" अगली बार, विरामचिन्‍ह बोलने का प्रयास करें जैसे \"पूर्णविराम\", \"अल्‍पविराम\", या \"प्रश्‍नचिह्न\"."</string>
- <string name="cancel" msgid="6830980399865683324">"रद्द करें"</string>
- <string name="ok" msgid="7898366843681727667">"ठीक"</string>
- <string name="voice_input" msgid="2466640768843347841">"ध्‍वनि इनपुट"</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="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="selectInputMethod" msgid="315076553378705821">"इनपुट विधि का चयन करें"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"इनपुट पद्धति कॉन्‍फ़िगर करें"</string>
<string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषा"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"भाषा बदलने के लिए अंगुली को spacebar पर स्लाइड करें"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← सहेजने के लिए फिर से स्‍पर्श करें"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"लॉग में टाइमस्‍टैम्‍प नोट करें"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"रिकॉर्ड किया गया टाइमस्टैम्प"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"इस सत्र को लॉग न करें"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"सत्र लॉग हटाया जा रहा है"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"सत्र लॉग हटाया गया"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"सत्र लॉग हटाया नहीं गया"</string>
+ <string name="select_language" msgid="3693815588777926848">"इनपुट भाषाएं"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"सहेजने के लिए पुन: स्‍पर्श करें"</string>
<string name="has_dictionary" msgid="6071847973466625007">"शब्‍दकोश उपलब्‍ध है"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"उपयोगकर्ता फ़ीडबैक सक्षम करें"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"उपयोग के आंकड़े और क्रैश रिपोर्ट Google को स्वचालित रूप से भेज कर इस इनपुट पद्धति संपादक को बेहतर बनाने में सहायता करें."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"सही शब्‍दों को स्‍पर्श करें"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"दर्ज किए गए शब्‍दों को सही करने के लिए उन्‍हें स्‍पर्श करें, केवल तब जब सुझाव दिखाई दें"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"चेक कीबोर्ड"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"अरबी कीबोर्ड"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"डैनिश कीबोर्ड"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"जर्मन कीबोर्ड"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"जर्मन QWERTY कीबोर्ड"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"अंग्रेज़ी (यूके) कीबोर्ड"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"अंग्रेज़ी (यूएस) कीबोर्ड"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"स्‍पेनिश कीबोर्ड"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"फ़िनिश कीबोर्ड"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"फ्रांसीसी कीबोर्ड"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"फ़्रांसीसी (कनाडा) कीबोर्ड"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"फ़्रांसीसी (स्‍विट्ज़रलैंड) कीबोर्ड"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"क्रोएशियाई कीबोर्ड"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"हंगेरियाई कीबोर्ड"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"हिब्रू कीबोर्ड"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"इतालवी कीबोर्ड"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"नॉरवेजियन कीबोर्ड"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"डच कीबोर्ड"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"पोलिश कीबोर्ड"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"पुर्तगाली कीबोर्ड"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"रूसी कीबोर्ड"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"साइबेरियाई कीबोर्ड"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"स्‍वीडिश कीबोर्ड"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"तुर्की कीबोर्ड"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"अफ़्रीकी ध्‍वनि"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"चेक ध्‍वनि"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"जर्मन ध्‍वनि"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"अंग्रेज़ी ध्‍वनि"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"स्‍पेनिश ध्‍वनि"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"फ्रांसीसी ध्‍वनि"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"इतालवी ध्‍वनि"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"जापानी ध्‍वनि"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"कोरियाई ध्‍वनि"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"डच ध्‍वनि"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"पोलिश ध्‍वनि"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"पुर्तगाली ध्‍वनि"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"रूसी ध्‍वनि"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"तुर्की ध्‍वनि"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"चीनी, यू ध्‍वनि"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"चीनी, मंदारिन ध्‍वनि"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"ज़ूलू ध्‍वनि"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेज़ी (यूके)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेज़ी (यूएस)"</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_no_language" msgid="141420857808801746">"कोई भाषा नहीं"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"कोई भाषा नहीं (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"कोई भाषा नहीं (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"कोई भाषा नहीं (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"कोई भाषा नहीं (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"कोई भाषा नहीं (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"कोई भाषा नहीं (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"कुंजी-स्‍पर्श कंपन अवधि सेटिंग"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"कुंजी-स्‍पर्श ध्‍वनि वॉल्‍यूम सेटिंग"</string>
</resources>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 1516f8cdf..f8a198df2 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -21,61 +21,69 @@
<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">"Android tipkovnica"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tipkovnica (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Postavke tipkovnice za Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Istraživanje naredbi dnevnika"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidova provjera pravopisa"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidova provjera pravopisa (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Postavke provjere pravopisa"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Potražite imena kontakata"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Provjera pravopisa upotrebljava unose iz vašeg popisa kontakata"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibracija pri pritisku na tipku"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri pritisku tipke"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Povećanja na pritisak tipke"</string>
<string name="general_category" msgid="1859088467017573195">"Općenito"</string>
<string name="correction_category" msgid="2236750915056607613">"Ispravak teksta"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Prijedlozi na temelju prethodnih riječi"</string>
<string name="misc_category" msgid="6894192814868233453">"Ostale opcije"</string>
<string name="advanced_settings" msgid="362895144495591463">"Napredne postavke"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcije za stručne korisnike"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcije za stručnjake"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prebaci na druge unose"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tipka za prebacivanje jezika pokriva i druge načine unosa"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Spriječi tipku za jezike"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Odgoda prikaza tipki"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez odgode"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Zadano"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Predlaži imena kontakata"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Upotreba imena iz Kontakata za prijedloge i ispravke"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Omogući ponovne ispravke"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Postavite prijedloge za ponovne ispravke"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatsko pisanje velikih slova"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfiguracija rječnika"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Brzi popravci"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Ispravlja uobičajene pogreške u pisanju"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Rječnici-dodaci"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Glavni rječnik"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Pokaži prijedloge ispravka"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Prikazivanje predloženih riječi prilikom upisivanja"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Uvijek prikaži"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Prikaži u portretnom načinu"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Uvijek sakrij"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Razmaknica za jezike"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Prikaži tipku postavki"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatski"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Uvijek prikaži"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Uvijek sakrij"</string>
<string name="auto_correction" msgid="4979925752001319458">"Samoispravak"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Razmak i interpunkcija automatski ispravljaju krive riječi"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Isključeno"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Skromno"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivno"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Vrlo agresivno"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram prijedlozi"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Upotrijebi prethodnu riječ radi poboljšanja prijedloga"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram predviđanje"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Prijedlozi za sljedeću riječ"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Upotrijebi prethodnu riječ radi poboljšanja prijedloga"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Predviđanje sljedeće riječi"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Upotrijebite prethodnu riječ i za predviđanje"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Više"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift je omogućen"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock omogućen"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Uključena tipka Shift (dotaknite da onemogućite)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Uključeno je pisanje velikim slovima (Caps Lock) (dotaknite da onemogućite)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Slova"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Glasovni unos"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smješko"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Zarez"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Točka"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Lijeva zagrada"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Desna zagrada"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dvotočka"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Točka-zarez"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uskličnik"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Upitnik"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dvostruki navodnici"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Jednostruki navodnici"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Pretraživanje"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Točka"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratni korijen"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Zaštitni znak"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"U ruke"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Zvjezdica"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"funta"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tri točke"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Donji dvostruki navodnici"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Glasovni ulaz"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Vaš jezik trenutno nije podržan za glasovni unos, ali radi za engleski."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Glasovni unos upotrebljava Googleovo prepoznavanje govora. Primjenjuju se "<a href="http://m.google.com/privacy">"Pravila o privatnosti za uslugu Mobile"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Za isključivanje glasovnog unosa idite na postavke načina unosa."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Za upotrebu glasovnog unosa pritisnite gumb mikrofona."</string>
- <string name="voice_listening" msgid="467518160751321844">"Govorite sad"</string>
- <string name="voice_working" msgid="6666937792815731889">"Obrada"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Pogreška. Pokušajte ponovo."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Spajanje nije bilo moguće"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Pogreška, predugi govor."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problem sa zvukom"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Pogreška na poslužitelju"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nije se čuo govor"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nisu pronađeni rezultati"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Glasovno pretraživanje nije instalirano"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Savjet:"</b>" Prijeđite preko tipkovnice pa govorite"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Savjet:"</b>" Sljedeći put pokušajte izgovoriti znakove interpunkcije poput \"točka, \"zarez\" ili \"upitnik\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Odustani"</string>
- <string name="ok" msgid="7898366843681727667">"U redu"</string>
- <string name="voice_input" msgid="2466640768843347841">"Glasovni ulaz"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Omogućena tipka Shift"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Omogućeno pisanje velikih slova"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Onemogućena tipka Shift"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Način unosa simbola"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Način pisanja slova"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonski način rada"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Način unosa telefonskih simbola"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tipka za glasovni unos"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavnoj tipkovnici"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipkovnici simb."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Isključeno"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na gl. tipkovnici"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. simb."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. unos onemog."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Odabir ulazne metode"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Kliznite prstom po razmaknici za promjenu jezika"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Dodirnite opet za spremanje"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Zabilježi razdoblje u dnevniku"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zabilježeno razdoblje"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ne bilježi ovu sesiju"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Brisanje dnevnika sesije"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Izbrisan dnevnik sesije"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Dnevnik sesije NIJE izbrisan"</string>
+ <string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dodirnite ponovo za spremanje"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Omogući korisničke povratne informacije"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Pomozite u poboljšanju ovog urednika ulazne metode automatskim slanjem statistike upotrebe i padova Googleu."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Dodirnite za ispravak riječi"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Dodirnite unesene riječi da biste ih ispravili samo kada su prijedlozi vidljivi"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Češka tipkovnica"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arapska tipkovnica"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Danska tipkovnica"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Njemačka tipkovnica"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Njemačka QWERTY tipkovnica"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Engleska (UK) tipkovnica"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Engleska (SAD) tipkovnica"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Španjolska tipkovnica"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finska tipkovnica"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Francuska tipkovnica"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Francuska (Kanada) tipkovnica"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Francuska (Švicarska) tipkovnica"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Hrvatska tipkovnica"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Mađarska tipkovnica"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebrejska tipkovnica"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Talijanska tipkovnica"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norveška tipkovnica"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Nizozemska tipkovnica"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Poljska tipkovnica"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugalska tipkovnica"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Ruska tipkovnica"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Srpska tipkovnica"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Švedska tipkovnica"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turska tipkovnica"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"afrikaans glasovno"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Češki glasovni"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Njemački glasovni"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"engleski glasovno"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Španjolski glas"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Francuski glas"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Talijanski glas"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japanski glas"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Korejski glas"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Nizozemski glas"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Poljski glas"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugalski glas"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Ruski glas"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Turski glas"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"kineski, Yue glasovno"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"kineski, mandarinski glasovno"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu glasovno"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engleski (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engleski (SAD)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"engleski (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"engleski (SAD) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Nema jezika"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nema jezika (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nema jezika (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nema jezika (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nema jezika (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nema jezika (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nema jezika (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Prilagođeni stilovi unosa"</string>
+ <string name="add_style" msgid="6163126614514489951">"Dodaj stil"</string>
+ <string name="add" msgid="8299699805688017798">"Dodaj"</string>
+ <string name="remove" msgid="4486081658752944606">"Ukloni"</string>
+ <string name="save" msgid="7646738597196767214">"Spremi"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Jezik"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Izgled"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Prilagođeni stil unosa mora biti omogućen. Omogućiti sada?"</string>
+ <string name="enable" msgid="5031294444630523247">"Omogući"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ne sada"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Već postoji isti stil unosa: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način studije upotrebljivosti"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Postavke trajanja vibracije kod pritiska tipke"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Postavke glasnoće zvuka kod pritiska tipke"</string>
</resources>
diff --git a/java/res/values-hu/donottranslate-altchars.xml b/java/res/values-hu/donottranslate-altchars.xml
deleted file mode 100644
index ae28cc5b8..000000000
--- a/java/res/values-hu/donottranslate-altchars.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">á,à,â,ä,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,é,è,ê,ë,ę,ė,ē</string>
- <string name="alternates_for_i">8,í,î,ï,ì,į,ī</string>
- <string name="alternates_for_o">9,ó,ö,ő,ô,ò,õ,œ,ø,ō</string>
- <string name="alternates_for_u">7,ú,ü,ű,û,ù,ū</string>
- <string name="alternates_for_y"></string>
- <string name="alternates_for_z">6</string>
-</resources>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 563857a82..fc1ac1227 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -21,61 +21,69 @@
<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">"Android-billentyűzet"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-billentyűzet (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android billentyűzetbeállítások"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beállítások"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Naplózási parancsok"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidos helyesírás-ellenőrző"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidos helyesírás-ellenőrző (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Helyesírás-ellenőrzés beállításai"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"A helyesírás-ellenőrző használja a névjegyek bejegyzéseit"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés billentyű megnyomása esetén"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Hangjelzés billentyű megnyomása esetén"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Legyen nagyobb billentyű lenyomásakor"</string>
<string name="general_category" msgid="1859088467017573195">"Általános"</string>
<string name="correction_category" msgid="2236750915056607613">"Szövegjavítás"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Javaslatok korábbi szavak alapján"</string>
<string name="misc_category" msgid="6894192814868233453">"Egyéb beállítások"</string>
<string name="advanced_settings" msgid="362895144495591463">"Speciális beállítások"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Beállítások gyakorlott felhasználóknak"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Beállítások gyakorlott felhasználóknak"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Váltás más beviteli módra"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A nyelvkapcsoló gomb egyéb beviteli módokat is tartalmaz"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"A nyelvkapcsoló elrejtése"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Gombeltüntetés késése"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nincs késés"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Alapbeállítás"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Javasolt névjegyek"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"A névjegyek használata a javaslatokhoz és javításokhoz"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Újbóli javítás engedélyezése"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Javaslatok beállítása az újbóli javításokhoz"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatikusan nagy kezdőbetű"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Szótárak konfigurálása"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Gyorsjavítások"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Kijavítja a gyakori gépelési hibákat"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Bővítmények: szótárak"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Fő szótár"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Javítási ajánlások megjelenítése"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"A javasolt szavak megjelenítése gépelés közben"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mindig látszik"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Megjelenítés álló tájolásban"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Mindig rejtve"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Nyelvváltás: szóköz"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Beállítások billentyű megjelenítése"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatikus"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mindig látszik"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Mindig rejtve"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automatikus javítás"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Szóköz és központozás automatikusan javítja az elgépelést"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Ki"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mérsékelt"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresszív"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Nagyon agresszív"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram javaslatok"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Előző szó használata a javaslatok javításához"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram előrejelzés"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Következő szóra vonatkozó javaslatok"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Javaslatok fejlesztése az előző szó használatával"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Következő szó előrejelzése"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Az előző szó használata a prediktív bevitelhez is"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Egyebek"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift engedélyezve"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock bekapcsolva"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift be van kapcsolva (érintse meg a kikapcsoláshoz)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock be van kapcsolva (érintse meg a kikapcsoláshoz)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Törlés"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Szimbólumok"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Betűk"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Hangbevitel"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Mosolygós arc"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Vessző"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Pont"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Nyitó zárójel"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Berekesztő zárójel"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Kettőspont"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Pontosvessző"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Felkiáltójel"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Kérdőjel"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dupla idézőjel"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Szimpla idézőjel"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Keresés"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Pont"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Négyzetgyök"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Védjegy"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Százalék"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Csillag"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Kettős kereszt"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Kihagyás"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Alsó dupla idézőjel"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Hangbevitel"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"A hangbevitel szolgáltatás jelenleg nem támogatja az Ön nyelvét, ám angolul működik."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"A hangbevitel a Google beszédfelismerő technológiáját használja, amelyre a "<a href="http://m.google.com/privacy">"Mobil adatvédelmi irányelvek"</a>" érvényesek."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"A hangbevitelt a beviteli mód beállításai között lehet kikapcsolni."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"A hangbevitel használatához nyomja meg a mikrofon gombot."</string>
- <string name="voice_listening" msgid="467518160751321844">"Most beszéljen"</string>
- <string name="voice_working" msgid="6666937792815731889">"Feldolgozás"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Hiba történt. Kérjük, próbálja újra."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Nem sikerült kapcsolódni"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Hiba történt; túl sokat beszélt."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Hangprobléma"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Szerverhiba"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nem hallatszott beszéd"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nem található egyezés"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"A hangalapú keresés nincs telepítve"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tipp:"</b>" húzza végig az ujját a billentyűzeten a beszédhez"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tipp:"</b>" következő alkalommal próbálja ki az írásjelek kimondását is, pl. \"period\", \"comma\" vagy \"question mark\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Mégse"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Hangbevitel"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift bekapcsolva"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock bekapcsolva"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift kikapcsolva"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"\"Szimbólumok\" mód"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"\"Betű\" mód"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"\"Telefon\" mód"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"\"Telefonos szimbólumok\" mód"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Hangbeviteli gomb"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"A fő billentyűzeten"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Szimbólumoknál"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Ki"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. a billentyűzeten"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. a szimbólumoknál"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hangbevivel KI"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Beviteli mód kiválasztása"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"A nyelv módosításához húzza végig az ujját a szóköz billentyűn"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Érintse meg újra a mentéshez"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Időbélyegző naplózáskor"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Rögzített időbélyegzők"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ne naplózza"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Napló törlése folyamatban"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Napló törölve"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Napló NINCS törölve"</string>
+ <string name="select_language" msgid="3693815588777926848">"Beviteli nyelvek"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Érintse meg újból a mentéshez"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Van elérhető szótár"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Felhasználói visszajelzés engedélyezése"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Segíthet ennek a beviteli módszernek a javításában, ha engedélyezi a használati statisztikák és a hibajelentések elküldését a Google-nak."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Javítás a szavak megérintésével"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"A beírt szavakat csak akkor javíthatja ki megérintve, ha látszanak javaslatok"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Billentyűzettéma"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Cseh billentyűzet"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"arab billentyűzetkiosztás"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Dán billentyűzet"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Német billentyűzet"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"német billentyűzetkiosztás (QWERTY)"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Angol (UK) billentyűzet"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Angol (US) billentyűzet"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spanyol billentyűzet"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"finn billentyűzetkiosztás"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Francia billentyűzet"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Francia (kanadai) billentyűzet"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Francia (svájci) billentyűzet"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"horvát billentyűzetkiosztás"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"magyar billentyűzetkiosztás"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"héber billentyűzetkiosztás"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Olasz billentyűzet"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norvég billentyűzet"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Holland billentyűzet"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"lengyel billentyűzetkiosztás"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"portugál billentyűzetkiosztás"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Orosz billentyűzet"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Szerb billentyűzet"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Svéd billentyűzet"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"török billentyűzetkiosztás"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaans hang"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Cseh hang"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Német hang"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Angol hang"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spanyol hang"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Francia hang"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Olasz hang"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japán hang"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Koreai hang"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Holland hang"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Lengyel hang"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugál hang"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Orosz hang"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Török hang"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Kínai (jüe) hang"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Kínai (mandarin) hang"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu hang"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"angol (brit)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"angol (amerikai)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"angol (brit) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"angol (amerikai) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Nincs nyelv"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nincs nyelv (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nincs nyelv (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nincs nyelv (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nincs nyelv (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nincs nyelv (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nincs nyelv (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Egyedi bevitelstílusok"</string>
+ <string name="add_style" msgid="6163126614514489951">"Új stílus"</string>
+ <string name="add" msgid="8299699805688017798">"Hozzáadás"</string>
+ <string name="remove" msgid="4486081658752944606">"Eltávolítás"</string>
+ <string name="save" msgid="7646738597196767214">"Mentés"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Nyelv"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Elrendezés"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Az egyéni stílust először engedélyezni kell. Engedélyezi most?"</string>
+ <string name="enable" msgid="5031294444630523247">"Engedélyezés"</string>
+ <string name="not_now" msgid="6172462888202790482">"Most nem"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ugyanez a bemenetstílus már létezik: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Használhatósági teszt"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Gombnyomás rezgési időtartamának beállításai"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Gombnyomás hangerejének beállításai"</string>
</resources>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 94ea9b47e..a7a2c0383 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -21,61 +21,69 @@
<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">"Keyboard Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Keyboard Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Setelan keyboard Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Riset Perintah Log"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Pemeriksa ejaan Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pemeriksa ejaan Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Setelan pemeriksaan ejaan"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kontak"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pemeriksa ejaan menggunakan entri dari daftar kontak Anda"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar jika tombol ditekan"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Berbunyi jika tombol ditekan"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Muncul saat tombol ditekan"</string>
<string name="general_category" msgid="1859088467017573195">"Umum"</string>
<string name="correction_category" msgid="2236750915056607613">"Koreksi teks"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Saran berdasarkan kata sebelumnya"</string>
<string name="misc_category" msgid="6894192814868233453">"Opsi lain"</string>
<string name="advanced_settings" msgid="362895144495591463">"Setelan lanjutan"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Pilihan untuk pengguna ahli"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opsi untuk ahli"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Beralih ke metode masukan lain"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tombol beralih bahasa juga mencakup metode masukan lain"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Redam tombol alih bahasa"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tundaan singkir munculan kunci"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tanpa penundaan"</string>
- <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Bawaan"</string>
- <string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kenalan"</string>
- <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kenalan untuk saran dan koreksi"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kontak"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kontak untuk saran dan koreksi"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Aktifkan koreksi ulang"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setel saran untuk koreksi ulang"</string>
<string name="auto_cap" msgid="1719746674854628252">"Kapitalisasi otomatis"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurasikan kamus"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Perbaikan cepat"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Memperbaiki kesalahan ketik umum"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Kamus pengaya"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Tampilkan saran koreksi"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Tampilkan kata yang disarankan ketika mengetik"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Selalu tampilkan"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Tampilkan pada mode potret"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Selalu sembunyikan"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Gunakan pengalih bahasa bilah spasi"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Lihat tombol setelan"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Otomatis"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Selalu tampilkan"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Selalu sembunyikan"</string>
<string name="auto_correction" msgid="4979925752001319458">"Koreksi otomatis"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Bilah spasi dan tanda baca secara otomatis dikoreksi pada kata yang salah ketik"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Mati"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Sederhana"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sangat agresif"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Saran bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Gunakan kata sebelumnya untuk meningkatkan sara"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Prediksi bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Saran kata berikutnya"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gunakan kata sebelumnya untuk meningkatkan saran"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Prediksi kata berikutnya"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Gunakan kata sebelumnya juga untuk prediksi"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Lainnya"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift diaktifkan"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock diaktifkan"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aktif (ketuk untuk menonaktifkan)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock aktif (ketuk untuk menonaktifkan)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Hapus"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simbol"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Huruf"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Masukan suara"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Wajah tersenyum"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Kembali"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Titik"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kurung tutup"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Kurung buka"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Titik Dua"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Titik koma"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Tanda seru"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Tanda tanya"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Tanda petik"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Petik tunggal"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Telusuri"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Akar pangkat dua"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Merek dagang"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Dengan alamat"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Bintang"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Pon"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Elipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Tanda petik bawah"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Masukan suara"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Masukan suara saat ini tidak didukung untuk bahasa Anda, tetapi bekerja dalam Bahasa Inggris."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Masukan suara menggunakan pengenalan ucapan Google. "<a href="http://m.google.com/privacy">"Kebijakan Privasi Seluler"</a>" berlaku."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Untuk mematikan masukan suara, buka setelan metode masukan."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Untuk menggunakan masukan suara, tekan tombol mikrofon."</string>
- <string name="voice_listening" msgid="467518160751321844">"Ucapkan sekarang"</string>
- <string name="voice_working" msgid="6666937792815731889">"Bekerja"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Galat: Coba lagi."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Tidak dapat menyambung"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Galat, terlalu banyak ucapan."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Masalah audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Galat server"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Tidak terdengar ucapan"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Tak ditemukan yang cocok"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Penelusuran suara tidak terpasang"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Petunjuk:"</b>" Gesek keyboard untuk berbicara"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Petunjuk:"</b>" Selanjutnya, coba ucapkan tanda baca seperti \"titik\", \"koma\", atau \"tanda tanya\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Batal"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Masukan suara"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift diaktifkan"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock diaktifkan"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift dinonaktifkan"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode simbol"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode huruf"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode telepon"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode simbol telepon"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tombol masukan suara"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pada keyboard utama"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pada keyboard simbol"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Mati"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik pada keyboard utama"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik pada keyboard simbol"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Masukan suara dinonaktifkan"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Pilih metode masukan"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Geser jari pada bilah spasi untuk mengubah bahasa"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Sentuh sekali lagi untuk menyimpan"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Catat cap waktu di log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Cap waktu yang direkam"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Jangan simpan log sesi ini"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Menghapus log sesi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Log sesi dihapus"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Log sesi BELUM dihapus"</string>
+ <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string>
- <string name="prefs_enable_log" msgid="6620424505072963557">"Aktifkan umpan balik pengguna"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktifkan masukan pengguna"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Bantu tingkatkan metode editor masukan dengan mengirim statistik penggunaan dan laporan kerusakan ke Google secara otomatis."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Sentuh untuk memperbaiki kata"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Sentuh kata yang dimasukkan untuk memperbaikinya, hanya saat saran dapat dilihat"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema keyboard"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Keyboard Cheska"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Keyboard Arab"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Keyboard Denmark"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Keyboard Jerman"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Keyboard QWERTY Jerman"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Keyboard Inggris (Britania Raya)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Keyboard Inggris (AS)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Keyboard Spanyol"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Keyboard Suomi"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Keyboard Prancis"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Keyboard Prancis (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Keyboard Prancis (Swiss)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Keyboard Kroat"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Keyboard Magyar"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Keyboard Ibrani"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Keyboard Italia"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Keyboard Norwegia"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Keyboard Belanda"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Keyboard Polski"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Keyboard Portugis"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Keyboard Rusia"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Keyboard Serbia"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Keyboard Swedia"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Keyboard Turki"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Suara Bahasa Afrika"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Suara Bahasa Cheska"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Suara Bahasa Jerman"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Suara Bahasa Inggris"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Suara Bahasa Spanyol"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Suara Bahasa Prancis"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Suara Bahasa Italia"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Suara Bahasa Jepang"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Suara Bahasa Korea"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Suara Bahasa Belanda"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Suara Bahasa Polandia"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Suara Bahasa Portugis"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Suara Bahasa Rusia"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Suara Bahasa Turki"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Suara Bahasa China, Yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Suara Bahasa China, Mandarin"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Suara Zulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Inggris (Inggris)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Inggris (AS)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inggris (Inggris) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inggris (AS) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Tidak ada bahasa"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Tanpa bahasa (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Tanpa bahasa (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Tanpa bahasa (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Tanpa bahasa (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Tanpa bahasa (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Tanpa bahasa (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Gaya masukan khusus"</string>
+ <string name="add_style" msgid="6163126614514489951">"Tambah gaya"</string>
+ <string name="add" msgid="8299699805688017798">"Tambahkan"</string>
+ <string name="remove" msgid="4486081658752944606">"Hapus"</string>
+ <string name="save" msgid="7646738597196767214">"Simpan"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Bahasa"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Tata Letak"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Gaya masukan khusus harus aktif sebelum digunakan. Aktifkan?"</string>
+ <string name="enable" msgid="5031294444630523247">"Aktifkan"</string>
+ <string name="not_now" msgid="6172462888202790482">"Nanti saja"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sudah ada gaya masukan yang sama: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus studi daya guna"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Setelan durasi getaran saat tombol ditekan"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Setelan volume suara saat tombol ditekan"</string>
</resources>
diff --git a/java/res/values-it/donottranslate-altchars.xml b/java/res/values-it/donottranslate-altchars.xml
deleted file mode 100644
index 1131d4852..000000000
--- a/java/res/values-it/donottranslate-altchars.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">à,á,â,ä,æ,ã,å,ā,ª</string>
- <string name="alternates_for_e">3,è,é,ê,ë,ę,ė,ē</string>
- <string name="alternates_for_i">8,ì,í,î,ï,į,ī</string>
- <string name="alternates_for_o">9,ò,ó,ô,ö,õ,œ,ø,ō,º</string>
- <string name="alternates_for_u">7,ù,ú,û,ü,ū</string>
-</resources>
diff --git a/java/res/values-it/donottranslate.xml b/java/res/values-it/donottranslate.xml
index adb2a9a9d..58e94361b 100644
--- a/java/res/values-it/donottranslate.xml
+++ b/java/res/values-it/donottranslate.xml
@@ -19,5 +19,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Symbols that do NOT separate words -->
- <string name="non_word_separator_symbols"></string>
+ <string name="symbols_excluded_from_word_separators"></string>
</resources>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index ca1e7e26d..e77a0d04d 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -21,61 +21,69 @@
<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">"Tastiera Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastiera Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Impostazioni tastiera Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Ricerca comandi di log"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Controllo ortografico Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Controllo ortografico Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Impostazioni di controllo ortografico"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca in nomi contatti"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"La funzione di controllo ortografico usa voci dell\'elenco contatti"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrazione tasti"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Suono tasti"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Popup sui tasti"</string>
<string name="general_category" msgid="1859088467017573195">"Generali"</string>
<string name="correction_category" msgid="2236750915056607613">"Correzione testo"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Suggerimenti in base alle parole precedenti"</string>
<string name="misc_category" msgid="6894192814868233453">"Altre opzioni"</string>
<string name="advanced_settings" msgid="362895144495591463">"Impostazioni avanzate"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opzioni per utenti esperti"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opzioni per esperti"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Altri metodi immissione"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Il tasto per cambiare lingua offre altri metodi di immissione"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Elimina tasto cambio lingua"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ritardo eliminaz. popup tasto"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nessun ritardo"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggerisci nomi di contatti"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizza nomi di Contatti per suggerimenti e correzioni"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Attiva nuove correzioni"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Imposta suggerimenti per nuove correzioni"</string>
<string name="auto_cap" msgid="1719746674854628252">"Maiuscole automatiche"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configura dizionari"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Correzioni veloci"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corregge gli errori di digitazione più comuni"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dizionari aggiuntivi"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Dizionario principale"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostra suggerimenti correzioni"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Visualizza le parole suggerite durante la digitazione"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostra sempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostra in modalità verticale"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Nascondi sempre"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Selezione lingua da barra spaziatrice"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Mostra tasto impostazioni"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatico"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mostra sempre"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Nascondi sempre"</string>
<string name="auto_correction" msgid="4979925752001319458">"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_modest" msgid="8788366690620799097">"Media"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Massima"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Massima"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Suggerimenti sui bigrammi"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utilizza parola precedente per migliorare il suggerimento"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Previsione bigramma"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Suggerimenti parola successiva"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usa parola precedente per migliorare suggerimenti"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Previsione parola successiva"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Usa anche la parola precedente per la previsione"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Altro"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Maiuscolo attivo"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Blocco maiuscole attivo"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Maiuscolo attivo (tocca per disattivare)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Blocco maiuscole attivo (tocca per disattivare)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Cancella"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Lettere"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Input vocale"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smile"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Invio"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Virgola"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punto"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parentesi aperta"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parentesi chiusa"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Due punti"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Punto e virgola"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Punto esclamativo"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Punto interrogativo"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Virgolette doppie"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Virgolette semplici"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Cerca"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Pallino"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Radice quadrata"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi greco"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marchio commerciale"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Presso"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Asterisco"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Cancelletto"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellissi"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Virgolette doppie basse"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Comandi vocali"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"I comandi vocali non sono attualmente supportati per la tua lingua ma funzionano in inglese."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"L\'input vocale utilizza il riconoscimento vocale di Google. Sono valide le "<a href="http://m.google.com/privacy">"norme sulla privacy di Google Mobile"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Per disattivare l\'input vocale, vai alle impostazioni del metodo di input."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Per utilizzare l\'input vocale, premi il pulsante del microfono."</string>
- <string name="voice_listening" msgid="467518160751321844">"Parla ora"</string>
- <string name="voice_working" msgid="6666937792815731889">"Elaborazione..."</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Errore. Riprova più tardi."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Impossibile connettersi."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Errore: conversazione troppo lunga."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Errore del server"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nessuna frase vocale rilevata"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nessuna corrispondenza trovata"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Ricerca vocale non installata"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Suggerimento."</b>" Fai scorrere il dito sulla tastiera per parlare"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Suggerimento."</b>" La prossima volta, prova a pronunciare termini relativi alla punteggiatura come \"punto\", \"virgola\" o \"punto di domanda\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Annulla"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Comandi vocali"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maiuscolo attivo"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Blocco maiuscole attivo"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Maiuscolo disattivato"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modalità simboli"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modalità lettere"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modalità telefono"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modalità simboli telefono"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tasto immissione 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_summary_main_keyboard" msgid="6586544292900314339">"Mic su tastiera principale"</string>
- <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic su tastiera simboli"</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">"Comandi vocali disatt."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Seleziona metodo di inserimento"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Scorri il dito sulla barra spaziatrice per cambiare la lingua"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tocca di nuovo per salvare"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Indicazione temporale log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Indicazione temporale registrata"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Non registrare la sessione"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Eliminazione log sessione"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Log di sessione eliminato"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Log sessione non eliminato"</string>
+ <string name="select_language" msgid="3693815588777926848">"Lingue comandi"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tocca di nuovo per salvare"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Attiva commenti degli utenti"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Aiuta a migliorare l\'editor del metodo di inserimento inviando automaticamente a Google statistiche sull\'utilizzo e segnalazioni sugli arresti anomali."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tocca per correggere"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Tocca le parole inserite per correggerle, solo quando sono visibili i suggerimenti"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema della tastiera"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tastiera ceca"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Tastiera araba"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Tastiera danese"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Tastiera tedesca"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Tastiera QWERTY tedesca"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Tastiera inglese (Regno Unito)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Tastiera inglese (Stati Uniti)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Tastiera spagnola"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Tastiera finlandese"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Tastiera francese"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Tastiera francese (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Tastiera francese (Svizzera)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Tastiera croata"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Tastiera ungherese"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Tastiera ebraica"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Tastiera italiana"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Tastiera norvegese"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Tastiera olandese"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Tastiera polacca"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Tastiera portoghese"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Tastiera russa"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Tastiera serba"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Tastiera svedese"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Tastiera turca"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voce afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voce ceca"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voce tedesca"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voce inglese"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voce spagnola"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voce francese"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voce italiana"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voce giapponese"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voce coreana"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voce olandese"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voce polacca"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voce portoghese"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voce russa"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voce turca"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voce cinese Yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voce cinese mandarino"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voce isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Inglese (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Inglese (USA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglese (Regno Unito) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglese (Stati Uniti) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Nessuna lingua"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nessuna lingua (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nessuna lingua (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nessuna lingua (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nessuna lingua (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nessuna lingua (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nessuna lingua (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Stili personalizzati"</string>
+ <string name="add_style" msgid="6163126614514489951">"Aggiungi stile"</string>
+ <string name="add" msgid="8299699805688017798">"Aggiungi"</string>
+ <string name="remove" msgid="4486081658752944606">"Rimuovi"</string>
+ <string name="save" msgid="7646738597196767214">"Salva"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Lingua"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Lo stile di ingresso personalizzato deve essere attivato prima dell\'utilizzo. Vuoi attivarlo?"</string>
+ <string name="enable" msgid="5031294444630523247">"Attiva"</string>
+ <string name="not_now" msgid="6172462888202790482">"Non ora"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Esiste già uno stile di inuput uguale: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modalità Studio sull\'usabilità"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Durata vibrazione alla pressione tasto"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volume audio alla pressione di un tasto"</string>
</resources>
diff --git a/java/res/values-iw/donottranslate.xml b/java/res/values-iw/donottranslate.xml
new file mode 100644
index 000000000..57de2538b
--- /dev/null
+++ b/java/res/values-iw/donottranslate.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- The all letters need to be mirrored are found at
+ http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt -->
+ <!-- Symbols that are suggested between words -->
+ <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string>
+</resources>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index cfd677d52..000c9f337 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -21,61 +21,69 @@
<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">"מקלדת Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"מקלדת Android ‏(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"הגדרות מקלדת של Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"אפשרויות קלט"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"פקודות יומן מחקר"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"בודק האיות של Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"בודק האיות של Android ‏(AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"הגדרות בדיקת איות"</string>
+ <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="ngram_category" msgid="5337109164339320257">"הצעות המבוססות על מילים קודמות"</string>
<string name="misc_category" msgid="6894192814868233453">"אפשרויות אחרות"</string>
<string name="advanced_settings" msgid="362895144495591463">"הגדרות מתקדמות"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"אפשרויות עבור משתמשים מתקדמים"</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="suppress_language_switch_key" msgid="8003788410354806368">"הסתר את מתג החלפת השפה"</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="use_contacts_dict" msgid="4435317977804180815">"הצע שמות של אנשי קשר"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"השתמש בשמות מרשימת אנשי הקשר עבור הצעות ותיקונים"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"הפוך תיקונים חוזרים לפעילים"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"הגדר הצעות עבור תיקונים חוזרים"</string>
<string name="auto_cap" msgid="1719746674854628252">"הפיכת אותיות לרישיות באופן אוטומטי"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"הגדרת מילונים"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"תיקונים מהירים"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"מתקן שגיאות הקלדה נפוצות"</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="3551821800439659812">"הצג בפריסה לאורך"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"הסתר תמיד"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"השתמש במחליף השפה של מקש הרווח"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"הצג מקש הגדרות"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"אוטומטי"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"הצג תמיד"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"הסתר תמיד"</string>
<string name="auto_correction" msgid="4979925752001319458">"תיקון אוטומטי"</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_aggeressive" msgid="3524029103734923819">"מחמיר"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"מחמיר מאוד"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"הצעות של צמדי אותיות (Bigram)"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"השתמש במילה הקודמת כדי לשפר את ההצעה"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"חיזוי צמדי אותיות (Bigram)"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"הצעות המילה הבאה"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"השתמש במילה הקודמת כדי לשפר את ההצעות"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"חיזוי המילה הבאה"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"השתמש במילה הקודמת גם עבור חיזוי"</string>
<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_to_alpha_key" msgid="4793983863798817523">"אבג"</string>
- <string name="label_more_key" msgid="3760239494604948502">"עוד"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"השהה"</string>
<string name="label_wait_key" msgid="6402152600878093134">"המתן"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"חבר אוזניות כדי לשמוע הקראה של מפתחות סיסמה."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"הטקסט הנוכחי הוא %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"לא הוזן טקסט"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"קוד מקש %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift מופעל"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"פסיק"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"נקודה"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"סוגריים שמאליים"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"סוגריים ימניים"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"נקודתיים"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"נקודה פסיק"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"סימן קריאה"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"סימן שאלה"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"מרכאות כפולות"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"גרש בודד"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"חיפוש"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"נקודה"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"שורש ריבועי"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"פאי"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"דלתה"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"סימן מסחרי"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"לכבוד"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"כוכב"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"סולמית"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"שלוש נקודות"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"מרכאות כפולות תחתונות"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"קלט קולי"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"קלט קולי אינו נתמך בשלב זה בשפתך, אך הוא פועל באנגלית."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"קלט קולי משתמש בזיהוי דיבור של Google.‏ "<a href="http://m.google.com/privacy">"מדיניות הפרטיות של \'Google לנייד\'"</a>" חלה במקרה זה."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"כדי לכבות את הקלט הקולי, עבור להגדרות של שיטת קלט."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"כדי להשתמש בקלט קולי, לחץ על לחצן המיקרופון."</string>
- <string name="voice_listening" msgid="467518160751321844">"דבר עכשיו"</string>
- <string name="voice_working" msgid="6666937792815731889">"פועל"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"שגיאה. נסה שוב."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"אין אפשרות להתחבר"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"שגיאה, קטע דיבור ארוך מדי."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"בעיה באודיו"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"שגיאת שרת"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"לא ניתן לשמוע דיבור"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"לא נמצאו התאמות"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"חיפוש קולי לא מותקן"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"רמז:"</b>" העבר על המקלדת כדי לדבר"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"רמז:"</b>" בפעם הבאה, נסה לומר את סימני הפיסוק כגון \"נקודה\", \"פסיק\" או \"סימן שאלה\"."</string>
- <string name="cancel" msgid="6830980399865683324">"ביטול"</string>
- <string name="ok" msgid="7898366843681727667">"אישור"</string>
- <string name="voice_input" msgid="2466640768843347841">"קלט קולי"</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="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="selectInputMethod" msgid="315076553378705821">"בחר שיטת קלט"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"הגדרת שיטות קלט"</string>
<string name="language_selection_title" msgid="1651299598555326750">"שפות קלט"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"החלק את האצבע על מקש הרווח כדי לשנות שפה"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← גע פעם נוספת לשמירה"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ציין חותמת זמן ביומן"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"חותמת זמן מתועדת"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"אל תרשום הפעלה זו ביומן"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"מוחק יומן הפעלה"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"יומן הפעלה נמחק"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"יומן הפעלה לא נמחק"</string>
+ <string name="select_language" msgid="3693815588777926848">"שפות קלט"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"גע שוב כדי לשמור"</string>
<string name="has_dictionary" msgid="6071847973466625007">"מילון זמין"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"הפוך משוב ממשתמשים לפעיל"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"עזור לשפר את עורך שיטת הקלט על ידי שליחה אוטומטית של סטטיסטיקת שימוש ודוחות קריסת מחשב ל-Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"גע כדי לתקן מילים"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"גע במילים שהוזנו כדי לתקן אותן רק כאשר ההצעות גלויות"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"עיצוב מקלדת"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"מקלדת צ\'כית"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"מקלדת בערבית"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"מקלדת דנית"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"מקלדת גרמנית"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"מקלדת QWERTY גרמנית"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"מקלדת אנגלית (בריטניה)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"מקלדת אנגלית (ארה\"ב)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"מקלדת ספרדית"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"מקלדת בפינית"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"מקלדת צרפתית"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"מקלדת צרפתית (קנדה)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"מקלדת צרפתית (שוויץ)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"מקלדת בשפה הקרואטית"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"מקלדת בהונגרית"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"מקלדת בעברית"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"מקלדת איטלקית"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"מקלדת נורווגית"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"מקלדת הולנדית"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"מקלדת בפולנית"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"מקלדת בפורטוגזית"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"מקלדת רוסית"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"מקלדת סרבית"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"מקלדת שוודית"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"מקלדת בטורקית"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Google Voice באפריקאנס"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Google Voice בצ\'כית"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Google Voice בגרמנית"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Google Voice באנגלית"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Google Voice בספרדית"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Google Voice בצרפתית"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"קול באיטלקית"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Google Voice ביפנית"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Google Voice בקוריאנית"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Google Voice בהולנדית"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Google Voice בפולנית"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Google Voice בפורטוגזית"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Google Voice ברוסית"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Google Voice בטורקית"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Google Voice בסינית, יו"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Google Voice בסינית, מנדרינית"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Google Voice באיסיזולו"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"אנגלית (בריטניה)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"אנגלית (ארה\"ב)"</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_no_language" msgid="141420857808801746">"ללא שפה"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"אין שפה (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"אין שפה (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"אין שפה (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"אין שפה (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"אין שפה (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"אין שפה (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"הגדרות משך רטט בלחיצה על מקש"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"הגדרות עוצמת קול בלחיצה על מקש"</string>
</resources>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 99d882652..05dd3a364 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -21,61 +21,69 @@
<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">"Androidキーボード"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androidキーボード(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Androidキーボードの設定"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"入力オプション"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ログコマンドの検索"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidスペルチェッカー"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidスペルチェッカー(AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"スペルチェックの設定"</string>
+ <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="ngram_category" msgid="5337109164339320257">"前の語句に基づいた入力候補表示"</string>
<string name="misc_category" msgid="6894192814868233453">"他のオプション"</string>
<string name="advanced_settings" msgid="362895144495591463">"詳細設定"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"上級ユーザー向けオプション"</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="suppress_language_switch_key" msgid="8003788410354806368">"言語切り替えキーを非表示"</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="use_contacts_dict" msgid="4435317977804180815">"候補の連絡先名を表示"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"連絡先の名前を使用して候補表示や自動修正を行います"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"再修正を有効にする"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"再修正の候補を挿入する"</string>
<string name="auto_cap" msgid="1719746674854628252">"自動大文字変換"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"辞書を設定"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"クイックフィックス"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"よくある誤字・脱字を修正します"</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="3551821800439659812">"縦向きで表示"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"常に非表示"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"スペースバーで切替"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"設定キーを表示"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"自動"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"常に表示"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"常に非表示"</string>
<string name="auto_correction" msgid="4979925752001319458">"自動修正"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"誤入力をスペースまたは句読点キーで修正する"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"OFF"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"中"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"強"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"最も強い"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"バイグラム入力候補表示"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"直前の単語から入力候補を予測します"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"バイグラム予測"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"次の入力候補"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"直前の単語から入力候補を予測します"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"次の入力候補を予測"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"前の語句も予測に使用"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Shift"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"停止"</string>
<string name="label_wait_key" msgid="6402152600878093134">"待機"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"パスワードのキーが音声出力されるのでヘッドセットを接続してください。"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"現在のテキスト:%s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"テキストが入力されていません"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"キーコード:%d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift有効"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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">"DEL"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"記号"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"英字"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"音声入力"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"顔文字"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"カンマ"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"ピリオド"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"左かっこ"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"右かっこ"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"コロン"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"セミコロン"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"感嘆符"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"疑問符"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"二重引用符"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"単一引用符"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"検索"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"中点"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"平方根"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"円周率記号"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"デルタ"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"商標記号"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"宛名記号"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"アスタリスク"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"ナンバー記号"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"省略記号"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"下付き二重引用符"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"音声入力"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"音声入力は現在英語には対応していますが、日本語には対応していません。"</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"音声入力ではGoogleの音声認識技術を利用します。"<a href="http://m.google.com/privacy">"モバイルプライバシーポリシー"</a>"が適用されます。"</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"音声入力をOFFにするには、入力方法の設定を開きます。"</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"音声入力するには、マイクボタンを押してください。"</string>
- <string name="voice_listening" msgid="467518160751321844">"お話しください"</string>
- <string name="voice_working" msgid="6666937792815731889">"処理中"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"エラーです。もう一度お試しください。"</string>
- <string name="voice_network_error" msgid="6649556447401862563">"接続できませんでした"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"音声が長すぎてエラーになりました。"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"オーディオエラー"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"サーバーエラー"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"音声が聞き取れません"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"該当なし"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Voice Searchはインストールされていません"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"ヒント:"</b>" 音声入力するにはキーボードをスワイプします"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"ヒント:"</b>" 次回は句読点として「period」、「comma」、「question mark」などの音声入力を試してみてください。"</string>
- <string name="cancel" msgid="6830980399865683324">"キャンセル"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"音声入力"</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="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">"OFF"</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="selectInputMethod" msgid="315076553378705821">"入力方法の選択"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"入力方法を設定"</string>
<string name="language_selection_title" msgid="1651299598555326750">"入力言語"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"スペースバーで指をスライドさせて言語を変更する"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"←保存するにはもう一度タップ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"タイムスタンプを記録"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"タイムスタンプ記録済み"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"セッションを記録しない"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"セッションログ削除中"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"セッションログ削除済み"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"セッションログ未削除"</string>
+ <string name="select_language" msgid="3693815588777926848">"入力言語"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"保存するにはもう一度タップ"</string>
<string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"ユーザーフィードバックを有効にする"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"IMEの機能向上のため、使用統計状況やクラッシュレポートをGoogleに自動送信します。"</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"タップして語句を修正"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"候補が表示されているときのみ、入力した語句をタップして修正する"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"キーボードのテーマ"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"チェコ語のキーボード"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"アラビア語のキーボード"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"デンマーク語のキーボード"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"ドイツ語のキーボード"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"ドイツ語QWERTYキーボード"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"英語(英国)のキーボード"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"英語(米国)のキーボード"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"スペイン語のキーボード"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"フィンランド語キーボード"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"フランス語のキーボード"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"フランス語(カナダ)のキーボード"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"フランス語(スイス)のキーボード"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"クロアチア語キーボード"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"ハンガリー語キーボード"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"ヘブライ語のキーボード"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"イタリア語のキーボード"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"ノルウェー語のキーボード"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"オランダ語のキーボード"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"ポーランド語のキーボード"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"ポルトガル語のキーボード"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"ロシア語のキーボード"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"セルビア語のキーボード"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"スウェーデン語のキーボード"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"トルコ語のキーボード"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"アフリカーンス語の音声"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"チェコ語の音声"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"ドイツ語の音声"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"英語の音声"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"スペイン語の音声"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"フランス語の音声"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"イタリア語の音声"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"日本語の音声"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"韓国語の音声"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"オランダ語の音声"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"ポーランド語の音声"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"ポルトガル語の音声"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"ロシア語の音声"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"トルコ語の音声"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"中国語(広東語)の音声"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"中国語(標準語)の音声"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"ズールー語の音声"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"英語(英国)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"英語(米国)"</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_no_language" msgid="141420857808801746">"言語設定なし"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"言語設定なし(QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"言語設定なし(QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"言語設定なし(AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"言語設定なし(Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"言語設定なし(Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"言語設定なし(PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"キー操作バイブの振動時間の設定"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"キー操作音の音量設定"</string>
</resources>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 993ab473f..6a998838a 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -21,61 +21,69 @@
<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">"Android 키보드"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 키보드(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android 키보드 설정"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"입력 옵션"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"로그 명령 탐색"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android 맞춤법 검사기"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 맞춤법 검사기(AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"맞춤법 검사 설정"</string>
+ <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="ngram_category" msgid="5337109164339320257">"이전 단어에 기반한 추천"</string>
<string name="misc_category" msgid="6894192814868233453">"기타 옵션"</string>
<string name="advanced_settings" msgid="362895144495591463">"고급 설정"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"전문 사용자용 옵션"</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="suppress_language_switch_key" msgid="8003788410354806368">"언어 전환 키 제거"</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="use_contacts_dict" msgid="4435317977804180815">"주소록 이름 활용"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"추천 및 수정에 주소록의 이름 사용"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"재수정 가능 설정"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"재수정 추천어 사전 활성화"</string>
<string name="auto_cap" msgid="1719746674854628252">"자동 대문자화"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"사전 설정"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"빠른 수정"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"자주 발생하는 오타를 수정합니다."</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="3551821800439659812">"세로 화면일 때만 표시"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"항상 숨기기"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"스페이스 바 언어 교환기 사용"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"설정 키 표시"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"자동"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"항상 표시"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"항상 숨기기"</string>
<string name="auto_correction" msgid="4979925752001319458">"자동 수정"</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_aggeressive" msgid="3524029103734923819">"중"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"강"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram 추천"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"이전 단어를 사용하여 추천 기능 개선"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram 예측"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"이전 단어를 사용하여 예상 검색어를 표시합니다."</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"다음 추천 검색어"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"이전 단어를 사용하여 추천 검색어 개선"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"다음 예상 검색어"</string>
+ <string name="bigram_prediction_summary" msgid="1747261921174300098">"이전 단어를 사용하여 예상 검색어 표시"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"더보기"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"일시 중지"</string>
<string name="label_wait_key" msgid="6402152600878093134">"대기"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"비밀번호 키를 음성으로 들으려면 헤드셋을 연결하세요."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"입력한 텍스트: %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"입력한 텍스트 없음"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"키 코드 %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"시프트 키"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift 키 누름"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"쉼표"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"마침표"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"왼쪽 괄호"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"오른쪽 괄호"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"콜론"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"세미콜론"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"느낌표"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"물음표"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"큰따옴표"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"작은따옴표"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"검색"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"점"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"제곱근"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"파이"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"델타"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"상표(™)"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"퍼센트 키"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"별표"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"파운드"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"생략 부호"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"아래쪽 큰따옴표"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"음성 입력"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"음성 입력은 현재 자국어로 지원되지 않으며 영어로 작동됩니다."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"음성 입력에서는 Google의 음성 인식 기능을 사용합니다. "<a href="http://m.google.com/privacy">"모바일 개인정보취급방침"</a>"이 적용됩니다."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"음성 입력을 사용하지 않으려면 입력 방법 설정으로 이동하세요."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"음성 입력을 사용하려면 마이크 버튼을 누르세요."</string>
- <string name="voice_listening" msgid="467518160751321844">"지금 말하세요."</string>
- <string name="voice_working" msgid="6666937792815731889">"인식 중"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"오류가 발생했습니다. 다시 시도해 보세요."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"연결할 수 없습니다."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"음성을 너무 많이 입력했습니다."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"오디오 문제"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"서버 오류"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"음성이 인식되지 않았습니다."</string>
- <string name="voice_no_match" msgid="4285117547030179174">"일치하는 항목 없음"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"음성 검색이 설치되지 않았습니다."</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"도움말:"</b>" 키보드 위로 손가락을 미끄러지듯 움직이고 나서 말하세요."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"도움말:"</b>" 다음 번에는 \'마침표\', \'쉼표\', \'물음표\'와 같은 구두점을 말해 보세요."</string>
- <string name="cancel" msgid="6830980399865683324">"취소"</string>
- <string name="ok" msgid="7898366843681727667">"확인"</string>
- <string name="voice_input" msgid="2466640768843347841">"음성 입력"</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="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="selectInputMethod" msgid="315076553378705821">"입력 방법 선택"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"입력 방법 설정"</string>
<string name="language_selection_title" msgid="1651299598555326750">"입력 언어"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"손가락을 스페이스바에서 미끄러지듯 움직여 언어 변경"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← 저장하려면 다시 터치하세요."</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"로그에 타임스탬프를 기록"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"타임스탬프를 기록함"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"이 세션을 로그하지 마세요."</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"세션 로그 삭제"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"세션 로그가 삭제됨"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"세션 로그가 삭제되지 않음"</string>
+ <string name="select_language" msgid="3693815588777926848">"입력 언어"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"저장하려면 다시 터치"</string>
<string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"사용자 의견 사용"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"사용 통계 및 충돌 보고서를 Google에 자동으로 전송하여 입력 방법 편집기의 개선에 도움을 줍니다."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"터치하여 단어 수정"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"입력한 단어를 터치하여 수정(추천 단어가 표시되는 경우에만)"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"키보드 테마"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"체코어 키보드"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"아랍어 키보드"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"덴마크어 키보드"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"독일어 키보드"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"독일어 QWERTY 키보드"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"영어(영국) 키보드"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"영어(미국) 키보드"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"스페인어 키보드"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"핀란드어 키보드"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"프랑스어 키보드"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"프랑스어(캐나다) 키보드"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"프랑스어(스위스) 키보드"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"크로아티아어 키보드"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"헝가리어 키보드"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"히브리어 키보드"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"이탈리아어 키보드"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"노르웨이어 키보드"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"네덜란드어 키보드"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"폴란드어 키보드"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"포르투갈어 키보드"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"러시아어 키보드"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"세르비아어 키보드"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"스웨덴어 키보드"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"터키어 키보드"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"아프리칸스어 음성"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"체코어 음성"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"독일어 음성"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"영어 음성"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"스페인어 음성"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"프랑스어 음성"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"이탈리아어 음성"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"일본어 키보드"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"한국어 음성"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"네덜란드어 음성"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"폴란드어 음성"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"포르투갈어 음성"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"러시아어 음성"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"터키어 음성"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"중국어, 광둥어 음성"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"중국어, 북경어 음성"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"줄루어 음성"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"영어(영국)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"영어(미국)"</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_no_language" msgid="141420857808801746">"언어가 없음"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"언어가 없음(QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"언어 없음(QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"언어 없음(AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"언어 없음(드보락)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"언어 없음(콜맥)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"언어 없음(PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"키를 누를 때 진동 시간 설정"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"키를 누를 때 효과음 설정"</string>
</resources>
diff --git a/java/res/values-ky/strings.xml b/java/res/values-ky/strings.xml
new file mode 100644
index 000000000..85925257c
--- /dev/null
+++ b/java/res/values-ky/strings.xml
@@ -0,0 +1,221 @@
+<?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_name (7252517407088836577) -->
+ <skip />
+ <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
+ <skip />
+ <!-- no translation found for english_ime_settings (6661589557206947774) -->
+ <skip />
+ <!-- no translation found for english_ime_input_options (3909945612939668554) -->
+ <skip />
+ <!-- no translation found for spell_checker_service_name (7338064335159755926) -->
+ <skip />
+ <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
+ <skip />
+ <!-- no translation found for android_spell_checker_settings (5822324635435443689) -->
+ <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 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 suppress_language_switch_key (8003788410354806368) -->
+ <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 use_contacts_dict (4435317977804180815) -->
+ <skip />
+ <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
+ <skip />
+ <!-- no translation found for enable_span_insert (7204653105667167620) -->
+ <skip />
+ <!-- no translation found for enable_span_insert_summary (2947317657871394467) -->
+ <skip />
+ <!-- no translation found for auto_cap (1719746674854628252) -->
+ <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 (3551821800439659812) -->
+ <skip />
+ <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
+ <skip />
+ <!-- no translation found for auto_correction (4979925752001319458) -->
+ <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_aggeressive (3524029103734923819) -->
+ <skip />
+ <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
+ <skip />
+ <!-- no translation found for bigram_suggestion (8169311444438922902) -->
+ <skip />
+ <!-- no translation found for bigram_suggestion_summary (6635527607242625713) -->
+ <skip />
+ <!-- no translation found for bigram_prediction (3216364899483135294) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (1747261921174300098) -->
+ <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>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"АБВ"</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) -->
+ <skip />
+ <!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
+ <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_dot (40711082435231673) -->
+ <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 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 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 (5827825607258246003) -->
+ <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_no_language_qwerty (2956121451616633133) -->
+ <skip />
+ <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
+ <skip />
+ <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
+ <skip />
+ <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
+ <skip />
+</resources>
diff --git a/java/res/values-de/config.xml b/java/res/values-land/config.xml
index 272ff326f..7d93cc2ff 100644
--- a/java/res/values-de/config.xml
+++ b/java/res/values-land/config.xml
@@ -19,5 +19,5 @@
-->
<resources>
- <bool name="config_require_umlaut_processing">true</bool>
+ <bool name="config_use_fullscreen_mode">true</bool>
</resources>
diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml
index d6e096278..62597258c 100644
--- a/java/res/values-land/dimens.xml
+++ b/java/res/values-land/dimens.xml
@@ -19,40 +19,53 @@
-->
<resources>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=0.260in -->
- <dimen name="keyboardHeight">1.100in</dimen>
+ <!-- Preferable keyboard height in absolute scale: 1.100in -->
+ <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+ <dimen name="keyboardHeight">176.0dp</dimen>
<fraction name="minKeyboardHeight">45%p</fraction>
<!-- key_height + key_bottom_gap = popup_key_height -->
-<!-- <dimen name="key_height">0.260in</dimen>-->
- <dimen name="key_bottom_gap">0.020in</dimen>
- <dimen name="popup_key_height">0.280in</dimen>
- <dimen name="keyboard_top_padding">0.00in</dimen>
- <dimen name="keyboard_bottom_padding">0.00in</dimen>
- <dimen name="key_bottom_gap_ics">0.04in</dimen>
- <dimen name="key_horizontal_gap_ics">0.01in</dimen>
- <dimen name="keyboard_top_padding_ics">0.03in</dimen>
- <dimen name="keyboard_bottom_padding_ics">0.00in</dimen>
- <dimen name="keyboard_horizontal_edges_padding">0.0in</dimen>
+ <dimen name="popup_key_height">44.8dp</dimen>
+
+ <fraction name="keyboard_top_padding">1.818%p</fraction>
+ <fraction name="keyboard_bottom_padding">0.0%p</fraction>
+ <fraction name="key_bottom_gap">4.330%p</fraction>
+ <fraction name="key_horizontal_gap">0.405%p</fraction>
+
+ <fraction name="key_bottom_gap_stone">5.010%p</fraction>
+ <fraction name="key_horizontal_gap_stone">1.159%p</fraction>
+
+ <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>
<!-- left or right padding of label alignment -->
- <dimen name="key_label_horizontal_alignment_padding">8dip</dimen>
+ <dimen name="key_label_horizontal_padding">8dp</dimen>
- <fraction name="key_letter_ratio">55%</fraction>
- <fraction name="key_large_letter_ratio">68%</fraction>
- <fraction name="key_label_ratio">35%</fraction>
- <fraction name="key_hint_letter_ratio">28%</fraction>
- <fraction name="key_hint_label_ratio">45%</fraction>
+ <fraction name="key_letter_ratio">65%</fraction>
+ <fraction name="key_large_letter_ratio">74%</fraction>
+ <fraction name="key_label_ratio">40%</fraction>
+ <fraction name="key_hint_letter_ratio">30%</fraction>
+ <fraction name="key_hint_label_ratio">52%</fraction>
<fraction name="key_uppercase_letter_ratio">40%</fraction>
<fraction name="key_preview_text_ratio">90%</fraction>
- <dimen name="key_preview_offset">0.08in</dimen>
+ <fraction name="spacebar_text_ratio">40.000%</fraction>
+ <dimen name="key_preview_offset">0.0dp</dimen>
- <dimen name="key_preview_offset_ics">0.01in</dimen>
+ <dimen name="key_preview_offset_ics">1.6dp</dimen>
+ <!-- popup_key_height x -0.5 -->
+ <dimen name="more_keys_keyboard_vertical_correction_ics">-22.4dp</dimen>
- <dimen name="candidate_strip_height">38dip</dimen>
- <dimen name="candidate_strip_fading_edge_length">63dip</dimen>
+ <dimen name="suggestions_strip_height">36dp</dimen>
+ <dimen name="more_suggestions_row_height">36dp</dimen>
+ <integer name="max_more_suggestions_row">2</integer>
+ <fraction name="min_more_suggestions_width">60%</fraction>
<!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
<!-- popup_key_height x 1.2 -->
- <dimen name="mini_keyboard_slide_allowance">0.336in</dimen>
+ <dimen name="more_keys_keyboard_slide_allowance">53.76dp</dimen>
<!-- popup_key_height x -1.0 -->
- <dimen name="mini_keyboard_vertical_correction">-0.280in</dimen>
+ <dimen name="more_keys_keyboard_vertical_correction">-44.8dp</dimen>
</resources>
diff --git a/java/res/values-land/keyboard-heights.xml b/java/res/values-land/keyboard-heights.xml
new file mode 100644
index 000000000..4ebeda559
--- /dev/null
+++ b/java/res/values-land/keyboard-heights.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- Build.HARDWARE,keyboard_height_in_dp -->
+ <string-array name="keyboard_heights" translatable="false">
+ <!-- Preferable keyboard height in absolute scale: 1.100in -->
+ <!-- Droid -->
+ <item>sholes,194.3333</item>
+ <!-- Nexus One -->
+ <item>mahimahi,186.2667</item>
+ <!-- Nexus S -->
+ <item>herring,171.9385</item>
+ <!-- Galaxy Nexus -->
+ <item>tuna,173.4207</item>
+ <!-- Preferable keyboard height in absolute scale: 45.0mm -->
+ <!-- Xoom -->
+ <item>stingray,265.4378</item>
+ </string-array>
+</resources>
diff --git a/java/res/values-large-land/dimens.xml b/java/res/values-large-land/dimens.xml
deleted file mode 100644
index 5d1fbc748..000000000
--- a/java/res/values-large-land/dimens.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
- <dimen name="keyboardHeight">45.0mm</dimen>
- <fraction name="minKeyboardHeight">45%p</fraction>
- <!-- key_height + key_bottom_gap = popup_key_height -->
- <!-- <dimen name="key_height">14.5mm</dimen> -->
- <dimen name="key_bottom_gap">1.3mm</dimen>
- <dimen name="key_horizontal_gap">1.3mm</dimen>
- <dimen name="keyboard_top_padding">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding">0.0mm</dimen>
- <dimen name="key_bottom_gap_ics">1.3mm</dimen>
- <dimen name="key_horizontal_gap_ics">1.3mm</dimen>
- <dimen name="keyboard_top_padding_ics">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding_ics">0.0mm</dimen>
- <dimen name="popup_key_height">13.0mm</dimen>
-
- <!-- left or right padding of label alignment -->
- <dimen name="key_label_horizontal_alignment_padding">18dip</dimen>
-
- <fraction name="key_letter_ratio">45%</fraction>
- <fraction name="key_large_letter_ratio">45%</fraction>
- <fraction name="key_label_ratio">32%</fraction>
- <fraction name="key_hint_letter_ratio">23%</fraction>
- <fraction name="key_hint_label_ratio">34%</fraction>
- <fraction name="key_uppercase_letter_ratio">29%</fraction>
-
- <dimen name="candidate_strip_padding">40.0mm</dimen>
-</resources>
diff --git a/java/res/values-large/dimens.xml b/java/res/values-large/dimens.xml
deleted file mode 100644
index 675f40c2e..000000000
--- a/java/res/values-large/dimens.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
- <dimen name="keyboardHeight">48.0mm</dimen>
- <fraction name="maxKeyboardHeight">50%p</fraction>
- <fraction name="minKeyboardHeight">-35.0%p</fraction>
- <!-- key_height + key_bottom_gap = popup_key_height -->
- <!-- <dimen name="key_height">14.5mm</dimen> -->
- <dimen name="key_bottom_gap">1.0mm</dimen>
- <dimen name="key_horizontal_gap">1.0mm</dimen>
- <dimen name="popup_key_height">10.0mm</dimen>
- <dimen name="keyboard_top_padding">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding">0.0mm</dimen>
- <dimen name="key_bottom_gap_ics">1.0mm</dimen>
- <dimen name="key_horizontal_gap_ics">1.0mm</dimen>
- <dimen name="keyboard_top_padding_ics">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding_ics">0.0mm</dimen>
- <dimen name="mini_keyboard_key_horizontal_padding">12dip</dimen>
- <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
- <!-- popup_key_height x 1.2 -->
- <dimen name="mini_keyboard_slide_allowance">15.6mm</dimen>
- <!-- popup_key_height x -1.0 -->
- <dimen name="mini_keyboard_vertical_correction">-13.0mm</dimen>
-
- <!-- left or right padding of label alignment -->
- <dimen name="key_label_horizontal_alignment_padding">6dip</dimen>
-
- <fraction name="key_letter_ratio">37%</fraction>
- <fraction name="key_large_letter_ratio">37%</fraction>
- <fraction name="key_label_ratio">22%</fraction>
- <fraction name="key_hint_letter_ratio">23%</fraction>
- <fraction name="key_hint_label_ratio">26%</fraction>
- <fraction name="key_uppercase_letter_ratio">25%</fraction>
- <fraction name="key_preview_text_ratio">50%</fraction>
- <dimen name="key_preview_height">15.0mm</dimen>
- <dimen name="key_preview_offset">0.1in</dimen>
-
- <dimen name="key_preview_height_ics">15.0mm</dimen>
- <dimen name="key_preview_offset_ics">0.05in</dimen>
-
- <dimen name="candidate_strip_height">46dip</dimen>
- <dimen name="candidate_strip_padding">15.0mm</dimen>
- <dimen name="candidate_min_width">0.3in</dimen>
- <dimen name="candidate_padding">12dip</dimen>
- <dimen name="candidate_text_size">22dip</dimen>
-</resources>
diff --git a/java/res/values-lt/donottranslate-altchars.xml b/java/res/values-lt/donottranslate-altchars.xml
deleted file mode 100644
index 4aba93a3a..000000000
--- a/java/res/values-lt/donottranslate-altchars.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">ą,à,á,â,ä,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,ė,ę,è,é,ê,ë,ē</string>
- <string name="alternates_for_i">8,į,î,ï,ì,í,ī</string>
- <string name="alternates_for_u">7,ų,ū,û,ü,ù,ú</string>
- <string name="alternates_for_s">š,ß,ś</string>
- <string name="alternates_for_c">č,ç,ć</string>
- <string name="alternates_for_z">ž,ź,ż</string>
-</resources>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 51f77231a..86bfc3714 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -21,61 +21,69 @@
<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">"„Android“ klaviatūra"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"„Android“ klaviatūra (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"„Android“ klaviatūros nustatymai"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Įvesties parinktys"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Tyrinėti žurnalo komandas"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"„Android“ rašybos tikrinimo programa"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"„Android“ rašybos tikrinimo programa (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Rašybos tikrinimo nustatymai"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktų vardų paieška"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rašybos tikrinimo progr. naudoja įrašus, esančius kontaktų sąraše"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibruoti, kai paspaudžiami klavišai"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Klavišo paspaudimo garsas"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Iššoka paspaudus klavišą"</string>
<string name="general_category" msgid="1859088467017573195">"Bendra"</string>
<string name="correction_category" msgid="2236750915056607613">"Teksto taisymas"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Pasiūlymai pagal ankstesnius žodžius"</string>
<string name="misc_category" msgid="6894192814868233453">"Kitos parinktys"</string>
<string name="advanced_settings" msgid="362895144495591463">"Išplėstiniai nustatymai"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Parinktys ekspertams"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Parinktys ekspertams"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Perj. į kt. įvesties būd."</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kalbos perjungimo klavišu taip pat perjungiami įvesties būdai"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Nerodyti klb. keit. klav."</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pagr. išš. l. atsis. d."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Be delsos"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Numatytasis"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Siūlyti kontaktų vardus"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Siūlant ir taisant naudoti vardus iš „Kontaktų“"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Įdiegti pakartotinius pataisymus"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nustatyti pakartotinio pataisymo pasiūlymus"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatinis didžiųjų raidžių rašymas"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigūruoti žodynus"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Greiti pataisymai"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Taiso dažnai padarytas rašybos klaidas"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Papildomi žodynai"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Pagrindinis žodynas"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Rodyti taisymo pasiūlymus"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Įvedant tekstą pateikti siūlomų žodžių"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Visada rodyti"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Rodyti stačiuoju režimu"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Visada slėpti"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Naud. tarpo kl. k. jung."</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Rodyti nustatymų raktą"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatinis"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Visada rodyti"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Visada slėpti"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automatinis taisymas"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Tarpo kl. ir skyr. ženkl. aut. išt. neteis. įv. žodž."</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Išjungta"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Vidutinis"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Atkaklus"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Labai agresyviai"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigramų pasiūlymai"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Naudoti ankstesnį žodį pasiūlymui patobulinti"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigramų numatymas"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Kito žodžio pasiūlymai"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Naudoti ankstesnį žodį pasiūlymams patobulinti"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Kito žodžio numatymas"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Numatant naudoti ir ankstesnį žodį"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Daugiau"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Antrojo lygio klavišas įgalintas"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Įgalintas didžiųjų raidžių klavišas"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Įjungtas antrasis lygis (palieskite, kad išjungtumėte)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Įjungtos didžiosios raidės (palieskite, kad išjungtumėte)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Ištrinti"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboliai"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Raidės"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Įvestis balsu"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Šypsenėlė"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Grįžti"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Kablelis"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Taškas"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kairysis skliaustas"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Dešinysis skliaustas"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dvitaškis"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Kabliataškis"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Šauktukas"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Klaustukas"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dvigubos kabutės"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Viengubos kabutės"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Ieškoti"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Taškas"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratinė šaknis"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Prekės ženklas"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Perduoti"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Pažymėti žvaigždute"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Svaras"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Daugtaškis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Apatinės dvigubos kabutės"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Balso įvestis"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Šiuo metu balso įvestis jūsų kompiuteryje nepalaikoma, bet ji veikia anglų k."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Balso įvesčiai naudojamas „Google“ kalbos atpažinimas. Taikoma "<a href="http://m.google.com/privacy">"privatumo politika mobiliesiems"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Jei norite išjungti balso įvestį, eikite į įvesties metodo nustatymus."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Jei norite naudoti balso įvestį, paspauskite mikrofono mygtuką."</string>
- <string name="voice_listening" msgid="467518160751321844">"Kalbėkite dabar"</string>
- <string name="voice_working" msgid="6666937792815731889">"Veikia"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Klaida. Bandykite dar kartą."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Nepavyko prijungti"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Klaida, per daug kalbos."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema su garsu"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Serverio klaida"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Negirdima jokia kalba"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Atitikmenų nerasta"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Balso paieška neįdiegta"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Užuomina:"</b>" perbraukite klaviatūra, kad galėtumėte kalbėti"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Užuomina:"</b>" kitą kartą pabandykite sakyti skyrybos ženklų pavadinimus, pvz., „taškas“, „kablelis“ arba „klaustukas“."</string>
- <string name="cancel" msgid="6830980399865683324">"Atšaukti"</string>
- <string name="ok" msgid="7898366843681727667">"Gerai"</string>
- <string name="voice_input" msgid="2466640768843347841">"Balso įvestis"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Įgalintas antrasis lygis"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Įgalintos didžiosios raidės"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Antrasis lygis išjungtas"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Simbolių režimas"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Raidžių režimas"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefono režimas"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefono simbolių režimas"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Įvesties balsu klavišas"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pagr. klaviatūroje"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Simbolių klaviatūr."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Išjungta"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrof. pagr. klav."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrof. simb. klav."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balso įv. neleidž."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Pasirinkti įvesties metodą"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigūruoti įvesties metodus"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Įvesties kalbos"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Pirštu slyskite tarpo klavišu, kad pakeistumėte kalbą"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Kad išsaugotumėte, dar kartą palieskite"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Pažym. laiko žymę žurnale"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Įrašyta laiko žymė"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Neįrašyti šios sesijos"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Ištrinam. sesijos žurnal."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sesijos žurnalas ištrint."</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sesij. žurnal. NEIŠTRINT."</string>
+ <string name="select_language" msgid="3693815588777926848">"Įvesties kalbos"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Jei norite išsaugoti, palieskite dar kartą"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Žodynas galimas"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Įgalinti naudotojų atsiliepimus"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Padėkite patobulinti šią įvesties metodo redagavimo programą automatiškai „Google“ siųsdami naudojimo statistiką ir strigčių ataskaitas."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Jei norite ištais. žodž., paliesk."</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Jei norite ištaisyti įvestus žodžius, palieskite juos tik tada, kai matomi pasiūlymai"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Klaviatūros tema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Čekiška klaviatūra"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabiška klaviatūra"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Daniška klaviatūra"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Vokiška klaviatūra"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Vokiška QWERTY klaviatūra"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Angliška (JK) klaviatūra"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Angliška (JAV) klaviatūra"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Ispaniška klaviatūra"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Suomiška klaviatūra"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Prancūziška klaviatūra"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Prancūziška (Kanada) klaviatūra"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Prancūziška (Šveicarija) klaviatūra"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatiška klaviatūra"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Vengriška klaviatūra"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebrajiška klaviatūra"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Itališka klaviatūra"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norvegiška klaviatūra"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Olandiška klaviatūra"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Lenkiška klaviatūra"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugališka klaviatūra"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Rusiška klaviatūra"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbiška klaviatūra"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Švediška klaviatūra"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turkiška klaviatūra"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"„Voice“ afrikanų k."</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"„Voice“ čekų k."</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"„Voice“ vokiečių k."</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"„Voice“ anglų k."</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"„Voice“ ispanų k."</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"„Voice“ prancūzų k."</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"„Voice“ italų k."</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"„Voice“ japonų k."</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"„Voice“ korėjiečių k."</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"„Voice“ olandų k."</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"„Voice“ lenkų k."</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"„Voice“ portugalų k."</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"„Voice“ rusų k."</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"„Voice“ turkų k."</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"„Voice“ kinų (dziue) k."</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"„Voice“ kinų (mandarinų) k."</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"„Voice“ zulų k."</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Anglų k. (JK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Anglų k. (JAV)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Angliška (JK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Angliška (JAV) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Kalbos nėra"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nėra kalbos (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nėra kalbos (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nėra kalbos (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nėra kalbos (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nėra kalbos (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nėra kalbos (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Pasirinkti įvesties stilių"</string>
+ <string name="add_style" msgid="6163126614514489951">"Prid. stilių"</string>
+ <string name="add" msgid="8299699805688017798">"Pridėti"</string>
+ <string name="remove" msgid="4486081658752944606">"Pašalinti"</string>
+ <string name="save" msgid="7646738597196767214">"Išsaugoti"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Kalba"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Išdėstymas"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Norint pradėti naudoti pasirinkiamą įvesties stilių, reikia jį įgalinti. Ar norite įgalinti jį dabar?"</string>
+ <string name="enable" msgid="5031294444630523247">"Įgalinti"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ne dabar"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Toks pat įvesties stilius jau yra: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tinkamumo tyrimo režimas"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Vibracijos paspaudus mygtuką trukmės nustatymai"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Garso paspaudus mygtuką garsumo nustatymai"</string>
</resources>
diff --git a/java/res/values-lv/donottranslate-altchars.xml b/java/res/values-lv/donottranslate-altchars.xml
deleted file mode 100644
index 05d9bc894..000000000
--- a/java/res/values-lv/donottranslate-altchars.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">ā,à,á,â,ä,æ,ã,å</string>
- <string name="alternates_for_e">3,ē,è,é,ê,ë,ę,ė</string>
- <string name="alternates_for_i">8,ī,î,ï,ì,í,į</string>
- <string name="alternates_for_u">7,ū,û,ü,ù,ú</string>
- <string name="alternates_for_s">š,ß,ś</string>
- <string name="alternates_for_n">ņ,ñ,ń</string>
- <string name="alternates_for_c">č,ç,ć</string>
- <string name="alternates_for_r">4,ŗ</string>
- <string name="alternates_for_z">ž,ź,ż</string>
- <string name="alternates_for_k">ķ</string>
- <string name="alternates_for_l">ļ,ł</string>
- <string name="alternates_for_g">ģ</string>
-</resources>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 62f0ee2b8..403e0f2d1 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -21,61 +21,69 @@
<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">"Android tastatūra"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tastatūra (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android tastatūras iestatījumi"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Izpētes žurnāla komandas"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android pareizrakstības pārbaudītājs"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android pareizrakstības pārbaudītājs (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Pareizrakstības pārbaudes iestatījumi"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Meklēt kontaktp. vārdus"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pareizrakst. pārbaudītājs lieto ierakstus no kontaktp. saraksta."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrēt, nospiežot taustiņu"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Skaņa, nospiežot taustiņu"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Nospiežot taustiņu, parādīt uznirstošo izvēlni"</string>
<string name="general_category" msgid="1859088467017573195">"Vispārīgi"</string>
<string name="correction_category" msgid="2236750915056607613">"Teksta korekcija"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Ieteikumi, kuru pamatā ir iepriekšējie vārdi"</string>
<string name="misc_category" msgid="6894192814868233453">"Citas opcijas"</string>
<string name="advanced_settings" msgid="362895144495591463">"Papildu iestatījumi"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcijas speciālistiem"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcijas ekspertiem"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Pārsl. uz citām iev. met."</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Valodas pārslēgš. taustiņu var lietot arī citām ievades metodēm."</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Atsp. val. pārsl. taust."</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Taust. uzn. loga noraid. aizk."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez aizkaves"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Noklusējums"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Ieteikt kontaktp. vārdus"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Izmantot kontaktpersonu vārdus kā ieteikumus un labojumus"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Iespējot atk. labojumus"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Iestatīt atkārtotu labojumu ieteikumus"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automātiska lielo burtu lietošana"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurēt vārdnīcas"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Ātrie labojumi"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Nodrošina izplatītu drukas kļūdu labošanu."</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Papildinājumu vārdnīcas"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Galvenā vārdnīca"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Rādīt labojumu ieteikumus"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Ievades laikā attēlot ieteiktos vārdus"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vienmēr rādīt"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Rādīt portreta režīmā"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vienmēr slēpt"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Val. pārsl. izm. atst. taust."</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Rādīt iestatījumu taustiņu"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automātiski"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Vienmēr rādīt"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Vienmēr slēpt"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automāt. korekcija"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Atstarpes taustiņš un interpunkcija; automātiska kļūdainu vārdu labošana"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Izslēgta"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mērena"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresīva"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Ļoti radikāla"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigrammu ieteikumi"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Ieteikuma uzlabošanai izmantot iepriekšējo vārdu"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigrammu prognozes"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Nākamā vārda ieteikumi"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Ieteikumu uzlabošanai izmantot iepriekšējo vārdu"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Nākamā vārda prognozēšana"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Izmantot iepriekšējo vārdu arī prognozēm"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Vairāk"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Pārslēgšanas taustiņš iespējots"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Burtslēgs iespējots"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Pārslēgšanas taustiņš iespējots (pieskarieties, lai atspējotu)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Burtslēgs iespējots (pieskarieties, lai atspējotu)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Dzēšanas taustiņš"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Burti"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Balss ievade"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smaidoša seja"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Ievadīšanas taustiņš"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komats"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punkts"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kreisā iekava"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Labā iekava"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Kols"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikols"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Izsaukuma zīme"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Jautājuma zīme"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Pēdiņas"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Vienpēdiņas"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Meklēt"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkts"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadrātsakne"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pī"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Preču zīme"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"c/o"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Zvaigznīte"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Cipara simbols"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Daudzpunkte"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Apakšējās pēdiņas"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Balss ievade"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Balss ievade jūsu valodā pašlaik netiek atbalstīta, taču tā ir pieejama angļu valodā."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Balss ievadei tiek izmantota Google runas atpazīšanas funkcija. Uz šīs funkcijas lietošanu attiecas "<a href="http://m.google.com/privacy">"mobilo sakaru ierīču lietošanas konfidencialitātes politika"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Lai izslēgtu balss ievadi, atveriet ievades metodes iestatījumus."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Lai izmantotu balss ievadi, nospiediet mikrofona taustiņu."</string>
- <string name="voice_listening" msgid="467518160751321844">"Runājiet!"</string>
- <string name="voice_working" msgid="6666937792815731889">"Notiek apstrāde"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Kļūda. Lūdzu, mēģiniet vēlreiz."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Nevar izveidot savienojumu."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Kļūda, pārāk ilga balss ievade."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Audio problēma"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Servera kļūda"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nekas nav dzirdams."</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nav atrasta neviena atbilstība."</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Balss meklēšana nav instalēta."</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Ieteikums:"</b>" slidiniet pirkstu pār tastatūru, lai veiktu balss ievadi."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Ieteikums:"</b>" nākamreiz mēģiniet izrunāt pieturzīmes, piemēram, “punkts”, “komats” vai “jautājuma zīme”."</string>
- <string name="cancel" msgid="6830980399865683324">"Atcelt"</string>
- <string name="ok" msgid="7898366843681727667">"Labi"</string>
- <string name="voice_input" msgid="2466640768843347841">"Balss ievade"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pārslēgšanas režīms iespējots"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Burtslēgs iespējots"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Pārslēgšanas režīms atspējots"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Simbolu režīms"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Burtu režīms"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Tālruņa režīms"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Tālruņa simbolu režīms"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Balss ievades atslēga"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Uz galv. tastatūras"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Uz simbolu tastat."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Izslēgts"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr.uz galv.tastat."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr.uz simb.tastat."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balss iev. atspējota"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Atlasīt ievades metodi"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Ievades metožu konfigurēšana"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Slidiniet pirkstu uz atstarpes taustiņa, lai mainītu valodu"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Pieskarieties vēlreiz, lai saglabātu"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Atzīmēt laiksp. žurnālā"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Laikspied. ir reģistrēts."</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nereģistrēt šo sesiju"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Not. sesijas žurn. dzēš."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sesijas žurnāls ir dzēsts"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sesijas žurn. NAV dzēsts"</string>
+ <string name="select_language" msgid="3693815588777926848">"Ievades valodas"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pieskarieties vēlreiz, lai saglabātu."</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Iespējot lietotāju atsauksmes"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Palīdziet uzlabot šo ievades metodes redaktoru, automātiski nosūtot lietojuma statistiku un pārskatus par avārijām uzņēmumam Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Pieskarties, lai izlabotu vārdus"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Pieskarties ievadītajiem vārdiem, lai tos labotu (tikai tad, ja tiek rādīti ieteikumi)."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tastatūras motīvs"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Čehu tastatūra"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arābu valodas tastatūra"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Dāņu tastatūra"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Vācu tastatūra"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Vācu QWERTY tastatūra"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Angļu (Lielbritānija) tastatūra"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Angļu (ASV) tastatūra"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spāņu tastatūra"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Somu valodas tastatūra"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Franču tastatūra"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Franču (Kanāda) tastatūra"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Franču (Šveices) tastatūra"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Horvātu valodas tastatūra"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ungāru valodas tastatūra"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Ebreju valodas tastatūra"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Itāļu tastatūra"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norvēģu tastatūra"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Holandiešu tastatūra"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Poļu valodas tastatūra"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugāļu valodas tastatūra"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Krievu tastatūra"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbu tastatūra"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Zviedru tastatūra"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turku valodas tastatūra"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Balss afrikandu valodā"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voice čehu valodā"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voice vācu valodā"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Balss angļu valodā"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voice spāņu valodā"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voice franču valodā"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Itāļu balss"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voice japāņu valodā"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voice korejiešu valodā"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Holandiešu balss"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voice poļu valodā"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voice portugāļu valodā"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voice krievu valodā"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voice turku valodā"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Balss ķīniešu val. (Kantonas dial.)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Balss ķīniešu v. (mandarīnu dial.)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Balss zulu valodā"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Angļu valoda (Lielbritānija)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Angļu valoda (ASV)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Angļu (Lielbritānija) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Angļu (ASV) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Nav valodas"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nav valodas (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nav valodas (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nav valodas (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nav valodas (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nav valodas (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nav valodas (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Pielāg. ievades stili"</string>
+ <string name="add_style" msgid="6163126614514489951">"Piev. stilu"</string>
+ <string name="add" msgid="8299699805688017798">"Pievienot"</string>
+ <string name="remove" msgid="4486081658752944606">"Noņemt"</string>
+ <string name="save" msgid="7646738597196767214">"Saglabāt"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Valoda"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Izkārtojums"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Lai lietotu pielāgoto stilu, tas ir jāiespējo. Vai iespējot?"</string>
+ <string name="enable" msgid="5031294444630523247">"Iespējot"</string>
+ <string name="not_now" msgid="6172462888202790482">"Vēlāk"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Šāds ievades stils jau pastāv: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Lietojamības izpētes režīms"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Taustiņu nospiešanas vibrācijas ilguma iestatījumi"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Taustiņu nospiešanas skaņas skaļuma iestatījumi"</string>
</resources>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index 351e2f04c..60f5a4133 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -21,61 +21,69 @@
<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">"Papan kekunci Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Papan kekunci Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Tetapan papan kekunci Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Arahan Log Penyelidikan"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Penyemak ejaan Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Penyemak ejaan Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Tetapan penyemakan ejaan"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Penyemak ejaan menggunakan entri dari senarai kenalan anda"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar pada tekanan kekunci"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Bunyi pada tekanan kekunci"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop timbul pada tekanan kunci"</string>
<string name="general_category" msgid="1859088467017573195">"Umum"</string>
<string name="correction_category" msgid="2236750915056607613">"Pembetulan teks"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Cadangan berdasarkan perkataan sebelumnya"</string>
<string name="misc_category" msgid="6894192814868233453">"Pilihan lain"</string>
<string name="advanced_settings" msgid="362895144495591463">"Tetapan terperinci"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Pilihan untuk pengguna pakar"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Pilihan untuk pakar"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Tukar ke kaedah input lain"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kunci pertukaran bahasa meliputi kaedah masukan lain juga"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Tekan kunci alih bahasa"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pop tmbl knci ketpkn lengah"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tiada lengah"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lalai"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Cadangkan nama Kenalan"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama daripada Kenalan untuk cadangan dan pembetulan"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Dayakan pembetulan semula"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Tetapkan cadangan untuk pembetulan semula"</string>
<string name="auto_cap" msgid="1719746674854628252">"Huruf besar auto"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurasikan kamus"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Pembaikan pantas"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Membetulkan kesalahan menaip yang biasa"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Kamus tambahan"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Tunjukkan cadangan pembetulan"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Paparkan cadangan perkataan semasa menaip"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Sentiasa tunjukkan"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Tunjukkan pada mod potret"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sentiasa sembunyikan"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Gunakan penukar bahasa bar ruang"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Tunjukkan kekunci tetapan"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatik"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Sentiasa tunjukkan"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Sentiasa sembunyikan"</string>
<string name="auto_correction" msgid="4979925752001319458">"Auto Pembetulan"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Bar ruang dan tanda baca secara automatik membetulkan perkataan yang ditaip salah"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Matikan"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Sederhana"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sangat agresif"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Cadangan bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Gunakan perkataan sebelumnya untuk memperbaik cadangan"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Ramalan bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Cadangan perkataan seterusnya"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gunakan perkataan sebelumnya untuk memperbaik cadangan"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Ramalan perkataan seterusnya"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Gunakan juga perkataan sebelumnya untuk ramalan"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Lagi"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Jeda"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Tnggu"</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>
<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="954941524766465022">"Shift didayakan"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Kunci huruf besar didayakan"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Kunci anjak dihidupkan (ketik untuk melumpuhkan)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Kunci huruf besar dihidupkan (ketik untuk melumpuhkan)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Padam"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simbol"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Huruf"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Input suara"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Muka senyum"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Tempoh"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Tanda kurung kiri"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Tanda kurung kanan"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Titik bertindih"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Koma bertitik"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Tanda seru"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Tanda soal"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Tanda petikan berganda"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Tanda petikan tunggal"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Carian"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Punca kuasa dua"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Tanda dagangan"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Dengan alamat"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Bintang"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Paun"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Elipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Tanda petikan berganda rendah"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Input suara"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Input suara tidak disokong untuk bahasa anda pada masa ini tetapi ia berfungsi dalam bahasa Inggeris."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Input suara menggunakan pengecaman pertuturan Google. "<a href="http://m.google.com/privacy">"Dasar Privasi Mudah Alih"</a>" digunakan."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Untuk mematikan input suara, pergi ke tetapan kaedah input."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Untuk menggunakan input suara, tekan butang mikrofon."</string>
- <string name="voice_listening" msgid="467518160751321844">"Sebutkan sekarang"</string>
- <string name="voice_working" msgid="6666937792815731889">"Berfungsi"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Ralat. Sila cuba lagi."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Tidak boleh disambungkan"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Ralat, terlalu banyak pertuturan."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Masalah audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Ralat pelayan"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Tiada pertuturan didengari"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Tiada padanan ditemui"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Carian suara tidak dipasang"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021">"Petunjuk"<b>":"</b>" Leret merentasi papan kekunci untuk bercakap"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Petunjuk:"</b>" Lain kali, cuba ucapkan tanda baca seperti \"titik\", \"koma\" atau \"tanda soal\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Batal"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Input suara"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Kunci anjak didayakan"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kunci huruf besar didayakan"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Kunci anjak dilumpuhkan"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mod simbol"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mod huruf"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mod telefon"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mod simbol telefon"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Kunci input suara"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Hidpkn kekunci utama"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pd ppn k’unci simbol"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Matikan"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. pd kekunci utma"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. pd kekunci smbl"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input suara dilmphkn"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Pilih kaedah input"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Luncurkan jari pada spacebar untuk menukar bahasa"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Sentuh sekali lagi untuk menyimpan"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Tanda cap waktu dalam log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Cap waktu direkodkan"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Jangan log sesi ini"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Memadam log sesi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Log sesi dipadam"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Log sesi TIDAK dipadam"</string>
+ <string name="select_language" msgid="3693815588777926848">"Bahasa input"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Dayakan maklum balas pengguna"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Bantu memperbaik editor input ini dengan menghantar statistik penggunaan dan laporan runtuhan kepada Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Sentuh untuk membetulkan perkataan"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Sentuh perkataan yang dimasukkan untuk membetulkannya, hanya apabila cadangan boleh dilihat"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema papan kekunci"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Papan kekunci Czech"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Papan kekunci bahasa Arab"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Papan kekunci Denmark"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Papan kekunci Jerman"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Papan kekunci QWERTY Jerman"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Papan kekunci Inggeris (UK)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Papan kekunci Inggeris (AS)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Papan kekunci Sepanyol"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Papan kekunci Finland"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Papan kekunci Perancis"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Papan kekunci Perancis (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Ppan kekunci Perancis (Switzerland)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Papan kekunci Croatia"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Papan kekunci Hungary"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Papan kekunci bahasa Ibrani"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Papan kekunci Itali"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Papan kekunci Norway"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Papan kekunci Belanda"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Papan kekunci Poland"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Papan kekunci Portugis"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Papan kekunci Rusia"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Papan kekunci Serbia"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Papan kekunci Sweden"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Papan kekunci Turki"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Suara Bahasa Afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Suara Orang Czech"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Suara Orang Jerman"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Suara Bahasa Inggeris"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Suara Orang Sepanyol"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Suara Orang Perancis"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Suara Bahasa Itali"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Suara Orang Jepun"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Suara Orang Korea"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Suara Bahasa Belanda"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Suara Orang Poland"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Suara Orang Portugis"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Suara Orang Rusia"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Suara Orang Turki"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Cina, Suara Bahasa Yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Cina, Suara Bahasa Mandarin"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Suara bahasa isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Bahasa Inggeris (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Bahasa Inggeris (AS)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Bahasa Inggeris (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Bahasa Inggeris (AS) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Tiada bahasa"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Tiada bahasa (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Tiada bahasa (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Tiada bahasa (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Tiada bahasa (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Tiada bahasa (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Tiada bahasa (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Gaya input peribadi"</string>
+ <string name="add_style" msgid="6163126614514489951">"Tambah gaya"</string>
+ <string name="add" msgid="8299699805688017798">"Tambah"</string>
+ <string name="remove" msgid="4486081658752944606">"Alih keluar"</string>
+ <string name="save" msgid="7646738597196767214">"Simpan"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Bahasa"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Reka Letak"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Gaya input tersuai anda perlu didayakan sebelum anda mula menggunakannya. Adakah anda ingin mendayakannya sekarang?"</string>
+ <string name="enable" msgid="5031294444630523247">"Dayakan"</string>
+ <string name="not_now" msgid="6172462888202790482">"Bukan sekarang"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Gaya input yang sama sudah wujud: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mod kajian kebolehgunaan"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Tetapan tempoh getaran tekan kekunci"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Tetapan kelantangan bunyi tekanan kekunci"</string>
</resources>
diff --git a/java/res/values-nb/donottranslate-altchars.xml b/java/res/values-nb/donottranslate-altchars.xml
deleted file mode 100644
index 798e51c9a..000000000
--- a/java/res/values-nb/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">à,ä,á,â,ã,ā</string>
- <string name="alternates_for_e">3,é,è,ê,ë,ę,ė,ē</string>
- <string name="alternates_for_o">9,ô,ò,ó,ö,õ,œ,ō</string>
- <string name="alternates_for_u">7,ü,û,ù,ú,ū</string>
- <string name="keylabel_for_scandinavia_row2_10">ø</string>
- <string name="keylabel_for_scandinavia_row2_11">æ</string>
- <string name="alternates_for_scandinavia_row2_10">ö</string>
- <string name="alternates_for_scandinavia_row2_11">ä</string>
-</resources>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 881a95cd3..fc2bd5539 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -21,61 +21,69 @@
<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">"Skjermtastatur"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Innstillinger for skjermtastatur"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Kommandoer for undersøkelseslogging"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-stavekontroll"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontroll (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Innstillinger for stavekontroll"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå opp kontaktnavn"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruker oppføringer fra kontaktlisten din"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer ved tastetrykk"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetrykk"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Hurtigvindu ved tastetrykk"</string>
<string name="general_category" msgid="1859088467017573195">"Generelt"</string>
<string name="correction_category" msgid="2236750915056607613">"Tekstkorrigering"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Forslag basert på tidligere ord"</string>
<string name="misc_category" msgid="6894192814868233453">"Andre alternativer"</string>
<string name="advanced_settings" msgid="362895144495591463">"Avanserte innstillinger"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Alternativer for ekspertbrukere"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Alternativer for eksperter"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Bytt inndatametode"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasten for språkbytte dekker også andre inndatametoder"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Skjul språkbyttetasten"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tregt tastevindu"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"U/ forsinkelse"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå kontaktnavn"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Bruk navn fra Kontakter til forslag og korrigeringer"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Aktiver korrigeringer"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angi forslag for korrigeringer"</string>
<string name="auto_cap" msgid="1719746674854628252">"Stor forbokstav"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurer ordbøker"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Autokorrektur"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Retter vanlige stavefeil"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tilleggsordbøker"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Hovedordliste"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Vis rettingsforslag"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Vis ordforslag under skriving"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vis alltid"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Vis i stående modus"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Skjul alltid"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Bytt språk med mellomrom"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Vis innstillingsnøkkel"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatisk"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Vis alltid"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Skjul alltid"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automatisk retting"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Mellomromstast og skilletegn retter automat. feilstavede ord"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Av"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Omfattende"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Veldig aggressiv"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram-forslag"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Bruk forrige ord til å forbedre forslaget"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram-prediksjon"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Forslag til rettelser av neste ord"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Bruk forrige ord til å forbedre forslagene"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Forslag til neste ord"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Bruk forrige ord også for forslag"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string>
- <string name="label_go_key" msgid="1635148082137219148">"Gå"</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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mer"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift er aktivert"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock er aktivert"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift er på (trykk for å deaktivere)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock er på (trykk for å deaktivere)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Slett"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboler"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Bokstaver"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Taleinndata"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smilefjes"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punktum"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Venstre parentes"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Høyre parentes"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Kolon"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Utropstegn"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Spørsmålstegn"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dobbelt anførselstegn"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkelt anførselstegn"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Søk"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Prikk"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratrot"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Varemerke"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"c/o"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Stjerne"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Firkant"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipse"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Lavt dobbelt anførselstegn"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Stemmedata"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Stemmedata håndteres foreløpig ikke på ditt språk, men fungerer på engelsk."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Google Voice bruker Googles talegjenkjenning. "<a href="http://m.google.com/privacy">"Personvernreglene for mobil"</a>" gjelder."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Gå til innstillinger for inndatametode for å slå av stemmedata."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Trykk på mikrofonknappen for å aktivere stemmedata."</string>
- <string name="voice_listening" msgid="467518160751321844">"Snakk nå"</string>
- <string name="voice_working" msgid="6666937792815731889">"Arbeider"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Feil. Prøv på nytt."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke koble til"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Feil – for mye tale"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Lydproblem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Tjenerfeil"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Ingen tale høres"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Ingen treff"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Talesøk ikke installert"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021">"Hint:"<b>" Sveip over tastaturet for å snakke"</b></string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" Neste gang kan du prøve å tale inn tegnsettingen ved for eksempel å si «punktum», «komma» eller «spørsmålstegn»."</string>
- <string name="cancel" msgid="6830980399865683324">"Avbryt"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Talekommando"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift er aktivert"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock er aktivert"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift er deaktivert"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolmodus"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Bokstavmodus"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Ringemodus"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Ringemodus med symboler"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tast for taleinndata"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På hovedtastatur"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På talltastatur"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Av"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon på hovedtast."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon på talltastatur"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Taleinndata er deaktiv."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Velg inndatametode"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Inndataspråk"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Dra fingeren på mellomromstasten for å endre språk"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"Trykk på nytt for å lagre"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Notér tidsstempel i logg"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Registrerte tidsstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ikke loggfør denne økten"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sletter øktloggen"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Øktloggen ble slettet"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Øktloggen ble IKKE slettet"</string>
+ <string name="select_language" msgid="3693815588777926848">"Inndataspråk"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Trykk på nytt for å lagre"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Aktiver brukertilbakemelding"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Ved å sende bruksstatistikk og programstopprapporter til Google automatisk, hjelper du oss med å gjøre redigeringsfunksjonen for denne inndatametoden enda bedre."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Trykk for å endre ord"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Når forslag er synlige, kan du trykke på ord du har skrevet inn, for å endre dem"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tsjekkisk tastatur"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabisk tastatur"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Dansk tastatur"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Tysk tastatur"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Tysk QWERTY-tastatur"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Engelsk tastatur (Storbritannia)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Engelsk tastatur (USA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spansk tastatur"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finsk tastatur"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Fransk tastatur"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Fransk tastatur (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Fransk tastatur (Sveits)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatisk tastatur"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ungarsk tastatur"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebraisk tastatur"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italiensk tastatur"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norsk tastatur"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Nederlandsk tastatur"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polsk tastatur"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugisisk tastatur"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russisk tastatur"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbisk tastatur"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Svensk tastatur"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Tyrkisk tastatur"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaans tale"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Tsjekkisk tale"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Tysk tale"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Engelsk tale"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spansk tale"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Fransk tale"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italiensk stemme"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japansk tale"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Koreansk tale"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Nederlandsk stemme"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Polsk tale"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugisisk tale"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russisk tale"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Tyrkisk tale"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Kinesisk (yue) tale"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Kinesisk (mandarin) tale"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu tale"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannia)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Engelsk (Storbritannia) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Engelsk (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Ingen språk"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Ingen språk (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Ingen språk (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Ingen språk (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Ingen språk (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Ingen språk (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Ingen språk (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Egendefinerte inndata"</string>
+ <string name="add_style" msgid="6163126614514489951">"Legg til stil"</string>
+ <string name="add" msgid="8299699805688017798">"Legg til"</string>
+ <string name="remove" msgid="4486081658752944606">"Fjern"</string>
+ <string name="save" msgid="7646738597196767214">"Lagre"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Språk"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Oppsett"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Tilpasset inndatastil må aktiveres før bruk. Vil du aktivere nå?"</string>
+ <string name="enable" msgid="5031294444630523247">"Aktiver"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ikke nå"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Inndatastilen finnes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Nyttighetsmodus"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Innstillinger for vibrasjonsvarighet ved tastetrykk"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Innstillinger for lydstyrke ved tastetrykk"</string>
</resources>
diff --git a/java/res/values-nl/donottranslate-altchars.xml b/java/res/values-nl/donottranslate-altchars.xml
deleted file mode 100644
index e26a74967..000000000
--- a/java/res/values-nl/donottranslate-altchars.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">á,ä,â,à,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,é,ë,ê,è,ę,ė,ē</string>
- <string name="alternates_for_i">8,í,ï,ì,î,į,ī</string>
- <string name="alternates_for_o">9,ó,ö,ô,ò,õ,œ,ø,ō</string>
- <string name="alternates_for_u">7,ú,ü,û,ù,ū</string>
- <string name="alternates_for_n">ñ,ń</string>
-</resources>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index fd1dd7cbe..26d5e3f20 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -21,61 +21,69 @@
<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">"Android-toetsenbord"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-toetsenbord (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Instellingen voor Android-toetsenbord"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Opdrachten in onderzoekslogbestand"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Spellingcontrole van Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Spellingcontrole van Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Instellingen voor spellingcontrole"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Contactnamen opzoeken"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"De spellingcontrole gebruikt items uit uw contactenlijst"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Trillen bij toetsaanslag"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Geluid bij toetsaanslag"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bij toetsaanslag"</string>
<string name="general_category" msgid="1859088467017573195">"Algemeen"</string>
<string name="correction_category" msgid="2236750915056607613">"Tekstcorrectie"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Suggesties op basis van eerdere woorden"</string>
<string name="misc_category" msgid="6894192814868233453">"Andere opties"</string>
<string name="advanced_settings" msgid="362895144495591463">"Geavanceerde instellingen"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opties voor ervaren gebruikers"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opties voor experts"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Invoermeth. overschakelen"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Schakelknop voor taal ook van toepassing op andere invoermethoden"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Taal schakelen onderdr."</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Afwijz.vertr. toetspop-up"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen vertraging"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standaard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Contactnamen suggereren"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen uit Contacten gebruiken voor suggesties en correcties"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Verbeteringen inschakelen"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Suggesties instellen voor verbeteringen"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-hoofdlettergebruik"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Woordenboeken configureren"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Snelle oplossingen"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Hiermee worden veelvoorkomende typefouten gecorrigeerd"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Woordenboeken toevoegen"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Algemeen woordenboek"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Correctievoorstellen weergeven"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Voorgestelde woorden weergeven tijdens typen"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Altijd weergeven"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Weergeven in staande modus"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Altijd verbergen"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Taal schakelen via spatiebalk"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Instellingscode weergeven"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatisch"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Altijd weergeven"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Altijd verbergen"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autocorrectie"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Met spatiebalk en interpunctie worden verkeerd gespelde woorden automatisch gecorrigeerd"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Uitgeschakeld"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Normaal"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressief"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Zeer agressief"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Digram-suggesties"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Vorig woord gebruiken om suggestie te verbeteren"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Digram-voorspelling"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Volgende woordsuggesties"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Vorig woord gebruiken om suggesties te verbeteren"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Volgende woordvoorspelling"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Het voorgaande woord ook voor voorspelling gebruiken"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Meer"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift ingeschakeld"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock ingeschakeld"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aan (tik om uit te schakelen)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock aan (tik om uit te schakelen)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Verwijderen"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbolen"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Letters"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Spraakinvoer"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley-gezichtje"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punt"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Linkerhaakje"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Rechterhaakje"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dubbele punt"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Puntkomma"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uitroepteken"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Vraagteken"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dubbele aanhalingstekens"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkel aanhalingsteken"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Zoeken"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Stip"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Vierkantswortel"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Handelsmerk"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Ten attentie van"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Ster"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Hekje"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Weglatingsteken"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Lage dubbele aanhalingstekens"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Spraakinvoer"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Spraakinvoer wordt momenteel niet ondersteund in uw taal, maar is wel beschikbaar in het Engels."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Spraakinvoer maakt gebruik van de spraakherkenning van Google. Het "<a href="http://m.google.com/privacy">"Privacybeleid van Google Mobile"</a>" is van toepassing."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Als u spraakinvoer wilt uitschakelen, gaat u naar de instellingen voor invoermethoden."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Druk op de microfoontoets om spraakinvoer te gebruiken."</string>
- <string name="voice_listening" msgid="467518160751321844">"Nu spreken"</string>
- <string name="voice_working" msgid="6666937792815731889">"Wordt uitgevoerd"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Fout. Probeer het opnieuw."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Kan geen verbinding maken"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Fout, te lange spraakinvoer."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Audioprobleem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Serverfout"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Geen spraak te horen"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Geen resultaten gevonden"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Spraakgestuurd zoeken is niet geïnstalleerd"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hint:"</b>" schuif over het toetsenbord om te spreken"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" spreek de volgende keer interpunctie uit, zoals \'period\' (punt), \'comma\' (komma) of \'question mark\' (vraagteken)."</string>
- <string name="cancel" msgid="6830980399865683324">"Annuleren"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Spraakinvoer"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ingeschakeld"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock ingeschakeld"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift uitgeschakeld"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolen"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Alfanumeriek toetsenbord"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Toetsenbord telefoon"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefoonsymbolen"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Sleutel voor spraakinvoer"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Op hoofdtoetsenbord"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Op symbooltoetsenb."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Uitgeschakeld"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic op hoofdtoetsb."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic op symb.toetsb."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spraakinvoer is uit"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Invoermethode selecteren"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Schuif uw vinger over de spatiebalk om de taal te wijzigen"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Raak nogmaals aan om op te slaan"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Tijdstempel opnemen in logbestand"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Opgenomen tijdstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Sessie niet registreren"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sessielogbestand verwijderen"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sessielogbestand verwijderd"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sessielogbestand NIET verwijderd"</string>
+ <string name="select_language" msgid="3693815588777926848">"Invoertalen"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak nogmaals aan om op te slaan"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Gebruikersfeedback inschakelen."</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Help deze invoermethode te verbeteren door automatisch gebruiksstatistieken en crashmeldingen naar Google te verzenden."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Raak aan om woorden te corrigeren"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Ingevoerde woorden aanraken om ze te verbeteren, alleen mogelijk wanneer suggesties zichtbaar zijn"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Toetsenbordthema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tsjechisch toetsenbord"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabisch toetsenbord"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Deens toetsenbord"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Duits toetsenbord"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Duits QWERTY-toetsenbord"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Engels toetsenbord (VK)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Engels toetsenbord (VS)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spaans toetsenbord"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Fins toetsenbord"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Frans toetsenbord"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Frans toetsenbord (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Frans toetsenbord (Zwitserland)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatisch toetsenbord"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Hongaars toetsenbord"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebreeuws toetsenbord"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italiaans toetsenbord"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Noors toetsenbord"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Nederlands toetsenbord"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Pools toetsenbord"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugees toetsenbord"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russisch toetsenbord"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Servisch toetsenbord"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Zweeds toetsenbord"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turks toetsenbord"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaanse stem"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Tsjechische stem"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Duitse stem"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Engelse stem"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spaanse stem"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Franse stem"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italiaanse stem"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japanse stem"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Koreaanse stem"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Nederlandse stem"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Poolse stem"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portugese stem"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russische stem"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Turkse stem"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Chinese stem (Yue)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Chinese stem (Mandarijn)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu stem"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engels (GB)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Engels (VK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Engels (VS) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Geen taal"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Geen taal (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Geen taal (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Geen taal (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Geen taal (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Geen taal (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Geen taal (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Aangep. invoerstijlen"</string>
+ <string name="add_style" msgid="6163126614514489951">"Stijl toev."</string>
+ <string name="add" msgid="8299699805688017798">"Toevoegen"</string>
+ <string name="remove" msgid="4486081658752944606">"Verwijderen"</string>
+ <string name="save" msgid="7646738597196767214">"Opslaan"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Taal"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Lay-out"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"U moet uw aangepaste invoerstijl inschakelen voor u deze kunt gebruiken. Wilt u de invoerstijl nu inschakelen?"</string>
+ <string name="enable" msgid="5031294444630523247">"Inschakelen"</string>
+ <string name="not_now" msgid="6172462888202790482">"Niet nu"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Dezelfde invoerstijl bestaat al: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus voor gebruiksvriendelijkheidsonderzoek"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Instellingen voor trillingsduur bij druk op een toets"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Instellingen voor geluidsvolume bij druk op een toets"</string>
</resources>
diff --git a/java/res/values-pl/donottranslate-altchars.xml b/java/res/values-pl/donottranslate-altchars.xml
deleted file mode 100644
index 971d73bc5..000000000
--- a/java/res/values-pl/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">ą,á,à,â,ä,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,ę,è,é,ê,ë,ė,ē</string>
- <string name="alternates_for_o">9,ó,ö,ô,ò,õ,œ,ø,ō</string>
- <string name="alternates_for_s">ś,ß,š</string>
- <string name="alternates_for_n">ń,ñ</string>
- <string name="alternates_for_c">ć,ç,č</string>
- <string name="alternates_for_z">ż,ź,ž</string>
- <string name="alternates_for_l">ł</string>
-</resources>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 2d6ec85b8..dc4f396a7 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -21,61 +21,69 @@
<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">"Klawiatura Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klawiatura Androida (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ustawienia klawiatury Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Polecenia dziennika badań"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Słownik Androida"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Sprawdzanie pisowni na Androidzie (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ustawienia sprawdzania pisowni"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj kontakty"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów."</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Wibracja przy naciśnięciu"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Dźwięk przy naciśnięciu"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Powiększ po naciśnięciu"</string>
<string name="general_category" msgid="1859088467017573195">"Ogólne"</string>
<string name="correction_category" msgid="2236750915056607613">"Poprawianie tekstu"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Podpowiedzi na podstawie wcześniejszych słów"</string>
<string name="misc_category" msgid="6894192814868233453">"Inne opcje"</string>
<string name="advanced_settings" msgid="362895144495591463">"Ustawienia zaawansowane"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcje dla zaawansowanych użytkowników"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcje dla ekspertów"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Włącz inne metody wprowadzania"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klawisz zmiany języka obejmuje też inne metody wprowadzania"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Wyłącz klawisz zmiany języka"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Opóźnienie znikania klawiszy"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez opóźnienia"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Wartość domyślna"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Proponuj osoby z kontaktów"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"W propozycjach i poprawkach użyj nazwisk z kontaktów"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Włącz poprawki"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ustaw sugestie poprawek"</string>
<string name="auto_cap" msgid="1719746674854628252">"Wstawiaj wielkie litery"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfiguruj słowniki"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Szybkie poprawki"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Poprawia częste błędy wpisywania"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dodatkowe słowniki"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Słownik główny"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Pokazuj propozycje poprawek"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Wyświetl proponowane słowa podczas wpisywania"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Zawsze pokazuj"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Pokaż w trybie pionowym"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Zawsze ukrywaj"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Spacja przełącza język"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Pokaż klawisz ustawień"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatycznie"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Zawsze pokazuj"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Zawsze ukrywaj"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autokorekta"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Spacja i znaki przestankowe poprawiają błędnie wpisane słowa"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Wyłącz"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Umiarkowana"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresywna"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Bardzo agresywna"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Podpowiadanie dwuznaków"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Używaj poprzedniego wyrazu, aby polepszyć sugestię"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Przewidywanie dwuznaków"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestie kolejnych słów"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Używaj poprzedniego wyrazu, by polepszyć sugestie"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Przewidywanie następnego wyrazu"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Przewiduj również na podstawie poprzedniego słowa"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Więcej"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift włączony"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock włączony"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift włączony (kliknij, by wyłączyć)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock włączony (kliknij, by wyłączyć)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Usuń"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbole"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Litery"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Wprowadzanie głosowe"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Uśmiechnięta buźka"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Przecinek"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Kropka"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Lewy nawias"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Prawy nawias"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dwukropek"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Średnik"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Wykrzyknik"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Pytajnik"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Cudzysłów podwójny"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Cudzysłów pojedynczy"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Szukaj"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Pierwiastek kwadratowy"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Znak towarowy"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Znak „przez grzeczność”"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Gwiazdka"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Krzyżyk"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Wielokropek"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Cudzysłów podwójny dolny"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Wprowadzanie głosowe"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Wprowadzanie głosowe obecnie nie jest obsługiwane w Twoim języku, ale działa w języku angielskim."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Funkcja wprowadzania głosowego wykorzystuje mechanizm rozpoznawania mowy. Obowiązuje "<a href="http://m.google.com/privacy">"Polityka prywatności w usługach mobilnych"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Aby wyłączyć rozpoznawanie mowy, przejdź do ustawień sposobu wprowadzania tekstu."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Aby użyć wprowadzania głosowego, naciśnij przycisk mikrofonu."</string>
- <string name="voice_listening" msgid="467518160751321844">"Mów teraz"</string>
- <string name="voice_working" msgid="6666937792815731889">"W toku"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Błąd. Spróbuj ponownie."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Nie można nawiązać połączenia"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Błąd, zbyt długa wypowiedź."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problem z dźwiękiem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Błąd serwera"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nie wykryto mowy"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Brak wyników"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Wyszukiwanie głosowe nie jest zainstalowane"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Wskazówka:"</b>" przesuń palcem po klawiaturze, aby mówić."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Wskazówka:"</b>" następnym razem spróbuj wypowiadać nazwy znaków interpunkcyjnych: „kropka”, „przecinek” lub „pytajnik”."</string>
- <string name="cancel" msgid="6830980399865683324">"Anuluj"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Wprowadzanie głosowe"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift włączony"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock włączony"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift wyłączony"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Tryb symboli"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Tryb liter"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Tryb telefonu"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Tryb symboli telefonu"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Klawisz rozpoznawania mowy"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na klawiaturze głównej"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klawiaturze z symbolami"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Wyłącz"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na klawiaturze głównej"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon na klawiaturze z symbolami"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Wprowadzanie głosowe jest wyłączone"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Wybierz sposób wprowadzania tekstu"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Przesuń palcem po spacji, aby zmienić język"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Dotknij ponownie, aby zapisać"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Znacznik czasu uwagi w dzienniku"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zapisano znacznik czasu"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nie rejestruj tej sesji"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Usuwanie dziennika sesji"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Usunięto dziennik sesji"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Dziennik sesji NIEUSUNIĘTY"</string>
+ <string name="select_language" msgid="3693815588777926848">"Języki wprowadzania"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotknij ponownie, aby zapisać"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Włącz przesyłanie opinii użytkownika"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Pomóż ulepszyć edytor wprowadzania tekstu, automatycznie wysyłając do Google statystyki użycia i raporty o awariach."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Popraw dotknięte słowo"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Dotykaj wprowadzonych słów, aby je poprawiać tylko wówczas, gdy widoczne są sugestie."</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Motyw klawiatury"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Klawiatura czeska"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Klawiatura arabska"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Klawiatura duńska"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Klawiatura niemiecka"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Niemiecka klawiatura QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Klawiatura angielska (UK)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Klawiatura angielska (USA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Klawiatura hiszpańska"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Klawiatura fińska"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Klawiatura francuska"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Klawiatura francuska (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Klawiatura francuska (Szwajcaria)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Klawiatura chorwacka"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Klawiatura węgierska"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Klawiatura hebrajska"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Klawiatura włoska"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Klawiatura norweska"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Klawiatura holenderska"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Klawiatura polska"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Klawiatura portugalska"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Klawiatura rosyjska"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Klawiatura serbska"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Klawiatura szwedzka"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Klawiatura turecka"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Mowa afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Mowa czeska"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Mowa niemiecka"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Mowa angielska"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Mowa hiszpańska"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Mowa francuska"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Mowa włoska"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Mowa japońska"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Mowa koreańska"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Mowa holenderska"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Mowa polska"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Mowa portugalska"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Mowa rosyjska"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Mowa turecka"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Mowa chińska (kantoński)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Mowa chińska (mandaryński)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Mowa isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Angielska (Wielka Brytania)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Angielska (Stany Zjednoczone)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"angielski (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"angielski (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Brak języka"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Brak języka (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Brak języka (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Brak języka (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Brak języka (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Brak języka (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Brak języka (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Style niestandardowe"</string>
+ <string name="add_style" msgid="6163126614514489951">"Dodaj styl"</string>
+ <string name="add" msgid="8299699805688017798">"Dodaj"</string>
+ <string name="remove" msgid="4486081658752944606">"Usuń"</string>
+ <string name="save" msgid="7646738597196767214">"Zapisz"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Język"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Układ"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Niestandardowy styl wprowadzania trzeba przed użyciem włączyć. Zrobić to teraz?"</string>
+ <string name="enable" msgid="5031294444630523247">"Włącz"</string>
+ <string name="not_now" msgid="6172462888202790482">"Nie teraz"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Taki styl wprowadzania już istnieje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tryb badania przydatności"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Czas trwania wibracji przy naciśnięciu"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Głośność dźwięku przy naciśnięciu"</string>
</resources>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index df8bec9b3..35eedd82a 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -21,61 +21,69 @@
<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">"Teclado do Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Definições de teclado do Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opções de introdução"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos de Reg. Invest."</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Verificador ortográfico do Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificador ortográfico do Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Definições da verificação ortográfica"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Procurar nomes de contac."</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico utiliza entradas da sua lista de contactos"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao primir as teclas"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Som ao premir as teclas"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Mostrar popup ao premir tecla"</string>
<string name="general_category" msgid="1859088467017573195">"Geral"</string>
<string name="correction_category" msgid="2236750915056607613">"Correção de texto"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Sugestões baseadas em palavras anteriores"</string>
<string name="misc_category" msgid="6894192814868233453">"Outras opções"</string>
<string name="advanced_settings" msgid="362895144495591463">"Definições avançadas"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opções para utilizadores experientes"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opções para especialistas"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Mudar p/ outros mét. ent."</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla de mudança de idioma abrange outros métodos de entrada"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suprimir tecla alt idioma"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Atraso p/ ignorar pop-up"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinido"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de Contactos"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nomes dos Contactos para sugestões e correções"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Ativar correções"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Definir sugestões para correções"</string>
<string name="auto_cap" msgid="1719746674854628252">"Letras maiúsculas automáticas"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configurar dicionários"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Correcções rápidas"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige os erros de escrita comuns"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dicionários extras"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Dicionário principal"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugestões de correcção"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Apresentar sugestões de palavras ao escrever"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar no modo de retrato"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar sempre"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Utilizar barra esp. alt. idioma"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla das definições"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automático"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mostrar sempre"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Ocultar sempre"</string>
<string name="auto_correction" msgid="4979925752001319458">"Auto correcção"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Correcção automática de palavras mal escritas c/ barra de espaços e pontuação"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desligar"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderada"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressiva"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Sugestões Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utilizar a palavra anterior para melhorar a sugestão"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Predição Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestões da palavra seguinte"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilizar palavra anterior para melhorar sugestões"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Previsão da palavra seguinte"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar a palavra anterior também para predição"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string>
<string name="label_done_key" msgid="2441578748772529288">"Feito"</string>
<string name="label_send_key" msgid="2815056534433717444">"Enviar"</string>
<string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mais"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift ativado"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock ativado"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ativado (tocar para desativar)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock ativado (tocar para desativar)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Cara sorridente"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Vírgula"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Ponto final"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parêntese esquerdo"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parêntese direito"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dois pontos"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Ponto e vírgula"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ponto de exclamação"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Ponto de interrogação"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Aspas"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Plica"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Pesquisar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Raiz quadrada"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marca comercial"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Ao cuidado de"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Marcar com estrela"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Cardinal"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Reticências"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Aspas duplas baixas"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Entrada de voz"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualmente, a entrada de voz não é suportada para o seu idioma, mas funciona em inglês."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"A entrada de voz utiliza o reconhecimento de voz da Google. É aplicável a "<a href="http://m.google.com/privacy">"Política de privacidade do Google Mobile"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desactivar a entrada de voz, aceda às definições do método de entrada."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para utilizar a entrada de voz, prima o botão do microfone."</string>
- <string name="voice_listening" msgid="467518160751321844">"Falar agora"</string>
- <string name="voice_working" msgid="6666937792815731889">"A executar"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Não foi possível ligar"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, discurso demasiado longo."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema de áudio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Erro no servidor"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nenhuma voz ouvida"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Não foram encontradas correspondências"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Pesquisa de voz não instalada"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugestão:"</b>" Deslize no teclado para falar"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugestão:"</b>" Da próxima vez, experimente dizer a pontuação como \"ponto final\", \"vírgula\" ou \"ponto de interrogação\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Entrada de voz"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift desativado"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo de símbolos"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo de letras"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo de telemóvel"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo de símbolos de telemóvel"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Chave de entrada de voz"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"No teclado principal"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"No teclado símbolos"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Desligar"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. tecl. principal"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic. tecl. símbolos"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. voz desact."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Selecionar método de entrada"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Deslize o dedo pela barra de espaço para alterar o idioma"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Toque novamente para guardar"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Anotar car. data no reg."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Carimbo de data gravado"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Não registar esta sessão"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"A eliminar reg. da sessão"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Reg. de sessão eliminado"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Reg. de sessão NÃO elim."</string>
+ <string name="select_language" msgid="3693815588777926848">"Idiomas de introdução"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para guardar"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Activar comentários do utilizador"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Envie automaticamente estatísticas de utilização e relatórios de falhas para a Google e ajude-nos a melhorar este editor de método de introdução."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tocar para corrigir palavras"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Tocar nas palavras introduzidas para as corrigir, apenas quando as sugestões estiverem visíveis"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Teclado checo"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Teclado Árabe"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Teclado dinamarquês"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Teclado alemão"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Teclado QWERTY Alemão"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Teclado inglês (Reino Unido)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Teclado inglês (EUA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Teclado espanhol"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Teclado Finlandês"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Teclado francês"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Teclado francês (Canadá)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Teclado francês (Suíça)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Teclado Croata"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Teclado Húngaro"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Teclado Hebraico"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Teclado italiano"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Teclado norueguês"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Teclado holandês"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Teclado Polaco"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Teclado Português"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Teclado russo"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Teclado sérvio"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Teclado sueco"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Teclado Turco"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voz em africânder"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voz checa"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voz alemã"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voz em inglês"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voz espanhola"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voz francesa"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voz italiana"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voz japonesa"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voz coreana"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voz holandesa"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voz polaca"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voz portuguesa"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voz russa"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voz turca"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voz em yue, chinês"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voz em mandarim, chinês"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voz em isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (RU)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglês (RU) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglês (EUA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Nenhum idioma"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nenhum idioma (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nenhum idioma (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nenhum idioma (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nenhum idioma (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nenh. idioma (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nenhum idioma (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos entrada pers."</string>
+ <string name="add_style" msgid="6163126614514489951">"Adic. estilo"</string>
+ <string name="add" msgid="8299699805688017798">"Adicionar"</string>
+ <string name="remove" msgid="4486081658752944606">"Remover"</string>
+ <string name="save" msgid="7646738597196767214">"Guardar"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Esquema"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Tem de ativar o estilo de introdução personalizado antes de o usar. Quer ativar?"</string>
+ <string name="enable" msgid="5031294444630523247">"Ativar"</string>
+ <string name="not_now" msgid="6172462888202790482">"Agora não"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Já existe o mesmo estilo de introdução: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo da capacidade de utilização"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Definições de duração da vibração ao premir as teclas"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Definições de volume de som ao premir as teclas"</string>
</resources>
diff --git a/java/res/values-pt/donottranslate-altchars.xml b/java/res/values-pt/donottranslate-altchars.xml
deleted file mode 100644
index a39976151..000000000
--- a/java/res/values-pt/donottranslate-altchars.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">á,ã,à,â,ä,å,æ,ª</string>
- <string name="alternates_for_e">3,é,ê,è,ę,ė,ē,ë</string>
- <string name="alternates_for_i">8,í,î,ì,ï,į,ī</string>
- <string name="alternates_for_o">9,ó,õ,ô,ò,ö,œ,ø,ō,º</string>
- <string name="alternates_for_u">7,ú,ü,ù,û,ū</string>
- <string name="alternates_for_c">ç,č,ć</string>
-</resources>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 072c881b8..a12fc23e1 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -21,61 +21,69 @@
<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">"Teclado Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Configurações de teclado Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opções de entrada"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Pesq. comandos de reg."</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Corretor ortográfico do Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corretor ortográfico do Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Configurações de verificação ortográfica"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nomes de contatos"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico usa entradas de sua lista de contatos"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar a tecla"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Som ao tocar a tecla"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Exibir pop-up ao digitar"</string>
<string name="general_category" msgid="1859088467017573195">"Geral"</string>
<string name="correction_category" msgid="2236750915056607613">"Correção de texto"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Sugestões baseadas em palavras anteriores"</string>
<string name="misc_category" msgid="6894192814868233453">"Outras opções"</string>
<string name="advanced_settings" msgid="362895144495591463">"Configurações avançadas"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opções para usuários experientes"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opções para especialistas"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Outros métodos de entrada"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla p/ mudar o idioma também cobre outros métodos de entrada"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Ocult. tecla mudar idioma"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Dispens. atraso chave princ."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Padrão"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de contato"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nomes dos Contatos para sugestões e correções"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Ativar recorreções"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Definir sugestões para recorreções"</string>
<string name="auto_cap" msgid="1719746674854628252">"Capitaliz. automática"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configurar dicionários"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Reparos rápidos"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige erros comuns de digitação"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dicionários complementares"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Dicionário principal"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Exibir sugestões de correção"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Exibir sugestões de palavras durante a digitação"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar em modo retrato"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sempre ocultar"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Alternar idioma com a barra de espaço"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla de config."</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automático"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Mostrar sempre"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Sempre ocultar"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autocorreção"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"A barra de espaço e a pontuação corrigem automaticamente palavras com erro de digitação"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desativado"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressivo"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Sugestões de bigrama"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Usar palavra anterior para melhorar a sugestão"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Previsão de bigrama"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestões p/ palavra seguinte"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palavra anterior para melhorar as sugestões"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Previsão da palavra seguinte"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Use também a palavra anterior para prever"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mais"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift ativado"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock ativado"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ativado (toque para desativar)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock ativado (toque para desativar)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Excluir"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Carinha sorridente"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Voltar"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Vírgula"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Ponto final"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parêntese esquerdo"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parêntese direito"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dois pontos"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Ponto e vírgula"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ponto de exclamação"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Ponto de interrogação"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Aspa dupla"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Aspa simples"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Pesquisar"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Raiz quadrada"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marca registrada"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Porcentagem"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Asterisco"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Sustenido"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Reticências"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Aspas duplas inferiores"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Entrada de voz"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"A entrada de voz não é suportada no momento para o seu idioma, mas funciona em inglês."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"A entrada de texto por voz usa o reconhecimento de voz do Google. "<a href="http://m.google.com/privacy">"A política de privacidade para celulares"</a>" é aplicada."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desativar a entrada de texto por voz, vá para configurações do método de entrada."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para usar a entrada de texto por voz, pressione o botão do microfone."</string>
- <string name="voice_listening" msgid="467518160751321844">"Fale agora"</string>
- <string name="voice_working" msgid="6666937792815731889">"Trabalhando"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Não foi possível conectar"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, fala muito longa."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema com o áudio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Erro do servidor"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nenhuma fala ouvida"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Não há resultados compatíveis"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"A pesquisa por voz não está instalada"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Dica:"</b>" Deslize sobre o teclado para falar"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Dica:"</b>" Da próxima vez, tente falar o nome da pontuação como \"ponto\", \"vírgula\" ou \"ponto de interrogação\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Entrada de voz"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift desativado"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo de símbolos"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo de cartas"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo de telefone"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo de símbolos de telefone"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Chave de entrada de texto por voz"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"No teclado principal"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"No teclado de símb."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Desativado"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. no teclado"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic. no teclado"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Texto por voz desat."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Selecionar método de entrada"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Deslize o dedo na barra de espaços para alterar o idioma"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Toque novamente para salvar"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Indicar data/hora no reg."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Data/hora registrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Não registrar esta sessão"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Excluindo reg. de sessão"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registro excluído"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Registro NÃO excluído"</string>
+ <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para salvar"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Ativar comentário do usuário"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Ajude a melhorar este editor de método de entrada enviando automaticamente ao Google estatísticas de uso e relatórios de falhas."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tocar para corrigir"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Toque nas palavras digitadas para corrigi-las apenas quando as sugestões estiverem visíveis"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Teclado em tcheco"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Teclado árabe"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Teclado para dinamarquês"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Teclado para alemão"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Teclado QWERTY alemão"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Teclado para inglês (Reino Unido)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Teclado para inglês (EUA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Teclado para espanhol"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Teclado finlandês"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Teclado para francês"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Teclado para francês (Canadá)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Teclado para francês (Suíça)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Teclado croata"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Teclado húngaro"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Teclado hebraico"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Teclado para italiano"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Teclado para norueguês"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Teclado para holandês"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Teclado polonês"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Teclado em português"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Teclado para russo"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Teclado para sérvio"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Teclado para sueco"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Teclado turco"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voz em africâner"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voz em tcheco"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voz em alemão"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voz em inglês"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voz em espanhol"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voz em francês"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voz italiana"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voz em japonês"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voz em coreano"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voz holandesa"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voz em polonês"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voz em português"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voz em russo"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voz em turco"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voz em chinês, cantonês"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voz em chinês, mandarim"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voz em zulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (Reino Unido)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglês (Reino Unido) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglês (EUA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Sem idioma"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nenhum idioma (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nenhum idioma (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nenhum idioma (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nenhum idioma (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nenhum idioma (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nenhum idioma (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos personalizados"</string>
+ <string name="add_style" msgid="6163126614514489951">"Adic. estilo"</string>
+ <string name="add" msgid="8299699805688017798">"Adicionar"</string>
+ <string name="remove" msgid="4486081658752944606">"Remover"</string>
+ <string name="save" msgid="7646738597196767214">"Salvar"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Deseja ativar e usar o estilo de entrada personalizado?"</string>
+ <string name="enable" msgid="5031294444630523247">"Ativar"</string>
+ <string name="not_now" msgid="6172462888202790482">"Agora não"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"O estilo de entrada já existe: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo de utilização"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Configurações de duração da vibração ao tocar a tecla"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Config. volume ao tocar a tecla"</string>
</resources>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index 22dc2f3d4..c6c936e49 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -21,9 +21,23 @@
<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">"Tastatura Android"</string>
+ <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
+ <skip />
<string name="english_ime_settings" msgid="6661589557206947774">"Parameters da la tastatura Android"</string>
<!-- no translation found for english_ime_input_options (3909945612939668554) -->
<skip />
+ <!-- no translation found for english_ime_research_log (8492602295696577851) -->
+ <skip />
+ <!-- no translation found for spell_checker_service_name (7338064335159755926) -->
+ <skip />
+ <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
+ <skip />
+ <!-- no translation found for android_spell_checker_settings (5822324635435443689) -->
+ <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 />
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar cun smatgar in buttun"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Tun cun smatgar in buttun"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Pop-up cun smatgar ina tasta"</string>
@@ -31,13 +45,17 @@
<skip />
<!-- no translation found for correction_category (2236750915056607613) -->
<skip />
- <!-- no translation found for ngram_category (5337109164339320257) -->
- <skip />
<!-- no translation found for misc_category (6894192814868233453) -->
<skip />
<!-- no translation found for advanced_settings (362895144495591463) -->
<skip />
- <!-- no translation found for advanced_settings_summary (5193513161106637254) -->
+ <!-- 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 suppress_language_switch_key (8003788410354806368) -->
<skip />
<!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
<skip />
@@ -49,11 +67,15 @@
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
<skip />
+ <!-- no translation found for enable_span_insert (7204653105667167620) -->
+ <skip />
+ <!-- no translation found for enable_span_insert_summary (2947317657871394467) -->
+ <skip />
<string name="auto_cap" msgid="1719746674854628252">"Maiusclas automaticas"</string>
- <!-- no translation found for configure_dictionaries_title (3758288002414557345) -->
+ <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
+ <skip />
+ <!-- no translation found for main_dictionary (4798763781818361168) -->
<skip />
- <string name="quick_fixes" msgid="5353213327680897927">"Correcturas sveltas"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Curregia sbagls da tippar currents"</string>
<!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
<skip />
<!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
@@ -64,16 +86,6 @@
<skip />
<!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
<skip />
- <!-- no translation found for prefs_use_spacebar_language_switch (8828538114550634449) -->
- <skip />
- <!-- no translation found for prefs_settings_key (4623341240804046498) -->
- <skip />
- <!-- no translation found for settings_key_mode_auto_name (2993460277873684680) -->
- <skip />
- <!-- no translation found for settings_key_mode_always_show_name (3047567041784760575) -->
- <skip />
- <!-- no translation found for settings_key_mode_always_hide_name (7833948046716923994) -->
- <skip />
<!-- no translation found for auto_correction (4979925752001319458) -->
<skip />
<!-- no translation found for auto_correction_summary (5625751551134658006) -->
@@ -86,26 +98,33 @@
<skip />
<!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
<skip />
- <!-- no translation found for bigram_suggestion (2636414079905220518) -->
+ <!-- no translation found for bigram_suggestion (8169311444438922902) -->
<skip />
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Meglierar la proposta cun agid dal pled precedent"</string>
- <!-- no translation found for bigram_prediction (8914273444762259739) -->
+ <!-- no translation found for bigram_suggestion_summary (6635527607242625713) -->
+ <skip />
+ <!-- no translation found for bigram_prediction (3216364899483135294) -->
<skip />
<!-- no translation found for bigram_prediction_summary (1747261921174300098) -->
<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_to_alpha_key (4793983863798817523) -->
<skip />
- <!-- no translation found for label_more_key (3760239494604948502) -->
+ <!-- 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) -->
<skip />
<!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
@@ -114,9 +133,9 @@
<skip />
<!-- no translation found for spoken_description_shift (244197883292549308) -->
<skip />
- <!-- no translation found for spoken_description_shift_shifted (954941524766465022) -->
+ <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) -->
<skip />
- <!-- no translation found for spoken_description_caps_lock (5660626444912131764) -->
+ <!-- no translation found for spoken_description_caps_lock (3276478269526304432) -->
<skip />
<!-- no translation found for spoken_description_delete (8740376944276199801) -->
<skip />
@@ -138,70 +157,26 @@
<skip />
<!-- no translation found for spoken_description_return (8178083177238315647) -->
<skip />
- <!-- no translation found for spoken_description_comma (4970844442999724586) -->
- <skip />
- <!-- no translation found for spoken_description_period (5286614628077903945) -->
- <skip />
- <!-- no translation found for spoken_description_left_parenthesis (8524822120595052415) -->
- <skip />
- <!-- no translation found for spoken_description_right_parenthesis (1085757995851933164) -->
- <skip />
- <!-- no translation found for spoken_description_colon (4312420908484277077) -->
- <skip />
- <!-- no translation found for spoken_description_semicolon (37737920987155179) -->
- <skip />
- <!-- no translation found for spoken_description_exclamation_mark (2625684427460737157) -->
- <skip />
- <!-- no translation found for spoken_description_question_mark (7074097784255379666) -->
- <skip />
- <!-- no translation found for spoken_description_double_quote (5485320575389905967) -->
- <skip />
- <!-- no translation found for spoken_description_single_quote (4451320362665463938) -->
+ <!-- no translation found for spoken_description_search (1247236163755920808) -->
<skip />
<!-- no translation found for spoken_description_dot (40711082435231673) -->
<skip />
- <!-- no translation found for spoken_description_square_root (190595160284757811) -->
- <skip />
- <!-- no translation found for spoken_description_pi (4554418247799952239) -->
+ <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) -->
<skip />
- <!-- no translation found for spoken_description_delta (3607948313655721579) -->
+ <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) -->
<skip />
- <!-- no translation found for spoken_description_trademark (475877774077871369) -->
+ <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) -->
<skip />
- <!-- no translation found for spoken_description_care_of (7492800237237796530) -->
+ <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) -->
<skip />
- <!-- no translation found for spoken_description_star (1009742725387231977) -->
+ <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) -->
<skip />
- <!-- no translation found for spoken_description_pound (5530577649206922631) -->
+ <!-- no translation found for spoken_description_mode_phone (6520207943132026264) -->
<skip />
- <!-- no translation found for spoken_description_ellipsis (1687670869947652062) -->
+ <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) -->
<skip />
- <!-- no translation found for spoken_description_low_double_quote (3551394572784840975) -->
+ <!-- no translation found for voice_input (3583258583521397548) -->
<skip />
- <string name="voice_warning_title" msgid="4419354150908395008">"Cumonds vocals"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"\"Cumonds vocals en Vossa lingua na vegnan actualmain betg sustegnids, ma la funcziun è disponibla per englais.\""</string>
- <!-- no translation found for voice_warning_may_not_understand (5596289095878251072) -->
- <skip />
- <!-- no translation found for voice_warning_how_to_turn_off (3190378129944934856) -->
- <skip />
- <!-- no translation found for voice_hint_dialog_message (1420686286820661548) -->
- <skip />
- <string name="voice_listening" msgid="467518160751321844">"Ussa discurrer"</string>
- <string name="voice_working" msgid="6666937792815731889">"Operaziun en progress"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Errur. Empruvai anc ina giada."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Impussibel da connectar."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Errur - discurrì memia ditg."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problem audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Errur dal server"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Betg udì ina frasa vocala"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Betg chattà correspundenzas"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Betg installà la tschertga vocala"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Commentari:"</b>" Stritgai cun il det sur la tastatura per discurrer."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754">"\""<b>"Commentari:"</b>" Empruvai la proxima giada d\'agiuntar segns d\'interpuncziun sco \"\"punct\"\", \"\"comma\"\" u \"\"segn da dumonda\"\" cun cumonds vocals.\""</string>
- <string name="cancel" msgid="6830980399865683324">"Interrumper"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Cumonds vocals"</string>
<!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) -->
<skip />
<!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) -->
@@ -214,103 +189,78 @@
<skip />
<!-- no translation found for voice_input_modes_summary_off (63875609591897607) -->
<skip />
- <!-- no translation found for selectInputMethod (315076553378705821) -->
+ <!-- no translation found for configure_input_method (373356270290742459) -->
<skip />
<string name="language_selection_title" msgid="1651299598555326750">"Linguas da cumonds vocals"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Stritgar cun il det sur la tasta da vid per midar la lingua"</string>
- <!-- no translation found for hint_add_to_dictionary (9006292060636342317) -->
- <skip />
- <string name="has_dictionary" msgid="6071847973466625007">"Dicziunari disponibel"</string>
- <string name="prefs_enable_log" msgid="6620424505072963557">"Activar il feedback da l\'utilisader"</string>
- <string name="prefs_description_log" msgid="5827825607258246003">"Gidai a meglierar quest editur da la metoda d\'endataziun cun trametter automaticamain datas statisticas davart l\'utilisaziun e rapports da collaps a Google."</string>
- <!-- no translation found for prefs_enable_recorrection (4588408906649533582) -->
- <skip />
- <!-- no translation found for prefs_enable_recorrection_summary (5082041365862396329) -->
- <skip />
- <!-- no translation found for keyboard_layout (8451164783510487501) -->
- <skip />
- <!-- no translation found for subtype_mode_cs_keyboard (1141718931112377586) -->
+ <!-- no translation found for note_timestamp_for_researchlog (1889446857977976026) -->
<skip />
- <!-- no translation found for subtype_mode_ar_keyboard (2655338636329774995) -->
+ <!-- no translation found for notify_recorded_timestamp (8036429032449612051) -->
<skip />
- <!-- no translation found for subtype_mode_da_keyboard (1243570804427922104) -->
+ <!-- no translation found for do_not_log_this_session (413762473641146336) -->
<skip />
- <!-- no translation found for subtype_mode_de_keyboard (1990979135959462145) -->
+ <!-- no translation found for notify_session_log_deleting (3299507647764414623) -->
<skip />
- <!-- no translation found for subtype_mode_de_qwerty_keyboard (54890770769303956) -->
+ <!-- no translation found for notify_session_log_deleted (8687927130100934686) -->
<skip />
- <!-- no translation found for subtype_mode_en_GB_keyboard (7945856548410373708) -->
+ <!-- no translation found for notify_session_log_not_deleted (2592908998810755970) -->
<skip />
- <!-- no translation found for subtype_mode_en_US_keyboard (3708655163769735410) -->
+ <!-- no translation found for select_language (3693815588777926848) -->
<skip />
- <!-- no translation found for subtype_mode_es_keyboard (1775125478866113148) -->
+ <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
<skip />
- <!-- no translation found for subtype_mode_fi_keyboard (3198596464082614532) -->
- <skip />
- <!-- no translation found for subtype_mode_fr_keyboard (8016515336759761014) -->
- <skip />
- <!-- no translation found for subtype_mode_fr_CA_keyboard (2628517247158376263) -->
- <skip />
- <!-- no translation found for subtype_mode_fr_CH_keyboard (6742806653181621228) -->
- <skip />
- <!-- no translation found for subtype_mode_hr_keyboard (7177182405440070112) -->
- <skip />
- <!-- no translation found for subtype_mode_hu_keyboard (8843338355732633647) -->
- <skip />
- <!-- no translation found for subtype_mode_iw_keyboard (1787536828253289950) -->
- <skip />
- <!-- no translation found for subtype_mode_it_keyboard (4934199655425394484) -->
- <skip />
- <!-- no translation found for subtype_mode_nb_keyboard (1175783216100212360) -->
+ <string name="has_dictionary" msgid="6071847973466625007">"Dicziunari disponibel"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"Activar il feedback da l\'utilisader"</string>
+ <string name="prefs_description_log" msgid="5827825607258246003">"Gidai a meglierar quest editur da la metoda d\'endataziun cun trametter automaticamain datas statisticas davart l\'utilisaziun e rapports da collaps a Google."</string>
+ <!-- no translation found for keyboard_layout (8451164783510487501) -->
<skip />
- <!-- no translation found for subtype_mode_nl_keyboard (5090278083256037936) -->
+ <!-- no translation found for subtype_en_GB (88170601942311355) -->
<skip />
- <!-- no translation found for subtype_mode_pl_keyboard (2225816414814396047) -->
+ <!-- no translation found for subtype_en_US (6160452336634534239) -->
<skip />
- <!-- no translation found for subtype_mode_pt_keyboard (7503997804861754840) -->
+ <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) -->
<skip />
- <!-- no translation found for subtype_mode_ru_keyboard (1383995915064277943) -->
+ <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) -->
<skip />
- <!-- no translation found for subtype_mode_sr_keyboard (5019440799612208168) -->
+ <!-- no translation found for subtype_no_language (141420857808801746) -->
<skip />
- <!-- no translation found for subtype_mode_sv_keyboard (4933838139861753401) -->
+ <!-- no translation found for subtype_no_language_qwerty (2956121451616633133) -->
<skip />
- <!-- no translation found for subtype_mode_tr_keyboard (3155981874829226370) -->
+ <!-- no translation found for subtype_no_language_qwertz (1177848172397202890) -->
<skip />
- <!-- no translation found for subtype_mode_af_voice (7542487489657902699) -->
+ <!-- no translation found for subtype_no_language_azerty (8721460968141187394) -->
<skip />
- <!-- no translation found for subtype_mode_cs_voice (1136386688120958641) -->
+ <!-- no translation found for subtype_no_language_dvorak (3122976737669823935) -->
<skip />
- <!-- no translation found for subtype_mode_de_voice (8378803143958089866) -->
+ <!-- no translation found for subtype_no_language_colemak (4205992994906097244) -->
<skip />
- <!-- no translation found for subtype_mode_en_voice (6643420989651848728) -->
+ <!-- no translation found for subtype_no_language_pcqwerty (8840928374394180189) -->
<skip />
- <!-- no translation found for subtype_mode_es_voice (1323473601346507487) -->
+ <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
<skip />
- <!-- no translation found for subtype_mode_fr_voice (4675914209337824269) -->
+ <!-- no translation found for add_style (6163126614514489951) -->
<skip />
- <!-- no translation found for subtype_mode_it_voice (5077373057157441323) -->
+ <!-- no translation found for add (8299699805688017798) -->
<skip />
- <!-- no translation found for subtype_mode_ja_voice (6604859132669646367) -->
+ <!-- no translation found for remove (4486081658752944606) -->
<skip />
- <!-- no translation found for subtype_mode_ko_voice (4890391190762324561) -->
+ <!-- no translation found for save (7646738597196767214) -->
<skip />
- <!-- no translation found for subtype_mode_nl_voice (2603552312869575021) -->
+ <!-- no translation found for subtype_locale (8576443440738143764) -->
<skip />
- <!-- no translation found for subtype_mode_pl_voice (2076196021014840487) -->
+ <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
<skip />
- <!-- no translation found for subtype_mode_pt_voice (8036522712795994397) -->
+ <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
<skip />
- <!-- no translation found for subtype_mode_ru_voice (8034596947963787529) -->
+ <!-- no translation found for enable (5031294444630523247) -->
<skip />
- <!-- no translation found for subtype_mode_tr_voice (3402067436761140005) -->
+ <!-- no translation found for not_now (6172462888202790482) -->
<skip />
- <!-- no translation found for subtype_mode_yue_voice (1576887891614624263) -->
+ <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
<skip />
- <!-- no translation found for subtype_mode_zh_voice (4360533229467271152) -->
+ <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
<skip />
- <!-- no translation found for subtype_mode_zu_voice (1146122571698884636) -->
+ <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
<skip />
- <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
+ <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
<skip />
</resources>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 734237e23..523a855c7 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -21,61 +21,69 @@
<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">"Tastatură Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastatură Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Setările tastaturii Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opţiuni de introducere text"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comenzi jurnal cercetare"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Verificator ortografic Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificator ortografic Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Setări de verificare ortografică"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Verificare nume în agendă"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Verificatorul ortografic utilizează intrări din lista de contacte"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrare la apăsarea tastei"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Sunet la apăsarea tastei"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Fereastră pop-up la apăsarea tastei"</string>
<string name="general_category" msgid="1859088467017573195">"General"</string>
<string name="correction_category" msgid="2236750915056607613">"Corectare text"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Sugestii bazate pe cuvinte anterioare"</string>
<string name="misc_category" msgid="6894192814868233453">"Alte opţiuni"</string>
<string name="advanced_settings" msgid="362895144495591463">"Setări avansate"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Opţiuni pt. utiliz. experţi"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Opţiuni pentru experţi"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Comut. alte metode de introd."</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasta de comutare între limbi include şi alte metode de introd."</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suprim. tasta comut. limbi"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Înt. înch. pop-up esenţ."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fără întârziere"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Prestabilit"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugeraţi nume din Agendă"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizaţi numele din Agendă pentru sugestii şi corecţii"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Activaţi rectificările"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setaţi sugestii pentru rectificări"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalizare"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Configuraţi dicţionare"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Remedieri rapide"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Corectează greşelile introduse frecvent"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dicţionare suplimentare"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Dicţionar principal"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Afişaţi sugestii de corectare"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Afişaţi sugestii de cuvinte în timpul introducerii textului"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Afişaţi întotdeauna"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Afişaţi în modul Portret"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ascundeţi întotdeauna"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Spaţiul comută limba"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Afişaţi tasta setări"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automat"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Afişaţi întotdeauna"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Ascundeţi întotdeauna"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autocorecţie"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Corectare automată cuvinte prin bară spaţiu/semne punctuaţie"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Dezactivată"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderată"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivă"</string>
- <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Foarte agresiv"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Sugestii de tip bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utilizaţi cuvântul anterior pentru a îmbunătăţi sugestia"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Predicţii de tip bigram"</string>
+ <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Foarte exigentă"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestii pentru cuvântul următor"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilizaţi cuvântul anterior pentru a îmbunătăţi sugestiile"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Predicţia cuvântului următor"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Se utilizează şi cuvântul precedent pentru predicţii"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mai multe"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Shift activat"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock activat"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Tasta Shift este activată (apăsaţi pentru a o dezactiva)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Tasta Caps Lock este activată (apăsaţi pentru a o dezactiva)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboluri"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Litere"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Intrare vocală"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Faţă zâmbitoare"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Virgulă"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punct"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Paranteză închisă"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paranteză deschisă"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Două puncte"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Punct şi virgulă"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Semn de exclamaţie"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Semn de întrebare"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Ghilimele duble"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Ghilimele simple"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Căutaţi"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punct"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Rădăcină pătrată"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Marcă comercială"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"În atenţia"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Stea"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Diez"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Puncte de suspensie"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Ghilimele duble de deschidere"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Intrare voce"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Intrarea vocală nu este acceptată în prezent pentru limba dvs., însă funcţionează în limba engleză."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Intrarea vocală utilizează funcţia Google de recunoaştere vocală. Se aplică "<a href="http://m.google.com/privacy">"Politica de confidenţialitate Google Mobil"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Pentru a dezactiva intrarea vocală, accesaţi setările metodei de intrare."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Pentru a utiliza intrarea vocală, apăsaţi pe butonul Microfon."</string>
- <string name="voice_listening" msgid="467518160751321844">"Vorbiţi acum"</string>
- <string name="voice_working" msgid="6666937792815731889">"Se analizează"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Eroare. Încercaţi din nou."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Conectare imposibilă"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Eroare, discurs prea lung."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problemă audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Eroare de server"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nu s-a auzit vorbirea"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nicio potrivire"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Căutarea vocală nu este instalată"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Indiciu:"</b>" glisaţi de-a lungul tastaturii pentru a vorbi"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Indiciu:"</b>" data viitoare, încercaţi să rostiţi şi punctuaţia, cum ar fi „punct”, „virgulă”, sau „semn de întrebare”."</string>
- <string name="cancel" msgid="6830980399865683324">"Anulaţi"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Intrare voce"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Tasta Shift a fost activată"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Tasta Caps Lock a fost activată"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Tasta Shift a fost dezactivată"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modul Simboluri"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modul Alfanumeric"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modul Telefon"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modul Telefon cu simboluri"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tastă pentru intrarea vocală"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pe tastat. princip."</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pe tastat. simbol."</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Dezactivată"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. pe tast. princ."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micr. pe tast. simb."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Intr. vocală dezact."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Selectaţi metoda de introducere a textului"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configuraţi metodele de intrare"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Selectaţi limba"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Glisaţi degetul pe bara de spaţiu pentru a schimba limba"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Atingeţi din nou pentru a salva"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Înreg. marc. temp. jurnal"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marcaj temporal înregis."</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nu înregistraţi sesiunea"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Se șterge jurnal sesiune"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Jurnal de sesiune șters"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Jurnal sesiune neşters"</string>
+ <string name="select_language" msgid="3693815588777926848">"Limbi de intrare"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Atingeţi din nou pentru a salva"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dicţionar disponibil"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Activaţi feedback de la utilizatori"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Ajutaţi la îmbunătăţirea acestui instrument de editare a metodelor de introducere a textului trimiţând în mod automat la Google statistici de utilizare şi rapoarte de blocare."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Atingeţi pentru a corecta cuvintele"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Atingeţi cuvintele introduse pentru a le corecta, numai când pot fi văzute sugestii"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Temă pentru tastatură"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tastatură cehă"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Tastatură arabă"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Tastatură daneză"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Tastatură germană"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Tastatură germană QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Tastatură engleză (Marea Britanie)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Tastatură engleză (S.U.A.)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Tastatură spaniolă"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Tastatură finlandeză"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Tastatură franceză"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Tastatură franceză (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Tastatură franceză (Elveţia)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Tastatură croată"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Tastatură maghiară"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Tastatură ebraică"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Tastatură italiană"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Tastatură norvegiană"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Tastatură olandeză"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Tastatură poloneză"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Tastatură portugheză"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Tastatură rusă"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Tastatură sârbă"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Tastatură suedeză"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Tastatură turcă"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voce afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Voce cehă"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Voce germană"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voce engleză"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Voce spaniolă"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Voce franceză"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voce italiană"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Voce japoneză"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Voce coreeană"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voce olandeză"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Voce poloneză"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Voce portugheză"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Voce rusă"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Voce turcă"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voce chineză, yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voce chineză, mandarină"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voce isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engleză (Marea Britanie)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engleză (S.U.A.)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Engleză (Regatul Unit) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Engleză (S.U.A.) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Nicio limbă"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Nicio limbă (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Nicio limbă (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Nicio limbă (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Nicio limbă (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Nicio limbă (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Nicio limbă (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Stiluri personalizate"</string>
+ <string name="add_style" msgid="6163126614514489951">"Stil"</string>
+ <string name="add" msgid="8299699805688017798">"Adăugaţi"</string>
+ <string name="remove" msgid="4486081658752944606">"Eliminaţi"</string>
+ <string name="save" msgid="7646738597196767214">"Salvaţi"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Limbă"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Aspect"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Stilul de introducere personalizat trebuie să fie activat pentru a-l utiliza. Îl activaţi acum?"</string>
+ <string name="enable" msgid="5031294444630523247">"Activaţi"</string>
+ <string name="not_now" msgid="6172462888202790482">"Nu acum"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Acelaşi stil de introducere există deja: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modul Studiu privind utilizarea"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Setări pentru durata vibrării la apăsarea tastei"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Setări pentru volumul sunetului la apăsarea tastei"</string>
</resources>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 6973ae482..34fdb0f5c 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -21,61 +21,69 @@
<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">"Клавиатура Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавиатура Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Клавиатура Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Настройки"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Все команды"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Проверка правописания Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Проверка правописания Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Настройка проверки правописания"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Подсказки, основанные на предыдущих словах"</string>
<string name="misc_category" msgid="6894192814868233453">"Другие варианты"</string>
<string name="advanced_settings" msgid="362895144495591463">"Расширенные настройки"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Для опытных пользователей"</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="suppress_language_switch_key" msgid="8003788410354806368">"Блок. кл. перекл. языков"</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="use_contacts_dict" msgid="4435317977804180815">"Подсказки имен контактов"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Подсказки и исправления на основе имен из контактов"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Автоисправление"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Показывать варианты исправления"</string>
<string name="auto_cap" msgid="1719746674854628252">"Заглавные автоматически"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Настроить словари"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Быстрое исправление"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Исправлять распространенные опечатки"</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="3551821800439659812">"Показать вертикально"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Всегда скрывать"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Переключать язык пробелом"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Кнопка настроек"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Автоматически"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Всегда показывать"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Всегда скрывать"</string>
<string name="auto_correction" msgid="4979925752001319458">"Автоисправление"</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_aggeressive" msgid="3524029103734923819">"Активное"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Очень активно"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Биграммные подсказки"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Используйте предыдущее слово, чтобы исправить подсказку"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Биграммный прогноз"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Следующие варианты"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Использовать предыдущее слово, чтобы исправить предложенные варианты"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Следующая подсказка"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Использовать предыдущее слово для прогнозирования"</string>
<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_to_alpha_key" msgid="4793983863798817523">"АБВ"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Ещё"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Пауза"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Ждать"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Подключите гарнитуру, чтобы услышать пароль."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Введенный текст: %s."</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст не введен"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Код клавиши:%d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Клавиша верхнего регистра"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Верхний регистр включен"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Включена фиксация верхнего регистра"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Верхний регистр включен (нажмите, чтобы отключить)"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"Запятая"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Точка"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Открывающая скобка"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Закрывающая скобка"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Двоеточие"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Точка с запятой"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Восклицательный знак"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Вопросительный знак"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Двойная кавычка"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Одинарные кавычки"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Поиск"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Точка"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратный корень"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Число \"пи\""</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Дельта"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Товарный знак"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Знак процента"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Пометить"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Английский фунт"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Многоточие"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Нижние двойные кавычки"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Голосовой ввод"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"В настоящее время функция голосового ввода не поддерживает ваш язык, но вы можете пользоваться ей на английском."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Голосовой ввод использует алгоритмы распознавания речи Google. Действует "<a href="http://m.google.com/privacy">"политика конфиденциальности для мобильных устройств"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Функция голосового ввода отключается в настройках способа ввода."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Чтобы использовать голосовой ввод, нажмите кнопку микрофона."</string>
- <string name="voice_listening" msgid="467518160751321844">"Говорите"</string>
- <string name="voice_working" msgid="6666937792815731889">"Обработка запроса"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Ошибка. Повторите попытку."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Ошибка подключения"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Слишком длинная фраза"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Неполадка со звуком"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Ошибка сервера"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Речи не слышно"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Ничего не найдено"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Голосовой поиск не установлен"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Совет"</b>". Проведите пальцем по клавиатуре для голосового ввода."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Совет"</b>". В следующий раз проговаривайте знаки препинания, например \"точка\", \"запятая\", \"вопросительный знак\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Отмена"</string>
- <string name="ok" msgid="7898366843681727667">"ОК"</string>
- <string name="voice_input" msgid="2466640768843347841">"Голосовой ввод"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Верхний регистр включен"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock включен"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Верхний регистр отключен"</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="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="selectInputMethod" msgid="315076553378705821">"Выбрать способ ввода"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Настройка способов ввода"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Языки ввода"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Для изменения языка проведите пальцем по пробелу"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Нажмите, чтобы сохранить"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Закладка в журнале"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Закладка сохранена"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Не сохранять этот сеанс"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Удаление…"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Запись сеанса удалена"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Запись сеанса НЕ удалена"</string>
+ <string name="select_language" msgid="3693815588777926848">"Языки ввода"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Нажмите, чтобы сохранить"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Включить отправку сведений"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Помогите усовершенствовать редактор способа ввода, разрешив отправку статистики и отчетов о сбоях в Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Исправление нажатием"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Нажмите на слово, чтобы исправить его (при наличии подсказок)"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Тема клавиатуры"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Клавиатура: чешская"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Арабская раскладка"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Клавиатура: датская"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Клавиатура: немецкая"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Немецкая раскладка QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Клавиатура: английская (Великобритания)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Клавиатура: английская (США)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Клавиатура: испанская"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Финская раскладка"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Клавиатура: французская"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Клавиатура: французская"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Клавиатура: французская (Швейцария)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Хорватская раскладка"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Венгерская раскладка"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Раскладка для иврита"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Клавиатура: итальянская"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Клавиатура: норвежская"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Клавиатура: голландская"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Польская раскладка"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Португальская раскладка"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Клавиатура: русская"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Клавиатура: сербская"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Голос: шведский"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Турецкая раскладка"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Голосовой ввод на африкаанс"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Голос: чешский"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Голос: немецкий"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Голосовой ввод на английском"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Голос: испанский"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Голос: французский"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Голосовой ввод на итальянском"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Голос: японский"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Голос: корейский"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Голосовой ввод на голландском"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Голос: польский"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Голос: португальский"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Голос: русский"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Голос: турецкий"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Голосовой ввод на китайском (диалект юэ)"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Голосовой ввод на китайском (мандаринский диалект)"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Голосовой ввод на зулу"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"английский (Великобритания)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"английский (США)"</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_no_language" msgid="141420857808801746">"Язык не указан"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"QWERTY-клавиатура"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Язык не задан (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Язык не задан (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Язык не задан (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Яз. не задан (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Язык не задан (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки вибросигнала при нажатии клавиш"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки громкости звука при нажатии клавиш"</string>
</resources>
diff --git a/java/res/values-sk/donottranslate-altchars.xml b/java/res/values-sk/donottranslate-altchars.xml
deleted file mode 100644
index 6d9836e9c..000000000
--- a/java/res/values-sk/donottranslate-altchars.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_a">ä,á,à,â,æ,ã,å,ā</string>
- <string name="alternates_for_e">3,é,ě,è,ê,ë,ę,ė,ē</string>
- <string name="alternates_for_i">8,í,î,ï,ì,į,ī</string>
- <string name="alternates_for_o">9,ô,ó,ö,ò,õ,œ,ø,ō</string>
- <string name="alternates_for_u">7,ú,ú,û,ü,ù,ū</string>
- <string name="alternates_for_s">š,ß,ś</string>
- <string name="alternates_for_n">ň,ñ,ń</string>
- <string name="alternates_for_c">č,ç,ć</string>
- <string name="alternates_for_y">6,ý,ÿ</string>
- <string name="alternates_for_d">ď</string>
- <string name="alternates_for_r">4,ŕ,ř</string>
- <string name="alternates_for_t">5,ť</string>
- <string name="alternates_for_z">ž,ź,ż</string>
- <string name="alternates_for_l">ľ,ĺ,ł</string>
-</resources>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index f992ba28f..41fc0cf24 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -21,61 +21,69 @@
<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">"Klávesnica Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klávesnica Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Nastavenia klávesnice Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávania textu a údajov"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Príkazy denníka výskumu"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Kontrola pravopisu Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavenia kontroly pravopisu"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhľadať kontakty"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používa záznamy z vášho zoznamu kontaktov"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Pri stlačení klávesu vibrovať"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri stlačení klávesu"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Zobraziť znaky pri stlačení klávesu"</string>
<string name="general_category" msgid="1859088467017573195">"Všeobecné"</string>
<string name="correction_category" msgid="2236750915056607613">"Oprava textu"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Návrhy na základe predchádzajúcich slov"</string>
<string name="misc_category" msgid="6894192814868233453">"Ďalšie možnosti"</string>
<string name="advanced_settings" msgid="362895144495591463">"Rozšírené nastavenia"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Možnosti pre skúsených používateľov"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti pre odborníkov"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prepnúť na iné metódy vstupu"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kláves na prepnutie jazyka pokrýva aj ďalšie metódy vstupu"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Blok. kláves prep. jazyka"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Onesk. zrušenia kľúč. kon. okna"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez oneskorenia"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predvolená"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Navrhnúť mená kontaktov"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Používať mená z Kontaktov na návrhy a opravy"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Povoliť opätovné opravy"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastaviť návrhy pre opätovné opravy"</string>
<string name="auto_cap" msgid="1719746674854628252">"Veľké písmená automaticky"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurovať slovníky"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Rýchle opravy"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Opravuje najčastejšie chyby pri písaní"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Doplnkové slovníky"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Hlavný slovník"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Zobraziť návrhy opráv"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Zobrazovať navrhované slová počas písania"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vždy zobrazovať"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Zobraziť v režime na výšku"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vždy skrývať"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Prepín. jazykov medzerníkom"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Zobraziť kláves Nastavenia"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automaticky"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Vždy zobrazovať"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Vždy skrývať"</string>
<string name="auto_correction" msgid="4979925752001319458">"Automatické opravy"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Stlačením medzerníka a interpunkcie sa aut. opravia chybné slová"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Vypnuté"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mierne"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresívne"</string>
- <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Veľmi agresívna"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Návrhy Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Na zlepšenie návrhu použiť predchádzajúce slovo"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Odhady Bigram"</string>
+ <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Veľmi agresívne"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Návrhy ďalšieho slova"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Na zlepšenie návrhov použiť predchádzajúce slovo"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Odhad ďalšieho slova"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Použiť predchádzajúce slovo aj pre predpoveď"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Viac"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Povolený kláves Shift"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Povolený kláves Caps Lock"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Kláves Shift je zapnutý (zakážete ho klepnutím)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Kláves Caps Lock je zapnutý (zakážete ho klepnutím)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboly"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Písmená"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Hlasový vstup"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Usmiata tvár"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Čiarka"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Bodka"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Ľavá zátvorka"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Pravá zátvorka"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dvojbodka"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Bodkočiarka"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Výkričník"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Otáznik"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Úvodzovky"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Jednoduché úvodzovky"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Hľadať"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Bodka"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Odmocnina"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pí"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Percento"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Hviezdička"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Libra"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tri bodky"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Dolné úvodzovky"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Hlasový vstup"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Pre váš jazyk aktuálne nie je hlasový vstup podporovaný, ale funguje v angličtine."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Hlasový vstup používa rozpoznávanie hlasu Google. Na používanie hlasového vstupu sa vzťahujú "<a href="http://m.google.com/privacy">"Pravidlá ochrany osobných údajov pre mobilné služby"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ak chcete vypnúť hlasový vstup, prejdite na nastavenia metódy vstupu."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ak chcete použiť hlasový vstup, stlačte tlačidlo mikrofón."</string>
- <string name="voice_listening" msgid="467518160751321844">"Hovorte"</string>
- <string name="voice_working" msgid="6666937792815731889">"Prebieha spracovanie"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Chyba. Skúste to znova."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Pripojenie sa nepodarilo."</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Chyba, reč je príliš dlhá."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problém so zvukom"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Chyba servera"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Nebola zistená žiadna reč."</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Nenašli sa žiadne zhody"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Hlasové vyhľadávanie nie je nainštalované"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tip:"</b>" Ak chcete aktivovať hlasový vstup, prejdite prstom po klávesnici."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tip:"</b>" Nabudúce skúste vysloviť interpunkciu, napríklad „bodka“, „čiarka“ alebo „otáznik“."</string>
- <string name="cancel" msgid="6830980399865683324">"Zrušiť"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Hlasový vstup"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Kláves Shift je povolený"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kláves Caps Lock je povolený"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Kláves Shift je zakázaný"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Režim symbolov"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Režim písmen"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Režim telefónu"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Režim telefónnych symbolov"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Kľúč hlasového vstupu"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavnej klávesnici"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici so symbolmi"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Vypnuté"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofón na hlavnej klávesnici"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofón na klávesnici so symbolmi"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup je zakázaný"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Výber metódy vstupu"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurovať metódy vstupu"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Jazyk môžete zmeniť posunutím prsta po medzerníku."</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Ďalším dotykom slovo uložíte"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Časová pečiatka denníka"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Časová pečiatka zaznamenaná"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Neukl. reláciu do denníka"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Odstraň. denníka relácie"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Denník relácie odstránený"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Denník relácie NIE JE odstr."</string>
+ <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opätovným dotykom uložíte"</string>
<string name="has_dictionary" msgid="6071847973466625007">"K dispozícii je slovník"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Povoliť spätnú väzbu od používateľov"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Automatickým zasielaním štatistík o využívaní editora metódy vstupu a správ o jeho zlyhaní do služby Google môžete prispieť k vylepšeniu tohto nástroja."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Dotykom opravíte slová"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Dotykom zadaných slov tieto slová opravíte, musia však byť viditeľné návrhy"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Motív klávesnice"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"klávesnica – čeština"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Klávesnica – arabčina"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"klávesnica – dánčina"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"klávesnica – nemčina"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Nemecká klávesnica QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"klávesnica – angličtina (br.)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"klávesnica – angličtina (am.)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"klávesnica – španielčina"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Fínska klávesnica"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"klávesnica – francúzština"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"klávesnica – francúzština (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"klávesnica – francúzština (Švajč.)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Chorvátska klávesnica"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Maďarská klávesnica"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Klávesnica – hebrejčina"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"klávesnica – taliančina"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"klávesnica – nórčina"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"klávesnica – holandčina"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Poľská klávesnica"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugalská klávesnica"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"klávesnica – ruština"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"hlas – srbčina"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"klávesnica – švédčina"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turecká klávesnica"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Hlas – afrikánčina"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"hlas – čeština"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"hlas – nemčina"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Hlas – angličtina"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"hlas – španielčina"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"hlas – francúzština"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"hlas – taliančina"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"hlas – japončina"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"hlas – kórejčina"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"hlas – holandčina"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"hlas – poľština"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"hlas – portugalčina"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"hlas – ruština"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"hlas – turečtina"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Hlas – čínština, kantónčina"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Hlas – čínština, mandarínska"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Hlas – Zulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Anglická klávesnica (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Anglická klávesnica (US)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"angličtina (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"angličtina (USA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Žiadny jazyk"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Žiadny jazyk (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Žiadny jazyk (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Žiadny jazyk (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Žiadny jazyk (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Žiadny jazyk (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Žiadny jazyk (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Vlastné štýly vstupu"</string>
+ <string name="add_style" msgid="6163126614514489951">"Pridať štýl"</string>
+ <string name="add" msgid="8299699805688017798">"Pridať"</string>
+ <string name="remove" msgid="4486081658752944606">"Odstrániť"</string>
+ <string name="save" msgid="7646738597196767214">"Uložiť"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Jazyk"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Rozloženie"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Pred použitím vlastného štýlu vstupu ho musíte povoliť. Chcete ho povoliť?"</string>
+ <string name="enable" msgid="5031294444630523247">"Povoliť"</string>
+ <string name="not_now" msgid="6172462888202790482">"Teraz nie"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Rovnaký štýl vstupu už existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim štúdie použiteľnosti"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Nastavenia trvania vibrovania pri stlačení klávesu"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Nastavenia hlasitosti zvuku pri stlačení klávesu"</string>
</resources>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index ad37f7d31..f18de78bc 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -21,61 +21,69 @@
<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">"Tipkovnica Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tipkovnica Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Nastavitve tipkovnice Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti vnosa"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Ukazi za dnevnik raziskav"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Črkovalnik za Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Črkovalnik za Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavitve preverjanja črkovanja"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Iskanje imen stikov"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Črkovalnik uporablja vnose s seznama stikov"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibriranje ob pritisku tipke"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Zvok ob pritisku tipke"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Povečaj črko ob pritisku"</string>
<string name="general_category" msgid="1859088467017573195">"Splošno"</string>
<string name="correction_category" msgid="2236750915056607613">"Popravljanje besedila"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Predlogi, ki temeljijo na prejšnjih besedah"</string>
<string name="misc_category" msgid="6894192814868233453">"Druge možnosti"</string>
<string name="advanced_settings" msgid="362895144495591463">"Dodatne nastavitve"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Možnosti za izkušene uporabnike"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti za strokovnjake"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prekl. na drug nač. vnosa"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tipka za preklop jezika, ki vključuje tudi druge načine vnosa"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Onemogoči tipko za preklop jezika"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Trajanje povečanja tipke"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Brez zakasnitve"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Privzeto"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Predlagaj imena stikov"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Uporaba imen iz stikov za predloge in popravke"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Omogoči vnovične popravke"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastavitev predlogov za vnovične popravke"</string>
<string name="auto_cap" msgid="1719746674854628252">"Samod. velike začetnice"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfiguracija slovarjev"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Hitri popravki"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Popravi pogoste tipkarske napake"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dodatni slovarji"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Glavni slovar"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Pokaži predloge popravkov"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Pokaži predlagane besede med tipkanjem"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vedno pokaži"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Pokaži v pokončnem načinu"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vedno skrij"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Preklapljanje med jeziki s preslednico"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Tipka za prikaz nastavitev"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Samodejno"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Vedno pokaži"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Vedno skrij"</string>
<string name="auto_correction" msgid="4979925752001319458">"Samodejni popravek"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Preslednica in ločila samodejno popravijo napačno vtipkane besede"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Izklopljeno"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Zmerno"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Strogo"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Zelo strogo"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigramni predlogi"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Predlog izboljšaj s prejšnjo besedo"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigramsko predvidevanje"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Predlogi naslednje besede"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Predloge izboljšaj s prejšnjo besedo"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Predvidevanje naslednje besede"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Uporabi prejšnjo besedo tudi za predvidevanje"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Več"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Tipka »Shift« je omogočena"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Funkcija »Caps Lock« je omogočena"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift je vklopljen (dotaknite se, da onemogočite)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock je vklopljen (dotaknite se, da onemogočite)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Pisma"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Glasovni vnos"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smeško"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Vračalka"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Vejica"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Pika"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Levi oklepaj"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Desni oklepaj"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dvopičje"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Podpičje"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Klicaj"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Vprašaj"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dvojni narekovaji"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enojni narekovaj"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Iskanje"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Pika"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Koren"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Blagovna znamka"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Odstotek"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Zvezdica"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Lojtra"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tri pike"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Spodnji dvojni narekovaji"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Glasovni vnos"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Glasovni vnos trenutno ni podprt v vašem jeziku, deluje pa v angleščini."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Glasovni vnos uporablja Googlovo prepoznavanje govora. Zanj velja "<a href="http://m.google.com/privacy">"pravilnik o zasebnosti za mobilne naprave"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Glasovni vnos izklopite v nastavitvah načina vnosa."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Če želite uporabljati glasovni vnos, pritisnite gumb z mikrofonom."</string>
- <string name="voice_listening" msgid="467518160751321844">"Začnite govoriti"</string>
- <string name="voice_working" msgid="6666937792815731889">"Obdelava"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Napaka. Poskusite znova."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Povezava ni mogoča"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Napaka, preveč govora."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Težave z zvokom"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Napaka strežnika"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Govora se ne sliši"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Ni rezultatov"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Glasovno iskanje ni nameščeno"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Nasvet:"</b>" za govorjenje s prstom povlecite po tipkovnici"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Nasvet:"</b>" naslednjič poskusite ločila izgovoriti, npr. »pika«, »vejica« ali »vprašaj«."</string>
- <string name="cancel" msgid="6830980399865683324">"Prekliči"</string>
- <string name="ok" msgid="7898366843681727667">"V redu"</string>
- <string name="voice_input" msgid="2466640768843347841">"Glasovni vnos"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Način »Shift« je omogočen"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Način »Caps Lock« je omogočen"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Način »Shift« je onemogočen"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Način simbolov"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Način črk"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Način telefona"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Način simbolov telefona"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Tipka za glasovni vnos"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavni tipkovnici"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipk. s simboli"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Izklopljeno"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. na glavni tipk."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. s sim."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. vnos je onem."</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Izberite način vnosa"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Podrsajte s prstom po preslednici, da zamenjate jezik"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Še enkrat se dotaknite, da shranite"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"V dnev. zabeleži čas. žig"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Časovni žig zabeležen"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Brez dnevnika za to sejo"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Brisanje seje dnevnika"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Dnevnik seje izbrisan"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Dnevnik seje NI izbrisan"</string>
+ <string name="select_language" msgid="3693815588777926848">"Jeziki vnosa"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotaknite se še enkrat, da shranite"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Omogoči povratne informacije uporabnikov"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"S samodejnim pošiljanjem statističnih podatkov o uporabi in poročil o zrušitvah Googlu nam lahko pomagate izboljšati urejevalnik načina vnosa."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Dotaknite se besed in jih popravite"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Dotaknite se vnesenih besed in jih popravite, samo ko so predlogi vidni"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Češka tipkovnica"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabska tipkovnica"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Danska tipkovnica"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Nemška tipkovnica"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Nemška tipkovnica QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Tipkovnica za britansko angleščino"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Tipkovnica za ameriško angleščino"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Španska tipkovnica"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finska tipkovnica"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Francoska tipkovnica"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Tipkovnica za kanadsko francoščino"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Tipkovnica za švicarsko francoščino"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Hrvaška tipkovnica"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Madžarska tipkovnica"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebrejska tipkovnica"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italijanska tipkovnica"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norveška tipkovnica"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Nizozemska tipkovnica"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Poljska tipkovnica"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugalska tipkovnica"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Ruska tipkovnica"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Srbska tipkovnica"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Švedska tipkovnica"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turška tipkovnica"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Govor v afrikanščini"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Govor v češčini"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Govor v nemščini"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Govor v angleščini"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Govor v španščini"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Govor v francoščini"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Govor v italijanščini"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Govor v japonščini"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Govor v korejščini"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Govor v nizozemščini"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Govor v poljščini"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Govor v portugalščini"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Govor v ruščini"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Govor v turščini"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Govor v kitajščini, jue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Govor v kitajščini, mandarinščini"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Govor v zulujščini"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"angleščina (Združeno kraljestvo)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"angleščina (ZDA)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Angleška (Zdr. kralj.) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Angleška (ZDA) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Ni jezika"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Ni jezika (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Ni jezika (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Ni jezika (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Ni jezika (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Ni jezika (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Ni jezika (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Slogi vnosa po meri"</string>
+ <string name="add_style" msgid="6163126614514489951">"Dodaj slog"</string>
+ <string name="add" msgid="8299699805688017798">"Dodaj"</string>
+ <string name="remove" msgid="4486081658752944606">"Odstrani"</string>
+ <string name="save" msgid="7646738597196767214">"Shrani"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Jezik"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Postavitev"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Slog vnosa po meri morate omogočiti. Ali ga želite omogočiti?"</string>
+ <string name="enable" msgid="5031294444630523247">"Omogoči"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ne zdaj"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Isti slog vnosa že obstaja: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način za preučevanje uporabnosti"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Nastavitve za trajanje vibriranja ob pritisku tipke"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Nastavitve za glasnost zvoka ob pritisku tipke"</string>
</resources>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index e159facf9..11e678ebc 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -21,61 +21,69 @@
<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">"Android тастатура"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android тастатура (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Подешавања Android тастатуре"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Опције уноса"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Команде евиденције истраживања"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android провера правописа"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android провера правописа (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Подешавања провере правописа"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Предлози на основу претходних речи"</string>
<string name="misc_category" msgid="6894192814868233453">"Друге опције"</string>
<string name="advanced_settings" msgid="362895144495591463">"Напредна подешавања"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Опције за искусне кориснике"</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="suppress_language_switch_key" msgid="8003788410354806368">"Искључи тастер за језике"</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="use_contacts_dict" msgid="4435317977804180815">"Предложи имена контаката"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Користи имена из Контаката за предлоге и исправке"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Омогући поновне исправке"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Подешавање предлога за поновне исправке"</string>
<string name="auto_cap" msgid="1719746674854628252">"Аутоматски унос великих слова"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Конфигуриши речнике"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Брзе исправке"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Исправља честе грешке у куцању"</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="3551821800439659812">"Прикажи у усправном режиму"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Увек сакриј"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Користи размак за избор језика"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Прикажи тастер за подешавања"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Аутоматски"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Увек прикажи"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Увек сакриј"</string>
<string name="auto_correction" msgid="4979925752001319458">"Аутоматско исправљање"</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_aggeressive" msgid="3524029103734923819">"Агресивно"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Веома агресивно"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram предлози"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Користи претходну реч за побољшање предлога"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram предвиђање"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Предлози за следећу реч"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Користи претходну реч за побољшање предлога"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Предвиђање следеће речи"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Користи претходну реч и за предвиђање"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Још"</string>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"АБВ"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Пауза"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Чекај"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Укључите слушалице да бисте чули наглас изговорене тастере за лозинку."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Тренутни текст је %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст није унет"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Кôд тастера %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Тастер Shift је омогућен"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"Зарез"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Тачка"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Лева заграда"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Десна заграда"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Две тачке"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Тачка-зарез"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Знак узвика"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Знак питања"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Дупли наводник"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Полунаводник"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Претражи"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Тачка"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратни корен"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Пи"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Делта"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Жиг"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"За"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Звездица"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Фунта"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Три тачке"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Отворени доњи наводници"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Гласовни унос"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Гласовни унос тренутно није подржан за ваш језик, али функционише на енглеском."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Гласовни унос користи Google-ову функцију за препознавање гласа. Примењује се "<a href="http://m.google.com/privacy">"политика приватности за мобилне уређаје"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Да бисте искључили гласовни унос, идите на подешавања за начин уноса."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Да бисте користили гласовни унос, притисните дугме за микрофон."</string>
- <string name="voice_listening" msgid="467518160751321844">"Говорите сада"</string>
- <string name="voice_working" msgid="6666937792815731889">"Обрада"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Грешка. Покушајте поново."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Повезивање није могуће"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Грешка, говорите предуго."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Проблем са звуком"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Грешка сервера"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Не чује се говор"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Нема подударања"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Гласовна претрага није инсталирана"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Савет:"</b>" Превуците прстом преко тастатуре за гласовни унос"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Савет:"</b>" Следећи пут покушајте да изговорите знакове интерпункције као што су „тачка“, „зарез“ или „знак питања“."</string>
- <string name="cancel" msgid="6830980399865683324">"Откажи"</string>
- <string name="ok" msgid="7898366843681727667">"Потврди"</string>
- <string name="voice_input" msgid="2466640768843347841">"Гласовни унос"</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="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="selectInputMethod" msgid="315076553378705821">"Изаберите метод уноса"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Конфигурисање метода уноса"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Језици за унос"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Превуците прст преко тастера за размак да бисте променили језик"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Поново додирните да бисте сачували"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Наведи временску ознаку у евиденцији"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Снимљена временска ознака"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Не евидентирај ову сесију"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Брисање евиденције сесије"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Евиденција сесије је обрисана"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Евиденција сесије НИЈЕ избрисана"</string>
+ <string name="select_language" msgid="3693815588777926848">"Језици уноса"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Поново додирните да бисте сачували"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Речник је доступан"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Омогући повратну информацију корисника"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Помозите да се побољша овај уређивач режима уноса тако што ће се аутоматски послати статистика о коришћењу и извештаји о грешкама компанији Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Додирните да бисте исправили речи"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Додирните унете речи да бисте их исправили само када су предлози видљиви"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Тема тастатуре"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Језик тастатуре: чешки"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Језик тастатуре: арапски"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Језик тастатуре: дански"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Језик тастатуре: немачки"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Језик QWERTY тастатуре: немачки"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Језик тастатуре: енглески (УК)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Језик тастатуре: енглески (САД)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Језик тастатуре: шпански"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Језик тастатуре: фински"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Језик тастатуре: француски"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Језик тастатуре: француски (Канада)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Језик тастатуре: француски (Швајц.)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Језик тастатуре: хрватски"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Језик тастатуре: мађарски"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Језик тастатуре: хебрејски"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Језик тастатуре: италијански"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Језик тастатуре: норвешки"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Језик тастатуре: холандски"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Језик тастатуре: пољски"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Језик тастатуре: португалски"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Језик тастатуре: руски"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Језик тастатуре: српски"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Језик тастатуре: шведски"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Језик тастатуре: турски"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Глас на африкансу"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Глас на чешком"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Глас на немачком"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Глас на енглеском"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Глас на шпанском"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Глас на француском"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Глас на италијанском"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Глас на јапанском"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Глас на корејском"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Глас на холандском"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Глас на пољском"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Глас на португалском"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Глас на руском"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Глас на турском"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Глас на јуе кинеском"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Глас на мандаринском кинеском"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Глас на језику исизулу"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"енглески (УК)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"енглески (САД)"</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_no_language" msgid="141420857808801746">"Без језика"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Нема језика (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Без језика (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Без језика (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Без језика (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Без језика (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Без језика (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Подешавања трајања вибрације при притиску на тастере"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Подешавања јачине звука при притиску на тастере"</string>
</resources>
diff --git a/java/res/values-sv/donottranslate-altchars.xml b/java/res/values-sv/donottranslate-altchars.xml
deleted file mode 100644
index d03ae1a6c..000000000
--- a/java/res/values-sv/donottranslate-altchars.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_e">3,é,è,ê,ë,ę</string>
- <string name="alternates_for_o">9,œ,ô,ò,ó,õ,ō</string>
- <string name="alternates_for_u">7,ü,û,ù,ú,ū</string>
- <string name="alternates_for_s">ß,ś,š</string>
- <string name="keylabel_for_scandinavia_row2_10">ö</string>
- <string name="keylabel_for_scandinavia_row2_11">ä</string>
- <string name="alternates_for_scandinavia_row2_10">ø</string>
- <string name="alternates_for_scandinavia_row2_11">æ</string>
-</resources>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 7fe9dc537..bf1e5054f 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -21,61 +21,69 @@
<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">"Androids tangentbord"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androids tangentbord (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Inställningar för Androids tangentbord"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Loggkommandon"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Stavningskontroll i Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Stavningskontroll i Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Inställningar för stavningskontroll"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Sök namn på kontakter"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"I stavningskontrollen används poster från kontaktlistan"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrera vid tangenttryck"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Knappljud"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Popup vid knapptryck"</string>
<string name="general_category" msgid="1859088467017573195">"Allmänt"</string>
<string name="correction_category" msgid="2236750915056607613">"Textkorrigering"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Förslag baserade på tidigare ord"</string>
<string name="misc_category" msgid="6894192814868233453">"Andra alternativ"</string>
<string name="advanced_settings" msgid="362895144495591463">"Avancerade inställningar"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Alternativ för expertanvändare"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Alternativ för experter"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Byt till annan inmatning"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Språkbytesknappen omfattar även andra inmatningsmetoder"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Stäng av språkbytesknapp"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ta bort popup-fördröjning"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fördröj inte"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Föreslå kontaktnamn"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Använd namn från Kontakter för förslag och korrigeringar"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Aktivera omkorrigeringar"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ställ in förslag för omkorrigeringar"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatiska versaler"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Konfigurera ordböcker"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Snabba lösningar"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Åtgärdar automatiskt vanliga misstag"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tilläggsordlistor"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Huvudordlistan"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Visa rättningsförslag"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Visar ordförslag när du skriver"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Visa alltid"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Visa stående"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Dölj alltid"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Byt språk med mellanslag"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Visa inställningsknapp"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Automatiskt"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Visa alltid"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Dölj alltid"</string>
<string name="auto_correction" msgid="4979925752001319458">"Autokorrigering"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Blanksteg/skiljetecken rättar felstavning"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Av"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Måttlig"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressiv"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Mycket aggressivt"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigramförslag"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Förbättra förslaget med föregående ord"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigramförslag"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Föreslå nästa ord"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Förbättra förslagen med föregående ord"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Förutspå nästa ord"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Använd även föregående ord för att ge förslag"</string>
<string name="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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Mer"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Skift aktiverat"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock är aktiverat"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Skift på (knacka lätt för att inaktivera)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock på (knacka lätt för att inaktivera)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboler"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Bokstäver"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Röstinmatning"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Uttryckssymbol"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Retur"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Punkt"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Vänster parentes"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Högerparentes"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Kolon"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Utropstecken"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Frågetecken"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dubbla citattecken"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkla citattecken"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Sök"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratrot"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Stjärna"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Fyrkant"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellips"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Nedre dubbla citattecken"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Röstindata"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Röstindata stöds inte på ditt språk än, men tjänsten fungerar på engelska."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Röstinmatning använder sig av Googles tjänst för taligenkänning. "<a href="http://m.google.com/privacy">"Sekretesspolicyn för mobila enheter"</a>" gäller."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Om du vill stänga av röstinmatning öppnar du inställningarna för inmatningsmetod."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Om du vill använda röstinmatning trycker du på mikrofonknappen."</string>
- <string name="voice_listening" msgid="467518160751321844">"Tala nu"</string>
- <string name="voice_working" msgid="6666937792815731889">"Fungerar"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Fel. Försök igen."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Det gick inte att ansluta"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Fel, för mycket tal."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Ljudproblem"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Serverfel"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Hörde inget tal"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Inga träffar hittades"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Voice Search är inte installerat"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tips!"</b>" Dra över tangentbordet om du vill tala"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tips!"</b>" Nästa gång testar du att säga skiljetecknen, som \"punkt\", \"komma\" eller \"frågetecken\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Avbryt"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Röstindata"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift är aktiverat"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock är aktiverat"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Skift är inaktiverat"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolläge"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Bokstavsläge"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonläge"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefonsymbolläge"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Röstinmatningsknapp"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På huvudtangentbord"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På symboltangentbord"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Av"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mick huvudtangentbord"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mick bland symboler"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Röstinmatning inaktiv"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Välj inmatningsmetod"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Inmatningsspråk"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Dra med fingret på blanksteg om du vill ändra språk"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tryck igen för att spara"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Markera tidpunkt i loggen"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Tidpunkten har sparats"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Logga inte detta besök"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Besöksloggen tas bort"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Besöksloggen togs bort"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Besöksloggen togs EJ bort"</string>
+ <string name="select_language" msgid="3693815588777926848">"Inmatningsspråk"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Spara genom att trycka igen"</string>
<string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Aktivera synpunkter från användare"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Du kan hjälpa till att förbättra inmatningsmetoden genom att automatiskt skicka användningsstatistik och felrapporter till Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Tryck om du vill korrigera ord"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Tryck på skrivna ord om du vill korrigera dem, endast när förslag visas"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tangentbordstema"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Tjeckiskt tangentbord"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabiskt tangentbord"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Danskt tangentbord"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Tyskt tangentbord"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Tyskt QWERTY-tangentbord"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Engelskt tangentbord (Storbrit.)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Engelskt tangentbord (USA)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spanskt tangentbord"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finskt tangentbord"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Franskt tangentbord"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Franskt tangentbord (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Franskt tangentbord (Schweiz)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kroatiskt tangentbord"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ungerskt tangentbord"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebreiskt tangentbord"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italienskt tangentbord"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norskt tangentbord"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Holländskt tangentbord"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polskt tangentbord"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portugisiskt tangentbord"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Ryskt tangentbord"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbiskt tangentbord"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Svenskt tangentbord"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turkiskt tangentbord"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Röst, afrikaans"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Röst på tjeckiska"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Röst på tyska"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Röst, engelska"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Röst på spanska"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Röst på franska"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Röst på italienska"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Röst på japanska"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Röst på koreanska"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Röst på holländska"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Röst på polska"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Röst på portugisiska"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Röst på ryska"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Röst på turkiska"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Röst, kinesiska, yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Röst, kinesiska, mandarin"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Röst, isiZulusk"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Engelskt (brittiskt)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Engelskt (amerikanskt)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Engelskt (brittiskt) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Engelskt (amerikanskt) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Inget språk"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Inget språk (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Inget språk (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Inget språk (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Inget språk (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Inget språk (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Inget språk (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Anpassade indatastilar"</string>
+ <string name="add_style" msgid="6163126614514489951">"Ny stil"</string>
+ <string name="add" msgid="8299699805688017798">"Lägg till"</string>
+ <string name="remove" msgid="4486081658752944606">"Ta bort"</string>
+ <string name="save" msgid="7646738597196767214">"Spara"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Språk"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Din anpassade indatatyp måste aktiveras innan du börjar använda den. Vill du aktivera den nu?"</string>
+ <string name="enable" msgid="5031294444630523247">"Aktivera"</string>
+ <string name="not_now" msgid="6172462888202790482">"Inte nu"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Samma indatastil finns redan: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Läge för studie av användbarhet"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Inställningar för vibrationslängd vid knapptryck"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volyminställningar för knappljud"</string>
</resources>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 6d4ba8c08..f416fcd76 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -21,61 +21,69 @@
<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">"Kibodi ya Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Kicharazio cha Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Mipangilio ya kibodi ya Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Kikagua tahajia cha Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kikagua tahajia cha Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Mipangilio ya kukagua sarufi"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya wasiliani"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia ingizo kutoka kwa orodha yako ya anwani"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Toa sauti unapobofya kitufe"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Ibuka kitufe kinapobonyezwa"</string>
<string name="general_category" msgid="1859088467017573195">"Kawaida"</string>
<string name="correction_category" msgid="2236750915056607613">"Marekebisho ya maandishi"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Mapendekezo yanayohusiana na maneno yaliyopita"</string>
<string name="misc_category" msgid="6894192814868233453">"Chaguo zingine"</string>
<string name="advanced_settings" msgid="362895144495591463">"Mipangilio mahiri"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Machaguo ya watumiaji wataalamu"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Chaguo za wataalamu"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Badilisha hadi kwa mbinu zingine za ingizo"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ufunguo wa kubadilisha lugha unashughulikia mbinu zingine za ingizo pia"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Zuia ufunguo wa kubadili lugha"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Kuchelewesha kutupa kitufe ibukizi"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Hakuna kuchelewa"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Pendekeza majini ya Anwani"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Tumia majina kutoka kwa Anwani kwa mapendekezo na marekebisho"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Wezesha masahihisho mapya"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Weka mapendekezo kwa ajili ya kusahihisha upya"</string>
<string name="auto_cap" msgid="1719746674854628252">"Uwekaji wa herufi kubwa kiotomatiki"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Sanidi kamusi"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Utatuzi wa haraka"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Husahihisha makosa ya kawaida yaliyoandikwa"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Nyongeza za kamusi"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Kamusi kuu"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Onyesha mapendekezo ya marekebisho"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Onyesha maneno yaliyopendekezwa wakati unachapa"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Onyesha kila wakati"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Onyesha kwenye hali wima"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ficha kila wakati"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Tumia kibadilishi cha mwamba nafasi ya lugha"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Onyesha kitufe cha mipangilio"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Kiotomatiki"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Onyesha kila wakati"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">" Ficha kila mara"</string>
<string name="auto_correction" msgid="4979925752001319458">"Usahihishaji Kioto"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Kiaamba na kiakifishi hurekebisha maneno ambayo yamechapishwa vibaya"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Zima"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Ya wastani"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Ya hima"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Changamfu zaidi"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Mapendekezo ya bigramu"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Tumia neno la hapo awali ili kuboresha pendekezo"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Udadisi wa bigramu"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Mapendekezo ya neno lifuatalo"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Tumia neno la awali ili kuboresha mapendekezo"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Utabiri wa neno lifuatalo"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Tumia neno la awali pia kwa udadisi"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Imehifadhiwa"</string>
<string name="label_go_key" msgid="1635148082137219148">"Nenda"</string>
<string name="label_next_key" msgid="362972844525672568">"Ifuatayo"</string>
+ <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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Zaidi"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"? 123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Kuhamisha kumewezeshwa"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Herufi kubwa imewezeshwa"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift imewashwa (gonga ili kulemaza)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock imewashwa (gonga ili kulemaza)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Futa"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Alama"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Herufi"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Uingizaji sauti"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Uso wenye tabasamu"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Rudi"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Muda"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Mabano ya kushoto"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"mabano ya kulia"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Nukta mbili juu na chini"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikoloni"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Alama ya mshangao"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Alama ya kiulizio"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Nukuu mara mbili"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Nukuu moja"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Tafuta"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Nukta"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Square root"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Chapa ya Biashara"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Kwa ulinzi wa"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Nyota"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Pauni"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Nukuu ya chini maradufu"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Uingizaji wa sauti"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Uingizaji wa sauti hauhimiliwi kwa lugha yako kwa sasa, lakini inafanya kazi kwa Kiingereza."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Uingizaji wa sauti hutumia utambuaji wa usemi wa Google. "<a href="http://m.google.com/privacy">"Sera ya Faragha ya Simu za mkononi "</a>" hutumika."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ili kuzima uingizaji sauti, nenda kwa mipangilio ya mbinu ya uingizaji."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ili kutumia uingizaji wa sauti, bonyeza kitufe cha maikrofoni."</string>
- <string name="voice_listening" msgid="467518160751321844">"Ongea sasa"</string>
- <string name="voice_working" msgid="6666937792815731889">"Inafanya kazi"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Hitilafu. Tafadhali jaribu tena."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Haiwezi kuunganisha"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Hitilafu, usemi ni zaidi."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Tatizo la sauti"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Hitilafu ya Seva"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Hakuna matamshi yaliyosikizwa"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Hakuna zinazolingana zilizopatikana."</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Utafutaji wa sauti haujawekwa"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Kidokezo:"</b>" Telezesha kidole kwenye kibodi ili utamke"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Kidokezo:"</b>" Wakati mwingine, jaribu kutamka uakifishaji kama vile \"kituo\", \"koma\", au \"kiulizio cha swali\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Ghairi"</string>
- <string name="ok" msgid="7898366843681727667">"Sawa"</string>
- <string name="voice_input" msgid="2466640768843347841">"Uingizaji wa sauti"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift imewezeshwa"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock imewezeshwa"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift imelemazwa"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Hali ya alama"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Hali ya barua"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Hali ya simu"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Hali ya alama za simu"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Kibao cha kuingizia sauti"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Kwenye kibodi kuu"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Kwenye kibodi ya ishara"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Zima"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Maikrofoni kwenye kibodi kuu"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Maikrofoni kwenye kibodi ya ishara"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Uingizaji sauti umelemazwa"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Chagua mtindo wa uingizaji"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Telezesha kidole kwenye kitufe cha nafasi ili kubadilisha lugha"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Gusa tena ili kuhifadhi"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Dokeza mhuri wa muda kwenye kumbukumbu"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Mhuri wa muda uliorekodiwa"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Usihifadhi kumbukumbu za kipindi hiki"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Inafuta kumbukumbu za kipindi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Kumbukumbu za kipindi zimefutwa"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Kumbukumbu za kipindi HAZIJAFUTWA"</string>
+ <string name="select_language" msgid="3693815588777926848">"Lugha zinazoruhusiwa"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gusa tena ili kuhifadhi"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Wezesha maoni ya watumiaji"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Saidia kuimarisha mbinu ya uingizaji wa kihariri, kwa kutuma takwimu za matumizi na ripoti za kuvurugika kwa Google kiotomatiki."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Gusa ili kurekebisha maneno"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Gusa maneno yaliyoingizwa ili kuyasahihisha, wakati mapendekezo yanaonekana tu"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Maandhari ya kibodi"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Kibodi ya Kicheki"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Kibodi ya Kiarabu"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Kibodi ya Kidenmaki"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Kibodi ya Kijerumani"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Kibodi cha QWERTY cha Kijerumani"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Kibodi ya Kiingereza (Uingereza)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Kibodi ya Kiingereza (Marekani)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Kibodi ya Kihispania"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Kibodi ya Kifini"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Kibodi ya Kifaransa"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Kibodi ya Kifaransa (Kanada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Kibodi ya Kifaransa (Uswizi)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Kibodi ya Kikorasia"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Kibodi ya Kihangari"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Kibodi ya Kiyahudi"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Kibodi ya Kiitaliano"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Kibodi ya Kinorwe"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Kibodi ya Kiholanzi"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Kibodi ya Kipolishi"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Kibodi ya Kireno"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Kibodi ya Kirusi"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Kibodi ya Kiserbia"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Kibodi ya Kiswidi"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Kibodi ya Kituruki"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Sauti ya Afrikaan"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Sauti ya Kicheki"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Sauti ya Kijerumani"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Sauti ya Kiingereza"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Sauti ya Kihispania"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Sauti ya Kifaransa"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Sauti ya Kiitalia"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Sauti ya Kijapani"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Sauti ya Kikorea"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"sauti ya Kiduchi"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Sauti ya Kipolandi"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Sauti ya Kireno"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Sauti ya Kirusi"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Sauti ya Kituruki"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Kichina, sauti ya Yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Kichina, sauti ya Mandarini"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu Voice"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Kiingereza cha (Uingereza)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Kiingereza cha (Marekani)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Kiingereza (Uingereza) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Kiingereza (Marekani) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Hakuna lugha"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Hakuna lugha (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Hakuna lugha (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Hakuna lugha (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Hakuna lugha (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Hakuna lugha (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Hakuna lugha (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Mitindo maalum ya ingizo"</string>
+ <string name="add_style" msgid="6163126614514489951">"Ongeza mtindo"</string>
+ <string name="add" msgid="8299699805688017798">"Ongeza"</string>
+ <string name="remove" msgid="4486081658752944606">"Ondoa"</string>
+ <string name="save" msgid="7646738597196767214">"Hifadhi"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Lugha"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Mpangilio"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Mtindo wa ingizo lako maalum unahitaji kuwa umewezeshwa kabla uanze kulitumia. Unataka kuuwesha sasa?"</string>
+ <string name="enable" msgid="5031294444630523247">"Wezesha"</string>
+ <string name="not_now" msgid="6172462888202790482">"Sio sasa"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Mfumo sawa wa maingizo tayari upo: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modi ya uchunguzi wa utumizi"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Bonyeza mipangilio ya kipindi cha mtetemo"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Bonyeza mipangilio ya nguvu za sauti"</string>
</resources>
diff --git a/java/res/values-rm/donottranslate-altchars.xml b/java/res/values-sw600dp-land/config.xml
index 0a5d2aad1..b3cd7278d 100644
--- a/java/res/values-rm/donottranslate-altchars.xml
+++ b/java/res/values-sw600dp-land/config.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
** limitations under the License.
*/
-->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_o">9,ò,ó,ö,ô,õ,œ,ø</string>
+
+<resources>
+ <bool name="config_use_fullscreen_mode">false</bool>
</resources>
diff --git a/java/res/values-sw600dp-land/dimens.xml b/java/res/values-sw600dp-land/dimens.xml
new file mode 100644
index 000000000..a478df89a
--- /dev/null
+++ b/java/res/values-sw600dp-land/dimens.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- Preferable keyboard height in absolute scale: 45.0mm -->
+ <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+ <dimen name="keyboardHeight">283.5dp</dimen>
+ <fraction name="minKeyboardHeight">45%p</fraction>
+
+ <fraction name="keyboard_top_padding">2.444%p</fraction>
+ <fraction name="keyboard_bottom_padding">0.0%p</fraction>
+ <fraction name="key_bottom_gap">4.911%p</fraction>
+ <fraction name="key_horizontal_gap">1.284%p</fraction>
+
+ <fraction name="key_bottom_gap_stone">4.355%p</fraction>
+ <fraction name="key_horizontal_gap_stone">1.505%p</fraction>
+
+ <fraction name="key_bottom_gap_gb">5.200%p</fraction>
+ <fraction name="key_horizontal_gap_gb">1.447%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_bottom_padding_ics">0.0%p</fraction>
+
+ <dimen name="popup_key_height">81.9dp</dimen>
+
+ <!-- left or right padding of label alignment -->
+ <dimen name="key_label_horizontal_padding">18dp</dimen>
+
+ <fraction name="key_letter_ratio">50%</fraction>
+ <fraction name="key_large_letter_ratio">48%</fraction>
+ <fraction name="key_label_ratio">32%</fraction>
+ <fraction name="key_hint_letter_ratio">23%</fraction>
+ <fraction name="key_hint_label_ratio">34%</fraction>
+ <fraction name="key_uppercase_letter_ratio">29%</fraction>
+ <fraction name="spacebar_text_ratio">30.0%</fraction>
+ <dimen name="key_uppercase_letter_padding">4dp</dimen>
+
+ <dimen name="suggestions_strip_padding">252.0dp</dimen>
+ <integer name="max_more_suggestions_row">5</integer>
+ <fraction name="min_more_suggestions_width">50%</fraction>
+</resources>
diff --git a/java/res/values-large/config.xml b/java/res/values-sw600dp/config.xml
index 75c0edf87..2f35d9ae5 100644
--- a/java/res/values-large/config.xml
+++ b/java/res/values-sw600dp/config.xml
@@ -19,26 +19,23 @@
-->
<resources>
- <bool name="config_enable_show_settings_key_option">true</bool>
<bool name="config_enable_show_voice_key_option">false</bool>
<bool name="config_enable_show_popup_on_keypress_option">false</bool>
- <bool name="config_enable_show_recorrection_option">false</bool>
- <bool name="config_enable_quick_fixes_option">false</bool>
<bool name="config_enable_bigram_suggestions_option">false</bool>
- <bool name="config_swipe_down_dismiss_keyboard_enabled">false</bool>
- <bool name="config_sliding_key_input_enabled">false</bool>
- <bool name="config_digit_popup_characters_enabled">false</bool>
<!-- Whether or not Popup on key press is enabled by default -->
<bool name="config_default_popup_preview">false</bool>
<bool name="config_default_sound_enabled">true</bool>
<bool name="config_auto_correction_spacebar_led_enabled">false</bool>
- <bool name="config_use_spacebar_language_switcher">false</bool>
- <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
- <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
<!-- The language is never displayed if == 0, always displayed if < 0 -->
<integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer>
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
- <string name="config_default_keyboard_theme_id" translatable="false">5</string>
- <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
- <integer name="config_max_popup_keyboard_column">5</integer>
+ <string name="config_default_keyboard_theme_index" translatable="false">5</string>
+ <integer name="config_max_more_keys_column">5</integer>
+ <!--
+ Configuration for LatinKeyboardView
+ -->
+ <bool name="config_sliding_key_input_enabled">false</bool>
+ <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if
+ false -->
+ <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool>
</resources>
diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
new file mode 100644
index 000000000..5596ba41c
--- /dev/null
+++ b/java/res/values-sw600dp/dimens.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- Preferable keyboard height in absolute scale: 48.0mm -->
+ <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+ <dimen name="keyboardHeight">302.4dp</dimen>
+ <fraction name="maxKeyboardHeight">46%p</fraction>
+ <fraction name="minKeyboardHeight">-35.0%p</fraction>
+
+ <dimen name="popup_key_height">63.0dp</dimen>
+
+ <fraction name="keyboard_top_padding">2.291%p</fraction>
+ <fraction name="keyboard_bottom_padding">0.0%p</fraction>
+ <fraction name="key_bottom_gap">3.750%p</fraction>
+ <fraction name="key_horizontal_gap">1.857%p</fraction>
+
+ <fraction name="key_bottom_gap_stone">3.75%p</fraction>
+ <fraction name="key_horizontal_gap_stone">1.602%p</fraction>
+
+ <fraction name="key_bottom_gap_gb">4.625%p</fraction>
+ <fraction name="key_horizontal_gap_gb">2.113%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_bottom_padding_ics">4.0%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. -->
+ <!-- popup_key_height x 1.2 -->
+ <dimen name="more_keys_keyboard_slide_allowance">98.3dp</dimen>
+ <!-- popup_key_height x -1.0 -->
+ <dimen name="more_keys_keyboard_vertical_correction">-81.9dp</dimen>
+
+ <!-- left or right padding of label alignment -->
+ <dimen name="key_label_horizontal_padding">6dp</dimen>
+ <dimen name="key_hint_letter_padding">3dp</dimen>
+ <dimen name="key_uppercase_letter_padding">3dp</dimen>
+
+ <fraction name="key_letter_ratio">42%</fraction>
+ <fraction name="key_large_letter_ratio">45%</fraction>
+ <fraction name="key_label_ratio">25%</fraction>
+ <fraction name="key_large_label_ratio">32%</fraction>
+ <fraction name="key_hint_letter_ratio">23%</fraction>
+ <fraction name="key_hint_label_ratio">28%</fraction>
+ <fraction name="key_uppercase_letter_ratio">22%</fraction>
+ <fraction name="key_preview_text_ratio">50%</fraction>
+ <fraction name="spacebar_text_ratio">28.0%</fraction>
+ <dimen name="key_preview_height">94.5dp</dimen>
+ <dimen name="key_preview_offset">16.0dp</dimen>
+
+ <dimen name="key_preview_offset_ics">8.0dp</dimen>
+ <!-- popup_key_height x -0.5 -->
+ <dimen name="more_keys_keyboard_vertical_correction_ics">-31.5dp</dimen>
+
+ <dimen name="suggestions_strip_height">44dp</dimen>
+ <dimen name="more_suggestions_row_height">44dp</dimen>
+ <integer name="max_more_suggestions_row">6</integer>
+ <fraction name="min_more_suggestions_width">90%</fraction>
+ <dimen name="suggestions_strip_padding">94.5dp</dimen>
+ <dimen name="suggestion_min_width">48.0dp</dimen>
+ <dimen name="suggestion_padding">12dp</dimen>
+ <dimen name="suggestion_text_size">22dp</dimen>
+ <dimen name="more_suggestions_hint_text_size">33dp</dimen>
+</resources>
diff --git a/java/res/drawable/background_voice.xml b/java/res/values-sw768dp-land/config.xml
index 3b6137df3..b3cd7278d 100644
--- a/java/res/drawable/background_voice.xml
+++ b/java/res/values-sw768dp-land/config.xml
@@ -17,9 +17,7 @@
** limitations under the License.
*/
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient
- android:startColor="#ff000000"
- android:endColor="#ff000e29"
- android:angle="90" />
-</shape> \ No newline at end of file
+
+<resources>
+ <bool name="config_use_fullscreen_mode">false</bool>
+</resources>
diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml
new file mode 100644
index 000000000..b95c858dc
--- /dev/null
+++ b/java/res/values-sw768dp-land/dimens.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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>
+ <!-- Preferable keyboard height in absolute scale: 58.0mm -->
+ <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+ <dimen name="keyboardHeight">365.4dp</dimen>
+ <fraction name="minKeyboardHeight">45%p</fraction>
+
+ <fraction name="keyboard_top_padding">1.896%p</fraction>
+ <fraction name="keyboard_bottom_padding">0.0%p</fraction>
+
+ <fraction name="key_bottom_gap">4.103%p</fraction>
+ <fraction name="key_horizontal_gap">1.034%p</fraction>
+
+ <fraction name="key_bottom_gap_stone">3.379%p</fraction>
+ <fraction name="key_horizontal_gap_stone">1.062%p</fraction>
+
+ <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>
+
+ <dimen name="popup_key_height">81.9dp</dimen>
+
+ <!-- left or right padding of label alignment -->
+ <dimen name="key_label_horizontal_padding">18dp</dimen>
+
+ <fraction name="key_letter_ratio">43%</fraction>
+ <fraction name="key_large_letter_ratio">42%</fraction>
+ <fraction name="key_label_ratio">28%</fraction>
+ <fraction name="key_hint_letter_ratio">23%</fraction>
+ <fraction name="key_hint_label_ratio">28%</fraction>
+ <fraction name="key_uppercase_letter_ratio">24%</fraction>
+ <fraction name="spacebar_text_ratio">24.00%</fraction>
+ <dimen name="key_preview_height">107.1dp</dimen>
+
+ <dimen name="key_preview_offset_ics">8.0dp</dimen>
+
+ <dimen name="suggestions_strip_padding">252.0dp</dimen>
+ <fraction name="min_more_suggestions_width">50%</fraction>
+</resources>
diff --git a/java/res/values-xlarge/config.xml b/java/res/values-sw768dp/config.xml
index 4025b0e41..5fcaeeb41 100644
--- a/java/res/values-xlarge/config.xml
+++ b/java/res/values-sw768dp/config.xml
@@ -19,27 +19,29 @@
-->
<resources>
- <bool name="config_enable_show_settings_key_option">false</bool>
<bool name="config_enable_show_voice_key_option">false</bool>
<bool name="config_enable_show_popup_on_keypress_option">false</bool>
- <bool name="config_enable_show_recorrection_option">false</bool>
- <bool name="config_enable_quick_fixes_option">false</bool>
<bool name="config_enable_bigram_suggestions_option">false</bool>
- <bool name="config_swipe_down_dismiss_keyboard_enabled">false</bool>
- <bool name="config_sliding_key_input_enabled">false</bool>
- <bool name="config_digit_popup_characters_enabled">false</bool>
<!-- Whether or not Popup on key press is enabled by default -->
<bool name="config_default_popup_preview">false</bool>
<bool name="config_default_sound_enabled">true</bool>
<bool name="config_auto_correction_spacebar_led_enabled">false</bool>
- <bool name="config_use_spacebar_language_switcher">false</bool>
- <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
- <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
- <integer name="config_delay_update_suggestions">180</integer>
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
- <string name="config_default_keyboard_theme_id" translatable="false">5</string>
- <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
- <integer name="config_max_popup_keyboard_column">5</integer>
- <!-- Screen metrics for logging. 0 = "mdpi", 1 = "hdpi", 2 = "xlarge" -->
+ <string name="config_default_keyboard_theme_index" translatable="false">5</string>
+ <integer name="config_max_more_keys_column">5</integer>
+ <!--
+ Configuration for LatinKeyboardView
+ -->
+ <bool name="config_sliding_key_input_enabled">false</bool>
+ <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if
+ false -->
+ <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool>
+ <!-- Screen metrics for logging.
+ 0 = "mdpi phone screen"
+ 1 = "hdpi phone screen"
+ 2 = "mdpi 11 inch tablet screen"
+ 3 = "xhdpi phone screen?"
+ 4 = ?
+ -->
<integer name="log_screen_metrics">2</integer>
</resources>
diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml
new file mode 100644
index 000000000..ce33b73cb
--- /dev/null
+++ b/java/res/values-sw768dp/dimens.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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>
+ <!-- Preferable keyboard height in absolute scale: 48.0mm -->
+ <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+ <dimen name="keyboardHeight">302.4dp</dimen>
+ <fraction name="maxKeyboardHeight">46%p</fraction>
+ <fraction name="minKeyboardHeight">-35.0%p</fraction>
+
+ <fraction name="keyboard_top_padding">2.291%p</fraction>
+ <fraction name="keyboard_bottom_padding">0.0%p</fraction>
+
+ <fraction name="key_bottom_gap">4.270%p</fraction>
+ <fraction name="key_horizontal_gap">1.551%p</fraction>
+
+ <fraction name="key_bottom_gap_stone">3.75%p</fraction>
+ <fraction name="key_horizontal_gap_stone">1.059%p</fraction>
+
+ <fraction name="key_bottom_gap_gb">4.687%p</fraction>
+ <fraction name="key_horizontal_gap_gb">1.272%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>
+
+ <dimen name="popup_key_height">63.0dp</dimen>
+
+ <dimen name="more_keys_keyboard_key_horizontal_padding">12dp</dimen>
+ <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
+ <!-- popup_key_height x 1.2 -->
+ <dimen name="more_keys_keyboard_slide_allowance">98.3dp</dimen>
+ <!-- popup_key_height x -1.0 -->
+ <dimen name="more_keys_keyboard_vertical_correction">-81.9dp</dimen>
+
+ <!-- left or right padding of label alignment -->
+ <dimen name="key_label_horizontal_padding">6dp</dimen>
+ <dimen name="key_hint_letter_padding">3dp</dimen>
+ <dimen name="key_uppercase_letter_padding">3dp</dimen>
+
+ <fraction name="key_letter_ratio">40%</fraction>
+ <fraction name="key_large_letter_ratio">42%</fraction>
+ <fraction name="key_label_ratio">28%</fraction>
+ <fraction name="key_large_label_ratio">28%</fraction>
+ <fraction name="key_hint_letter_ratio">23%</fraction>
+ <fraction name="key_hint_label_ratio">28%</fraction>
+ <fraction name="key_uppercase_letter_ratio">26%</fraction>
+ <fraction name="key_preview_text_ratio">50%</fraction>
+ <fraction name="spacebar_text_ratio">29.03%</fraction>
+ <dimen name="key_preview_height">94.5dp</dimen>
+ <dimen name="key_preview_offset">16.0dp</dimen>
+
+ <dimen name="key_preview_offset_ics">8.0dp</dimen>
+ <!-- popup_key_height x -0.5 -->
+ <dimen name="more_keys_keyboard_vertical_correction_ics">-31.5dp</dimen>
+
+ <dimen name="suggestions_strip_height">44dp</dimen>
+ <dimen name="more_suggestions_row_height">44dp</dimen>
+ <integer name="max_more_suggestions_row">6</integer>
+ <fraction name="min_more_suggestions_width">90%</fraction>
+ <dimen name="suggestions_strip_padding">94.5dp</dimen>
+ <dimen name="suggestion_min_width">46dp</dimen>
+ <dimen name="suggestion_padding">8dp</dimen>
+ <dimen name="suggestion_text_size">22dp</dimen>
+ <dimen name="more_suggestions_hint_text_size">33dp</dimen>
+</resources>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 060702deb..6f25a2024 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -21,61 +21,69 @@
<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">"แป้นพิมพ์ Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"การตั้งค่าแป้นพิมพ์ Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ตัวเลือกการป้อนข้อมูล"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"คำสั่งบันทึกการวิจัย"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"แอนดรอยด์ตรวจสอบการสะกด"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"แอนดรอยด์ตรวจสอบการสะกด (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"การตั้งค่าการตรวจสอบการสะกด"</string>
+ <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="ngram_category" msgid="5337109164339320257">"ข้อเสนอแนะตามคำก่อนหน้านี้"</string>
<string name="misc_category" msgid="6894192814868233453">"ตัวเลือกอื่นๆ"</string>
<string name="advanced_settings" msgid="362895144495591463">"การตั้งค่าขั้นสูง"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"ตัวเลือกสำหรับผู้ใช้ที่มีความเชี่ยวชาญ"</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="suppress_language_switch_key" msgid="8003788410354806368">"ยกเลิกแป้นสลับภาษา"</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="use_contacts_dict" msgid="4435317977804180815">"แนะนำชื่อผู้ติดต่อ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ใช้ชื่อจากรายชื่อติดต่อสำหรับคำแนะนำและการแก้ไข"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"เปิดใช้งานการแก้ไขซ้ำ"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"ตั้งค่าคำแนะนำสำหรับการแก้ไขซ้ำ"</string>
<string name="auto_cap" msgid="1719746674854628252">"ปรับเป็นตัวพิมพ์ใหญ่อัตโนมัติ"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"กำหนดค่าพจนานุกรม"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"แก้ไขด่วน"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"แก้ไขข้อผิดพลาดในการพิมพ์ที่พบบ่อย"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"พจนานุกรม Add-On"</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="3551821800439659812">"แสดงในโหมดแนวตั้ง"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"ซ่อนทุกครั้ง"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"ใช้แป้นเคาะสลับภาษา"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"แสดงแป้นการตั้งค่า"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"อัตโนมัติ"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"แสดงตลอดเวลา"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"ซ่อนตลอดเวลา"</string>
<string name="auto_correction" msgid="4979925752001319458">"การแก้ไขอัตโนมัติ"</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_aggeressive" msgid="3524029103734923819">"เข้มงวด"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"เข้มงวดมาก"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"คำแนะนำ Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"ใช้คำก่อนหน้านี้เพื่อปรับปรุงคำแนะนำ"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"การคาดคะเน Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"คำแนะนำสำหรับคำถัดไป"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ใช้คำก่อนหน้านี้เพื่อปรับปรุงคำแนะนำ"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"การคาดคะเนคำถัดไป"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"ใช้คำก่อนหน้านี้สำหรับการคาดคะเน"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"เพิ่มเติม"</string>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"กขค"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"หยุดชั่วคราว"</string>
<string name="label_wait_key" msgid="6402152600878093134">"รอ"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"เสียบชุดหูฟังเพื่อฟังเสียงเมื่อพิมพ์รหัสผ่าน"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"ข้อความปัจจุบันคือ %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"ไม่มีข้อความ"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"รหัสคีย์ %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"เปิดใช้งาน Shift แล้ว"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"เปิดใช้งาน 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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"เครื่องหมายจุลภาค"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"มหัพภาค"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"วงเล็บซ้าย"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"วงเล็บขวา"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"เครื่องหมายจุดคู่"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"อัฒภาค"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"อัศเจรีย์"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"เครื่องหมายคำถาม"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"อัญประกาศ"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"เครื่องหมายคำพูดเดี่ยว"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"ค้นหา"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"เครื่องหมายจุด"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"รากที่สอง"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"เดลตา"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"เครื่องหมายการค้า"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"ติดดาว"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"ปอนด์"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"จุดไข่ปลา"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"อัญประกาศล่าง"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"การป้อนข้อมูลด้วยเสียง"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"ขณะนี้การป้อนข้อมูลด้วยเสียงยังไม่ได้รับการสนับสนุนในภาษาของคุณ แต่ใช้ได้ในภาษาอังกฤษ"</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"ป้อนข้อมูลด้วยเสียงใช้การจดจำคำพูดของ Google "<a href="http://m.google.com/privacy">" นโยบายส่วนบุคคลของมือถือ"</a>"มีผลบังคับใช้"</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"หากต้องการปิดการป้อนข้อมูลด้วยเสียง ไปที่การตั้งค่าวิธีการป้อนข้อมูล"</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"หากต้องการใช้การป้อนข้อมูลด้วยเสียง ให้กดปุ่มไมโครโฟน"</string>
- <string name="voice_listening" msgid="467518160751321844">"พูดได้เลย"</string>
- <string name="voice_working" msgid="6666937792815731889">"กำลังทำงาน"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"ข้อผิดพลาด โปรดลองอีกครั้ง"</string>
- <string name="voice_network_error" msgid="6649556447401862563">"ไม่สามารถเชื่อมต่อได้"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"ข้อผิดพลาด คำพูดยาวเกินไป"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"ปัญหาด้านเสียง"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"ข้อผิดพลาดของเซิร์ฟเวอร์"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"ไม่ได้ยินเสียง"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"ไม่พบรายการที่ตรงกัน"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"ไม่ได้ติดตั้ง Voice Search"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"คำแนะนำ:"</b>" กวาดผ่านแป้นพิมพ์เพื่อพูด"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"คำแนะนำ:"</b>" ครั้งต่อไป ให้ลองเอ่ยถึงเครื่องหมายวรรคตอน เช่น \"มหัพภาค\" \"จุลภาค\" หรือ \"เครื่องหมายคำถาม\""</string>
- <string name="cancel" msgid="6830980399865683324">"ยกเลิก"</string>
- <string name="ok" msgid="7898366843681727667">"ตกลง"</string>
- <string name="voice_input" msgid="2466640768843347841">"การป้อนข้อมูลด้วยเสียง"</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="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="selectInputMethod" msgid="315076553378705821">"เลือกวิธีการป้อนข้อมูล"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"กำหนดค่าวิธีการป้อนข้อมูล"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ภาษาในการป้อนข้อมูล"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"เลื่อนนิ้วไปบนแป้นเคาะวรรคเพื่อเปลี่ยนภาษา"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← แตะอีกครั้งเพื่อบันทึก"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"จดเวลาบันทึกไว้ในบันทึก"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"บันทึกเวลาบันทึกแล้ว"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"อย่าบันทึกเซสชันนี้"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"กำลังลบบันทึกเซสชัน"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ลบบันทึกเซสชันแล้ว"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"บันทึกเซสชันไม่ถูกลบ"</string>
+ <string name="select_language" msgid="3693815588777926848">"ภาษาสำหรับการป้อนข้อมูล"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"แตะอีกครั้งเพื่อบัน​​ทึก"</string>
<string name="has_dictionary" msgid="6071847973466625007">"มีพจนานุกรมให้ใช้งาน"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"เปิดใช้งานการแสดงความคิดเห็นจากผู้ใช้"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"ช่วยปรับปรุงตัวแก้ไขวิธีการป้อนข้อมูลนี้โดยการส่งสถิติการใช้งานและรายงานการขัดข้องถึง Google โดยอัตโนมัติ"</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"แตะเพื่อแก้ไขคำ"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"แตะคำที่ป้อนไว้เพื่อแก้ไข เฉพาะเมื่อเห็นข้อเสนอแนะเท่านั้น"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"ชุดรูปแบบแป้นพิมพ์"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"แป้นพิมพ์ภาษาเช็ก"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"แป้นพิมพ์ภาษาอาหรับ"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"แป้นพิมพ์ภาษาเดนมาร์ก"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"แป้นพิมพ์ภาษาเยอรมัน"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"แป้นพิมพ์ภาษาเยอรมันแบบ QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"แป้นพิมพ์ภาษาอังกฤษ (สหราชอาณาจักร)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"แป้นพิมพ์ภาษาอังกฤษ (สหรัฐอเมริกา)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"แปันพิมพ์ภาษาสเปน"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"แป้นพิมพ์ภาษาฟินแลนด์"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"แป้นพิมพ์ภาษาฝรั่งเศส"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"แป้นพิมพ์ภาษาฝรั่งเศส (แคนาดา)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"แป้นพิมพ์ภาษาฝรั่งเศส (สวิตเซอร์แลนด์)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"แป้นพิมพ์ภาษาโครเอเชีย"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"แป้นพิมพ์ภาษาฮังการี"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"แป้นพิมพ์ภาษาฮิบรู"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"แป้นพิมพ์ภาษาอิตาลี"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"แป้นพิมพ์ภาษานอร์เวย์"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"แป้นพิมพ์ภาษาดัตช์"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"แป้นพิมพ์ภาษาโปแลนด์"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"แป้นพิมพ์ภาษาโปรตุเกส"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"แป้นพิมพ์ภาษารัสเซีย"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"แป้นพิมพ์ภาษาเซอร์เบีย"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"แป้นพิมพ์ภาษาสวีเดน"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"แป้นพิมพ์ภาษาตุรกี"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"เสียงภาษาแอฟริกัน"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"เสียงภาษาเช็ก"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"เสียงภาษาเยอรมัน"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"เสียงภาษาอังกฤษ"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"เสียงภาษาสเปน"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"เสียงภาษาฝรั่งเศส"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"เสียงภาษาอิตาลี"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"เสียงภาษาญี่ปุ่น"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"เสียงภาษาเกาหลี"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"เสียงภาษาดัตช์"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"เสียงภาษาโปแลนด์"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"เสียงภาษาโปรตุเกส"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"เสียงภาษารัสเซีย"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"เสียงภาษาตุรกี"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"เสียงภาษาจีนกวางตุ้ง"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"เสียงภาษาจีนกลาง"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"เสียงภาษาซูลู"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"อังกฤษ (สหราชอาณาจักร)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"อังกฤษ (อเมริกัน)"</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_no_language" msgid="141420857808801746">"ไม่มีภาษา"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"ไม่มีภาษา (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"ไม่มีภาษา (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"ไม่มีภาษา (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"ไม่มีภาษา (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"ไม่มีภาษา (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"ไม่มีภาษา (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"การตั้งค่าระยะเวลาการสั่นเมื่อกดแป้นพิมพ์"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"การตั้งค่าระดับเสียงเมื่อกดแป้นพิมพ์"</string>
</resources>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index 4cef60f36..e2fe6c5b4 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -21,61 +21,69 @@
<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">"Android keyboard"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Mga setting ng Android keyboard"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Cmmnd sa Log ng Pnnliksik"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Pang-check ng pagbabaybay ng Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pang-check ng pagbabaybay ng Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Mga setting ng pang-check ng pagbabaybay"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Maghanap pangalan contact"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Gumagamit pang-check pagbabaybay entry sa iyong listahan contact"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Mag-vibrate sa keypress"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Tunog sa keypress"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Popup sa keypress"</string>
<string name="general_category" msgid="1859088467017573195">"Pangkalahatan"</string>
<string name="correction_category" msgid="2236750915056607613">"Pagwawasto ng teksto"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Mga suhestiyon batay sa mga nakaraang salita"</string>
<string name="misc_category" msgid="6894192814868233453">"Iba pang mga pagpipilian"</string>
<string name="advanced_settings" msgid="362895144495591463">"Mga advanced na setting"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Mga pagpipilian para sa mga ekspertong user"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Mga pagpipilian para sa mga dalubhasa"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Lipat iba paraan ng input"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Saklaw din ng key ng pagpalit ng wika ang ibang paraan ng input"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Pigilan key pagpalit wika"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Balewala antala key popup"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Walang antala"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Mungkahi pangalan Contact"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gamitin pangalan mula Mga Contact sa mga mungkahi\'t pagwawasto"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Paganahin ang mga muling pagtatama"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Magtakda ng mga suhestyon para sa mga muling pagtatama"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalization"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"I-configure ang mga diksyunaryo"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Mga mabilisang pagsasaayos"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Itinatama ang mga karaniwang na-type na mali"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Mga diksyunaryo na add-on"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Pangunahing diksyunaryo"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Magpakita ng mga suhestiyon ng pagwawasto"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Ipakita ang mga iminumungkahing salita habang nagta-type"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Palaging ipakita"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Ipakita sa portrait mode"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Palaging itago"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Gamitin ang spacebar na panlipat ng wika"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Ipakita ang key ng mga setting"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Awtomatiko"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Palaging ipakita"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Palaging itago"</string>
<string name="auto_correction" msgid="4979925752001319458">"Awtomatikong pagwasto"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Awto tinatama ng spacebar at bantas ang maling na-type"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Naka-off"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresibo"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Napaka-agresibo"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Mga bigram na suhestiyon"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Gamitin ang nakaraang salita upang pahusayin ang suhestiyon"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram na hula"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Mga paghuhula sa susunod na salita"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gamitin ang naunang salita para mapahusay ang mga suhestiyon"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Paghuhula sa susunod na salita"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Gamitin ang nakaraang salita para din sa hula"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Higit pa"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Pinagana ang shift"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Pinagana ang caps lock"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Naka-on ang shift (i-tap upang huwag paganahin)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Naka-on ang caps lock (i-tap upang huwag paganahin)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Tanggalin"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Mga Simbolo"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Mga Titik"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Input ng boses"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley na mukha"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Bumalik"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Kuwit"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Tuldok"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kaliwang panaklong"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Kanang panaklong"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Tutuldok"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Tuldukuwit"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Tandang padamdam"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Tandang pananong"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Panipi"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Kudlit"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Paghahanap"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Tuldok"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Square root"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Star"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Pound"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Mababang panipi"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Pag-input ng boses"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Hindi kasalukuyang suportado ang pag-input ng boses para sa iyong wika, ngunit gumagana sa Ingles."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Gumagamit ang pag-input ng boses ng speech recognition ng Google. Nalalapat "<a href="http://m.google.com/privacy">"Ang Patakaran sa Privacy ng Mobile"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Upang i-off ang pag-input ng boses, pumunta sa mga setting ng pamamaraan ng pag-input."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Upang gamitin ang pag-input ng boses, pindutin ang pindutan na mikropono."</string>
- <string name="voice_listening" msgid="467518160751321844">"Magsalita ngayon"</string>
- <string name="voice_working" msgid="6666937792815731889">"Nagtatrabaho"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Error. Pakisubukang muli."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Hindi makakonekta"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, masyadong maraming pananalita."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Problema sa audio"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Error sa server"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Walang narinig na pananalita"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Walang nakitang mga tugma"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Hindi naka-install ang paghahanap ng boses"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Pahiwatig:"</b>" Mag-swipe sa keyboard upang magsalita"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Pahiwatig:"</b>" Sa susunod, subukang magsalita ng bantas tulad ng \"tuldok\", \"kuwit\", o \"tandang pananong\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Kanselahin"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Pag-input ng boses"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pinagana ang shift"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Pinagana ang caps lock"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Hindi pinagana ang shift"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode ng mga simbolo"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode ng mga titik"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode ng telepono"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode ng mga simbolo ng telepono"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sa pangunahing keyboard"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sa keyboard ng mga simbolo"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Naka-off"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic sa pangunahing keyboard"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic sa keyboard ng mga simbolo"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hindi pinagana ang voice input"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Pumili ng paraan ng pag-input"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"I-slide ang daliri sa spacebar upang palitan ang wika"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Pinduting muli upang i-save"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Tandaan timestamp sa log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Na-record na timestamp"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Huwag i-log ang session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Tinatanggl log ng session"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Tinanggal log ng session"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"HND ntnggl log ng session"</string>
+ <string name="select_language" msgid="3693815588777926848">"Mga wika ng input"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pinduting muli upang i-save"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Paganahin ang feedback ng user"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Tumulong na pahusayin ang editor ng paraan ng pag-input na ito sa pamamagitan ng awtomatikong pagpapadala ng mga istatistika ng paggamit at mga ulat ng crash sa Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Pindutin upang itama ang mga salita"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Pindutin ang mga inilagay na salita upang iwasto ang mga ito, kapag nakikita lang ang mga suhestiyon"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Tema ng keyboard"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Czech na Keyboard"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arabic na Keyboard"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Danish na Keyboard"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"German na Keyboard"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"German na QWERTY Keyboard"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Ingles (UK) na Keyboard"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Ingles (US) na Keyboard"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Spanish na Keyboard"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Finnish na Keyboard"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"French na Keyboard"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"French (Canada) na Keyboard"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"French (Switzerland) na Keyboard"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Croatian na Keyboard"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Hungarian na Keyboard"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Hebrew na Keyboard"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Italian na Keyboard"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norwegian na Keyboard"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Dutch na Keyboard"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Polish na Keyboard"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portuguese na Keyboard"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Russian na Keyboard"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Serbian na Keyboard"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Swedish na Keyboard"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Turkish na Keyboard"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikaans na Boses"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Czech na Boses"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"German na Boses"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Ingles na Boses"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Spanish na Boses"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"French na Boses"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Italian na Boses"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japanese na Boses"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Korean na Boses"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Dutch na Boses"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Polish na Boses"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portuguese na Boses"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Russian na Boses"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Turkish na Boses"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Chinese, Yue na Boses"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Chinese, Mandarin na Boses"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"isiZulu na Boses"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Ingles (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Ingles (Estados Unidos)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Ingles (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Ingles (US) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Walang wika"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Walang wika (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Walang wika (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Walang wika (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Walang wika (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Walang wika (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Walang wika (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Custom style ng input"</string>
+ <string name="add_style" msgid="6163126614514489951">"Dagdag style"</string>
+ <string name="add" msgid="8299699805688017798">"Idagdag"</string>
+ <string name="remove" msgid="4486081658752944606">"Alisin"</string>
+ <string name="save" msgid="7646738597196767214">"I-save"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Wika"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kailangan pinagana ang custom na istilo ng input bago simulang gamitin. Nais itong paganahin?"</string>
+ <string name="enable" msgid="5031294444630523247">"Paganahin"</string>
+ <string name="not_now" msgid="6172462888202790482">"Hindi ngayon"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Umiiral na ang parehong estilo ng input: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Study mode ng pagiging kapaki-pakinabang"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Mga setting ng tagal ng vibration ng keypress"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Mga setting ng volume ng tunog ng keypress"</string>
</resources>
diff --git a/java/res/values-tr/donottranslate-altchars.xml b/java/res/values-tr/donottranslate-altchars.xml
deleted file mode 100644
index 1b83b65c8..000000000
--- a/java/res/values-tr/donottranslate-altchars.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a">â</string>
- <string name="alternates_for_i">8,ı,î,ï,ì,í,į,ī</string>
- <string name="alternates_for_o">9,ö,ô,œ,ò,ó,õ,ø,ō</string>
- <string name="alternates_for_u">7,ü,û,ù,ú,ū</string>
- <string name="alternates_for_s">ş,ß,ś,š</string>
- <string name="alternates_for_g">ğ</string>
- <string name="alternates_for_c">ç,ć,č</string>
-</resources>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index daeac4353..16411b8ed 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -21,61 +21,69 @@
<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">"Android klavyesi"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android klavye (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android klavye ayarları"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Giriş seçenekleri"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Araştırma Günlüğü Komutları"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android yazım denetleyici"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android yazım denetleyici (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Yazım denetimi ayarları"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kişi adlarını denetle"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Yazım denetleyici, kişi listenizdeki girişleri kullanır"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Tuşa basıldığında titret"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Tuşa basıldığında ses çıkar"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Tuşa basıldığında pop-up aç"</string>
<string name="general_category" msgid="1859088467017573195">"Genel"</string>
<string name="correction_category" msgid="2236750915056607613">"Metin düzeltme"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Önceki kelimelere dayalı öneriler"</string>
<string name="misc_category" msgid="6894192814868233453">"Diğer seçenekler"</string>
<string name="advanced_settings" msgid="362895144495591463">"Gelişmiş ayarlar"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Uzman kullanıcılar için seçenekler"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tuş popup içn kaptm ertlm"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Uzmanlar için seçenekler"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Diğer giriş yöntemine geç"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Dil geçiş tuşu diğer giriş yöntemlerini de kapsar"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Dil geçiş tuşunu gösterme"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tuş popup\'ının kapatılmasını geciktirme"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Gecikme yok"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Kişi Adları öner"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Öneri ve düzeltmeler için Kişiler\'deki adları kullan"</string>
- <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük harf yap"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Sözlükleri yapılandır"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Hızlı onarımlar"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Yaygın olarak yapılan yazım hatalarını düzeltir"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Düzeltmeleri etkinleştir"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Yeniden düzeltmeler için önerileri ayarla"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük fark yap"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Ek sözlükler"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Ana sözlük"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Düzeltme önerilerini göster"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Yazarken, önerilen kelimeleri görüntüle"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Her zaman göster"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Dikey modda göster"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Her zaman gizle"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Boşluk çubuğuyla dil geçişini kullan"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Ayarları göster tuşu"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Otomatik"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Her zaman göster"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Her zaman gizle"</string>
<string name="auto_correction" msgid="4979925752001319458">"Otomatik düzeltme"</string>
- <string name="auto_correction_summary" msgid="5625751551134658006">"Boşluk çbğ ve nokt işr yanlış yazılan kelimeleri oto düzeltir"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"Boşluk tuşu ve noktalama işaretleri yanlış yazılan kelimeleri otomatikman düzeltir"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Kapalı"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Ölçülü"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Çok geniş ölçekte"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Bigram önerileri"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Öneriyi geliştirmek için önceki kelimeyi kullanın"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Bigram tahmini"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Sonraki kelime önerileri"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Önerileri geliştirmek için önceki kelimeyi kullan"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Sonraki kelime tahmini"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Önceki kelimeyi de tahmin için kullan"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Diğer"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Üst Karakter Etkin"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Büyük harf etkin"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Üst karakter açık (devre dışı bırakmak için hafifçe vurun)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Büyük harf kilidi açık (devre dışı bırakmak içinn hafifçe vurun)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simgeler"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Harfler"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Ses girişi"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Gülen yüz"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Virgül"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Nokta"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Sol parantez"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Sağ parantez"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"İki Nokta"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Noktalı virgül"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ünlem işareti"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Soru işareti"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Çift tırnak"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Tek tırnak işareti"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Ara"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Nokta"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Karekök"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Ticari marka"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Yüzde işareti"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Yıldız"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Kare"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Üç nokta"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Alt çift tırnak"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Ses girişi"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Ses girişi, şu anda sizin diliniz için desteklenmiyor ama İngilizce dilinde kullanılabilir."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Ses girişi Google\'ın konuşma tanıma işlevini kullanır. "<a href="http://m.google.com/privacy">" Mobil Gizlilik Politikası"</a>" geçerlidir."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ses girişini kapatmak için giriş yöntemi ayarlarına gidin."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ses girişini kullanmak için mikrofon düğmesine basın."</string>
- <string name="voice_listening" msgid="467518160751321844">"Şimdi konuşun"</string>
- <string name="voice_working" msgid="6666937792815731889">"Çalışıyor"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Hata. Lütfen tekrar deneyin."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Bağlanamadı"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Hata, çok uzun konuşma."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Ses sorunu"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Sunucu hatası"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Konuşma duyulmadı"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Eşleşme bulunamadı"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Sesle arama yüklenmedi"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"İpucu:"</b>" Konuşmak için parmağınızı klavye üzerinde kaydırın"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"İpucu:"</b>" Sonraki sefer, \"nokta\", \"virgül\" veya \"soru işareti\" gibi noktalama işaretlerini telaffuz etmeyi deneyin."</string>
- <string name="cancel" msgid="6830980399865683324">"İptal"</string>
- <string name="ok" msgid="7898366843681727667">"Tamam"</string>
- <string name="voice_input" msgid="2466640768843347841">"Ses girişi"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Üst karakter etkin"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Büyük harf kilidi etkin"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Üst karakter devre dışı"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Sembol modu"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Harf modu"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefon modu"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefon sembolleri modu"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Ses girişi tuşu"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Ana klavyede"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Simge klavyesinde"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Kapalı"</string>
- <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Ana klavyede mikrfn"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Ana klavyedeki mikrofon"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Simge klavysnd mikrf"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Sesle grş devre dışı"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Giriş yöntemini seç"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Giriş yöntemlerini yapılandır"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Giriş dilleri"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Dili değiştirmek için parmağınızı boşluk çubuğu üzerinde kaydırın"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Kaydetmek için tekrar dokunun"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Günlüğe zaman damgası koy"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zaman damgası kaydedildi"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Bu oturumu günlüğe kaydetme"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Oturum günlüğü siliniyor"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Oturum günlüğü silindi"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Oturum günlüğü SİLİNMEDİ"</string>
+ <string name="select_language" msgid="3693815588777926848">"Giriş dilleri"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Kaydetmek için tekrar dokunun"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Kullanıcı geri bildirimini etkinleştir"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Kullanım istatistiklerini ve kilitlenme raporlarını Google\'a otomatik olarak göndererek bu giriş yöntemi düzenleyicisinin iyileştirilmesine yardımcı olun."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Kelimeleri düzeltmek için dokunun"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Yalnızca öneriler görünür olduğunda, düzeltmek için girilen kelimelere dokunun"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Klavye teması"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Çekçe Klavye"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Arapça Klavye"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Danca Klavye"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Almanca Klavye"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Almanca QWERTY Klavye"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"İngilizce (İngiltere) Klavye"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"İngilizce (ABD) Klavye"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"İspanyolca Klavye"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Fince Klavye"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Fransızca Klavye"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Fransızca (Kanada) Klavye"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Fransızca (İsviçre) Klavye"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Hırvatça Klavye"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Macarca Klavye"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"İbranice Klavye"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"İtalyanca Klavye"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Norveççe Klavye"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Felemenkçe Klavye"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Lehçe Klavye"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Portekizce Klavye"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Rusça Klavye"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Sırpça Klavye"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"İsveççe Klavye"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Türkçe Klavye"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Afrikanca Ses"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Çekçe Ses"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Almanca Ses"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"İngilizce Ses"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"İspanyolca Ses"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Fransızca Ses"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"İtalyanca Ses"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Japonca Ses"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Korece Ses"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Felemenkçe Ses"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Lehçe Ses"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Portekizce Ses"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Rusça Ses"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Türkçe Ses"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Çince, Yue Ses"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Çince, Mandarin Ses"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Zuluca Ses"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"İngilizce (BK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"İngilizce (ABD)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"İngilizce (İngiltere) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"İngilizce (ABD) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Dil yok"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Dil yok (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Dil yok (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Dil yok (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Dil yok (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Dil yok (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Dil yok (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Özel giriş stilleri"</string>
+ <string name="add_style" msgid="6163126614514489951">"Stil ekle"</string>
+ <string name="add" msgid="8299699805688017798">"Ekle"</string>
+ <string name="remove" msgid="4486081658752944606">"Kaldır"</string>
+ <string name="save" msgid="7646738597196767214">"Kaydet"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Dil"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Düzen"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kullanmaya başlamadan önce özel giriş stilinizin etkinleştirilmesi gerekiyor. Şimdi etkinleştirmek ister misiniz?"</string>
+ <string name="enable" msgid="5031294444630523247">"Etkinleştir"</string>
+ <string name="not_now" msgid="6172462888202790482">"Şimdi değil"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Aynı giriş stili zaten var: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kullanılabilirlik çalışması modu"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Tuşa basma titreşim süresi ayarları"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Tuşa basma ses düzeyi ayarları"</string>
</resources>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 248f50faa..c2e743b45 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -21,61 +21,69 @@
<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">"Клавіатура Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавіатура Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Налашт-ня клавіат. Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Парам. введення"</string>
- <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібр при натиску клав."</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Команди журналу дослідж."</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Засіб перевірки орфографії Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Засіб перевірки орфографії Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Налаштування перевірки орфографії"</string>
+ <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="ngram_category" msgid="5337109164339320257">"Пропозиції на основі попередніх слів"</string>
<string name="misc_category" msgid="6894192814868233453">"Інші опції"</string>
<string name="advanced_settings" msgid="362895144495591463">"Розширені налаштування"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Налаштування для досвідчених користувачів"</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="suppress_language_switch_key" msgid="8003788410354806368">"Заблок.клавішу зміни мови"</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="use_contacts_dict" msgid="4435317977804180815">"Пропон. імена контактів"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Використ. імена зі списку контактів для пропозицій і виправлень"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Увімкнути виправлення"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Показувати варіанти автовиправлень"</string>
<string name="auto_cap" msgid="1719746674854628252">"Авто викор. вел. літер"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Налаштувати словники"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Шв. виправлення"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Виправляє поширені помилки"</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="3551821800439659812">"Показувати в книжковому режимі"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Завжди ховати"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Зміна мови пробілом"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Показ. клав. налашт."</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Автоматично"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Завжди показ."</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Завжди ховати"</string>
<string name="auto_correction" msgid="4979925752001319458">"Автомат. виправлення"</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_aggeressive" msgid="3524029103734923819">"Повне"</string>
- <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Повне виправлення"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Пропозиції з двох слів"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Викор. попер. слово для покращ. пропозиції"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Передбачений запит із двох слів"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Помірне"</string>
+ <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Активне"</string>
+ <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Дуже активне"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Пропозиції наступного слова"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Використати попереднє слово для покращення пропозицій"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Передбачення наступного слова"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Використовувати попереднє слово також як передбачений запит"</string>
<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_to_alpha_key" msgid="4793983863798817523">"Алфавіт"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Більше"</string>
+ <string name="label_to_alpha_key" msgid="4793983863798817523">"АБВ"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"Пауза"</string>
<string name="label_wait_key" msgid="6402152600878093134">"Чек."</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Підключіть гарнітуру, щоб прослухати відтворені вголос символи пароля."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Поточний текст – %s."</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст не введено"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Код клавіші – %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Клавіша Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift увімкнено"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"Кома"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Крапка"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Ліва дужка"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Права дужка"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Двокрапка"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Крапка з комою"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Знак оклику"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Знак питання"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Подвійні лапки"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Одинарні лапки"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Пошук"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Крапка"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратний корінь"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Пі"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Дельта"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Торговельна марка"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Через"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Зірочка"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Решітка"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Три крапки"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Нижні подвійні лапки"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Голос. ввід"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Голос. ввід наразі не підтрим. для вашої мови, але можна користуватися англійською."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Голосовий ввід використовує розпізнавання мовлення Google. Застосовується "<a href="http://m.google.com/privacy">"Політика конфіденційності для мобільних пристроїв"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Щоб вимкнути голосовий ввід, перейдіть до налаштувань методів введення."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Щоб використовувати голосовий ввід, натисніть кнопку мікрофона."</string>
- <string name="voice_listening" msgid="467518160751321844">"Диктуйте"</string>
- <string name="voice_working" msgid="6666937792815731889">"Працює"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Помилка. Спробуйте ще раз."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Неможл. під\'єднатися"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Помилка. Забагато продикт."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Проблема з аудіо"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Помилка сервера"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Не чути диктув."</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Збігів не знайдено"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Голос. пошук не встановлено"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Підк:"</b>" горт. на клавіат., щоб продикт."</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Підказка:"</b>" наступного разу продикт. знаки пункт. такі як \"крапка\", \"кома\" чи \"знак пит\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Скасувати"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Голос. ввід"</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="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">"Miкр. на осн. клав."</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Miкр. на симв. клавіат."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голос. ввід вимкнено"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Вибрати метод введення"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Налаштування методів введення"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Мови вводу"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Переміст. палець на пробіл, щоб змін. мову"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Торкн. ще, щоб збер."</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Мітка часу в журналі"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Записана мітка часу"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Не реєструвати цю сесію"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Видалення журналу сесії"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Журнал сесії видалено"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Журнал сесії НЕ видалено"</string>
+ <string name="select_language" msgid="3693815588777926848">"Мови введення"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Торкніться знову, щоб зберегти"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Словник доступний"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Увімк. відгуки корист."</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Допоможіть покращ. редактор методу введ., автомат. надсилаючи в Google статистику використ. та звіти про збої."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Торкн., щоб виправ. слова"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Торкніться введених слів, щоб виправити їх, лише коли ввімкнено пропозиції"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Тема клавіатури"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Чеська розкладка"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Розкладка для арабської мови"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Данська розкладка"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Німецька розкладка"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Німецька клавіатура QWERTY"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Англ. розкладка (Великобританія)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Англійська розкладка (США)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Іспанська розкладка"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Розкладка для фінської мови"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Французька розкладка"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Французька розкладка (Канада)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Французька розкладка (Швейцарія)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Розкладка для хорватської мови"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Розкладка для угорської мови"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Розкладка для івриту"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Італійська розкладка"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Норвезька розкладка"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Голланд. розклад."</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Розкладка для польської мови"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Розкладка для португальської мови"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Російська розкладка"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Сербська розкладка"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Шведська розкладка"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Розкладка для турецької мови"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Voice мовою африкаанс"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Голос чеською"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Голос німецькою"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Voice англійською мовою"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Голос іспанською"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Голос французькою"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Voice італійською мовою"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Голос японською"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Голос корейською"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Voice голландською мовою"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Голос польською"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Голос португальською"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Голос російською"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Голос турецькою"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Voice китайською, юеською мовою"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Voice китайською, мандарин. мовою"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Voice мовою ісізулу"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Англійська (Великобританія)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Англійська (США)"</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_no_language" msgid="141420857808801746">"Мову не вибрано"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Немає мови (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Без мови (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Без мови (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Без мови (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Без мови (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Без мови (ПК)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"Налаштування тривалості вібрації під час натискання клавіші"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Налаштування гучності звуку під час натискання клавіші"</string>
</resources>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index b0f0c53c9..9ce2d5a78 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -21,61 +21,69 @@
<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">"Bàn phím Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Bàn phím Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Cài đặt bàn phím Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Tùy chọn nhập"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Lệnh ghi nhật ký cho nghiên cứu"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Trình kiểm tra chính tả Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Trình kiểm tra chính tả Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Cài đặt kiểm tra chính tả"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Tra cứu tên liên hệ"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Âm thanh khi nhấn phím"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Cửa sổ bật lên khi nhấn phím"</string>
<string name="general_category" msgid="1859088467017573195">"Chung"</string>
<string name="correction_category" msgid="2236750915056607613">"Sửa văn bản"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Đề xuất dựa trên các từ trước đó"</string>
<string name="misc_category" msgid="6894192814868233453">"Tùy chọn khác"</string>
<string name="advanced_settings" msgid="362895144495591463">"Cài đặt nâng cao"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Tùy chọn cho người dùng chuyên gia"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Tùy chọn dành cho chuyên gia"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Phương thức nhập khác"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Khóa chuyển ngôn ngữ bao gồm cả các phương thức nhập liệu khác"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Bỏ khóa chuyển ngôn ngữ"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Loại bỏ hiển thị phím trễ"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Không có tgian trễ"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Mặc định"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Đề xuất tên liên hệ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Sử dụng tên từ Danh bạ cho các đề xuất và chỉnh sửa"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Bật sửa đổi lại"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Đặt đề xuất cho các sửa đổi lại"</string>
<string name="auto_cap" msgid="1719746674854628252">"Tự động viết hoa"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Cấu hình từ điển"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Sửa nhanh"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Sửa lỗi nhập thông thường"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Thêm từ điển"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Từ điển chính"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Hiển thị gợi ý sửa"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Hiển thị từ được đề xuất khi nhập"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Luôn hiển thị"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Hiển thị trên chế độ khổ đứng"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Luôn ẩn"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"SD trình CĐNN p.cách"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Hiển thị phím cài đặt"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Tự động"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Luôn hiển thị"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Luôn ẩn"</string>
<string name="auto_correction" msgid="4979925752001319458">"Tự động sửa"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Phím cách và dấu câu tự động sửa từ nhập sai"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Tắt"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Đơn giản"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Linh hoạt"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Rất linh hoạt"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Đề xuất Bigram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Sử dụng từ trước đó để cải tiến đề xuất"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Dự đoán Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Đề xuất từ tiếp theo"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Sử dụng từ trước đó để cải tiến đề xuất"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Dự đoán từ tiếp theo"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Cũng sử dụng từ trước đó để dự đoán"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Khác"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"Đã bật Shift"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Đã bật viết hoa"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift đang bật (bấm để tắt)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock đang bật (bấm để tắt)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Xóa"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Biểu tượng"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Chữ cái"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Nhập dữ liệu bằng giọng nói"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Mặt cười"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Quay lại"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Dấu phẩy"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Dấu chấm"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Dấu ngoặc trái"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Dấu ngoặc phải"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Dấu hai chấm"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Dấu chấm phẩy"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Dấu hỏi chấm"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Dấu chấm hỏi"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dấu ngoặc kép"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Dấu nháy đơn"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Tìm kiếm"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Dấu chấm"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Dấu khai căn"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Số Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Thương hiệu"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Dấu phần trăm"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Dấu sao"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Dấu thăng"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Dấu ba chấm"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Dấu nháy kép dưới"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Nhập liệu bằng giọng nói"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Nhập liệu bằng giọng nói hiện không được hỗ trợ cho ngôn ngữ của bạn nhưng hoạt động với ngôn ngữ tiếng Anh."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Nhập liệu bằng giọng nói sử dụng nhận dạng giọng nói của Google. Áp dụng "<a href="http://m.google.com/privacy">"Chính sách bảo mật dành cho điện thoại di động"</a>"."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Để tắt nhập liệu bằng giọng nói, đi tới cài đặt phương pháp nhập liệu."</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Để sử dụng nhập liệu bằng giọng nói, hãy nhấn nút micrô."</string>
- <string name="voice_listening" msgid="467518160751321844">"Nói ngay"</string>
- <string name="voice_working" msgid="6666937792815731889">"Đang hoạt động"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Lỗi. Vui lòng thử lại."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Không thể kết nối"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Lỗi, quá nhiều câu thoại."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Sự cố âm thanh"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Lỗi máy chủ"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Không nghe thấy tiếng nói nào"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Không tìm thấy kết quả phù hợp"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Tìm kiếm bằng giọng nói chưa được cài đặt"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Gợi ý:"</b>" Trượt qua bàn phím để nói"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Gợi ý:"</b>" Lần tới, thử nói dấu câu như \"dấu chấm\", \"dấu phẩy\" hoặc \"dấu hỏi\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Hủy"</string>
- <string name="ok" msgid="7898366843681727667">"OK"</string>
- <string name="voice_input" msgid="2466640768843347841">"Nhập liệu bằng giọng nói"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Đã bật Shift"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Đã bật Caps lock"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Đã tắt Shift"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Chế độ biểu tượng"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Chế độ chữ cái"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Chế độ điện thoại"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Chế độ biểu tượng điện thoại"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Khóa nhập giọng nói"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Trên bàn phím chính"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Trên bàn phím biểu tượng"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Tắt"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrô trên bàn phím chính"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrô trên bàn phím biểu tượng"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Nhập liệu bằng giọng nói đã bị tắt"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Chọn phương thức nhập"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Định cấu hình phương thức nhập"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Ngôn ngữ nhập"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Trượt ngón tay trên phím cách để thay đổi ngôn ngữ"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Chạm lại để lưu"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Dấu thời gian ghi chú trong nhật ký"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Dấu thời gian đã ghi"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Không ghi nhật ký phiên này"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Đang xóa nhật ký phiên"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Đã xóa nhật ký phiên"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Nhật ký phiên KHÔNG bị xóa"</string>
+ <string name="select_language" msgid="3693815588777926848">"Ngôn ngữ nhập"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Chạm lại để lưu"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Có sẵn từ điển"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Bật phản hồi của người dùng"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Giúp nâng cao trình chỉnh sửa phương thức nhập này bằng cách tự động gửi thống kê sử dụng và báo cáo sự cố cho Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Chạm để sửa từ"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Chạm các từ đã nhập để sửa, chỉ khi các đề xuất hiển thị"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Chủ đề bàn phím"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Bàn phím tiếng Séc"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Bàn phím tiếng Ả Rập"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Bàn phím tiếng Đan Mạch"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Bàn phím tiếng Đức"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Bàn phím QWERTY Tiếng Đức"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Bàn phím tiếng Anh (Anh)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Bàn phím tiếng Anh (Mỹ)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Bàn phím tiếng Tây Ban Nha"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Bàn phím tiếng Phần Lan"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Bàn phím tiếng Pháp"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Bàn phím tiếng Pháp (Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Bàn phím tiếng Pháp (Thụy Sĩ)"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Bàn phím tiếng Croatia"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Bàn phím tiếng Hungari"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Bàn phím tiếng Do Thái"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Bàn phím tiếng Ý"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Bàn phím tiếng Na Uy"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Bàn phím tiếng Hà Lan"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Bàn phím tiếng Ba Lan"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Bàn phím tiếng Bồ Đào Nha"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Bàn phím tiếng Nga"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Bàn phím tiếng Serbia"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Bàn phím tiếng Thụy Điển"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Bàn phím tiếng Thổ Nhĩ Kỳ"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Giọng tiếng Hà Lan ở Nam Phi"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Giọng nói tiếng Séc"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Giọng nói tiếng Đức"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"Giọng tiếng Anh"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Giọng nói tiếng Tây Ban Nha"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Giọng nói tiếng Pháp"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Giọng nói tiếng Ý"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Giọng nói tiếng Nhật"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Giọng nói tiếng Hàn"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Giọng nói tiếng Hà Lan"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Giọng nói tiếng Ba Lan"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Giọng nói tiếng Bồ Đào Nha"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Giọng nói tiếng Nga"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Giọng nói tiếng Thổ Nhĩ Kỳ"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"Giọng tiếng Trung, Yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"Giọng tiếng Trung, tiếng Quan thoại"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Giọng isiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Tiếng Anh (Anh)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Tiếng Anh (Mỹ)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Tiếng Anh (Anh) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Tiếng Anh (Mỹ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Không có ngôn ngữ nào"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Không có ngôn ngữ (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"0 ngôn ngữ (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"0 ngôn ngữ (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"0 ngôn ngữ (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"0 ngôn ngữ (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"0 ngôn ngữ (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Kiểu nhập tùy chỉnh"</string>
+ <string name="add_style" msgid="6163126614514489951">"Thêm kiểu"</string>
+ <string name="add" msgid="8299699805688017798">"Thêm"</string>
+ <string name="remove" msgid="4486081658752944606">"Xóa"</string>
+ <string name="save" msgid="7646738597196767214">"Lưu"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Ngôn ngữ"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Bố cục"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Bạn cần phải bật kiểu nhập tùy chỉnh trước khi bắt đầu sử dụng nó. Bạn có muốn bật kiểu nhập tùy chỉnh ngay bây giờ không?"</string>
+ <string name="enable" msgid="5031294444630523247">"Bật"</string>
+ <string name="not_now" msgid="6172462888202790482">"Để sau"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Đã tồn tại kiểu nhập tương tự: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Chế độ nghiên cứu tính khả dụng"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Cài đặt thời gian rung khi nhấn phím"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Cài đặt âm lượng khi nhấn phím"</string>
</resources>
diff --git a/java/res/values-xlarge-land/dimens.xml b/java/res/values-xlarge-land/dimens.xml
deleted file mode 100644
index 2201ce8a3..000000000
--- a/java/res/values-xlarge-land/dimens.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=14.5mm -->
- <dimen name="keyboardHeight">58.0mm</dimen>
- <fraction name="minKeyboardHeight">45%p</fraction>
- <!-- key_height + key_bottom_gap = popup_key_height -->
- <!-- <dimen name="key_height">14.5mm</dimen> -->
- <dimen name="key_bottom_gap">1.6mm</dimen>
- <dimen name="key_horizontal_gap">1.6mm</dimen>
- <dimen name="keyboard_top_padding">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding">0.0mm</dimen>
- <dimen name="key_bottom_gap_ics">1.6mm</dimen>
- <dimen name="key_horizontal_gap_ics">1.6mm</dimen>
- <dimen name="keyboard_top_padding_ics">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding_ics">0.0mm</dimen>
- <dimen name="popup_key_height">13.0mm</dimen>
- <dimen name="keyboard_horizontal_edges_padding">0.0mm</dimen>
-
- <!-- left or right padding of label alignment -->
- <dimen name="key_label_horizontal_alignment_padding">18dip</dimen>
-
- <fraction name="key_letter_ratio">38%</fraction>
- <fraction name="key_large_letter_ratio">38%</fraction>
- <fraction name="key_label_ratio">26%</fraction>
- <fraction name="key_hint_letter_ratio">23%</fraction>
- <fraction name="key_hint_label_ratio">26%</fraction>
- <fraction name="key_uppercase_letter_ratio">24%</fraction>
- <dimen name="key_preview_height">17.0mm</dimen>
-
- <dimen name="key_preview_height_ics">26.5mm</dimen>
- <dimen name="key_preview_offset_ics">0.05in</dimen>
-
- <dimen name="candidate_strip_padding">40.0mm</dimen>
-</resources>
diff --git a/java/res/values-xlarge/dimens.xml b/java/res/values-xlarge/dimens.xml
deleted file mode 100644
index 2e41db52a..000000000
--- a/java/res/values-xlarge/dimens.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=12mm -->
- <dimen name="keyboardHeight">48.0mm</dimen>
- <fraction name="maxKeyboardHeight">50%p</fraction>
- <fraction name="minKeyboardHeight">-35.0%p</fraction>
- <!-- key_height + key_bottom_gap = popup_key_height -->
- <!-- <dimen name="key_height">14.5mm</dimen> -->
- <dimen name="key_bottom_gap">1.1mm</dimen>
- <dimen name="key_horizontal_gap">1.1mm</dimen>
- <dimen name="keyboard_top_padding">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding">0.0mm</dimen>
- <dimen name="key_bottom_gap_ics">1.1mm</dimen>
- <dimen name="key_horizontal_gap_ics">1.1mm</dimen>
- <dimen name="keyboard_top_padding_ics">1.1mm</dimen>
- <dimen name="keyboard_bottom_padding_ics">0.0mm</dimen>
- <dimen name="popup_key_height">10.0mm</dimen>
- <dimen name="keyboard_horizontal_edges_padding">0.0mm</dimen>
- <dimen name="mini_keyboard_horizontal_padding_ics">40dip</dimen>
- <dimen name="mini_keyboard_key_horizontal_padding">12dip</dimen>
- <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
- <!-- popup_key_height x 1.2 -->
- <dimen name="mini_keyboard_slide_allowance">15.6mm</dimen>
- <!-- popup_key_height x -1.0 -->
- <dimen name="mini_keyboard_vertical_correction">-13.0mm</dimen>
-
- <!-- left or right padding of label alignment -->
- <dimen name="key_label_horizontal_alignment_padding">6dip</dimen>
-
- <fraction name="key_letter_ratio">38%</fraction>
- <fraction name="key_large_letter_ratio">38%</fraction>
- <fraction name="key_label_ratio">26%</fraction>
- <fraction name="key_hint_letter_ratio">23%</fraction>
- <fraction name="key_hint_label_ratio">26%</fraction>
- <fraction name="key_uppercase_letter_ratio">25%</fraction>
- <fraction name="key_preview_text_ratio">50%</fraction>
- <dimen name="key_preview_height">15.0mm</dimen>
- <dimen name="key_preview_offset">0.1in</dimen>
-
- <dimen name="key_preview_height_ics">15.0mm</dimen>
- <dimen name="key_preview_offset_ics">0.05in</dimen>
-
- <dimen name="candidate_strip_height">46dip</dimen>
- <!-- candidate_strip_minimum_height =
- key_preview_height_holo - key_preview_offset_holo + alpha -->
- <dimen name="candidate_strip_minimum_height">18mm</dimen>
- <dimen name="candidate_strip_padding">15.0mm</dimen>
- <dimen name="candidate_min_width">46dip</dimen>
- <dimen name="candidate_padding">8dip</dimen>
- <dimen name="candidate_text_size">22dip</dimen>
-</resources>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 32a0bb7bc..4907f202f 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -21,61 +21,69 @@
<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">"Android 键盘"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 键盘 (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android 键盘设置"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"输入选项"</string>
- <string name="vibrate_on_keypress" msgid="5258079494276955460">"按键时振动"</string>
- <string name="sound_on_keypress" msgid="6093592297198243644">"按键时播放音效"</string>
- <string name="popup_on_keypress" msgid="123894815723512944">"按键时显示弹出窗口"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"研究记录命令"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android 拼写检查工具"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 拼写检查工具 (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"拼写检查设置"</string>
+ <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="ngram_category" msgid="5337109164339320257">"根据前面的字词提供建议"</string>
<string name="misc_category" msgid="6894192814868233453">"其他选项"</string>
<string name="advanced_settings" msgid="362895144495591463">"高级设置"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"适合于资深用户的选项"</string>
- <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"关闭弹出键时的延迟"</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="suppress_language_switch_key" msgid="8003788410354806368">"隐藏语言切换键"</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="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="enable_span_insert" msgid="7204653105667167620">"允许再次更正"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"设置建议以用于再次更正"</string>
<string name="auto_cap" msgid="1719746674854628252">"自动大写"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"配置字典"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"快速纠正"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"纠正常见的输入错误"</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="3551821800439659812">"以纵向模式显示"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"在纵向模式时显示"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"始终隐藏"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"使用空格键切换语言"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"显示设置键"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"自动"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"始终显示"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"始终隐藏"</string>
<string name="auto_correction" msgid="4979925752001319458">"自动更正"</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_aggeressive" msgid="3524029103734923819">"大改"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"改动极大"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"双连词建议"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"使用以前的字词改进建议"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"双连词预测"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"下一字词建议"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"使用上一字词改进建议"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"下一字词预测"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"结合前一个字词进行预测"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"更多"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"暂停"</string>
<string name="label_wait_key" msgid="6402152600878093134">"等待"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"需要插入耳机才能听到密码的按键声。"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"当前文本为%s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"未输入文字"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"键码为 %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift 已启用"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock 已启用"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"逗号"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"句号"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"左括号"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"右括号"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"冒号"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"分号"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"感叹号"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"问号"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"双引号"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"单引号"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"搜索"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"点"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"平方根"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"圆周率"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"商标符号"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"百分号"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"星号"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"井号"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"省略号"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"低双引号"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"语音输入"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"语音输入功能当前还不支持您的语言,您只能输入英语语音。"</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"语音输入采用了 Google 的语音识别技术,因此请遵守"<a href="http://m.google.com/privacy">"“Google 移动”隐私权政策"</a>"。"</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"要关闭语音输入功能,请转至输入法设置。"</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"要使用语音输入功能,请按“麦克风”按钮。"</string>
- <string name="voice_listening" msgid="467518160751321844">"请开始说话"</string>
- <string name="voice_working" msgid="6666937792815731889">"正在处理"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"出错,请重试。"</string>
- <string name="voice_network_error" msgid="6649556447401862563">"无法连接"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"出错,语音过长。"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"音频问题"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"服务器出错"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"未听到语音"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"未找到匹配项"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"未安装语音搜索"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"提示:"</b>"在键盘上滑动手指可激活语音功能"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"提示:"</b>"稍后,请尝试使用语音输入标点符号,如“句号”、“逗号”或“问号”。"</string>
- <string name="cancel" msgid="6830980399865683324">"取消"</string>
- <string name="ok" msgid="7898366843681727667">"确定"</string>
- <string name="voice_input" msgid="2466640768843347841">"语音输入"</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="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="selectInputMethod" msgid="315076553378705821">"选择输入法"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"配置输入法"</string>
<string name="language_selection_title" msgid="1651299598555326750">"输入语言"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"在空格键上滑动手指可更改语言"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← 再次触摸即可保存"</string>
- <string name="has_dictionary" msgid="6071847973466625007">"提供字典"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"标记记录中的时间"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"已标记时间"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"不记录本次会话"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"正在删除会话记录"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"会话记录已删除"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"未能删除会话记录"</string>
+ <string name="select_language" msgid="3693815588777926848">"输入语言"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次触摸即可保存"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"有可用词典"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"启用用户反馈"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"自动向 Google 发送使用情况统计信息和崩溃报告,帮助改进该输入法编辑器。"</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"触摸以更正字词"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"仅在系统显示建议后,才触摸输入的字词进行更正"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"键盘主题"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"捷克语键盘"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"阿拉伯语键盘"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"丹麦语键盘"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"德语键盘"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"德语 QWERTY 键盘"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"英语(英国)键盘"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"英语(美国)键盘"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"西班牙语键盘"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"芬兰语键盘"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"法语键盘"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"法语(加拿大)键盘"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"法语(瑞士)键盘"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"克罗地亚语键盘"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"匈牙利语键盘"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"希伯来语键盘"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"意大利语键盘"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"挪威语键盘"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"荷兰语键盘"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"波兰语键盘"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"葡萄牙语键盘"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"俄语键盘"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"塞尔维亚语键盘"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"瑞典语键盘"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"土耳其语键盘"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"南非荷兰语语音"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"捷克语语音"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"德语语音"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"英语语音"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"西班牙语语音"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"法语语音"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"意大利语语音"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"日语语音"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"韩语语音"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"荷兰语语音"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"波兰语语音"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"葡萄牙语语音"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"俄语语音"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"土耳其语语音"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"中文,粤语语音"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"中文,普通话语音"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"祖鲁语语音"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"英语(英国)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"英语(美国)"</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_no_language" msgid="141420857808801746">"无语言"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"无语言(QWERTY 键盘)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"无语言(QWERTZ 键盘)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"无语言(AZERTY 键盘)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"无语言(Dvorak 键盘)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"无语言(Colemak 键盘)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"无语言(PC 键盘)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"按键振动持续时间设置"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"按键音量设置"</string>
</resources>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 5bad7dd86..9179e669b 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -21,61 +21,69 @@
<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">"Android 鍵盤"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 鍵盤 (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android 鍵盤設定"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"研究紀錄指令"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Android 拼字檢查"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 拼字檢查 (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"拼字檢查設定"</string>
+ <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="ngram_category" msgid="5337109164339320257">"根據先前字詞產生的建議"</string>
<string name="misc_category" msgid="6894192814868233453">"其他選項"</string>
<string name="advanced_settings" msgid="362895144495591463">"進階設定"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"提供給專業使用者的選項"</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="suppress_language_switch_key" msgid="8003788410354806368">"隱藏語言切換鍵"</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="use_contacts_dict" msgid="4435317977804180815">"建議聯絡人名稱"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"根據「聯絡人」名稱提供建議與修正"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"啟用重新更正"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"設定建議供重新更正"</string>
<string name="auto_cap" msgid="1719746674854628252">"自動大寫"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"設定字典"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"快速修正"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"修正一般打字錯誤"</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="3551821800439659812">"以垂直模式顯示"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"永遠隱藏"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"使用空白鍵切換語言"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"顯示設定鍵"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"自動"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"一律顯示"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"永遠隱藏"</string>
<string name="auto_correction" msgid="4979925752001319458">"自動修正"</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_aggeressive" msgid="3524029103734923819">"全部"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"更正範圍小"</string>
+ <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"更正範圍大"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"更正範圍極大"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"雙連詞建議"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"根據前一個字詞自動找出更適合的建議"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"雙連詞預測"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"同樣使用先前的字詞進行預測"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"下一個字詞建議"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"根據前一個字詞找出更適合的建議"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"下一個字詞預測"</string>
+ <string name="bigram_prediction_summary" msgid="1747261921174300098">"同樣使用前一個字詞進行預測"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"更多"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</string>
<string name="label_pause_key" msgid="181098308428035340">"暫停"</string>
<string name="label_wait_key" msgid="6402152600878093134">"等候"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"連接耳機即可聽取系統朗讀密碼按鍵。"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"目前文字為 %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"未輸入文字"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"按鍵代碼 %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift 鍵"</string>
- <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift 鍵已啟用"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"大寫鎖定已啟用"</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>
@@ -86,103 +94,59 @@
<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_comma" msgid="4970844442999724586">"逗號"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"句號"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"左括弧"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"右括弧"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"冒號"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"分號"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"驚嘆號"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"問號"</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"雙引號"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"單引號"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"搜尋"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"點"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"平方根"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"圓周率"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"商標"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"百分比"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"星號"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"井字鍵"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"省略符號"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"下雙引號"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"語音輸入"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"語音輸入目前不支援您的語言,但是可以辨識英文。"</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"語音輸入使用 Google 的語音辨識功能,並遵循《"<a href="http://m.google.com/privacy">"行動服務隱私權政策"</a>"》。"</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"如要關閉語音輸入,請前往輸入法設定。"</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"如要使用語音輸入,請按下麥克風按鈕。"</string>
- <string name="voice_listening" msgid="467518160751321844">"請說話"</string>
- <string name="voice_working" msgid="6666937792815731889">"辨識中"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"發生錯誤,請再試一次。"</string>
- <string name="voice_network_error" msgid="6649556447401862563">"無法連線"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"錯誤:語音內容過長。"</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"音訊問題"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"伺服器錯誤"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"沒有聽到任何聲音"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"找不到相符的項目"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"未安裝語音搜尋"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"提示:"</b>"滑過鍵盤即可說話"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"提示:"</b>"下次可嘗試說出標點符號,例如「句號」、「逗號」或「問號」。"</string>
- <string name="cancel" msgid="6830980399865683324">"取消"</string>
- <string name="ok" msgid="7898366843681727667">"確定"</string>
- <string name="voice_input" msgid="2466640768843347841">"語音輸入"</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="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="selectInputMethod" msgid="315076553378705821">"選擇輸入法"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string>
<string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"以手指在空白鍵上滑動可變更語言"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← 再次輕觸即可儲存"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"在紀錄中加註時間戳記"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"已記錄時間戳記"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"不要記錄這個工作階段"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"正在刪除工作階段紀錄"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"已刪除工作階段紀錄"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"「未」刪除工作階段紀錄"</string>
+ <string name="select_language" msgid="3693815588777926848">"輸入語言"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
<string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"啟用使用者意見回饋"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"自動將使用統計資料和當機報告傳送給 Google,協助改善這個輸入法編輯器。"</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"輕觸此處可修正字詞"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"輕觸輸入的字詞即可加以修正 (出現建議時才適用)"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"捷克文鍵盤"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"阿拉伯文鍵盤"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"丹麥文鍵盤"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"德文鍵盤"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"德文 QWERTY 鍵盤"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"英文 (英國) 鍵盤"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"英文 (美國) 鍵盤"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"西班牙文鍵盤"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"芬蘭文鍵盤"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"法文鍵盤"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"法文 (加拿大) 鍵盤"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"法文 (瑞士) 鍵盤"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"克羅埃西亞文鍵盤"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"匈牙利文鍵盤"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"希伯來文鍵盤"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"義大利文鍵盤"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"挪威文鍵盤"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"荷蘭文鍵盤"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"波蘭文鍵盤"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"葡萄牙文鍵盤"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"俄文鍵盤"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"塞爾維亞文鍵盤"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"瑞典文語音"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"土耳其文鍵盤"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"南非荷蘭文語音"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"捷克文語音"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"德文語音"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"英文語音"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"西班牙文語音"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"法文語音"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"義大利文語音"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"日文語音"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"韓文語音"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"荷蘭文語音"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"波蘭文語音"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"葡萄牙文語音"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"俄文語音"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"土耳其文語音"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"中文 (粵語) 語音"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"中文 (華語) 語音"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"祖魯文語音"</string>
- <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使用性研究模式"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英式)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美式)"</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_no_language" msgid="141420857808801746">"無語言"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"無語言 (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"無語言 (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"無語言 (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"無語言 (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"無語言 (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"無語言 (PC)"</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_keypress_vibration_duration_settings" msgid="1829950405285211668">"按鍵震動持續時間設定"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"按鍵音量設定"</string>
</resources>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 3d7d15f07..3f7c96b66 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -21,61 +21,69 @@
<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">"Ikhibhodi ye-Android"</string>
+ <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Ikhibhodi ye-Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Izilungiselelo zekhibhodi ye-Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Imiyalo yefayela lokungena lokucwaninga"</string>
+ <string name="spell_checker_service_name" msgid="7338064335159755926">"Isihloli sokupela se-Android"</string>
+ <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Isihloli sokupela se-Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="5822324635435443689">"Izilungiselelo zokuhlola ukupela"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Bheka amagama woxhumana nabo"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Isihloli sokupela sisebenzisa okungenayo kusuka kuhlu lalabo oxhumana nabo"</string>
<string name="vibrate_on_keypress" msgid="5258079494276955460">"Dlidlizelisa ngokucindezela inkinobho"</string>
<string name="sound_on_keypress" msgid="6093592297198243644">"Umsindo wokucindezela ukhiye"</string>
<string name="popup_on_keypress" msgid="123894815723512944">"Ugaxekile ngokucindezela ukhiye"</string>
<string name="general_category" msgid="1859088467017573195">"Okuvamile"</string>
<string name="correction_category" msgid="2236750915056607613">"Ukulungiswa kombhalo"</string>
- <string name="ngram_category" msgid="5337109164339320257">"Ukusikiselwa okusekelwe emagameni angaphambilini"</string>
<string name="misc_category" msgid="6894192814868233453">"Okunye okukhethwa kukho"</string>
<string name="advanced_settings" msgid="362895144495591463">"Izilungiselelo ezithuthukisiwe"</string>
- <string name="advanced_settings_summary" msgid="5193513161106637254">"Okukhethwa kukho kompetha babasebenzi"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Izinketho zezingcwenti"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Shintshela kwezinye izindlela zokungena"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ukhiye wokushintsha ulimi ubandakanya ezinye izindlela zokungenayo"</string>
+ <string name="suppress_language_switch_key" msgid="8003788410354806368">"Ukhiye wokushintshela wokuvimbela ulimi"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ukuvela kokhiye cashisa ukulibazisa"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Cha ukulibazisa"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Okuzenzakalelayo"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sikisela amagama Othintana nabo"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Amagama abasebenzisi kusuka Kothintana nabo bokusikisela nokulungisa"</string>
+ <string name="enable_span_insert" msgid="7204653105667167620">"Vumela ukulungiswa kabusha"</string>
+ <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setha iziphakamiso zokulungisa kabusha"</string>
<string name="auto_cap" msgid="1719746674854628252">"Ukwenza ofeleba okuzenzakalelayo"</string>
- <string name="configure_dictionaries_title" msgid="3758288002414557345">"Lungiselela izichaza mazwi"</string>
- <string name="quick_fixes" msgid="5353213327680897927">"Ukulungisa okusheshayo"</string>
- <string name="quick_fixes_summary" msgid="3405028402510332373">"Ilungisa amaphutha athayiphwa ngokuvamile"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Faka izichazamazwi"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Isichazamazwi sakho ngqangi"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"Bonisa ukusikesela kokulungisa"</string>
<string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Bonisa amagama aphakamisiwe ngenkathi uthayipha"</string>
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Bonisa njalo"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Bonisa kwimodi emile"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Fihla njalo"</string>
- <string name="prefs_use_spacebar_language_switch" msgid="8828538114550634449">"Sebenzisa isiguquli solimi somudwa wokwenza isikhala"</string>
- <string name="prefs_settings_key" msgid="4623341240804046498">"Bonisa ukhiye wezilungiselelo"</string>
- <string name="settings_key_mode_auto_name" msgid="2993460277873684680">"Okuzenzakalelayo"</string>
- <string name="settings_key_mode_always_show_name" msgid="3047567041784760575">"Bonisa njalo"</string>
- <string name="settings_key_mode_always_hide_name" msgid="7833948046716923994">"Fihla njalo"</string>
<string name="auto_correction" msgid="4979925752001319458">"Ukulungisa okuzenzakalelayo"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Ibha yesikhala nokubhala ngamagama amakhulu kulungisa amaphutha amagama athayiphwe kabi"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Valiwe"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Thobekile"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Bukhali"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Nobudlova kakhulu"</string>
- <string name="bigram_suggestion" msgid="2636414079905220518">"Iziphakamiso ze-Biagram"</string>
- <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Sebenzisa igama elandulele ukuthuthukisa okusikiselwayo"</string>
- <string name="bigram_prediction" msgid="8914273444762259739">"Ukuqagela kwe-Bigram"</string>
+ <string name="bigram_suggestion" msgid="8169311444438922902">"Iziphakamiso zegama elilandelayo"</string>
+ <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Sebenzisa igama elandulele ukuthuthukisa iziphakamiso"</string>
+ <string name="bigram_prediction" msgid="3216364899483135294">"Ukuqagela kwegama elilandelayo"</string>
<string name="bigram_prediction_summary" msgid="1747261921174300098">"Sebenzisa igama langaphambilini ukuze uqagele"</string>
<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_to_alpha_key" msgid="4793983863798817523">"ABC"</string>
- <string name="label_more_key" msgid="3760239494604948502">"Okungaphezulu"</string>
+ <string name="label_to_symbol_key" msgid="8516904117128967293">"?123"</string>
+ <string name="label_to_symbol_with_microphone_key" msgid="9035925553010061906">"123"</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>
<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="954941524766465022">"I-Shift inikwe amandla"</string>
- <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Ukunika amandla ukhiye wombhalo ngamagama amakhulu"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"U-Shift uvuliwe (thepha ukuwuvimbela)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Ofeleba bavuliwe (thepha ukubavimbela)"</string>
<string name="spoken_description_delete" msgid="8740376944276199801">"Susa"</string>
<string name="spoken_description_to_symbol" msgid="5486340107500448969">"Amasimbuli"</string>
<string name="spoken_description_to_alpha" msgid="23129338819771807">"Imbhalo"</string>
@@ -86,103 +94,59 @@
<string name="spoken_description_mic" msgid="615536748882611950">"Okungenayo kwezwi"</string>
<string name="spoken_description_smiley" msgid="2256309826200113918">"Ubuso-obumomothekayo"</string>
<string name="spoken_description_return" msgid="8178083177238315647">"Buyisela"</string>
- <string name="spoken_description_comma" msgid="4970844442999724586">"Ikhefu"</string>
- <string name="spoken_description_period" msgid="5286614628077903945">"Isikhathi"</string>
- <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"ama-parenthesis esobunxele"</string>
- <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"I-parenthesis yesokudla"</string>
- <string name="spoken_description_colon" msgid="4312420908484277077">"Ikholoni"</string>
- <string name="spoken_description_semicolon" msgid="37737920987155179">"Ikhefanangqi"</string>
- <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uphawu lokumemeza"</string>
- <string name="spoken_description_question_mark" msgid="7074097784255379666">"Imaki yombuzo."</string>
- <string name="spoken_description_double_quote" msgid="5485320575389905967">"Ukusho kabili"</string>
- <string name="spoken_description_single_quote" msgid="4451320362665463938">"Isibizo esisodwa"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Sesha"</string>
<string name="spoken_description_dot" msgid="40711082435231673">"Icashazi"</string>
- <string name="spoken_description_square_root" msgid="190595160284757811">"Impande yesikwele"</string>
- <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string>
- <string name="spoken_description_delta" msgid="3607948313655721579">"i-Delta"</string>
- <string name="spoken_description_trademark" msgid="475877774077871369">"Uphawu lomkhiqizo"</string>
- <string name="spoken_description_care_of" msgid="7492800237237796530">"Ukunakekela ko"</string>
- <string name="spoken_description_star" msgid="1009742725387231977">"Inkanyezi"</string>
- <string name="spoken_description_pound" msgid="5530577649206922631">"Iphawundi"</string>
- <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string>
- <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Isilinganiso esikabili esiphansi"</string>
- <string name="voice_warning_title" msgid="4419354150908395008">"Okufakwa ngezwi"</string>
- <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Okufakwa ngezwi akusekelwa olimini lwakho, kodwa kuyasebenza nge-English."</string>
- <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Okufakwayo ngezwi kusebenzisa ukufanisa izwi kwe-Google. "<a href="http://m.google.com/privacy">"Inqubomgomo Yobumfihlo Yefoni"</a>" iyasebenza."</string>
- <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ukuvala okufakwayo ngezwi, iya kuzilungiselelo zendlela yokufakwayo"</string>
- <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ukusebenzisa okufakwayo ngezwi, cindezela inkinobho yemakrofoni."</string>
- <string name="voice_listening" msgid="467518160751321844">"Khuluma manje"</string>
- <string name="voice_working" msgid="6666937792815731889">"Kuyasebenza"</string>
- <string name="voice_initializing" msgid="661962047129906646"></string>
- <string name="voice_error" msgid="5140896300312186162">"Iphutha. Sicela uzame futhi."</string>
- <string name="voice_network_error" msgid="6649556447401862563">"Ayikwazanga ukuxhuma"</string>
- <string name="voice_too_much_speech" msgid="5746973620134227376">"Iphutha, kunamagama amaningi."</string>
- <string name="voice_audio_error" msgid="5072707727016414454">"Inkinga yomsindo"</string>
- <string name="voice_server_error" msgid="7807129913977261644">"Iphutha leseva"</string>
- <string name="voice_speech_timeout" msgid="8461817525075498795">"Awekho amagama azwakele"</string>
- <string name="voice_no_match" msgid="4285117547030179174">"Akukho okufanayo okutholiwe"</string>
- <string name="voice_not_installed" msgid="5552450909753842415">"Ukusesha ngezwi akufakiwe"</string>
- <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Isexwayiso:"</b>"Shintshela kwikhibhodi ukuze ukhulume"</string>
- <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Isixwayiso: "</b>"Esikhathini esilandelayo, zama ukukhuluma izimpimiselo ezinjengo \"isikhathi, \"ikhefu\" noma \"uphawu lombuzo\"."</string>
- <string name="cancel" msgid="6830980399865683324">"Khansela"</string>
- <string name="ok" msgid="7898366843681727667">"KULUNGILE"</string>
- <string name="voice_input" msgid="2466640768843347841">"Okufakwa ngezwi"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"U-Shift uvunyelwe"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Ofeleba bavunyelwe"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"U-Shift uvimbelwe"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Imodi yezimpawu"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Imodi yezinhlamvu"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Imodi yefoni"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Imodi yezimpawu zefoni"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Inkinobho yokufaka izwi"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Kwikhibhodi eyisisekelo"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Ikhibhodi yezimpawu"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"VALIWE"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"I-mic kwikhibhodi eyisisekelo"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Ikhibhodi yezimpawu ze-mic"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Okufakwayo ngezwi kuvinjelwe"</string>
- <string name="selectInputMethod" msgid="315076553378705821">"Khetha indlela yokufaka"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string>
- <string name="language_selection_summary" msgid="187110938289512256">"Slayida umunwe kwibha yesikhala ukushintsha ulimi"</string>
- <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Thinta futhi ukulondoloza"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Qaphela isitembu sesikhathi efayeleni lokungena"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Isitembu sesikhathi esirekhodiwe"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ungenzi ifayela lokungena lalesi sikhathi"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Isusa ifayela lokungena lesikhathi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Ifayela lokungena lesikhathi lisusiwe"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Ifayela lokungena lesikhathi alisusiwe"</string>
+ <string name="select_language" msgid="3693815588777926848">"Izilimi zokufakwayo"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Thinta futhi ukuze ulondoloze"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string>
<string name="prefs_enable_log" msgid="6620424505072963557">"Vumela impendulo yomsebenzisi"</string>
<string name="prefs_description_log" msgid="5827825607258246003">"Siza ukuthuthukisa lo mhleli wendlela yokufakwa ngokusithumela ngokuzenzakalela izibalo zokusetshenziswa nokukhubeka ku-Google."</string>
- <string name="prefs_enable_recorrection" msgid="4588408906649533582">"Thinta ukulungisa amagama"</string>
- <string name="prefs_enable_recorrection_summary" msgid="5082041365862396329">"Thinta amagama afakiwe ukuwalungisa, kuphela lapho okusikiselwayo kubonakala"</string>
<string name="keyboard_layout" msgid="8451164783510487501">"Indikimba yekhibhodi"</string>
- <string name="subtype_mode_cs_keyboard" msgid="1141718931112377586">"Ikhibhodi yesi-Czech"</string>
- <string name="subtype_mode_ar_keyboard" msgid="2655338636329774995">"Ikhibhodi yesi-Arabhu"</string>
- <string name="subtype_mode_da_keyboard" msgid="1243570804427922104">"Ikhibhodi yesi-Danish"</string>
- <string name="subtype_mode_de_keyboard" msgid="1990979135959462145">"Ikhobhodi yei-German"</string>
- <string name="subtype_mode_de_qwerty_keyboard" msgid="54890770769303956">"Ikhibhodi ye-QWERTY yesiJalimane"</string>
- <string name="subtype_mode_en_GB_keyboard" msgid="7945856548410373708">"Ikhibhodi ye-English (UK)"</string>
- <string name="subtype_mode_en_US_keyboard" msgid="3708655163769735410">"Ikhobhodi ye-English (US)"</string>
- <string name="subtype_mode_es_keyboard" msgid="1775125478866113148">"Ikhobhodi yesi-Spanish"</string>
- <string name="subtype_mode_fi_keyboard" msgid="3198596464082614532">"Ikhibhodi Yesifinishi"</string>
- <string name="subtype_mode_fr_keyboard" msgid="8016515336759761014">"Ikhibhodi yesi-French"</string>
- <string name="subtype_mode_fr_CA_keyboard" msgid="2628517247158376263">"Ikhobhodi yesi-French (i-Canada)"</string>
- <string name="subtype_mode_fr_CH_keyboard" msgid="6742806653181621228">"Ikhibhodi yesi-French (i-Switzerland"</string>
- <string name="subtype_mode_hr_keyboard" msgid="7177182405440070112">"Ikhibhodi Yesikhruweyisha"</string>
- <string name="subtype_mode_hu_keyboard" msgid="8843338355732633647">"Ikhibhodi Yesihangari"</string>
- <string name="subtype_mode_iw_keyboard" msgid="1787536828253289950">"Ikhibhodi Yesihebheru"</string>
- <string name="subtype_mode_it_keyboard" msgid="4934199655425394484">"Ikhibhodi yesi-Italian"</string>
- <string name="subtype_mode_nb_keyboard" msgid="1175783216100212360">"Ikhibhodi yesi-Norwegian"</string>
- <string name="subtype_mode_nl_keyboard" msgid="5090278083256037936">"Ikhibhodi yesi-Dutch"</string>
- <string name="subtype_mode_pl_keyboard" msgid="2225816414814396047">"Ikhibhodi Yesipholishi"</string>
- <string name="subtype_mode_pt_keyboard" msgid="7503997804861754840">"Ikhibhodi Yesiputukezi"</string>
- <string name="subtype_mode_ru_keyboard" msgid="1383995915064277943">"Ikhobhodi yesi-Russian"</string>
- <string name="subtype_mode_sr_keyboard" msgid="5019440799612208168">"Ikhibhodi yesi-Serbian"</string>
- <string name="subtype_mode_sv_keyboard" msgid="4933838139861753401">"Ikhobhodi yesi-Swedish"</string>
- <string name="subtype_mode_tr_keyboard" msgid="3155981874829226370">"Ikhibhodi yaseThekhi"</string>
- <string name="subtype_mode_af_voice" msgid="7542487489657902699">"Izwi Lesibhunu"</string>
- <string name="subtype_mode_cs_voice" msgid="1136386688120958641">"Izwi le-Czech"</string>
- <string name="subtype_mode_de_voice" msgid="8378803143958089866">"Izwi lesi-German"</string>
- <string name="subtype_mode_en_voice" msgid="6643420989651848728">"i-English Izwi"</string>
- <string name="subtype_mode_es_voice" msgid="1323473601346507487">"Izwi lesi-Spanish"</string>
- <string name="subtype_mode_fr_voice" msgid="4675914209337824269">"Izwi lesi-French"</string>
- <string name="subtype_mode_it_voice" msgid="5077373057157441323">"Izwi Lesi-Italian"</string>
- <string name="subtype_mode_ja_voice" msgid="6604859132669646367">"Izwi lesi-Japanese"</string>
- <string name="subtype_mode_ko_voice" msgid="4890391190762324561">"Izwi lesi-Korean"</string>
- <string name="subtype_mode_nl_voice" msgid="2603552312869575021">"Dutch Voice"</string>
- <string name="subtype_mode_pl_voice" msgid="2076196021014840487">"Izwi lesi-Polish"</string>
- <string name="subtype_mode_pt_voice" msgid="8036522712795994397">"Izwi lesi-Portuguese"</string>
- <string name="subtype_mode_ru_voice" msgid="8034596947963787529">"Izwi lesi-Russian"</string>
- <string name="subtype_mode_tr_voice" msgid="3402067436761140005">"Izwi lesi-Turkish"</string>
- <string name="subtype_mode_yue_voice" msgid="1576887891614624263">"isi-Chinese, Izwi le-Yue"</string>
- <string name="subtype_mode_zh_voice" msgid="4360533229467271152">"isi-Chinese, isi-Mandarin Izwi"</string>
- <string name="subtype_mode_zu_voice" msgid="1146122571698884636">"Izwi LesiZulu"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"i-English(UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"i-English (US)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"I-English (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"I-English (US) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_no_language" msgid="141420857808801746">"Akunalimi"</string>
+ <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Akunalimi (QWERTY)"</string>
+ <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Alukho ulimi (QWERTZ)"</string>
+ <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Alukho ulimi (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Alukho ulimi (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Alukho ulimi (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Alukho ulimi (PC)"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Izitayela zokufaka ngokwezifiso"</string>
+ <string name="add_style" msgid="6163126614514489951">"Engeza isitayela"</string>
+ <string name="add" msgid="8299699805688017798">"Engeza"</string>
+ <string name="remove" msgid="4486081658752944606">"Khipha"</string>
+ <string name="save" msgid="7646738597196767214">"Londoloza"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Ulimi"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Isakhiwo"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Isitayela sakho sokufakwayo sokwenza ngokwezifiso sidinga ukunikwa amandla ngaphambi kokusisebenzisa. Ufuna ukusinika amandla manje?"</string>
+ <string name="enable" msgid="5031294444630523247">"Nika amandla"</string>
+ <string name="not_now" msgid="6172462888202790482">"Hhayi manje"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Isitayela sokufaka esifanayo sesivele sikhona: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
<string name="prefs_usability_study_mode" msgid="1261130555134595254">"Imodi yesitadi yokusebenziseka"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Izilungiselelo ze-keypress vibration duraton"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Izilungiselelo zevolumu yomsindo wekeypress"</string>
</resources>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 351be28f2..a18371fc9 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -18,18 +18,24 @@
<declare-styleable name="KeyboardTheme">
<!-- Keyboard style -->
<attr name="keyboardStyle" format="reference" />
+ <!-- TODO: Get rid of latinKeyboardStyle -->
<!-- LatinKeyboard style -->
<attr name="latinKeyboardStyle" format="reference" />
<!-- KeyboardView style -->
<attr name="keyboardViewStyle" format="reference" />
- <!-- PopupMiniKeyboardView style -->
- <attr name="popupMiniKeyboardViewStyle" format="reference" />
- <attr name="popupMiniKeyboardPanelStyle" format="reference" />
+ <!-- LatinKeyboardView style -->
+ <attr name="latinKeyboardViewStyle" format="reference" />
+ <!-- MoreKeysKeyboard style -->
+ <attr name="moreKeysKeyboardStyle" format="reference" />
+ <!-- MoreKeysKeyboardView style -->
+ <attr name="moreKeysKeyboardViewStyle" format="reference" />
+ <attr name="moreKeysKeyboardPanelStyle" format="reference" />
<!-- Suggestions strip style -->
<attr name="suggestionsStripBackgroundStyle" format="reference" />
+ <attr name="suggestionsViewStyle" format="reference" />
+ <attr name="moreSuggestionsViewStyle" format="reference" />
<attr name="suggestionBackgroundStyle" format="reference" />
<attr name="suggestionPreviewBackgroundStyle" format="reference" />
- <attr name="candidateViewStyle" format="reference" />
</declare-styleable>
<declare-styleable name="KeyboardView">
@@ -38,19 +44,34 @@
checkable+checked+pressed. -->
<attr name="keyBackground" format="reference" />
+ <!-- Size of the text for one letter keys. If not defined, keyLetterRatio takes effect. -->
+ <attr name="keyLetterSize" format="dimension" />
+ <!-- Size of the text for keys with multiple letters. If not defined, keyLabelRatio takes
+ effect. -->
+ <attr name="keyLabelSize" format="dimension" />
<!-- Size of the text for one letter keys, in the proportion of key height. -->
<attr name="keyLetterRatio" format="float" />
<!-- Large size of the text for one letter keys, in the proportion of key height. -->
<attr name="keyLargeLetterRatio" format="float" />
- <!-- Size of the text for keys with some text, in the proportion of key height. -->
+ <!-- Size of the text for keys with multiple letters, in the proportion of key height. -->
<attr name="keyLabelRatio" format="float" />
+ <!-- Large size of the text for keys with multiple letters, in the proportion of key height. -->
+ <attr name="keyLargeLabelRatio" format="float" />
<!-- Size of the text for hint letter (= one character hint label), in the proportion of
key height. -->
<attr name="keyHintLetterRatio" format="float" />
<!-- Size of the text for hint label, in the proportion of key height. -->
<attr name="keyHintLabelRatio" format="float" />
- <!-- Size of the text for upper case letter, in the proportion of key height. -->
- <attr name="keyUppercaseLetterRatio" format="float" />
+ <!-- Size of the text for shifted letter hint, in the proportion of key height. -->
+ <attr name="keyShiftedLetterHintRatio" format="float" />
+ <!-- Horizontal padding of left/right aligned key label to the edge of the key. -->
+ <attr name="keyLabelHorizontalPadding" format="dimension" />
+ <!-- Right padding of hint letter to the edge of the key.-->
+ <attr name="keyHintLetterPadding" format="dimension" />
+ <!-- Bottom padding of popup hint letter "..." to the edge of the key.-->
+ <attr name="keyPopupHintLetterPadding" format="dimension" />
+ <!-- Right padding of shifted letter hint to the edge of the key.-->
+ <attr name="keyShiftedLetterHintPadding" format="dimension" />
<!-- Color to use for the label in a key. -->
<attr name="keyTextColor" format="color" />
@@ -60,19 +81,18 @@
<attr name="keyHintLetterColor" format="color" />
<!-- Key hint label color -->
<attr name="keyHintLabelColor" format="color" />
- <!-- Upper case letter colors -->
- <attr name="keyUppercaseLetterInactivatedColor" format="color" />
- <attr name="keyUppercaseLetterActivatedColor" format="color" />
-
- <!-- Popup hint icon "..." -->
- <attr name="keyPopupHintIcon" format="reference" />
+ <!-- Shifted letter hint colors -->
+ <attr name="keyShiftedLetterHintInactivatedColor" format="color" />
+ <attr name="keyShiftedLetterHintActivatedColor" format="color" />
<!-- Layout resource for key press feedback.-->
<attr name="keyPreviewLayout" format="reference" />
<!-- The background for key press feedback. -->
<attr name="keyPreviewBackground" format="reference" />
- <!-- The background for spacebar press feedback. -->
- <attr name="keyPreviewSpacebarBackground" format="reference" />
+ <!-- The background for the left edge key press feedback. -->
+ <attr name="keyPreviewLeftBackground" format="reference" />
+ <!-- The background for the right edge key press feedback. -->
+ <attr name="keyPreviewRightBackground" format="reference" />
<!-- The text color for key press feedback. -->
<attr name="keyPreviewTextColor" format="color" />
<!-- Vertical offset of the key press feedback from the key. -->
@@ -81,19 +101,18 @@
<attr name="keyPreviewHeight" format="dimension" />
<!-- Size of the text for key press feedback popup, int the proportion of key height -->
<attr name="keyPreviewTextRatio" format="float" />
-
- <!-- Hysteresis distance for key debouncing -->
- <attr name="keyHysteresisDistance" format="dimension" />
+ <!-- Delay after key releasing and key press feedback dismissing in millisecond -->
+ <attr name="keyPreviewLingerTimeout" format="integer" />
<!-- Amount to offset the touch Y coordinate by, for bias correction. -->
<attr name="verticalCorrection" format="dimension" />
- <!-- Layout resource for popup keyboards. -->
- <attr name="popupLayout" format="reference" />
+ <!-- Layout resource for more keys panel -->
+ <attr name="moreKeysLayout" format="reference" />
<attr name="shadowColor" format="color" />
<attr name="shadowRadius" format="float" />
- <attr name="backgroundDimAmount" format="float" />
+ <attr name="backgroundDimAlpha" format="integer" />
<attr name="keyTextStyle" format="enum">
<!-- This should be aligned with Typeface.NORMAL etc. -->
@@ -104,165 +123,222 @@
</attr>
</declare-styleable>
- <declare-styleable name="CandidateView">
- <attr name="autoCorrectHighlight" format="integer">
+ <declare-styleable name="LatinKeyboardView">
+ <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" />
+ <attr name="autoCorrectionSpacebarLedIcon" format="reference" />
+ <!-- Size of the text for spacebar language label, in the proportion of key height. -->
+ <attr name="spacebarTextRatio" format="fraction" />
+ <attr name="spacebarTextColor" format="color" />
+ <attr name="spacebarTextShadowColor" format="color" />
+ <!-- Fadeout animator for spacebar language label. -->
+ <attr name="languageOnSpacebarFinalAlpha" format="integer" />
+ <attr name="languageOnSpacebarFadeoutAnimator" format="reference" />
+ <!-- Fadeout and fadein animator for altCodeWhileTyping keys. -->
+ <attr name="altCodeKeyWhileTypingFadeoutAnimator" format="reference" />
+ <attr name="altCodeKeyWhileTypingFadeinAnimator" format="reference" />
+ <!-- Key detection hysteresis distance. -->
+ <attr name="keyHysteresisDistance" format="dimension" />
+ <!-- Touch noise threshold time in millisecond -->
+ <attr name="touchNoiseThresholdTime" format="integer" />
+ <!-- Touch noise threshold distance in millimeter -->
+ <attr name="touchNoiseThresholdDistance" format="dimension" />
+ <!-- Sliding key input enable -->
+ <attr name="slidingKeyInputEnable" format="boolean" />
+ <!-- Key repeat start timeout -->
+ <attr name="keyRepeatStartTimeout" format="integer" />
+ <!-- Key repeat interval in millisecond. -->
+ <attr name="keyRepeatInterval" format="integer" />
+ <!-- Long press timeout of letter key in millisecond. -->
+ <attr name="longPressKeyTimeout" format="integer" />
+ <!-- Long press timeout of shift key in millisecond. -->
+ <attr name="longPressShiftKeyTimeout" format="integer" />
+ <!-- Ignore special key timeout while typing in millisecond. -->
+ <attr name="ignoreAltCodeKeyTimeout" format="integer" />
+ <!-- More keys keyboard will shown at touched point. -->
+ <attr name="showMoreKeysKeyboardAtTouchedPoint" format="boolean" />
+ </declare-styleable>
+
+ <declare-styleable name="SuggestionsView">
+ <attr name="suggestionStripOption" format="integer">
+ <!-- This should be aligned with SuggestionsViewParams.AUTO_CORRECT_* and etc. -->
<flag name="autoCorrectBold" value="0x01" />
<flag name="autoCorrectUnderline" value="0x02" />
- <flag name="autoCorrectInvert" value="0x04" />
+ <flag name="validTypedWordBold" value="0x04" />
</attr>
+ <attr name="colorValidTypedWord" format="color" />
<attr name="colorTypedWord" format="color" />
<attr name="colorAutoCorrect" format="color" />
<attr name="colorSuggested" format="color" />
- <attr name="iconExpandPane" format="reference" />
- <attr name="iconClosePane" format="reference" />
+ <attr name="alphaValidTypedWord" format="integer" />
+ <attr name="alphaTypedWord" format="integer" />
+ <attr name="alphaAutoCorrect" format="integer" />
+ <attr name="alphaSuggested" format="integer" />
+ <attr name="alphaObsoleted" format="integer" />
+ <attr name="suggestionsCountInStrip" format="integer" />
+ <attr name="centerSuggestionPercentile" format="integer" />
+ <attr name="maxMoreSuggestionsRow" format="integer" />
+ <attr name="minMoreSuggestionsWidth" format="float" />
</declare-styleable>
<declare-styleable name="Keyboard">
+ <attr name="themeId" format="integer" />
+ <!-- Touch position correction -->
+ <attr name="touchPositionCorrectionData" format="reference" />
<!-- Default keyboard height -->
- <attr name="keyboardHeight" format="dimension" />
+ <attr name="keyboardHeight" format="dimension|fraction" />
<!-- Maximum keyboard height, in pixels or percentage of display height -->
<attr name="maxKeyboardHeight" format="dimension|fraction" />
<!-- Minimum keyboard height represented in pixels, percentage of display height if fraction
is positive, or percentage of display width if fraction is negative. -->
<attr name="minKeyboardHeight" format="dimension|fraction" />
- <!-- Keyboard top and bottom paddings. -->
- <attr name="keyboardTopPadding" format="dimension" />
- <attr name="keyboardBottomPadding" format="dimension" />
- <!-- Default width of a key, in pixels or percentage of display width.
- If the value is zero, the actual key width will be determined to fill out the area up
- to the right edge of the keyboard.
- If the value is negative, the actual key width will be determined to fill out the
- area between the nearest key on the left hand side and the right edge of the keyboard.
- -->
- <attr name="keyWidth" format="dimension|fraction|enum">
- <enum name="fillRight" value="0" />
- <enum name="fillBoth" value="-1" />
- </attr>
+ <!-- Keyboard top, bottom, both horizontal edges paddings. -->
+ <attr name="keyboardTopPadding" format="dimension|fraction" />
+ <attr name="keyboardBottomPadding" format="dimension|fraction" />
+ <attr name="keyboardHorizontalEdgesPadding" format="dimension|fraction" />
<!-- Default height of a row (key height + vertical gap), in pixels or percentage of
keyboard height. -->
<attr name="rowHeight" format="dimension|fraction" />
- <!-- Default horizontal gap between keys. -->
+ <!-- Default horizontal gap between keys, in pixels or percentage of keyboard width. -->
<attr name="horizontalGap" format="dimension|fraction" />
- <!-- Default vertical gap between rows of keys. -->
+ <!-- Default vertical gap between rows of keys, in pixels or percentage of keyboard
+ height. -->
<attr name="verticalGap" format="dimension|fraction" />
- <!-- Popup keyboard layout template -->
- <attr name="popupKeyboardTemplate" format="reference" />
- <!-- Locale of the keyboard layout -->
- <attr name="keyboardLocale" format="string" />
- <!-- Icon set for key top and key preview. -->
+ <!-- More keys keyboard layout template -->
+ <attr name="moreKeysTemplate" format="reference" />
+ <!-- Icon set for key top and key preview.
+ These should be aligned with KeyboardIconsSet.NAMES_AND_ATTR_IDS[] -->
<attr name="iconShiftKey" format="reference" />
- <attr name="iconToSymbolKey" format="reference" />
- <attr name="iconToSymbolKeyWithShortcut" format="reference" />
<attr name="iconDeleteKey" format="reference" />
<attr name="iconSettingsKey" format="reference" />
- <attr name="iconShortcutKey" format="reference" />
<attr name="iconSpaceKey" format="reference" />
- <attr name="iconReturnKey" format="reference" />
+ <attr name="iconEnterKey" format="reference" />
<attr name="iconSearchKey" format="reference" />
<attr name="iconTabKey" format="reference" />
- <attr name="iconShiftedShiftKey" format="reference" />
- <attr name="iconPreviewSpaceKey" format="reference" />
- <attr name="iconPreviewTabKey" format="reference" />
- <attr name="iconPreviewSettingsKey" format="reference" />
- <attr name="iconPreviewShortcutKey" format="reference" />
+ <attr name="iconShortcutKey" format="reference" />
+ <attr name="iconShortcutForLabel" format="reference" />
+ <attr name="iconSpaceKeyForNumberLayout" format="reference" />
+ <attr name="iconShiftKeyShifted" format="reference" />
+ <attr name="iconShortcutKeyDisabled" format="reference" />
+ <attr name="iconTabKeyPreview" format="reference" />
+ <attr name="iconLanguageSwitchKey" format="reference" />
+ <attr name="iconZwnjKey" format="reference" />
+ <attr name="iconZwjKey" format="reference" />
</declare-styleable>
<declare-styleable name="Keyboard_Key">
- <!-- The unicode value that this key outputs. -->
- <attr name="code" format="integer" />
- <!-- The characters to display in the popup keyboard. -->
- <attr name="popupCharacters" format="string" />
- <!-- Maximum column of popup keyboard -->
- <attr name="maxPopupKeyboardColumn" format="integer" />
- <!-- Key edge flags. -->
- <attr name="keyEdgeFlags" format="integer">
- <!-- Key is anchored to the left of the keyboard. -->
- <flag name="left" value="1" />
- <!-- Key is anchored to the right of the keyboard. -->
- <flag name="right" value="2" />
+ <!-- The unicode value that this key outputs.
+ Code value represented in hexadecimal prefixed with "0x" or code value reference using
+ "!code/<code_name>" notation. -->
+ <attr name="code" format="string" />
+ <!-- The alternate unicode value that this key outputs while typing.
+ Code value represented in hexadecimal prefixed with "0x" or code value reference using
+ "!code/<code_name>" notation. -->
+ <attr name="altCode" format="string" />
+ <!-- The keys to display in the more keys keyboard. -->
+ <attr name="moreKeys" format="string" />
+ <!-- The keys to display in the more keys keyboard in addition to moreKeys.
+ The additional more keys are inserted at the '%' markers in the moreKeys if any.
+ They are inserted at the head of moreKeys if none.
+ If there are remaining entries of additionalMoreKeys even after all '%' markers have
+ been replaced, those remaining entries are appended at the end of moreKeys. -->
+ <attr name="additionalMoreKeys" format="string" />
+ <!-- Maximum column of more keys keyboard -->
+ <attr name="maxMoreKeysColumn" format="integer" />
+ <attr name="backgroundType" format="enum">
+ <!-- This should be aligned with Key.BACKGROUND_TYPE_* -->
+ <enum name="normal" value="0" />
+ <enum name="functional" value="1" />
+ <enum name="action" value="2" />
+ <enum name="stickyOff" value="3" />
+ <enum name="stickyOn" value="4" />
+ </attr>
+ <!-- The key action flags. -->
+ <attr name="keyActionFlags" format="integer">
+ <!-- This should be aligned with Key.ACTION_FLAGS_* -->
+ <flag name="isRepeatable" value="0x01" />
+ <flag name="noKeyPreview" value="0x02" />
+ <flag name="altCodeWhileTyping" value="0x04" />
+ <flag name="enableLongPress" value="0x08" />
</attr>
- <!-- Whether this is a functional key which has different key top than normal key. -->
- <attr name="isFunctional" format="boolean" />
- <!-- Whether this is a toggle key. -->
- <attr name="isSticky" format="boolean" />
- <!-- Whether long-pressing on this key will make it repeat. -->
- <attr name="isRepeatable" format="boolean" />
<!-- The string of characters to output when this key is pressed. -->
<attr name="keyOutputText" format="string" />
<!-- The label to display on the key. -->
<attr name="keyLabel" format="string" />
<!-- The hint label to display on the key in conjunction with the label. -->
<attr name="keyHintLabel" format="string" />
- <!-- The key label option. -->
- <attr name="keyLabelOption" format="integer">
- <!-- This should be aligned with Key.LABEL_OPTION_* -->
+ <!-- The key label flags. -->
+ <attr name="keyLabelFlags" format="integer">
+ <!-- This should be aligned with Key.LABEL_FLAGS__* -->
<flag name="alignLeft" value="0x01" />
<flag name="alignRight" value="0x02" />
- <flag name="alignBottom" value="0x04" />
<flag name="alignLeftOfCenter" value="0x08" />
- <flag name="largeLetter" value="0x10" />
- <flag name="fontNormal" value="0x20" />
- <flag name="fontMonoSpace" value="0x40" />
+ <flag name="fontNormal" value="0x10" />
+ <flag name="fontMonoSpace" value="0x20" />
+ <flag name="followKeyLargeLetterRatio" value="0x40" />
<flag name="followKeyLetterRatio" value="0x80" />
- <flag name="followKeyHintLabelRatio" value="0x100" />
+ <flag name="followKeyLabelRatio" value="0xC0" />
+ <flag name="followKeyLargeLabelRatio" value="0x100" />
+ <flag name="followKeyHintLabelRatio" value="0x140" />
<flag name="hasPopupHint" value="0x200" />
- <flag name="hasUppercaseLetter" value="0x400" />
+ <flag name="hasShiftedLetterHint" value="0x400" />
<flag name="hasHintLabel" value="0x800" />
+ <flag name="withIconLeft" value="0x1000" />
+ <flag name="withIconRight" value="0x2000" />
+ <flag name="autoXScale" value="0x4000" />
+ <!-- If true, character case of code, altCode, moreKeys, keyOutputText, keyLabel,
+ or keyHintLabel will never be subject to change. -->
+ <flag name="preserveCase" value="0x8000" />
+ <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and
+ keyTextInactivatedColor for the primary key top label. -->
+ <flag name="shiftedLetterActivated" value="0x10000" />
+ <!-- If true, use EditorInfo.actionLabel for the key label. -->
+ <flag name="fromCustomActionLabel" value="0x20000" />
+ <!-- If true, disable keyHintLabel. -->
+ <flag name="disableKeyHintLabel" value="0x40000000" />
+ <!-- If true, disable additionalMoreKeys. -->
+ <flag name="disableAdditionalMoreKeys" value="0x80000000" />
</attr>
<!-- The icon to display on the key instead of the label. -->
- <attr name="keyIcon" format="enum">
- <!-- This should be aligned with KeyboardIcons.ICON_* -->
- <enum name="iconShiftKey" value="1" />
- <enum name="iconToSymbolKey" value="2" />
- <enum name="iconToSymbolKeyWithShortcut" value="3" />
- <enum name="iconDeleteKey" value="4" />
- <enum name="iconSettingsKey" value="5" />
- <enum name="iconShortcutKey" value="6" />
- <enum name="iconSpaceKey" value="7" />
- <enum name="iconReturnKey" value="8" />
- <enum name="iconSearchKey" value="9" />
- <enum name="iconTabKey" value="10" />
- </attr>
- <!-- Shift key icon for shifted state -->
- <attr name="keyIconShifted" format="enum">
- <!-- This should be aligned with KeyboardIcons.ICON_SHIFTED_* -->
- <enum name="iconShiftedShiftKey" value="11" />
- </attr>
+ <attr name="keyIcon" format="string" />
+ <!-- The icon for disabled key -->
+ <attr name="keyIconDisabled" format="string" />
<!-- The icon to show in the popup preview. -->
- <attr name="keyIconPreview" format="enum">
- <!-- This should be aligned with KeyboardIcons.ICON_PREVIEW_* -->
- <enum name="iconPreviewSpaceKey" value="12" />
- <enum name="iconPreviewTabKey" value="13" />
- <enum name="iconPreviewSettingsKey" value="14" />
- <enum name="iconPreviewShortcutKey" value="15" />
- </attr>
+ <attr name="keyIconPreview" format="string" />
<!-- The key style to specify a set of key attributes defined by <key_style/> -->
<attr name="keyStyle" format="string" />
- <!-- The key is enabled and responds on press. -->
- <attr name="enabled" format="boolean" />
<!-- Visual insets -->
<attr name="visualInsetsLeft" format="dimension|fraction" />
<attr name="visualInsetsRight" format="dimension|fraction" />
+ <!-- Width of the key, in pixels or percentage of display width.
+ If the value is fillRight, the actual key width will be determined to fill out the area
+ up to the right edge of the keyboard. -->
+ <!-- This should be aligned with KeyboardBuilder.Row.KEYWIDTH_* -->
+ <attr name="keyWidth" format="dimension|fraction|enum">
+ <enum name="fillRight" value="-1" />
+ </attr>
<!-- The X-coordinate of upper right corner of this key including horizontal gap.
If the value is negative, the origin is the right edge of the keyboard. -->
<attr name="keyXPos" format="dimension|fraction" />
</declare-styleable>
- <declare-styleable name="Keyboard_Row">
- <!-- Row edge flags. -->
- <attr name="rowEdgeFlags" format="integer">
- <!-- Row is anchored to the top of the keyboard. -->
- <flag name="top" value="4" />
- <!-- Row is anchored to the bottom of the keyboard. -->
- <flag name="bottom" value="8" />
- </attr>
- </declare-styleable>
-
<declare-styleable name="Keyboard_Include">
<attr name="keyboardLayout" format="reference" />
</declare-styleable>
<declare-styleable name="Keyboard_Case">
+ <!-- This should be aligned with KeyboardLayoutSet_Element's elementName. -->
+ <attr name="keyboardLayoutSetElement" format="enum|string">
+ <enum name="alphabet" value="0" />
+ <enum name="alphabetManualShifted" value="1" />
+ <enum name="alphabetAutomaticShifted" value="2" />
+ <enum name="alphabetShiftLocked" value="3" />
+ <enum name="alphabetShiftLockShifted" value="4" />
+ <enum name="symbols" value="5" />
+ <enum name="symbolsShifted" value="6" />
+ <enum name="phone" value="7" />
+ <enum name="phoneSymbols" value="8" />
+ <enum name="number" value="9" />
+ </attr>
<!-- This should be aligned with KeyboardId.MODE_* -->
<attr name="mode" format="enum|string">
<enum name="text" value="0" />
@@ -272,19 +348,14 @@
<enum name="phone" value="4" />
<enum name="number" value="5" />
</attr>
- <attr name="navigateAction" format="boolean" />
+ <attr name="navigateNext" format="boolean" />
+ <attr name="navigatePrevious" format="boolean" />
<attr name="passwordInput" format="boolean" />
- <attr name="hasSettingsKey" format="boolean" />
- <!-- This should be aligned with KeyboardID.F2KEY_MODE_* -->
- <attr name="f2KeyMode" format="enum">
- <enum name="none" value="0" />
- <enum name="settings" value="1" />
- <enum name="shortcutIme" value="2" />
- <enum name="shortcutImeOrSettings" value="3" />
- </attr>
<attr name="clobberSettingsKey" format="boolean" />
- <attr name="voiceKeyEnabled" format="boolean" />
- <attr name="hasVoiceKey" format="boolean" />
+ <attr name="shortcutKeyEnabled" format="boolean" />
+ <attr name="hasShortcutKey" format="boolean" />
+ <attr name="languageSwitchKeyEnabled" format="boolean" />
+ <attr name="isMultiLine" format="boolean" />
<attr name="imeAction" format="enum">
<!-- This should be aligned with EditorInfo.IME_ACTION_* -->
<enum name="actionUnspecified" value="0" />
@@ -295,6 +366,8 @@
<enum name="actionNext" value="5" />
<enum name="actionDone" value="6" />
<enum name="actionPrevious" value="7" />
+ <!-- This should be aligned with KeyboardId.IME_ACTION_* -->
+ <enum name="actionCustomLabel" value="0x100" />
</attr>
<attr name="localeCode" format="string" />
<attr name="languageCode" format="string" />
@@ -306,15 +379,22 @@
<attr name="parentStyle" format="string" />
</declare-styleable>
- <declare-styleable name="LatinKeyboard">
- <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" />
- <attr name="autoCorrectionSpacebarLedIcon" format="reference" />
- <attr name="disabledShortcutIcon" format="reference" />
- <attr name="spacebarTextColor" format="color" />
- <attr name="spacebarTextShadowColor" format="color" />
- <attr name="spacebarArrowLeftIcon" format="reference" />
- <attr name="spacebarArrowRightIcon" format="reference" />
- <attr name="spacebarArrowPreviewLeftIcon" format="reference" />
- <attr name="spacebarArrowPreviewRightIcon" format="reference" />
+ <declare-styleable name="KeyboardLayoutSet_Element">
+ <!-- This should be aligned with KeyboardId.ELEMENT_* -->
+ <attr name="elementName" format="enum">
+ <enum name="alphabet" value="0" />
+ <enum name="alphabetManualShifted" value="1" />
+ <enum name="alphabetAutomaticShifted" value="2" />
+ <enum name="alphabetShiftLocked" value="3" />
+ <enum name="alphabetShiftLockShifted" value="4" />
+ <enum name="symbols" value="5" />
+ <enum name="symbolsShifted" value="6" />
+ <enum name="phone" value="7" />
+ <enum name="phoneSymbols" value="8" />
+ <enum name="number" value="9" />
+ </attr>
+ <attr name="elementKeyboard" format="reference"/>
+ <!-- Enable proximity characters correction. Disabled by default. -->
+ <attr name="enableProximityCharsCorrection" format="boolean" />
</declare-styleable>
</resources>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 40cca9543..589830d8e 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -19,70 +19,77 @@
-->
<resources>
- <bool name="config_swipeDisambiguation">true</bool>
- <bool name="config_enable_show_settings_key_option">true</bool>
+ <bool name="config_use_fullscreen_mode">false</bool>
<bool name="config_enable_show_voice_key_option">true</bool>
<bool name="config_enable_show_popup_on_keypress_option">true</bool>
- <bool name="config_enable_show_recorrection_option">true</bool>
- <bool name="config_enable_quick_fixes_option">true</bool>
- <bool name="config_enable_bigram_suggestions_option">true</bool>
- <bool name="config_enable_usability_study_mode_option">false</bool>
- <bool name="config_swipe_down_dismiss_keyboard_enabled">true</bool>
- <bool name="config_sliding_key_input_enabled">true</bool>
- <bool name="config_digit_popup_characters_enabled">true</bool>
+ <!-- TODO: Disable the following configuration for production. -->
+ <bool name="config_enable_usability_study_mode_option">true</bool>
<!-- Whether or not Popup on key press is enabled by default -->
<bool name="config_default_popup_preview">true</bool>
- <!-- Default values for whether quick fixes and bigram suggestions are activated -->
- <bool name="config_default_quick_fixes">true</bool>
- <!-- Default value for bigram suggestion: while showing candidates for a word should we weigh
- in the previous word? -->
- <bool name="config_default_bigram_suggestions">true</bool>
- <!-- Default value for bigram prediction: after entering a word and a space only, should we look
- at input history to suggest a hopefully helpful candidate for the next word? -->
- <bool name="config_default_bigram_prediction">false</bool>
- <bool name="config_default_recorrection_enabled">true</bool>
+ <!-- Default value for next word prediction: after entering a word and a space only, should we look
+ at input history to suggest a hopefully helpful suggestions for the next word? -->
+ <bool name="config_default_next_word_prediction">true</bool>
<bool name="config_default_sound_enabled">false</bool>
- <bool name="config_auto_correction_spacebar_led_enabled">true</bool>
- <bool name="config_use_spacebar_language_switcher">true</bool>
- <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
- <bool name="config_show_mini_keyboard_at_touched_point">false</bool>
- <!-- The language is never displayed if == 0, always displayed if < 0 -->
- <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer>
+ <bool name="config_default_vibration_enabled">true</bool>
<integer name="config_delay_update_suggestions">100</integer>
<integer name="config_delay_update_old_suggestions">300</integer>
<integer name="config_delay_update_shift_state">100</integer>
- <integer name="config_duration_of_fadeout_language_on_spacebar">50</integer>
- <integer name="config_final_fadeout_percentage_of_language_on_spacebar">50</integer>
- <integer name="config_delay_before_preview">0</integer>
- <integer name="config_delay_after_preview">70</integer>
- <integer name="config_mini_keyboard_fadein_anim_time">0</integer>
- <integer name="config_mini_keyboard_fadeout_anim_time">100</integer>
- <integer name="config_delay_before_key_repeat_start">400</integer>
- <integer name="config_key_repeat_interval">50</integer>
+ <integer name="config_language_on_spacebar_final_alpha">128</integer>
+ <integer name="config_more_keys_keyboard_fadein_anim_time">0</integer>
+ <integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer>
<integer name="config_keyboard_grid_width">32</integer>
<integer name="config_keyboard_grid_height">16</integer>
- <integer name="config_long_press_key_timeout">400</integer>
- <integer name="config_long_press_shift_key_timeout">1200</integer>
- <integer name="config_touch_noise_threshold_millis">40</integer>
<integer name="config_double_spaces_turn_into_period_timeout">1100</integer>
- <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen>
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
- <string name="config_default_keyboard_theme_id" translatable="false">5</string>
- <string name="config_text_size_of_language_on_spacebar" translatable="false">small</string>
- <integer name="config_max_popup_keyboard_column">5</integer>
+ <string name="config_default_keyboard_theme_index" translatable="false">5</string>
+ <integer name="config_max_more_keys_column">5</integer>
+ <!--
+ Configuration for KeyboardView
+ -->
+ <integer name="config_key_preview_linger_timeout">70</integer>
+ <!--
+ Configuration for LatinKeyboardView
+ -->
+ <dimen name="config_key_hysteresis_distance">8.0dp</dimen>
+ <integer name="config_touch_noise_threshold_time">40</integer>
+ <dimen name="config_touch_noise_threshold_distance">12.6dp</dimen>
+ <bool name="config_sliding_key_input_enabled">true</bool>
+ <integer name="config_key_repeat_start_timeout">400</integer>
+ <integer name="config_key_repeat_interval">50</integer>
+ <integer name="config_long_press_key_timeout">400</integer>
+ <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 -->
+ <integer name="config_long_press_shift_key_timeout">1200</integer>
+ <integer name="config_ignore_alt_code_key_timeout">350</integer>
+ <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if
+ false -->
+ <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool>
+ <!--
+ Configuration for auto correction
+ -->
<string-array name="auto_correction_threshold_values" translatable="false">
<!-- Off, When auto correction setting is Off, this value is not used. -->
<item></item>
<!-- Modest : Suggestion whose normalized score is greater than this value
will be subject to auto-correction. -->
- <item>0.22</item>
+ <item>0.185</item>
<!-- Aggressive -->
- <item>0.08</item>
+ <item>0.067</item>
<!-- Very Aggressive : Suggestion whose normalized score is greater than this value
will be subject to auto-correction. -->
<item>0</item>
</string-array>
- <!-- Screen metrics for logging. 0 = "mdpi", 1 = "hdpi", 2 = "xlarge" -->
+ <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare
+ a word to be "recommended" -->
+ <string name="spellchecker_recommended_threshold_value" translatable="false">0.11</string>
+ <!-- Threshold of the normalized score of any dictionary lookup to be offered as a suggestion
+ by the spell checker -->
+ <string name="spellchecker_suggestion_threshold_value" translatable="false">0.03</string>
+ <!-- Screen metrics for logging.
+ 0 = "mdpi phone screen"
+ 1 = "hdpi phone screen"
+ 2 = "mdpi 11 inch tablet screen"
+ 3 = "xhdpi phone screen?"
+ 4 = ?
+ -->
<integer name="log_screen_metrics">0</integer>
- <bool name="config_require_umlaut_processing">false</bool>
</resources>
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index c1ef86930..925eb55fa 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -19,64 +19,78 @@
-->
<resources>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=0.295in -->
- <dimen name="keyboardHeight">1.285in</dimen>
- <fraction name="maxKeyboardHeight">50%p</fraction>
+ <!-- Preferable keyboard height in absolute scale: 1.285in -->
+ <!-- This keyboardHeight value should match with keyboard-heights.xml -->
+ <dimen name="keyboardHeight">205.6dp</dimen>
+ <fraction name="maxKeyboardHeight">46%p</fraction>
<fraction name="minKeyboardHeight">-61.8%p</fraction>
- <!-- key_height + key_bottom_gap = popup_key_height -->
- <!-- <dimen name="key_height">0.295in</dimen> -->
- <dimen name="key_bottom_gap">0.035in</dimen>
- <dimen name="key_horizontal_gap">0.000in</dimen>
- <dimen name="popup_key_height">0.330in</dimen>
- <dimen name="keyboard_top_padding">0.00in</dimen>
- <dimen name="keyboard_bottom_padding">0.06in</dimen>
- <dimen name="keyboard_horizontal_edges_padding">0.0in</dimen>
- <dimen name="mini_keyboard_horizontal_padding">16dip</dimen>
- <dimen name="mini_keyboard_key_horizontal_padding">8dip</dimen>
- <dimen name="key_bottom_gap_ics">0.06in</dimen>
- <dimen name="key_horizontal_gap_ics">0.01in</dimen>
- <dimen name="keyboard_top_padding_ics">0.03in</dimen>
- <dimen name="keyboard_bottom_padding_ics">0.06in</dimen>
- <dimen name="mini_keyboard_horizontal_padding_ics">38dip</dimen>
+ <dimen name="popup_key_height">52.8dp</dimen>
+
+ <dimen name="more_keys_keyboard_key_horizontal_padding">8dp</dimen>
+
+ <fraction name="keyboard_top_padding">1.556%p</fraction>
+ <fraction name="keyboard_bottom_padding">4.669%p</fraction>
+ <fraction name="keyboard_horizontal_edges_padding">0%p</fraction>
+ <fraction name="key_bottom_gap">6.250%p</fraction>
+ <fraction name="key_horizontal_gap">1.352%p</fraction>
+
+ <fraction name="keyboard_top_padding_stone">1.556%p</fraction>
+ <fraction name="keyboard_bottom_padding_stone">0.778%p</fraction>
+ <fraction name="key_bottom_gap_stone">7.506%p</fraction>
+ <fraction name="key_horizontal_gap_stone">1.739%p</fraction>
+
+ <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>
+ <dimen name="more_keys_keyboard_horizontal_edges_padding_ics">4dp</dimen>
<!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
<!-- popup_key_height x 1.2 -->
- <dimen name="mini_keyboard_slide_allowance">0.396in</dimen>
+ <dimen name="more_keys_keyboard_slide_allowance">63.36dp</dimen>
<!-- popup_key_height x -1.0 -->
- <dimen name="mini_keyboard_vertical_correction">-0.330in</dimen>
- <!-- We use "inch", not "dip" because this value tries dealing with physical distance related
- to user's finger. -->
- <dimen name="keyboard_vertical_correction">-0.05in</dimen>
-
- <!-- left or right padding of label alignment -->
- <dimen name="key_label_horizontal_alignment_padding">4dip</dimen>
+ <dimen name="more_keys_keyboard_vertical_correction">-52.8dp</dimen>
+ <dimen name="keyboard_vertical_correction">0.0dp</dimen>
- <fraction name="key_letter_ratio">45%</fraction>
- <fraction name="key_large_letter_ratio">55%</fraction>
- <fraction name="key_label_ratio">29%</fraction>
- <fraction name="key_hint_letter_ratio">23%</fraction>
- <fraction name="key_hint_label_ratio">36%</fraction>
+ <fraction name="key_letter_ratio">55%</fraction>
+ <fraction name="key_large_letter_ratio">65%</fraction>
+ <fraction name="key_label_ratio">34%</fraction>
+ <fraction name="key_large_label_ratio">40%</fraction>
+ <fraction name="key_hint_letter_ratio">25%</fraction>
+ <fraction name="key_hint_label_ratio">44%</fraction>
<fraction name="key_uppercase_letter_ratio">35%</fraction>
<fraction name="key_preview_text_ratio">82%</fraction>
- <dimen name="key_preview_height">80sp</dimen>
- <dimen name="key_preview_offset">0.1in</dimen>
+ <fraction name="spacebar_text_ratio">33.735%</fraction>
+ <dimen name="key_preview_height">80dp</dimen>
+ <dimen name="key_preview_offset">-8.0dp</dimen>
- <dimen name="key_preview_height_ics">80sp</dimen>
- <dimen name="key_preview_offset_ics">0.05in</dimen>
+ <dimen name="key_label_horizontal_padding">4dp</dimen>
+ <dimen name="key_hint_letter_padding">1dp</dimen>
+ <dimen name="key_popup_hint_letter_padding">2dp</dimen>
+ <dimen name="key_uppercase_letter_padding">2dp</dimen>
- <dimen name="candidate_strip_height">42dip</dimen>
- <!-- candidate_strip_minimum_height =
- key_preview_height_holo - key_preview_offset_holo + alpha -->
- <dimen name="candidate_strip_minimum_height">100sp</dimen>
- <dimen name="candidate_strip_fading_edge_length">63dip</dimen>
- <dimen name="candidate_strip_padding">0dip</dimen>
- <dimen name="candidate_min_width">44dip</dimen>
- <dimen name="candidate_padding">6dip</dimen>
- <dimen name="candidate_text_size">18dip</dimen>
- <!-- If the screen height in landscape is larger than the below value, then the keyboard
- will not go into extract (fullscreen) mode. -->
- <dimen name="max_height_for_fullscreen">2.5in</dimen>
+ <dimen name="key_preview_offset_ics">8.0dp</dimen>
+ <!-- popup_key_height x -0.5 -->
+ <dimen name="more_keys_keyboard_vertical_correction_ics">-26.4dp</dimen>
- <dimen name="key_hysteresis_distance">0.05in</dimen>
+ <dimen name="suggestions_strip_height">40dp</dimen>
+ <dimen name="more_suggestions_key_horizontal_padding">12dp</dimen>
+ <dimen name="more_suggestions_row_height">40dp</dimen>
+ <dimen name="more_suggestions_bottom_gap">6dp</dimen>
+ <dimen name="more_suggestions_modal_tolerance">32.0dp</dimen>
+ <dimen name="more_suggestions_slide_allowance">16.0dp</dimen>
+ <integer name="max_more_suggestions_row">6</integer>
+ <fraction name="min_more_suggestions_width">90%</fraction>
+ <fraction name="more_suggestions_info_ratio">18%</fraction>
+ <dimen name="suggestions_strip_padding">0dp</dimen>
+ <dimen name="suggestion_min_width">44dp</dimen>
+ <dimen name="suggestion_padding">6dp</dimen>
+ <dimen name="suggestion_text_size">18dp</dimen>
+ <dimen name="more_suggestions_hint_text_size">27dp</dimen>
+ <integer name="suggestions_count_in_strip">3</integer>
+ <integer name="center_suggestion_percentile">36</integer>
</resources>
diff --git a/java/res/values/donottranslate-altchars.xml b/java/res/values/donottranslate-altchars.xml
deleted file mode 100644
index e77957578..000000000
--- a/java/res/values/donottranslate-altchars.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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="alternates_for_a"></string>
- <string name="alternates_for_e">3</string>
- <string name="alternates_for_i">8</string>
- <string name="alternates_for_o">9</string>
- <string name="alternates_for_u">7</string>
- <string name="alternates_for_s"></string>
- <string name="alternates_for_n"></string>
- <string name="alternates_for_c"></string>
- <string name="alternates_for_y">6</string>
- <string name="alternates_for_q">1</string>
- <string name="alternates_for_w">2</string>
- <string name="alternates_for_d"></string>
- <string name="alternates_for_r">4</string>
- <string name="alternates_for_t">5</string>
- <string name="alternates_for_z"></string>
- <string name="alternates_for_k"></string>
- <string name="alternates_for_l"></string>
- <string name="alternates_for_g"></string>
- <string name="alternates_for_p">0</string>
- <string name="alternates_for_v"></string>
- <string name="keylabel_for_scandinavia_row2_10"></string>
- <string name="keylabel_for_scandinavia_row2_11"></string>
- <string name="alternates_for_scandinavia_row2_10"></string>
- <string name="alternates_for_scandinavia_row2_11"></string>
- <string name="alternates_for_cyrillic_e"></string>
- <string name="alternates_for_cyrillic_soft_sign"></string>
- <string name="alternates_for_currency_dollar">¢,£,€,¥,₱</string>
- <string name="alternates_for_currency_euro">¢,£,$,¥,₱</string>
- <string name="alternates_for_currency_pound">¢,$,€,¥,₱</string>
- <string name="alternates_for_smiley">":-)|:-) ,:-(|:-( ,;-)|;-) ,:-P|:-P ,=-O|=-O ,:-*|:-* ,:O|:O ,B-)|B-) ,:-$|:-$ ,:-!|:-! ,:-[|:-[ ,O:-)|O:-) ,:-\\\\\\\\|:-\\\\\\\\ ,:\'(|:\'( ,:-D|:-D "</string>
- <string name="alternates_for_punctuation">"\\,,\?,!,:,-,\',\",(,),/,;,+,&amp;,\@"</string>
- <string name="alternates_for_web_tab_punctuation">".,\\,,\?,!,:,-,\',\",(,),/,;,+,&amp;,\@"</string>
- <string name="keylabel_for_popular_domain">".com"</string>
- <!-- popular web domains for the locale - most popular, displayed on the keyboard -->
- <string name="alternates_for_popular_domain">".net,.org,.gov,.edu"</string>
-</resources>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 21e6c55c6..d6a68d0dc 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -19,49 +19,31 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Symbols that are suggested between words -->
- <string name="suggested_punctuations">!?,\u0022\u0027:();-/@_</string>
- <!-- Symbols that should be swapped with a magic space -->
- <string name="magic_space_swapping_symbols">.,;:!?)]}\u0022</string>
- <!-- Symbols that should strip a magic space -->
- <string name="magic_space_stripping_symbols">\u0009\u0020\n/_\u0027-</string>
- <!-- Symbols that should convert magic spaces into real space -->
- <string name="magic_space_promoting_symbols">([*&amp;@{&lt;&gt;+=|</string>
+ <string name="suggested_punctuations">!,?,\\,,:,;,\",(,),\',-,/,@,_</string>
+ <!-- Symbols that should be swapped with a weak space -->
+ <string name="weak_space_swapping_symbols">.,;:!?)]}\"</string>
+ <!-- Symbols that should strip a weak space -->
+ <string name="weak_space_stripping_symbols">"&#x0009;&#x0020;\n/_\'-"</string>
+ <!-- Symbols that should convert weak spaces into real space -->
+ <string name="phantom_space_promoting_symbols">([*&amp;@{&lt;&gt;+=|</string>
<!-- Symbols that do NOT separate words -->
- <string name="non_word_separator_symbols">\u0027-</string>
+ <string name="symbols_excluded_from_word_separators">\'-</string>
<!-- Word separator list is the union of all symbols except those that are not separators:
- magic_space_swapping_symbols | magic_space_stripping_symbols |
- magic_space_neutral_symbols \ non_word_separator_symbols -->
-
- <!-- Label for ALT modifier key. Must be short to fit on key! -->
- <string name="label_alt_key">ALT</string>
- <!-- Label for "Tab" key. Must be short to fit on key! -->
- <string name="label_tab_key">Tab</string>
- <!-- Label for "switch to symbols" key. Must be short to fit on key! -->
- <string name="label_to_symbol_key">\?123</string>
- <!-- Label for "switch to phone numeric" key. Must be short to fit on key! -->
- <string name="label_to_phone_numeric_key">123</string>
- <!-- Label for "switch to phone symbols" key. Must be short to fit on key! -->
- <string name="label_to_phone_symbols_key">\uff0a\uff03\uff08</string>
-
- <!-- Option values to show/hide the settings key in onscreen keyboard -->
- <!-- Automatically decide to show or hide the settings key -->
- <string name="settings_key_mode_auto">0</string>
- <!-- Always show the settings key -->
- <string name="settings_key_mode_always_show">1</string>
- <!-- Always hide the settings key -->
- <string name="settings_key_mode_always_hide">2</string>
- <!-- Array of the settings key mode values -->
- <string-array name="settings_key_modes_values">
- <item>@string/settings_key_mode_auto</item>
- <item>@string/settings_key_mode_always_show</item>
- <item>@string/settings_key_mode_always_hide</item>
- </string-array>
- <!-- Array of the settings key modes -->
- <string-array name="settings_key_modes">
- <item>@string/settings_key_mode_auto_name</item>
- <item>@string/settings_key_mode_always_show_name</item>
- <item>@string/settings_key_mode_always_hide_name</item>
- </string-array>
+ weak_space_swapping_symbols | weak_space_stripping_symbols
+ \ symbols_excluded_from_word_separators -->
+ <!-- Symbol characters list that should switch back to the main layout -->
+ <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+ <!-- <string name="layout_switch_back_symbols">\"\'&#x2018;&#x2019;&#x201A;&#x201B;&#x201C;&#x201D;&#x201E;&#x201F;&#x00AB;&#x00BB;</string> -->
+ <string name="layout_switch_back_symbols"></string>
<!-- Always show the suggestion strip -->
<string name="prefs_suggestion_visibility_show_value">0</string>
@@ -124,6 +106,7 @@
<!-- Title for Latin keyboard debug settings activity / dialog -->
<string name="english_ime_debug_settings">Android keyboard Debug settings</string>
<string name="prefs_debug_mode">Debug Mode</string>
+ <string name="prefs_force_non_distinct_multitouch">Force non-distinct multitouch</string>
<!-- Keyboard theme names -->
<string name="layout_basic">Basic</string>
@@ -151,15 +134,56 @@
<item>5</item>
</string-array>
- <!-- Subtype locale name exceptions -->
+ <!-- Subtype locale display name exceptions.
+ For each exception, there should be related string resource for display name that has
+ explicit keyboard layout. The string resource name must be "subtype_with_layout_<locale>. -->
<string-array name="subtype_locale_exception_keys">
<item>en_US</item>
<item>en_GB</item>
- <item>de_ZZ</item>
</string-array>
<string-array name="subtype_locale_exception_values">
<item>English (US)</item>
<item>English (UK)</item>
- <item>Deutsch (QWERTY)</item>
</string-array>
+
+ <!-- Generic subtype label -->
+ <string name="subtype_generic">%s</string>
+
+ <!-- Predefined keyboard layouts for additional subtype -->
+ <string-array name="predefined_layouts">
+ <item>qwerty</item>
+ <item>qwertz</item>
+ <item>azerty</item>
+ <item>dvorak</item>
+ <item>colemak</item>
+ <item>pcqwerty</item>
+ </string-array>
+ <!-- Predefined keyboard layout display names -->
+ <string-array name="predefined_layout_display_names">
+ <item>QWERTY</item>
+ <item>QWERTZ</item>
+ <item>AZERTY</item>
+ <item>Dvorak</item>
+ <item>Colemak</item>
+ <item>PC</item>
+ </string-array>
+ <!-- Description for generic subtype that has predefined layout.
+ The string resource name must be "subtype_generic_<layout name>".
+ The string resource with "No language" also must be added to strings.xml and the resource
+ name must be "subtype_no_language_<layout name>" -->
+ <string name="subtype_generic_qwerty">%s (QWERTY)</string>
+ <string name="subtype_generic_qwertz">%s (QWERTZ)</string>
+ <string name="subtype_generic_azerty">%s (AZERTY)</string>
+ <string name="subtype_generic_dvorak">%s (Dvorak)</string>
+ <string name="subtype_generic_colemak">%s (Colemak)</string>
+ <string name="subtype_generic_pcqwerty">%s (PC)</string>
+
+ <!-- Description for Bulgarian (BDS) subtype. -->
+ <string name="subtype_bulgarian_bds">%s (BDS)</string>
+
+ <!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
+ <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
+ <string name="dictionary_pack_settings_activity">com.google.android.inputmethod.latin.dictionarypack.DictionarySettingsActivity</string>
+ <string name="settings_ms">ms</string>
+ <string name="settings_warning_researcher_mode">Attention! You are using the special keyboard for research purposes.</string>
</resources>
diff --git a/java/res/values/keyboard-heights.xml b/java/res/values/keyboard-heights.xml
new file mode 100644
index 000000000..7d85994be
--- /dev/null
+++ b/java/res/values/keyboard-heights.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- Build.HARDWARE,keyboard_height_in_dp -->
+ <string-array name="keyboard_heights" translatable="false">
+ <!-- Preferable keyboard height in absolute scale: 1.285in -->
+ <!-- Droid -->
+ <item>sholes,227.0167</item>
+ <!-- Nexus One -->
+ <item>mahimahi,217.5932</item>
+ <!-- Nexus S -->
+ <item>herring,200.8554</item>
+ <!-- Galaxy Nexus -->
+ <item>tuna,202.5869</item>
+ <!-- Preferable keyboard height in absolute scale: 48.0mm -->
+ <!-- Xoom -->
+ <item>stingray,283.1337</item>
+ </string-array>
+</resources>
diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml
index 4144b64ca..e9c5733b5 100644
--- a/java/res/values/keyboard-icons-black.xml
+++ b/java/res/values/keyboard-icons-black.xml
@@ -17,26 +17,27 @@
<resources>
<style name="KeyboardIcons.Black">
<!-- Keyboard icons -->
+ <!-- TODO: The following holo icon for phone (drawable-hdpi and drawable-xhdpi) are too
+ ambiguous.
+ sym_bkeyboard_voice_off
+ -->
<item name="iconShiftKey">@drawable/sym_bkeyboard_shift</item>
- <item name="iconToSymbolKeyWithShortcut">@drawable/sym_bkeyboard_123_mic</item>
<item name="iconDeleteKey">@drawable/sym_bkeyboard_delete</item>
<item name="iconSettingsKey">@drawable/sym_bkeyboard_settings</item>
- <item name="iconShortcutKey">@drawable/sym_bkeyboard_mic</item>
<item name="iconSpaceKey">@drawable/sym_bkeyboard_space</item>
- <item name="iconReturnKey">@drawable/sym_bkeyboard_return</item>
+ <item name="iconEnterKey">@drawable/sym_bkeyboard_return</item>
<item name="iconSearchKey">@drawable/sym_bkeyboard_search</item>
<item name="iconTabKey">@drawable/sym_bkeyboard_tab</item>
- <item name="iconShiftedShiftKey">@drawable/sym_bkeyboard_shift_locked</item>
- <item name="iconPreviewSpaceKey">@drawable/sym_keyboard_feedback_space</item>
- <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
- <item name="iconPreviewSettingsKey">@drawable/sym_keyboard_feedback_settings</item>
- <item name="iconPreviewShortcutKey">@drawable/sym_keyboard_feedback_mic</item>
- <!-- LatinKeyboard icons -->
- <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
- <item name="spacebarArrowLeftIcon">@null</item>
- <item name="spacebarArrowRightIcon">@null</item>
- <item name="spacebarArrowPreviewLeftIcon">@drawable/sym_keyboard_feedback_language_arrows_left</item>
- <item name="spacebarArrowPreviewRightIcon">@drawable/sym_keyboard_feedback_language_arrows_right</item>
+ <item name="iconShortcutKey">@drawable/sym_bkeyboard_mic</item>
+ <item name="iconShortcutForLabel">@drawable/sym_bkeyboard_label_mic</item>
+ <item name="iconSpaceKeyForNumberLayout">@drawable/sym_bkeyboard_space</item>
+ <item name="iconShiftKeyShifted">@drawable/sym_bkeyboard_shift_locked</item>
+ <item name="iconShortcutKeyDisabled">@drawable/sym_bkeyboard_voice_off</item>
+ <item name="iconTabKeyPreview">@drawable/sym_keyboard_feedback_tab</item>
+ <!-- TODO: Needs dedicated black theme globe icon -->
+ <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item>
+ <!-- TODO: Needs dedicated black theme ZWNJ and ZWJ icons -->
+ <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo</item>
+ <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo</item>
</style>
</resources>
diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml
index 86fb7bb96..8eba196de 100644
--- a/java/res/values/keyboard-icons-ics.xml
+++ b/java/res/values/keyboard-icons-ics.xml
@@ -17,44 +17,24 @@
<resources>
<style name="KeyboardIcons.IceCreamSandwich">
<!-- Keyboard icons -->
- <!-- TODO: The following holo icon for phone (drawable-hdpi and drawable-xhdpi) are too
- large for phone.
- sym_keyboard_shift_holo
- sym_keyboard_shift_locked_holo
- sym_keyboard_delete_holo,
- sym_keyboard_settings_holo
- sym_keyboard_voice_holo
- sym_keyboard_voice_holo_off
- sym_keyboard_space_holo
- sym_keyboard_return_holo
- sym_keyboard_tab_holo
- -->
<!-- TODO: The following holo icon for phone (drawable-hdpi and drawable-xhdpi) are missing.
sym_keyboard_123_mic_holo
- sym_keyboard_search_holo
- sym_keyboard_feedback_tab_holo
- sym_keyboard_feedback_voice_holo
-->
<item name="iconShiftKey">@drawable/sym_keyboard_shift_holo</item>
- <item name="iconToSymbolKeyWithShortcut">@drawable/sym_keyboard_123_mic_holo</item>
<item name="iconDeleteKey">@drawable/sym_keyboard_delete_holo</item>
<item name="iconSettingsKey">@drawable/sym_keyboard_settings_holo</item>
- <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo</item>
- <item name="iconSpaceKey">@drawable/sym_keyboard_space_holo</item>
- <item name="iconReturnKey">@drawable/sym_keyboard_return_holo</item>
- <item name="iconSearchKey">@drawable/sym_keyboard_search</item>
+ <item name="iconSpaceKey">@null</item>
+ <item name="iconEnterKey">@drawable/sym_keyboard_return_holo</item>
+ <item name="iconSearchKey">@drawable/sym_keyboard_search_holo</item>
<item name="iconTabKey">@drawable/sym_keyboard_tab_holo</item>
- <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked_holo</item>
- <item name="iconPreviewSpaceKey">@drawable/transparent</item>
- <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
- <item name="iconPreviewSettingsKey">@drawable/sym_keyboard_settings_holo</item>
- <item name="iconPreviewShortcutKey">@drawable/sym_keyboard_feedback_mic</item>
- <!-- LatinKeyboard icons -->
- <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
- <item name="spacebarArrowLeftIcon">@drawable/sym_keyboard_language_arrows_left</item>
- <item name="spacebarArrowRightIcon">@drawable/sym_keyboard_language_arrows_right</item>
- <item name="spacebarArrowPreviewLeftIcon">@null</item>
- <item name="spacebarArrowPreviewRightIcon">@null</item>
+ <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo</item>
+ <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo</item>
+ <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo</item>
+ <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo</item>
+ <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo</item>
+ <item name="iconTabKeyPreview">@drawable/sym_keyboard_feedback_tab</item>
+ <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item>
+ <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo</item>
+ <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo</item>
</style>
</resources>
diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml
index 63df28476..e52099867 100644
--- a/java/res/values/keyboard-icons-white.xml
+++ b/java/res/values/keyboard-icons-white.xml
@@ -18,25 +18,22 @@
<style name="KeyboardIcons">
<!-- Keyboard icons -->
<item name="iconShiftKey">@drawable/sym_keyboard_shift</item>
- <item name="iconToSymbolKeyWithShortcut">@drawable/sym_keyboard_123_mic</item>
<item name="iconDeleteKey">@drawable/sym_keyboard_delete</item>
<item name="iconSettingsKey">@drawable/sym_keyboard_settings</item>
- <item name="iconShortcutKey">@drawable/sym_keyboard_mic</item>
<item name="iconSpaceKey">@drawable/sym_keyboard_space</item>
- <item name="iconReturnKey">@drawable/sym_keyboard_return</item>
+ <item name="iconEnterKey">@drawable/sym_keyboard_return</item>ZZ
<item name="iconSearchKey">@drawable/sym_keyboard_search</item>
<item name="iconTabKey">@drawable/sym_keyboard_tab</item>
- <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked</item>
- <item name="iconPreviewSpaceKey">@drawable/sym_keyboard_feedback_space</item>
- <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
- <item name="iconPreviewSettingsKey">@drawable/sym_keyboard_feedback_settings</item>
- <item name="iconPreviewShortcutKey">@drawable/sym_keyboard_feedback_mic</item>
- <!-- LatinKeyboard icons -->
- <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
- <item name="spacebarArrowLeftIcon">@drawable/sym_keyboard_language_arrows_left</item>
- <item name="spacebarArrowRightIcon">@drawable/sym_keyboard_language_arrows_right</item>
- <item name="spacebarArrowPreviewLeftIcon">@drawable/sym_keyboard_feedback_language_arrows_left</item>
- <item name="spacebarArrowPreviewRightIcon">@drawable/sym_keyboard_feedback_language_arrows_right</item>
+ <item name="iconShortcutKey">@drawable/sym_keyboard_mic</item>
+ <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic</item>
+ <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space</item>
+ <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked</item>
+ <!-- TODO: Needs non-holo disabled shortcut icon drawable -->
+ <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo</item>
+ <item name="iconTabKeyPreview">@drawable/sym_keyboard_feedback_tab</item>
+ <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item>
+ <!-- TODO: Needs dedicated black theme ZWNJ and ZWJ icons -->
+ <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo</item>
+ <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo</item>
</style>
</resources>
diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml
deleted file mode 100644
index ee345291a..000000000
--- a/java/res/values/keycodes.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<resources>
- <!-- These code should be aligned with Keyboard.CODE_*. -->
- <integer name="key_tab">9</integer>
- <integer name="key_return">10</integer>
- <integer name="key_space">32</integer>
- <integer name="key_shift">-1</integer>
- <integer name="key_switch_alpha_symbol">-2</integer>
- <integer name="key_delete">-5</integer>
- <integer name="key_settings">-6</integer>
- <integer name="key_shortcut">-8</integer>
-</resources>
diff --git a/java/res/values-large/donottranslate.xml b/java/res/values/keypress-vibration-durations.xml
index 6d94c2811..2569f2317 100644
--- a/java/res/values-large/donottranslate.xml
+++ b/java/res/values/keypress-vibration-durations.xml
@@ -17,7 +17,10 @@
** limitations under the License.
*/
-->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Default value of the visibility of the suggestion strip -->
- <string name="prefs_suggestion_visibility_default_value" translatable="false">1</string>
+<resources>
+ <string-array name="keypress_vibration_durations" translatable="false">
+ <!-- Build.HARDWARE,duration_in_milliseconds -->
+ <item>herring,5</item>
+ <item>tuna,5</item>
+ </string-array>
</resources>
diff --git a/java/res/values/keypress-volumes.xml b/java/res/values/keypress-volumes.xml
new file mode 100644
index 000000000..3b433e4ab
--- /dev/null
+++ b/java/res/values/keypress-volumes.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <string-array name="keypress_volumes" translatable="false">
+ <!-- Build.HARDWARE,volume -->
+ <item>herring,0.5</item>
+ <item>tuna,0.5</item>
+ <item>stingray,0.4</item>
+ <item>grouper,0.3</item>
+ </string-array>
+</resources>
diff --git a/java/res/values/phantom_sudden_move_event_device_list.xml b/java/res/values/phantom_sudden_move_event_device_list.xml
new file mode 100644
index 000000000..63d12e96e
--- /dev/null
+++ b/java/res/values/phantom_sudden_move_event_device_list.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <string-array name="phantom_sudden_move_event_device_list" translatable="false">
+ <!-- "Build.HARDWARE,true" that needs "phantom sudden move event" hack.
+ See {@link com.android.inputmethod.keyboard.PointerTracker}. -->
+ <item>stingray,true</item> <!-- Xoom -->
+ </string-array>
+</resources>
diff --git a/java/res/values-xlarge/donottranslate.xml b/java/res/values/predefined-subtypes.xml
index 672dea589..602f53eac 100644
--- a/java/res/values-xlarge/donottranslate.xml
+++ b/java/res/values/predefined-subtypes.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -18,6 +18,6 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Default value of the visibility of the suggestion strip -->
- <string name="prefs_suggestion_visibility_default_value" translatable="false">2</string>
+ <!-- Predefined subtypes (language:layout[:extraValue]) in semicolon separated format -->
+ <string name="predefined_subtypes" translatable="false">de:qwerty:AsciiCapable;fr:qwertz:AsciiCapable</string>
</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 08cd35db3..0b781af79 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -20,10 +20,28 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title for Latin keyboard -->
<string name="english_ime_name">Android keyboard</string>
+ <!-- Application name for opensource Android keyboard. AOSP(Android Open Source Project) should not be translated. -->
+ <string name="aosp_android_keyboard_ime_name">Android keyboard (AOSP)</string>
<!-- Title for Latin keyboard settings activity / dialog -->
<string name="english_ime_settings">Android keyboard settings</string>
<!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
<string name="english_ime_input_options">Input options</string>
+ <!-- Title for Latin keyboard research log dialog, which contains special commands for users that contribute data for research. [CHAR LIMIT=33] -->
+ <string name="english_ime_research_log">Research Log Commands</string>
+
+ <!-- Name of Android spell checker service -->
+ <string name="spell_checker_service_name">Android spell checker</string>
+ <!-- Name of Android spell checker service. AOSP(Android Open Source Project) should not be translated. -->
+ <string name="aosp_spell_checker_service_name">Android spell checker (AOSP)</string>
+
+ <!-- Title for the spell checking service settings screen -->
+ <string name="android_spell_checker_settings">Spell checking settings</string>
+
+ <!-- Title for the spell checker option to turn on/off contact names lookup [CHAR LIMIT=25] -->
+ <string name="use_contacts_for_spellchecking_option_title">Look up contact names</string>
+
+ <!-- Description for the spell checker option to turn on/off contact names lookup. [CHAR LIMIT=65] -->
+ <string name="use_contacts_for_spellchecking_option_summary">Spell checker uses entries from your contact list</string>
<!-- Option to provide vibrate/haptic feedback on keypress -->
<string name="vibrate_on_keypress">Vibrate on keypress</string>
@@ -31,7 +49,7 @@
<!-- Option to play back sound on keypress in soft keyboard -->
<string name="sound_on_keypress">Sound on keypress</string>
- <!-- Option to pop up the character with a larger font above soft keyboard -->
+ <!-- Option to control whether or not to show a popup with a larger font on each key press. -->
<string name="popup_on_keypress">Popup on keypress</string>
<!-- Category title for general settings for Android keyboard -->
@@ -40,16 +58,20 @@
<!-- Category title for text prediction -->
<string name="correction_category">Text correction</string>
- <!-- Category title for ngrams -->
- <string name="ngram_category">Suggestions based on previous words</string>
-
<!-- Category title for misc options -->
<string name="misc_category">Other options</string>
<!-- Option name for advanced settings screen [CHAR LIMIT=25] -->
<string name="advanced_settings">Advanced settings</string>
<!-- Option summary for advanced settings screen [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] -->
- <string name="advanced_settings_summary">Options for expert users</string>
+ <string name="advanced_settings_summary">Options for experts</string>
+
+ <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
+ <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
+ <!-- Option summary for including other IMEs in the language switch list [CHAR LIMIT=65] -->
+ <string name="include_other_imes_in_language_switch_list_summary">Language switch key covers other input methods too</string>
+ <!-- Option to suppress language switch key [CHAR LIMIT=30] -->
+ <string name="suppress_language_switch_key">Suppress language switch key</string>
<!-- Option for the dismiss delay of the key popup [CHAR LIMIT=25] -->
<string name="key_preview_popup_dismiss_delay">Key popup dismiss delay</string>
@@ -63,16 +85,18 @@
<!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] -->
<string name="use_contacts_dict_summary">Use names from Contacts for suggestions and corrections</string>
+ <!-- Option name for enabling insertion of suggestion spans (advanced option) [CHAR LIMIT=25] -->
+ <string name="enable_span_insert">Enable recorrections</string>
+ <!-- Option summary for enabling insertion of suggestion spans (advanced option) [CHAR LIMIT=65] -->
+ <string name="enable_span_insert_summary">Set suggestions for recorrections</string>
+
<!-- Option to enable auto capitalization of sentences -->
<string name="auto_cap">Auto-capitalization</string>
<!-- Option to configure dictionaries -->
- <string name="configure_dictionaries_title">Configure dictionaries</string>
-
- <!-- Option to enable quick fixes -->
- <string name="quick_fixes">Quick fixes</string>
- <!-- Description for quick fixes -->
- <string name="quick_fixes_summary">Corrects commonly typed mistakes</string>
+ <string name="configure_dictionaries_title">Add-on dictionaries</string>
+ <!-- Name of the main dictionary, as opposed to auxiliary dictionaries (medical/entertainment/sports...) -->
+ <string name="main_dictionary">Main dictionary</string>
<!-- Option to enable showing suggestions -->
<string name="prefs_show_suggestions">Show correction suggestions</string>
@@ -81,61 +105,58 @@
<string name="prefs_suggestion_visibility_show_name">Always show</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name">Show on portrait mode</string>
<string name="prefs_suggestion_visibility_hide_name">Always hide</string>
- <!-- Option to enable spacebar language switcher [CHAR LIMIT=20]-->
- <string name="prefs_use_spacebar_language_switch">Use the spacebar language switcher</string>
-
- <!-- Option to show/hide the settings key -->
- <string name="prefs_settings_key">Show settings key</string>
- <!-- Option to automatically decide to show/hide the settings key -->
- <string name="settings_key_mode_auto_name">Automatic</string>
- <!-- Option to always show the settings key -->
- <string name="settings_key_mode_always_show_name">Always show</string>
- <!-- Option to always hide the settings key -->
- <string name="settings_key_mode_always_hide_name">Always hide</string>
<!-- Option to decide the auto correction threshold score -->
<!-- Option to enable auto correction [CHAR LIMIT=20]-->
<string name="auto_correction">Auto correction</string>
- <!-- Description for auto correction [CHAR LIMIT=35] -->
+ <!-- Description for auto correction [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] -->
<string name="auto_correction_summary">Spacebar and punctuation automatically correct mistyped words</string>
<!-- Option to disable auto correction. [CHAR LIMIT=20] -->
<string name="auto_correction_threshold_mode_off">Off</string>
- <!-- Option to suggest auto correction candidates modestly. Auto-corrects only to a word which has small edit distance from typed word. [CHAR LIMIT=20] -->
+ <!-- Option to suggest auto correction suggestions modestly. Auto-corrects only to a word which has small edit distance from typed word. [CHAR LIMIT=20] -->
<string name="auto_correction_threshold_mode_modest">Modest</string>
- <!-- Option to suggest auto correction candidates aggressively. Auto-corrects to a word which has even large edit distance from typed word. [CHAR LIMIT=20] -->
+ <!-- Option to suggest auto correction suggestions aggressively. Auto-corrects to a word which has even large edit distance from typed word. [CHAR LIMIT=20] -->
<string name="auto_correction_threshold_mode_aggeressive">Aggressive</string>
- <!-- Option to suggest auto correction candidates very aggressively. Auto-corrects to a word which has even large edit distance from typed word. [CHAR LIMIT=20] -->
+ <!-- Option to suggest auto correction suggestions very aggressively. Auto-corrects to a word which has even large edit distance from typed word. [CHAR LIMIT=20] -->
<string name="auto_correction_threshold_mode_very_aggeressive">Very aggressive</string>
- <!-- Option to enable bigram correction -->
- <string name="bigram_suggestion">Bigram suggestions</string>
- <!-- Description for auto correction -->
- <string name="bigram_suggestion_summary">Use previous word to improve suggestion</string>
- <!-- Option to enable using user-history bigram when no input -->
- <string name="bigram_prediction">Bigram prediction</string>
- <!-- Description for auto correction -->
+ <!-- Option to enable next word correction -->
+ <string name="bigram_suggestion">Next word suggestions</string>
+ <!-- Option to enable next word suggestion. This uses the previous word in an attempt to improve the suggestions quality -->
+ <string name="bigram_suggestion_summary">Use previous word to improve suggestions</string>
+ <!-- Option to enable using next word prediction -->
+ <string name="bigram_prediction">Next word prediction</string>
+ <!-- Description for "next word prediction" option. This displays suggestions even when there is no input, based on the previous word. -->
<string name="bigram_prediction_summary">Use previous word also for prediction</string>
<!-- 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! -->
+ <!-- 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! -->
+ <!-- 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 DONE action. Must be short to fit on key! -->
+ <!-- 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! -->
+ <!-- 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 "switch to alphabetic" key. Must be short to fit on key! -->
+ <!-- Label for "switch to alphabetic" key. Must be short to fit on key! [CHAR LIMIT=3] -->
<string name="label_to_alpha_key">ABC</string>
- <!-- Label for Shift modifier key of symbol keyboard. Must be short to fit on key! -->
- <string name="label_more_key">More</string>
+ <!-- Label for "switch to symbols" key. Must be short to fit on key! [CHAR LIMIT=4] -->
+ <string name="label_to_symbol_key">\?123</string>
+ <!-- Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
+ part because it'll be appended by the code. Must be short to fit on key! [CHAR LIMIT=3] -->
+ <string name="label_to_symbol_with_microphone_key">123</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>
+
<!-- Spoken description for the currently entered text -->
<string name="spoken_current_text_is">Current text is "%s"</string>
<!-- Spoken description when there is no text entered -->
@@ -143,12 +164,12 @@
<!-- Spoken description for unknown keyboard keys. -->
<string name="spoken_description_unknown">Key code %d</string>
- <!-- Spoken description for the "Shift" keyboard key. -->
+ <!-- Spoken description for the "Shift" keyboard key when "Shift" is off. -->
<string name="spoken_description_shift">Shift</string>
- <!-- Spoken description for the "Shift" keyboard key's pressed state. -->
- <string name="spoken_description_shift_shifted">Shift enabled</string>
- <!-- Spoken description for the "Shift" keyboard key's pressed state. -->
- <string name="spoken_description_caps_lock">Caps lock enabled</string>
+ <!-- Spoken description for the "Shift" keyboard key when "Shift" is on. -->
+ <string name="spoken_description_shift_shifted">Shift on (tap to disable)</string>
+ <!-- Spoken description for the "Shift" keyboard key when "Caps lock" is on. -->
+ <string name="spoken_description_caps_lock">Caps lock on (tap to disable)</string>
<!-- Spoken description for the "Delete" keyboard key. -->
<string name="spoken_description_delete">Delete</string>
<!-- Spoken description for the "To Symbol" keyboard key. -->
@@ -169,119 +190,29 @@
<string name="spoken_description_smiley">Smiley face</string>
<!-- Spoken description for the "Return" keyboard key. -->
<string name="spoken_description_return">Return</string>
-
- <!-- Spoken description for the "," keyboard key. -->
- <string name="spoken_description_comma">Comma</string>
- <!-- Spoken description for the "." keyboard key. -->
- <string name="spoken_description_period">Period</string>
- <!-- Spoken description for the "(" keyboard key. -->
- <string name="spoken_description_left_parenthesis">Left parenthesis</string>
- <!-- Spoken description for the ")" keyboard key. -->
- <string name="spoken_description_right_parenthesis">Right parenthesis</string>
- <!-- Spoken description for the ":" keyboard key. -->
- <string name="spoken_description_colon">Colon</string>
- <!-- Spoken description for the ";" keyboard key. -->
- <string name="spoken_description_semicolon">Semicolon</string>
- <!-- Spoken description for the "!" keyboard key. -->
- <string name="spoken_description_exclamation_mark">Exclamation mark</string>
- <!-- Spoken description for the "?" keyboard key. -->
- <string name="spoken_description_question_mark">Question mark</string>
- <!-- Spoken description for the """ keyboard key. -->
- <string name="spoken_description_double_quote">Double quote</string>
- <!-- Spoken description for the "'" keyboard key. -->
- <string name="spoken_description_single_quote">Single quote</string>
- <!-- Spoken description for the "•" keyboard key. -->
+ <!-- Spoken description for the "Search" keyboard key. -->
+ <string name="spoken_description_search">Search</string>
+ <!-- Spoken description for the "U+2022" (BULLET) keyboard key. -->
<string name="spoken_description_dot">Dot</string>
- <!-- Spoken description for the "√" keyboard key. -->
- <string name="spoken_description_square_root">Square root</string>
- <!-- Spoken description for the "π" keyboard key. -->
- <string name="spoken_description_pi">Pi</string>
- <!-- Spoken description for the "Δ" keyboard key. -->
- <string name="spoken_description_delta">Delta</string>
- <!-- Spoken description for the "™" keyboard key. -->
- <string name="spoken_description_trademark">Trademark</string>
- <!-- Spoken description for the "℅" keyboard key. -->
- <string name="spoken_description_care_of">Care of</string>
- <!-- Spoken description for the "*" keyboard key. -->
- <string name="spoken_description_star">Star</string>
- <!-- Spoken description for the "#" keyboard key. -->
- <string name="spoken_description_pound">Pound</string>
- <!-- Spoken description for the "…" keyboard key. -->
- <string name="spoken_description_ellipsis">Ellipsis</string>
- <!-- Spoken description for the "„" keyboard key. -->
- <string name="spoken_description_low_double_quote">Low double quote</string>
-
- <!-- Voice related labels -->
-
- <!-- Title of the warning dialog that shows when a user initiates voice input for
- the first time. -->
- <string name="voice_warning_title">Voice input</string>
-
- <!-- Message that gets put at the top of the warning dialog if the user is attempting to use
- voice input in a currently unsupported locale. Voice input will work for such a user,
- but it will only recognize them in English. -->
- <string name="voice_warning_locale_not_supported">Voice input is not currently supported for your language, but does work in English.</string>
-
- <!-- Message of the warning dialog that shows when a user initiates voice input for
- the first time, or turns it on in settings. [CHAR LIMIT=200] -->
- <string name="voice_warning_may_not_understand">Voice input uses Google\'s speech recognition. <a href="http://m.google.com/privacy">The Mobile Privacy Policy</a> applies.</string>
-
- <!-- An additional part of the warning dialog for voice input that only shows when the user
- actually initiates voice input, rather than just turning it on in settings. [CHAR LIMIT=200] -->
- <string name="voice_warning_how_to_turn_off">To turn off voice input, go to input method settings.</string>
-
- <!-- Message to show when user enables the voice input settings (which says
- "Press the microphone button"). [CHAR LIMIT=100] -->
- <string name="voice_hint_dialog_message">To use voice input, press the microphone button.</string>
-
- <!-- Short message to tell the user the system is ready for them to speak. -->
- <string name="voice_listening">Speak now</string>
- <!-- Short message shown after the user finishes speaking. -->
- <string name="voice_working">Working</string>
-
- <!-- Short message shown before the user should speak. -->
- <string name="voice_initializing"></string>
-
- <!-- Short message shown when a generic error occurs. -->
- <string name="voice_error">Error. Please try again.</string>
-
- <!-- Short message shown for a network error. -->
- <string name="voice_network_error">Couldn\'t connect</string>
-
- <!-- Short message shown for a network error where the utterance was really long,
- in which case we should suggest that the user speak less. -->
- <string name="voice_too_much_speech">Error, too much speech.</string>
-
- <!-- Short message shown for an audio error. -->
- <string name="voice_audio_error">Audio problem</string>
-
- <!-- Short message shown for an error with the voice server. -->
- <string name="voice_server_error">Server error</string>
-
- <!-- Short message shown when no speech is heard. -->
- <string name="voice_speech_timeout">No speech heard</string>
-
- <!-- Short message shown when the server couldn't parse any speech. -->
- <string name="voice_no_match">No matches found</string>
-
- <!-- Short message shown when the user initiates voice and voice search is not installed. -->
- <string name="voice_not_installed">Voice search not installed</string>
-
- <!-- Short hint shown in candidate view to explain voice input. -->
- <string name="voice_swipe_hint"><b>Hint:</b> Swipe across keyboard to speak</string>
-
- <!-- Short hint shown in candidate view to explain that user can speak punctuation. -->
- <string name="voice_punctuation_hint"><b>Hint:</b> Next time, try speaking punctuation like \"period\", \"comma\", or \"question mark\".</string>
-
- <!-- Label on button to stop recognition. Must be short to fit on button. -->
- <string name="cancel">Cancel</string>
-
- <!-- Label on button when an error occurs -->
- <string name="ok">OK</string>
+ <!-- Spoken feedback after turning "Shift" mode on. -->
+ <string name="spoken_description_shiftmode_on">Shift enabled</string>
+ <!-- Spoken feedback after turning "Caps lock" mode on. -->
+ <string name="spoken_description_shiftmode_locked">Caps lock enabled</string>
+ <!-- Spoken feedback after turning "Shift" mode off. -->
+ <string name="spoken_description_shiftmode_off">Shift disabled</string>
+
+ <!-- Spoken feedback after changing to the symbols keyboard. -->
+ <string name="spoken_description_mode_symbol">Symbols mode</string>
+ <!-- Spoken feedback after changing to the alphanumeric keyboard. -->
+ <string name="spoken_description_mode_alpha">Letters mode</string>
+ <!-- Spoken feedback after changing to the phone dialer keyboard. -->
+ <string name="spoken_description_mode_phone">Phone mode</string>
+ <!-- Spoken feedback after changing to the shifted phone dialer (symbols) keyboard. -->
+ <string name="spoken_description_mode_phone_shift">Phone symbols mode</string>
<!-- Preferences item for enabling speech input -->
- <string name="voice_input">Voice input</string>
+ <string name="voice_input">Voice input key</string>
<!-- Voice Input modes -->
<!-- On settings screen, voice input pop-up menu option to show voice key on main keyboard [CHAR LIMIT=20] -->
@@ -298,16 +229,31 @@
<!-- On settings screen, voice input pop-up menu summary text to never show voice key [CHAR LIMIT=20] -->
<string name="voice_input_modes_summary_off">Voice input is disabled</string>
- <!-- Title of the dialog for selecting input methods. [CHAR LIMIT=20] -->
- <string name="selectInputMethod">Select input method</string>
+ <!-- Title for configuring input method settings [CHAR LIMIT=35] -->
+ <string name="configure_input_method">Configure input methods</string>
<!-- Title for input language selection screen -->
<string name="language_selection_title">Input languages</string>
- <!-- Title summary for input language selection screen -->
- <string name="language_selection_summary">Slide finger on spacebar to change language</string>
+
+ <!-- Title for dialog option that lets user mark a particular time in the log for later review by experts [CHAR LIMIT=38] -->
+ <string name="note_timestamp_for_researchlog">Note timestamp in log</string>
+ <!-- Toast notification message that the time has been marked for later review. [CHAR LIMIT=25] -->
+ <string name="notify_recorded_timestamp">Recorded timestamp</string>
+
+ <!-- Title for dialog option to let users cancel logging and delete log for this session [CHAR LIMIT=35] -->
+ <string name="do_not_log_this_session">Do not log this session</string>
+ <!-- Toast notification that the system is processing the request to delete the log for this session [CHAR LIMIT=35] -->
+ <string name="notify_session_log_deleting">Deleting session log</string>
+ <!-- Toast notification that the system has successfully deleted the log for this session [CHAR LIMIT=35] -->
+ <string name="notify_session_log_deleted">Session log deleted</string>
+ <!-- Toast notification that the system has failed to delete the log for this session [CHAR LIMIT=35] -->
+ <string name="notify_session_log_not_deleted">Session log NOT deleted</string>
+
+ <!-- Preference for input language selection -->
+ <string name="select_language">Input languages</string>
<!-- Add to dictionary hint -->
- <string name="hint_add_to_dictionary">\u2190 Touch again to save</string>
+ <string name="hint_add_to_dictionary">Touch again to save</string>
<!-- Inform the user that a particular language has an available dictionary -->
<string name="has_dictionary">Dictionary available</string>
@@ -316,98 +262,62 @@
<string name="prefs_enable_log">Enable user feedback</string>
<!-- Description for enabling to send user statistics to Google -->
<string name="prefs_description_log">Help improve this input method editor by automatically sending usage statistics and crash reports to Google.</string>
- <!-- Preferences item for enabling to correct suggestions by touching words you have typed [CHAR LIMIT= 35] -->
- <string name="prefs_enable_recorrection">Touch to correct words</string>
- <!-- The summary for the preferences item for enabling to correct suggestions by touching words you have typed [CHAR LIMIT= 100] -->
- <string name="prefs_enable_recorrection_summary">Touch entered words to correct them, only when suggestions are visible</string>
<!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
<string name="keyboard_layout">Keyboard theme</string>
- <!-- Description for Czech keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_cs_keyboard">Czech Keyboard</string>
- <!-- Description for Arabic keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_ar_keyboard">Arabic Keyboard</string>
- <!-- Description for Danish keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_da_keyboard">Danish Keyboard</string>
- <!-- Description for German keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_de_keyboard">German Keyboard</string>
- <!-- Description for German QWERTY keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_de_qwerty_keyboard">German QWERTY Keyboard</string>
- <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_en_GB_keyboard">English (UK) Keyboard</string>
- <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_en_US_keyboard">English (US) Keyboard</string>
- <!-- Description for Spanish keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_es_keyboard">Spanish Keyboard</string>
- <!-- Description for Finnish keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_fi_keyboard">Finnish Keyboard</string>
- <!-- Description for French keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_fr_keyboard">French Keyboard</string>
- <!-- Description for French (Canada) keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_fr_CA_keyboard">French (Canada) Keyboard</string>
- <!-- Description for French (Switzerland) keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_fr_CH_keyboard">French (Switzerland) Keyboard</string>
- <!-- Description for Croatian keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_hr_keyboard">Croatian Keyboard</string>
- <!-- Description for Hungarian keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_hu_keyboard">Hungarian Keyboard</string>
- <!-- Description for Hebrew keyboard subtype [CHAR LIMIT=35] -->
- <!-- Java uses the deprecated "iw" code instead of the standard "he" code -->
- <string name="subtype_mode_iw_keyboard">Hebrew Keyboard</string>
- <!-- Description for Italian keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_it_keyboard">Italian Keyboard</string>
- <!-- Description for Norwegian keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_nb_keyboard">Norwegian Keyboard</string>
- <!-- Description for Dutch keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_nl_keyboard">Dutch Keyboard</string>
- <!-- Description for Polish keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_pl_keyboard">Polish Keyboard</string>
- <!-- Description for Portuguese keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_pt_keyboard">Portuguese Keyboard</string>
- <!-- Description for Russian keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_ru_keyboard">Russian Keyboard</string>
- <!-- Description for Serbian keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_sr_keyboard">Serbian Keyboard</string>
- <!-- Description for Swedish keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_sv_keyboard">Swedish Keyboard</string>
- <!-- Description for Turkish keyboard subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_tr_keyboard">Turkish Keyboard</string>
- <!-- Description for Afrikaans voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_af_voice">Afrikaans Voice</string>
- <!-- Description for Czech voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_cs_voice">Czech Voice</string>
- <!-- Description for German voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_de_voice">German Voice</string>
- <!-- Description for English voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_en_voice">English Voice</string>
- <!-- Description for Spanish voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_es_voice">Spanish Voice</string>
- <!-- Description for French voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_fr_voice">French Voice</string>
- <!-- Description for Italian voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_it_voice">Italian Voice</string>
- <!-- Description for Japanese voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_ja_voice">Japanese Voice</string>
- <!-- Description for Korean voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_ko_voice">Korean Voice</string>
- <!-- Description for Dutch voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_nl_voice">Dutch Voice</string>
- <!-- Description for Polish voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_pl_voice">Polish Voice</string>
- <!-- Description for Portuguese voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_pt_voice">Portuguese Voice</string>
- <!-- Description for Russian voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_ru_voice">Russian Voice</string>
- <!-- Description for Turkish voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_tr_voice">Turkish Voice</string>
- <!-- Description for Chinese, Yue voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_yue_voice">Chinese, Yue Voice</string>
- <!-- Description for Chinese, Mandarin voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_zh_voice">Chinese, Mandarin Voice</string>
- <!-- Description for isiZulu voice input subtype [CHAR LIMIT=35] -->
- <string name="subtype_mode_zu_voice">isiZulu Voice</string>
+ <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_en_GB">English (UK)</string>
+ <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_en_US">English (US)</string>
+ <!-- Description for English (United Kingdom) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+ This should be identical to subtype_en_GB aside from the trailing (%s). -->
+ <string name="subtype_with_layout_en_GB">English (UK) (<xliff:g id="layout">%s</xliff:g>)</string>
+ <!-- Description for English (United States) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+ This should be identical to subtype_en_US aside from the trailing (%s). -->
+ <string name="subtype_with_layout_en_US">English (US) (<xliff:g id="layout">%s</xliff:g>)</string>
+ <!-- Description for language agnostic keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language">No language</string>
+ <!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language_qwerty">No language (QWERTY)</string>
+ <!-- Description for language agnostic QWERTZ keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language_qwertz">No language (QWERTZ)</string>
+ <!-- Description for language agnostic AZERTY keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language_azerty">No language (AZERTY)</string>
+ <!-- Description for language agnostic Dvorak keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language_dvorak">No language (Dvorak)</string>
+ <!-- Description for language agnostic Colemak keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language_colemak">No language (Colemak)</string>
+ <!-- Description for language agnostic PC QWERTY keyboard subtype [CHAR LIMIT=25] -->
+ <string name="subtype_no_language_pcqwerty">No language (PC)</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] -->
+ <string name="add_style">Add style</string>
+ <!-- Title of the button to add custom style entry in the settings dialog [CHAR LIMIT=15] -->
+ <string name="add">Add</string>
+ <!-- Title of the button to remove a custom style entry in the settings dialog [CHAR LIMIT=15] -->
+ <string name="remove">Remove</string>
+ <!-- Title of the button to save a custom style entry in the settings dialog [CHAR LIMIT=15] -->
+ <string name="save">Save</string>
+ <!-- Title of the spinner for choosing a language of custom style in the settings dialog [CHAR LIMIT=15] -->
+ <string name="subtype_locale">Language</string>
+ <!-- Title of the spinner for choosing a keyboard layout of custom style in the settings dialog [CHAR LIMIT=15] -->
+ <string name="keyboard_layout_set">Layout</string>
+ <!-- The message of the dialog to note that a custom input style needs to be enabled. [CHAR LIMIT=64] -->
+ <string name="custom_input_style_note_message">"Your custom input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
+ <!-- Title of the button to enable a custom input style entry in the settings dialog [CHAR LIMIT=15] -->
+ <string name="enable">Enable</string>
+ <!-- Title of the button to postpone enabling a custom input style entry in the settings dialog [CHAR LIMIT=15] -->
+ <string name="not_now">Not now</string>
+ <!-- Toast text to describe the same input style already exists [CHAR LIMIT=64]-->
+ <string name="custom_input_style_already_exists">"The same input style already exists: <xliff:g id="input_style_name">%s</xliff:g>"</string>
<!-- Title of an option for usability study mode -->
<string name="prefs_usability_study_mode">Usability study mode</string>
+ <!-- Title of the settings for keypress vibration duration -->
+ <string name="prefs_keypress_vibration_duration_settings">Keypress vibration duration settings</string>
+ <!-- Title of the settings for keypress sound volume -->
+ <string name="prefs_keypress_sound_volume_settings">Keypress sound volume settings</string>
</resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 07a7f3c86..e9b0470ea 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -17,21 +17,20 @@
<resources>
<!-- Theme "Basic" -->
<style name="Keyboard">
+ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
+ <item name="themeId">0</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_empty</item>
<item name="rowHeight">25%p</item>
<item name="keyboardHeight">@dimen/keyboardHeight</item>
<item name="maxKeyboardHeight">@fraction/maxKeyboardHeight</item>
<item name="minKeyboardHeight">@fraction/minKeyboardHeight</item>
- <item name="popupKeyboardTemplate">@xml/kbd_popup_template</item>
- <item name="keyboardTopPadding">@dimen/keyboard_top_padding</item>
- <item name="keyboardBottomPadding">@dimen/keyboard_bottom_padding</item>
- <item name="horizontalGap">@dimen/key_horizontal_gap</item>
- <item name="verticalGap">@dimen/key_bottom_gap</item>
- <item name="maxPopupKeyboardColumn">@integer/config_max_popup_keyboard_column</item>
- </style>
- <style name="LatinKeyboard">
- <item name="autoCorrectionSpacebarLedEnabled">@bool/config_auto_correction_spacebar_led_enabled</item>
- <item name="spacebarTextColor">#FFC0C0C0</item>
- <item name="spacebarTextShadowColor">#80000000</item>
+ <item name="moreKeysTemplate">@xml/kbd_more_keys_keyboard_template</item>
+ <item name="keyboardTopPadding">@fraction/keyboard_top_padding</item>
+ <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding</item>
+ <item name="keyboardHorizontalEdgesPadding">@fraction/keyboard_horizontal_edges_padding</item>
+ <item name="horizontalGap">@fraction/key_horizontal_gap</item>
+ <item name="verticalGap">@fraction/key_bottom_gap</item>
+ <item name="maxMoreKeysColumn">@integer/config_max_more_keys_column</item>
</style>
<style name="KeyboardView">
<item name="android:background">@drawable/keyboard_background</item>
@@ -39,155 +38,349 @@
<item name="keyLetterRatio">@fraction/key_letter_ratio</item>
<item name="keyLargeLetterRatio">@fraction/key_large_letter_ratio</item>
<item name="keyLabelRatio">@fraction/key_label_ratio</item>
+ <item name="keyLargeLabelRatio">@fraction/key_large_label_ratio</item>
<item name="keyHintLetterRatio">@fraction/key_hint_letter_ratio</item>
<item name="keyHintLabelRatio">@fraction/key_hint_label_ratio</item>
- <item name="keyUppercaseLetterRatio">@fraction/key_uppercase_letter_ratio</item>
+ <item name="keyShiftedLetterHintRatio">@fraction/key_uppercase_letter_ratio</item>
<item name="keyTextStyle">normal</item>
<item name="keyTextColor">#FFFFFFFF</item>
<item name="keyTextInactivatedColor">#FFFFFFFF</item>
<item name="keyHintLetterColor">#80000000</item>
<item name="keyHintLabelColor">#E0E0E4E5</item>
- <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item>
- <item name="keyUppercaseLetterActivatedColor">#CCE0E4E5</item>
- <item name="keyPopupHintIcon">@drawable/hint_popup</item>
+ <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item>
+ <item name="keyShiftedLetterHintActivatedColor">#CCE0E4E5</item>
+ <item name="keyLabelHorizontalPadding">@dimen/key_label_horizontal_padding</item>
+ <item name="keyHintLetterPadding">@dimen/key_hint_letter_padding</item>
+ <item name="keyPopupHintLetterPadding">@dimen/key_popup_hint_letter_padding</item>
+ <item name="keyShiftedLetterHintPadding">@dimen/key_uppercase_letter_padding</item>
<item name="keyPreviewLayout">@layout/key_preview</item>
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback</item>
- <item name="keyPreviewSpacebarBackground">@drawable/keyboard_key_feedback</item>
+ <item name="keyPreviewLeftBackground">@null</item>
+ <item name="keyPreviewRightBackground">@null</item>
<item name="keyPreviewTextColor">#FFFFFFFF</item>
<item name="keyPreviewOffset">@dimen/key_preview_offset</item>
<item name="keyPreviewHeight">@dimen/key_preview_height</item>
<item name="keyPreviewTextRatio">@fraction/key_preview_text_ratio</item>
- <item name="popupLayout">@layout/keyboard_popup</item>
- <item name="keyHysteresisDistance">@dimen/key_hysteresis_distance</item>
+ <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
+ <item name="moreKeysLayout">@layout/more_keys_keyboard</item>
<item name="verticalCorrection">@dimen/keyboard_vertical_correction</item>
<item name="shadowColor">#BB000000</item>
<item name="shadowRadius">2.75</item>
- <item name="backgroundDimAmount">0.5</item>
+ <item name="backgroundDimAlpha">128</item>
+ <!-- Common attributes of LatinKeyboardView -->
+ <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item>
+ <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>
+ <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item>
+ <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item>
+ <item name="keyRepeatStartTimeout">@integer/config_key_repeat_start_timeout</item>
+ <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
+ <item name="longPressKeyTimeout">@integer/config_long_press_key_timeout</item>
+ <item name="longPressShiftKeyTimeout">@integer/config_long_press_shift_key_timeout</item>
+ <item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item>
+ <item name="showMoreKeysKeyboardAtTouchedPoint">@bool/config_show_more_keys_keyboard_at_touched_point</item>
+ <item name="languageOnSpacebarFinalAlpha">@integer/config_language_on_spacebar_final_alpha</item>
+ <item name="languageOnSpacebarFadeoutAnimator">@anim/language_on_spacebar_fadeout</item>
+ <item name="altCodeKeyWhileTypingFadeoutAnimator">@anim/alt_code_key_while_typing_fadeout</item>
+ <item name="altCodeKeyWhileTypingFadeinAnimator">@anim/alt_code_key_while_typing_fadein</item>
+ </style>
+ <style
+ name="LatinKeyboardView"
+ parent="KeyboardView">
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
+ <style
+ name="MoreKeysKeyboard"
+ parent="Keyboard"
+ >
+ <item name="keyboardTopPadding">0dp</item>
+ <item name="keyboardBottomPadding">0dp</item>
+ <item name="horizontalGap">0dp</item>
</style>
- <style name="PopupMiniKeyboardView" parent="KeyboardView">
+ <style
+ name="MoreKeysKeyboardView"
+ parent="KeyboardView"
+ >
<item name="keyBackground">@drawable/btn_keyboard_key_popup</item>
- <item name="keyHysteresisDistance">0dip</item>
- <item name="verticalCorrection">@dimen/mini_keyboard_vertical_correction</item>
+ <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction</item>
</style>
- <style name="PopupMiniKeyboardPanelStyle">
+ <style name="MoreKeysKeyboardPanelStyle">
<item name="android:background">@drawable/keyboard_popup_panel_background</item>
- <item name="android:paddingLeft">@dimen/mini_keyboard_horizontal_padding</item>
- <item name="android:paddingRight">@dimen/mini_keyboard_horizontal_padding</item>
</style>
<style name="SuggestionsStripBackgroundStyle">
<item name="android:background">@drawable/keyboard_suggest_strip</item>
</style>
+ <style
+ name="SuggestionsViewStyle"
+ parent="SuggestionsStripBackgroundStyle"
+ >
+ <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item>
+ <item name="colorValidTypedWord">#FFFCAE00</item>
+ <item name="colorTypedWord">@android:color/white</item>
+ <item name="colorAutoCorrect">#FFFCAE00</item>
+ <item name="colorSuggested">#FFFCAE00</item>
+ <item name="alphaObsoleted">50</item>
+ <item name="suggestionsCountInStrip">@integer/suggestions_count_in_strip</item>
+ <item name="centerSuggestionPercentile">@integer/center_suggestion_percentile</item>
+ <item name="maxMoreSuggestionsRow">@integer/max_more_suggestions_row</item>
+ <item name="minMoreSuggestionsWidth">@fraction/min_more_suggestions_width</item>
+ </style>
+ <style
+ name="MoreSuggestionsViewStyle"
+ parent="MoreKeysKeyboardView"
+ >
+ </style>
<style name="SuggestionBackgroundStyle">
- <item name="android:background">@drawable/btn_candidate</item>
+ <item name="android:background">@drawable/btn_suggestion</item>
</style>
<style name="SuggestionPreviewBackgroundStyle">
- <item name="android:background">@drawable/candidate_feedback_background</item>
- </style>
- <style name="CandidateViewStyle" parent="SuggestionsStripBackgroundStyle">
- <item name="autoCorrectHighlight">autoCorrectBold</item>
- <item name="colorTypedWord">#FFFFFFFF</item>
- <item name="colorAutoCorrect">#FFFCAE00</item>
- <item name="colorSuggested">#FFFCAE00</item>
- <item name="iconExpandPane">@drawable/btn_expand_candidates_pane</item>
- <item name="iconClosePane">@drawable/btn_close_candidates_pane</item>"
+ <item name="android:background">@drawable/suggestion_feedback_background</item>
</style>
<!-- Theme "Basic high contrast" -->
- <style name="KeyboardView.HighContrast" parent="KeyboardView">
+ <style
+ name="Keyboard.HighContrast"
+ parent="Keyboard"
+ >
+ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
+ <item name="themeId">1</item>
+ </style>
+ <style
+ name="KeyboardView.HighContrast"
+ parent="KeyboardView"
+ >
<item name="android:background">@android:color/black</item>
<item name="keyBackground">@drawable/btn_keyboard_key3</item>
</style>
- <!-- Theme "Stone" -->
- <style name="Keyboard.Stone" parent="Keyboard">
- <item name="horizontalGap">@dimen/key_horizontal_gap</item>
- <item name="verticalGap">@dimen/key_bottom_gap</item>
+ <style
+ name="LatinKeyboardView.HighContrast"
+ parent="KeyboardView.HighContrast"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
</style>
- <style name="LatinKeyboard.Stone" parent="LatinKeyboard">
- <item name="spacebarTextColor">#FF000000</item>
- <item name="spacebarTextShadowColor">#D0FFFFFF</item>
+ <!-- Theme "Stone" -->
+ <style
+ name="Keyboard.Stone"
+ parent="Keyboard"
+ >
+ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
+ <item name="themeId">6</item>
+ <item name="keyboardTopPadding">@fraction/keyboard_top_padding_stone</item>
+ <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_stone</item>
+ <item name="horizontalGap">@fraction/key_horizontal_gap_stone</item>
+ <item name="verticalGap">@fraction/key_bottom_gap_stone</item>
</style>
- <style name="KeyboardView.Stone" parent="KeyboardView">
+ <style
+ name="KeyboardView.Stone"
+ parent="KeyboardView"
+ >
<item name="keyBackground">@drawable/btn_keyboard_key_stone</item>
<item name="keyTextColor">#FF000000</item>
<item name="keyTextInactivatedColor">#FF808080</item>
<item name="keyHintLetterColor">#80000000</item>
<item name="keyHintLabelColor">#E0000000</item>
- <item name="keyUppercaseLetterInactivatedColor">#66000000</item>
- <item name="keyUppercaseLetterActivatedColor">#CC000000</item>
+ <item name="keyShiftedLetterHintInactivatedColor">#66000000</item>
+ <item name="keyShiftedLetterHintActivatedColor">#CC000000</item>
<item name="shadowColor">#FFFFFFFF</item>
</style>
- <style name="PopupMiniKeyboardView.Stone" parent="PopupMiniKeyboardView">
+ <style
+ name="LatinKeyboardView.Stone"
+ parent="KeyboardView.Stone"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FF000000</item>
+ <item name="spacebarTextShadowColor">#D0FFFFFF</item>
+ </style>
+ <style
+ name="MoreKeysKeyboard.Stone"
+ parent="Keyboard.Stone"
+ >
+ <item name="keyboardTopPadding">0dp</item>
+ <item name="keyboardBottomPadding">0dp</item>
+ <item name="horizontalGap">0dp</item>
+ </style>
+ <style
+ name="MoreKeysKeyboardView.Stone"
+ parent="MoreKeysKeyboardView"
+ >
<item name="keyBackground">@drawable/btn_keyboard_key_stone</item>
<item name="keyTextColor">#FF000000</item>
<item name="shadowColor">#FFFFFFFF</item>
</style>
<!-- Theme "Stone bold" -->
- <style name="KeyboardView.Stone.Bold" parent="KeyboardView.Stone">
+ <style
+ name="Keyboard.Stone.Bold"
+ parent="Keyboard.Stone"
+ >
+ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
+ <item name="themeId">7</item>
+ </style>
+ <style
+ name="KeyboardView.Stone.Bold"
+ parent="KeyboardView.Stone"
+ >
<item name="keyTextStyle">bold</item>
</style>
+ <style
+ name="LatinKeyboardView.Stone.Bold"
+ parent="KeyboardView.Stone.Bold"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FF000000</item>
+ <item name="spacebarTextShadowColor">#D0FFFFFF</item>
+ </style>
<!-- Theme "Gingerbread" -->
- <style name="KeyboardView.Gingerbread" parent="KeyboardView">
+ <style
+ name="Keyboard.Gingerbread"
+ parent="Keyboard"
+ >
+ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
+ <item name="themeId">8</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_gingerbread</item>
+ <item name="horizontalGap">@fraction/key_horizontal_gap_gb</item>
+ <item name="verticalGap">@fraction/key_bottom_gap_gb</item>
+ </style>
+ <style
+ name="KeyboardView.Gingerbread"
+ parent="KeyboardView"
+ >
<item name="android:background">@drawable/keyboard_dark_background</item>
<item name="keyBackground">@drawable/btn_keyboard_key_gingerbread</item>
<item name="keyTextStyle">bold</item>
</style>
- <style name="PopupMiniKeyboardView.Gingerbread" parent="PopupMiniKeyboardView">
+ <style
+ name="LatinKeyboardView.Gingerbread"
+ parent="KeyboardView.Gingerbread"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">true</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
+ <style
+ name="MoreKeysKeyboard.Gingerbread"
+ parent="Keyboard.Gingerbread"
+ >
+ <item name="keyboardTopPadding">0dp</item>
+ <item name="keyboardBottomPadding">0dp</item>
+ <item name="horizontalGap">0dp</item>
+ </style>
+ <style
+ name="MoreKeysKeyboardView.Gingerbread"
+ parent="MoreKeysKeyboardView"
+ >
<item name="android:background">@null</item>
</style>
<!-- Theme "IceCreamSandwich" -->
- <style name="Keyboard.IceCreamSandwich" parent="Keyboard" >
- <item name="keyboardTopPadding">@dimen/keyboard_top_padding_ics</item>
- <item name="keyboardBottomPadding">@dimen/keyboard_bottom_padding_ics</item>
- <item name="horizontalGap">@dimen/key_horizontal_gap_ics</item>
- <item name="verticalGap">@dimen/key_bottom_gap_ics</item>
- </style>
- <style name="LatinKeyboard.IceCreamSandwich" parent="LatinKeyboard">
- <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item>
+ <style
+ name="Keyboard.IceCreamSandwich"
+ parent="Keyboard"
+ >
+ <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] -->
+ <item name="themeId">5</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_ice_cream_sandwich</item>
</style>
- <style name="KeyboardView.IceCreamSandwich" parent="KeyboardView">
+ <style
+ name="KeyboardView.IceCreamSandwich"
+ parent="KeyboardView"
+ >
<item name="android:background">@drawable/keyboard_background_holo</item>
<item name="keyBackground">@drawable/btn_keyboard_key_ics</item>
<item name="keyTextStyle">bold</item>
<item name="keyTextInactivatedColor">#66E0E4E5</item>
<item name="keyHintLetterColor">#80000000</item>
<item name="keyHintLabelColor">#A0FFFFFF</item>
- <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item>
- <item name="keyUppercaseLetterActivatedColor">#FFFFFFFF</item>
+ <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item>
+ <item name="keyShiftedLetterHintActivatedColor">#FFFFFFFF</item>
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
- <item name="keyPreviewSpacebarBackground">@drawable/transparent</item>
+ <item name="keyPreviewLeftBackground">@drawable/keyboard_key_feedback_left_ics</item>
+ <item name="keyPreviewRightBackground">@drawable/keyboard_key_feedback_right_ics</item>
<item name="keyPreviewTextColor">#FFFFFFFF</item>
- <item name="keyPreviewHeight">@dimen/key_preview_height_ics</item>
<item name="keyPreviewOffset">@dimen/key_preview_offset_ics</item>
<item name="shadowColor">#00000000</item>
<item name="shadowRadius">0.0</item>
</style>
- <style name="PopupMiniKeyboardView.IceCreamSandwich" parent="PopupMiniKeyboardView">
+ <style
+ name="LatinKeyboardView.IceCreamSandwich"
+ parent="KeyboardView.IceCreamSandwich"
+ >
+ <item name="autoCorrectionSpacebarLedEnabled">false</item>
+ <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item>
+ <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
+ <item name="spacebarTextColor">#FFC0C0C0</item>
+ <item name="spacebarTextShadowColor">#80000000</item>
+ </style>
+ <style
+ name="MoreKeysKeyboard.IceCreamSandwich"
+ parent="Keyboard.IceCreamSandwich"
+ >
+ <item name="keyboardTopPadding">0dp</item>
+ <item name="keyboardBottomPadding">0dp</item>
+ <item name="horizontalGap">0dp</item>
+ </style>
+ <style
+ name="MoreKeysKeyboardView.IceCreamSandwich"
+ parent="MoreKeysKeyboardView"
+ >
<item name="android:background">@null</item>
<item name="keyBackground">@drawable/btn_keyboard_key_popup_ics</item>
+ <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_ics</item>
</style>
- <style name="PopupMiniKeyboardPanelStyle.IceCreamSandwich">
+ <style name="MoreKeysKeyboardPanelStyle.IceCreamSandwich">
<item name="android:background">@drawable/keyboard_popup_panel_background_holo</item>
- <item name="android:paddingLeft">@dimen/mini_keyboard_horizontal_padding_ics</item>
- <item name="android:paddingRight">@dimen/mini_keyboard_horizontal_padding_ics</item>
</style>
<style name="SuggestionsStripBackgroundStyle.IceCreamSandwich">
<item name="android:background">@drawable/keyboard_suggest_strip_holo</item>
</style>
+ <style
+ name="SuggestionsViewStyle.IceCreamSandwich"
+ parent="SuggestionsStripBackgroundStyle.IceCreamSandwich"
+ >
+ <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item>
+ <!-- android:color/holo_blue_light=#FF33B5E5 -->
+ <item name="colorValidTypedWord">@android:color/holo_blue_light</item>
+ <item name="colorTypedWord">@android:color/holo_blue_light</item>
+ <item name="colorAutoCorrect">@android:color/holo_blue_light</item>
+ <item name="colorSuggested">@android:color/holo_blue_light</item>
+ <item name="alphaValidTypedWord">85</item>
+ <item name="alphaTypedWord">85</item>
+ <item name="alphaSuggested">70</item>
+ <item name="alphaObsoleted">70</item>
+ <item name="suggestionsCountInStrip">@integer/suggestions_count_in_strip</item>
+ <item name="centerSuggestionPercentile">@integer/center_suggestion_percentile</item>
+ <item name="maxMoreSuggestionsRow">@integer/max_more_suggestions_row</item>
+ <item name="minMoreSuggestionsWidth">@fraction/min_more_suggestions_width</item>
+ </style>
+ <style
+ name="MoreSuggestionsViewStyle.IceCreamSandwich"
+ parent="MoreKeysKeyboardView.IceCreamSandwich"
+ >
+ </style>
<style name="SuggestionBackgroundStyle.IceCreamSandwich">
- <item name="android:background">@drawable/btn_candidate_ics</item>
+ <item name="android:background">@drawable/btn_suggestion_ics</item>
</style>
- <style name="SuggestionPreviewBackgroundStyle.IceCreamSandwich">
- <item name="android:background">@drawable/keyboard_popup_panel_background_holo</item>
+ <style
+ name="SuggestionPreviewBackgroundStyle.IceCreamSandwich"
+ parent="MoreKeysKeyboardPanelStyle.IceCreamSandwich"
+ >
</style>
- <style name="CandidateViewStyle.IceCreamSandwich" parent="SuggestionsStripBackgroundStyle.IceCreamSandwich">
- <item name="autoCorrectHighlight">autoCorrectUnderline|autoCorrectInvert</item>
- <item name="colorTypedWord">#FFFFFFFF</item>
- <item name="colorAutoCorrect">#FFFFFFFF</item>
- <item name="colorSuggested">#FFFFFFFF</item>
- <item name="iconExpandPane">@drawable/btn_expand_candidates_pane</item>
- <item name="iconClosePane">@drawable/btn_close_candidates_pane</item>"
- </style>
- <style name="PopupMiniKeyboardAnimation">
- <item name="android:windowEnterAnimation">@anim/mini_keyboard_fadein</item>
- <item name="android:windowExitAnimation">@anim/mini_keyboard_fadeout</item>
+ <style name="MoreKeysKeyboardAnimation">
+ <item name="android:windowEnterAnimation">@anim/more_keys_keyboard_fadein</item>
+ <item name="android:windowExitAnimation">@anim/more_keys_keyboard_fadeout</item>
</style>
</resources>
diff --git a/java/res/values-hr/donottranslate-altchars.xml b/java/res/values/sudden-jumping-touch-event-device-list.xml
index d0c9d4049..543992a81 100644
--- a/java/res/values-hr/donottranslate-altchars.xml
+++ b/java/res/values/sudden-jumping-touch-event-device-list.xml
@@ -17,11 +17,11 @@
** limitations under the License.
*/
-->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="alternates_for_s">š,ś,ß</string>
- <string name="alternates_for_n">ñ,ń</string>
- <string name="alternates_for_y"></string>
- <string name="alternates_for_z">6,ž,ź,ż</string>
- <string name="alternates_for_c">č,ć,ç</string>
- <string name="alternates_for_d">đ</string>
+<resources>
+ <string-array name="sudden_jumping_touch_event_device_list" translatable="false">
+ <!-- "Build.HARDWARE,true" that needs "sudden jump touch event" hack.
+ See {@link com.android.inputmethod.keyboard.SuddenJumpingTouchEventHandler}. -->
+ <item>mahimahi,true</item> <!-- Nexus One -->
+ <item>sholes,true</item> <!-- Droid -->
+ </string-array>
</resources>
diff --git a/java/res/values/themes-basic-highcontrast.xml b/java/res/values/themes-basic-highcontrast.xml
index 820f96216..19df42ce1 100644
--- a/java/res/values/themes-basic-highcontrast.xml
+++ b/java/res/values/themes-basic-highcontrast.xml
@@ -16,14 +16,16 @@
<resources>
<style name="KeyboardTheme.HighContrast" parent="KeyboardIcons">
- <item name="keyboardStyle">@style/Keyboard</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard</item>
+ <item name="keyboardStyle">@style/Keyboard.HighContrast</item>
<item name="keyboardViewStyle">@style/KeyboardView.HighContrast</item>
- <item name="popupMiniKeyboardViewStyle">@style/PopupMiniKeyboardView</item>
- <item name="popupMiniKeyboardPanelStyle">@style/PopupMiniKeyboardPanelStyle</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.HighContrast</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView</item>
+ <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item>
<item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item>
+ <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item>
+ <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
- <item name="candidateViewStyle">@style/CandidateViewStyle</item>
</style>
</resources>
diff --git a/java/res/values/themes-basic.xml b/java/res/values/themes-basic.xml
index 18cae4e24..5d477206d 100644
--- a/java/res/values/themes-basic.xml
+++ b/java/res/values/themes-basic.xml
@@ -17,13 +17,15 @@
<resources>
<style name="KeyboardTheme" parent="KeyboardIcons">
<item name="keyboardStyle">@style/Keyboard</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard</item>
<item name="keyboardViewStyle">@style/KeyboardView</item>
- <item name="popupMiniKeyboardViewStyle">@style/PopupMiniKeyboardView</item>
- <item name="popupMiniKeyboardPanelStyle">@style/PopupMiniKeyboardPanelStyle</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView</item>
+ <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item>
<item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item>
+ <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item>
+ <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
- <item name="candidateViewStyle">@style/CandidateViewStyle</item>
</style>
</resources>
diff --git a/java/res/values/themes-gingerbread.xml b/java/res/values/themes-gingerbread.xml
index 091baa737..a13979818 100644
--- a/java/res/values/themes-gingerbread.xml
+++ b/java/res/values/themes-gingerbread.xml
@@ -16,14 +16,16 @@
<resources>
<style name="KeyboardTheme.Gingerbread" parent="KeyboardIcons">
- <item name="keyboardStyle">@style/Keyboard</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard</item>
+ <item name="keyboardStyle">@style/Keyboard.Gingerbread</item>
<item name="keyboardViewStyle">@style/KeyboardView.Gingerbread</item>
- <item name="popupMiniKeyboardViewStyle">@style/PopupMiniKeyboardView.Gingerbread</item>
- <item name="popupMiniKeyboardPanelStyle">@style/PopupMiniKeyboardPanelStyle</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Gingerbread</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.Gingerbread</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.Gingerbread</item>
+ <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item>
<item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item>
+ <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item>
+ <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
- <item name="candidateViewStyle">@style/CandidateViewStyle</item>
</style>
</resources>
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 97c594408..e6fd4f451 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -17,13 +17,15 @@
<resources>
<style name="KeyboardTheme.IceCreamSandwich" parent="KeyboardIcons.IceCreamSandwich">
<item name="keyboardStyle">@style/Keyboard.IceCreamSandwich</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard.IceCreamSandwich</item>
<item name="keyboardViewStyle">@style/KeyboardView.IceCreamSandwich</item>
- <item name="popupMiniKeyboardViewStyle">@style/PopupMiniKeyboardView.IceCreamSandwich</item>
- <item name="popupMiniKeyboardPanelStyle">@style/PopupMiniKeyboardPanelStyle.IceCreamSandwich</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.IceCreamSandwich</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.IceCreamSandwich</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.IceCreamSandwich</item>
+ <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle.IceCreamSandwich</item>
<item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle.IceCreamSandwich</item>
+ <item name="suggestionsViewStyle">@style/SuggestionsViewStyle.IceCreamSandwich</item>
+ <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle.IceCreamSandwich</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle.IceCreamSandwich</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle.IceCreamSandwich</item>
- <item name="candidateViewStyle">@style/CandidateViewStyle.IceCreamSandwich</item>
</style>
</resources>
diff --git a/java/res/values/themes-stone-bold.xml b/java/res/values/themes-stone-bold.xml
index d33e6bf35..47de99e47 100644
--- a/java/res/values/themes-stone-bold.xml
+++ b/java/res/values/themes-stone-bold.xml
@@ -16,14 +16,16 @@
<resources>
<style name="KeyboardTheme.Stone.Bold" parent="KeyboardIcons.Black">
- <item name="keyboardStyle">@style/Keyboard.Stone</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard.Stone</item>
+ <item name="keyboardStyle">@style/Keyboard.Stone.Bold</item>
<item name="keyboardViewStyle">@style/KeyboardView.Stone.Bold</item>
- <item name="popupMiniKeyboardViewStyle">@style/PopupMiniKeyboardView.Stone</item>
- <item name="popupMiniKeyboardPanelStyle">@style/PopupMiniKeyboardPanelStyle</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Stone.Bold</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.Stone</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.Stone</item>
+ <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item>
<item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item>
+ <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item>
+ <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
- <item name="candidateViewStyle">@style/CandidateViewStyle</item>
</style>
</resources>
diff --git a/java/res/values/themes-stone.xml b/java/res/values/themes-stone.xml
index 230b2ca4d..a0b39e3e6 100644
--- a/java/res/values/themes-stone.xml
+++ b/java/res/values/themes-stone.xml
@@ -17,13 +17,15 @@
<resources>
<style name="KeyboardTheme.Stone" parent="KeyboardIcons.Black">
<item name="keyboardStyle">@style/Keyboard.Stone</item>
- <item name="latinKeyboardStyle">@style/LatinKeyboard.Stone</item>
<item name="keyboardViewStyle">@style/KeyboardView.Stone</item>
- <item name="popupMiniKeyboardViewStyle">@style/PopupMiniKeyboardView.Stone</item>
- <item name="popupMiniKeyboardPanelStyle">@style/PopupMiniKeyboardPanelStyle</item>
+ <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Stone</item>
+ <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.Stone</item>
+ <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.Stone</item>
+ <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item>
<item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item>
+ <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item>
+ <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
- <item name="candidateViewStyle">@style/CandidateViewStyle</item>
</style>
</resources>
diff --git a/java/res/values/touch-position-correction.xml b/java/res/values/touch-position-correction.xml
new file mode 100644
index 000000000..41b435ad0
--- /dev/null
+++ b/java/res/values/touch-position-correction.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!--
+ An entry of the touch_position_correction word should be:
+ 1. (float) (touch_center_x - key_center_x) / key_width
+ 2. (float) (touch_center_y - key_center_y) / key_height
+ 3. (float) sweet_spot_radius / (key_width^2 + key_height^2)
+ -->
+
+ <string-array
+ name="touch_position_correction_data_empty"
+ translatable="false"
+ >
+ <!-- empty -->
+ </string-array>
+
+ <string-array
+ name="touch_position_correction_data_gingerbread"
+ translatable="false"
+ >
+ <!-- First row -->
+ <item>0.0091285</item>
+ <item>0.1193203</item>
+ <item>0.1622607</item>
+
+ <!-- Second row -->
+ <item>-0.0233128</item>
+ <item>0.1379798</item>
+ <item>0.1585229</item>
+
+ <!-- Third row -->
+ <item>-0.0080185</item>
+ <item>0.1911477</item>
+ <item>0.1570948</item>
+ </string-array>
+
+ <string-array
+ name="touch_position_correction_data_ice_cream_sandwich"
+ translatable="false"
+ >
+ <!-- First row -->
+ <item>0.0038756</item>
+ <item>-0.0005677</item>
+ <item>0.1577026</item>
+
+ <!-- Second row -->
+ <item>-0.0236678</item>
+ <item>0.0381731</item>
+ <item>0.1529972</item>
+
+ <!-- Third row -->
+ <item>-0.0086827</item>
+ <item>0.0880847</item>
+ <item>0.1522819</item>
+ </string-array>
+</resources>
diff --git a/java/res/xml-fi/kbd_qwerty.xml b/java/res/xml-fi/kbd_qwerty.xml
deleted file mode 100644
index 75721e057..000000000
--- a/java/res/xml-fi/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fi"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
-</Keyboard>
diff --git a/java/res/xml-fr-rCH/kbd_qwerty.xml b/java/res/xml-fr-rCH/kbd_qwerty.xml
deleted file mode 100644
index 41b701d83..000000000
--- a/java/res/xml-fr-rCH/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fr_CH"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
-</Keyboard>
diff --git a/java/res/xml-fr/kbd_qwerty.xml b/java/res/xml-fr/kbd_qwerty.xml
deleted file mode 100644
index 8c730a24f..000000000
--- a/java/res/xml-fr/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fr"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_azerty" />
-</Keyboard>
diff --git a/java/res/xml-hr/kbd_qwerty.xml b/java/res/xml-hr/kbd_qwerty.xml
deleted file mode 100644
index ca92e86a7..000000000
--- a/java/res/xml-hr/kbd_qwerty.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="hr"
->
- <!-- TODO: Dedicated Croatian layout especially for tablet. -->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
-</Keyboard>
diff --git a/java/res/xml-land/kbd_number.xml b/java/res/xml-land/kbd_number.xml
new file mode 100644
index 000000000..7cc0fb274
--- /dev/null
+++ b/java/res/xml-land/kbd_number.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="26.67%p"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_number" />
+</Keyboard>
diff --git a/java/res/xml-land/kbd_phone.xml b/java/res/xml-land/kbd_phone.xml
new file mode 100644
index 000000000..aa54b8390
--- /dev/null
+++ b/java/res/xml-land/kbd_phone.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="26.67%p"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_phone" />
+</Keyboard>
diff --git a/java/res/xml-de/kbd_qwerty.xml b/java/res/xml-land/kbd_phone_symbols.xml
index 89e10b26d..41ba6cf3b 100644
--- a/java/res/xml-de/kbd_qwerty.xml
+++ b/java/res/xml-land/kbd_phone_symbols.xml
@@ -20,8 +20,9 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="de"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="26.67%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
+ latin:keyboardLayout="@xml/rows_phone_symbols" />
</Keyboard>
diff --git a/java/res/xml-large/kbd_key_styles.xml b/java/res/xml-large/kbd_key_styles.xml
deleted file mode 100644
index dbea4dcfd..000000000
--- a/java/res/xml-large/kbd_key_styles.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <!-- Base key style for the functional key -->
- <key-style
- latin:styleName="functionalKeyStyle"
- latin:isFunctional="true" />
- <!-- Base key style for the key which may have settings key as popup key -->
- <switch>
- <case
- latin:clobberSettingsKey="true"
- >
- <key-style
- latin:styleName="settingsPopupStyle"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <default>
- <key-style
- latin:styleName="settingsPopupStyle"
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="\@icon/5|\@integer/key_settings"
- latin:parentStyle="functionalKeyStyle" />
- </default>
- </switch>
- <!-- Functional key styles -->
- <key-style
- latin:styleName="shiftKeyStyle"
- latin:code="@integer/key_shift"
- latin:keyIcon="iconShiftKey"
- latin:keyIconShifted="iconShiftedShiftKey"
- latin:parentStyle="functionalKeyStyle"
- latin:isSticky="true" />
- <key-style
- latin:styleName="deleteKeyStyle"
- latin:code="@integer/key_delete"
- latin:keyIcon="iconDeleteKey"
- latin:parentStyle="functionalKeyStyle"
- latin:isRepeatable="true" />
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyIcon="iconReturnKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="spaceKeyStyle"
- latin:code="@integer/key_space"
- latin:keyIconPreview="iconPreviewSpaceKey" />
- <key-style
- latin:styleName="nonSpecialBackgroundSpaceKeyStyle"
- latin:code="@integer/key_space"
- latin:keyIconPreview="iconPreviewSpaceKey" />
- <key-style
- latin:styleName="smileyKeyStyle"
- latin:keyLabel=":-)"
- latin:keyOutputText=":-) "
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_smiley"
- latin:maxPopupKeyboardColumn="5" />
- <key-style
- latin:styleName="shortcutKeyStyle"
- latin:code="@integer/key_shortcut"
- latin:keyIcon="iconShortcutKey"
- latin:keyIconPreview="iconPreviewShortcutKey"
- latin:parentStyle="settingsPopupStyle" />
- <key-style
- latin:styleName="settingsKeyStyle"
- latin:code="@integer/key_settings"
- latin:keyIcon="iconSettingsKey"
- latin:keyIconPreview="iconPreviewSettingsKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="tabKeyStyle"
- latin:code="@integer/key_tab"
- latin:keyIcon="iconTabKey"
- latin:keyIconPreview="iconPreviewTabKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="toSymbolKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_symbol_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="toAlphaKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_alpha_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="moreKeyStyle"
- latin:code="@integer/key_shift"
- latin:keyLabel="@string/label_more_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle"
- latin:isSticky="true" />
- <key-style
- latin:styleName="comKeyStyle"
- latin:keyLabel="@string/keylabel_for_popular_domain"
- latin:keyLabelOption="fontNormal|hasPopupHint"
- latin:keyOutputText="@string/keylabel_for_popular_domain"
- latin:popupCharacters="@string/alternates_for_popular_domain" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <key-style
- latin:styleName="nonPasswordSymbolKeyStyle"
- latin:enabled="false" />
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <key-style
- latin:styleName="nonPasswordSymbolKeyStyle"
- latin:enabled="true" />
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml-large/kbd_number.xml b/java/res/xml-large/kbd_number.xml
deleted file mode 100644
index b3a1010d7..000000000
--- a/java/res/xml-large/kbd_number.xml
+++ /dev/null
@@ -1,204 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="16.75%p"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <!-- This row is intentionally not marked as a top row -->
- <Row>
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="24.875%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="24.875%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="24.875%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p"
- latin:keyEdgeFlags="left" />
- <Spacer
- latin:keyXPos="24.875%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <!-- This row is intentionally not marked as a top row -->
- <Row>
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="11.00%p"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="1"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="2"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="3"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="11.00%p"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="/"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="4"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="5"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="6"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <!-- There is an empty area below the "More" key and left of the "(" key. To
- ignore the touch event on the area, "(" is intentionally not marked as a left
- edge key. -->
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="11.00%p"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="="
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="7"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="8"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="9"
- latin:keyStyle="numKeyStyle" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyWidth="27.75%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="38.75%p" />
- <Key
- latin:keyLabel="0"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
- </default>
- </switch>
-</Keyboard>
diff --git a/java/res/xml-large/kbd_phone_symbols.xml b/java/res/xml-large/kbd_phone_symbols.xml
deleted file mode 100644
index d083ecb60..000000000
--- a/java/res/xml-large/kbd_phone_symbols.xml
+++ /dev/null
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="16.75%p"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row>
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="11.00%p"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:code="44"
- latin:keyLabel="@string/label_pause_key"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="11.00%p"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:code="59"
- latin:keyLabel="@string/label_wait_key"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="11.00%p"
- latin:keyEdgeFlags="left" />
- <!-- There is an empty area below the "More" key and left of the "(" key. To ignore
- the touch event on the area, "(" is intentionally not marked as a left edge key. -->
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyLabel="N"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyWidth="27.75%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="38.867%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
-</Keyboard>
diff --git a/java/res/xml-large/kbd_qwerty_f2.xml b/java/res/xml-large/kbd_qwerty_f2.xml
deleted file mode 100644
index 7638ee4b4..000000000
--- a/java/res/xml-large/kbd_qwerty_f2.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <switch>
- <case
- latin:f2KeyMode="settings"
- >
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </case>
- <case
- latin:f2KeyMode="shortcutIme"
- >
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </case>
- <!-- voiceKeyEnabled="false" -->
- <default>
- <Spacer />
- </default>
- </switch>
- </case>
- <case
- latin:f2KeyMode="shortcutImeOrSettings"
- >
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </case>
- <!-- voiceKeyEnabled="false" -->
- <default>
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </default>
- </switch>
- </case>
- <!-- f2KeyMode="none" -->
- <default>
- <Spacer />
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml-large/kbd_qwerty_row1.xml b/java/res/xml-large/kbd_qwerty_row1.xml
deleted file mode 100644
index b781d681e..000000000
--- a/java/res/xml-large/kbd_qwerty_row1.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <Row
- latin:keyWidth="9.0%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
-</merge>
diff --git a/java/res/xml-large/kbd_qwerty_row2.xml b/java/res/xml-large/kbd_qwerty_row2.xml
deleted file mode 100644
index 05b005af1..000000000
--- a/java/res/xml-large/kbd_qwerty_row2.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <Row
- latin:keyWidth="9.0%p"
- >
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyXPos="4.5%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
-</merge>
diff --git a/java/res/xml-large/kbd_qwerty_row3.xml b/java/res/xml-large/kbd_qwerty_row3.xml
deleted file mode 100644
index 278db13fc..000000000
--- a/java/res/xml-large/kbd_qwerty_row3.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
-</merge>
diff --git a/java/res/xml-large/kbd_qwerty_row4.xml b/java/res/xml-large/kbd_qwerty_row4.xml
deleted file mode 100644
index 4f41c17b4..000000000
--- a/java/res/xml-large/kbd_qwerty_row4.xml
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <!-- This row is intentionally not marked as a bottom row -->
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="13.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="tabKeyStyle" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyStyle="comKeyStyle" />
- </case>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyStyle="comKeyStyle" />
- </case>
- <default>
- <Key
- latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\@"
- latin:popupCharacters="\@" />
- </default>
- </switch>
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyXPos="30.750%p"
- latin:keyWidth="39.750%p" />
- <switch>
- <case
- latin:languageCode="ru"
- >
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="-"
- latin:keyWidth="9.750%p" />
- </case>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel=":"
- latin:popupCharacters=":"
- latin:keyWidth="9.750%p" />
- </case>
- <default>
- <Key
- latin:keyLabel="\?"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="_"
- latin:popupCharacters="_"
- latin:keyWidth="9.750%p" />
- </default>
- </switch>
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="_"
- latin:keyWidth="9.750%p" />
- </case>
- <default>
- <Key
- latin:keyLabel="!"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\'"
- latin:popupCharacters="\'"
- latin:keyWidth="9.750%p" />
- </default>
- </switch>
- </case>
- <!-- not languageCode="ru" -->
- <default>
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="-"
- latin:keyWidth="9.750%p" />
- </case>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel=":"
- latin:popupCharacters=":"
- latin:keyWidth="9.750%p" />
- </case>
- <default>
- <Key
- latin:keyLabel="\'"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="&quot;"
- latin:popupCharacters="&quot;"
- latin:keyWidth="9.750%p" />
- </default>
- </switch>
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="_"
- latin:keyWidth="9.750%p" />
- </case>
- <default>
- <Key
- latin:keyLabel="-"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="_"
- latin:popupCharacters="_"
- latin:keyWidth="9.750%p" />
- </default>
- </switch>
- </default>
- </switch>
- <Spacer
- latin:keyXPos="-10.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
-</merge>
diff --git a/java/res/xml-large/kbd_rows_arabic.xml b/java/res/xml-large/kbd_rows_arabic.xml
deleted file mode 100644
index bc37d5a9f..000000000
--- a/java/res/xml-large/kbd_rows_arabic.xml
+++ /dev/null
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This file for Arabic layout is an alpha version. It allows to enter -->
-<!-- some right-to-left text, but it has gone through no study whatsoever, -->
-<!-- and needs to be run through UX. -->
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="8.0%p"
- >
- <Key
- latin:keyLabel="ض"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ص" />
- <Key
- latin:keyLabel="ث" />
- <Key
- latin:keyLabel="ق" />
- <Key
- latin:keyLabel="ف"
- latin:popupCharacters="ف,ڤ" />
- <Key
- latin:keyLabel="غ" />
- <Key
- latin:keyLabel="ع" />
- <Key
- latin:keyLabel="ه"
- latin:popupCharacters="ه,هـ" />
- <Key
- latin:keyLabel="خ" />
- <Key
- latin:keyLabel="ح" />
- <Key
- latin:keyLabel="ج"
- latin:popupCharacters="ج,چ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.0%p"
- >
- <Key
- latin:keyLabel="ش"
- latin:keyXPos="3.0%p" />
- <Key
- latin:keyLabel="س" />
- <Key
- latin:keyLabel="ي" />
- <Key
- latin:keyLabel="ب"
- latin:popupCharacters="ب,پ" />
- <Key
- latin:keyLabel="ل"
- latin:popupCharacters="ل,لا" />
- <Key
- latin:keyLabel="ا"
- latin:popupCharacters="ا,أ,إ,آ" />
- <Key
- latin:keyLabel="ت" />
- <Key
- latin:keyLabel="ن" />
- <Key
- latin:keyLabel="م" />
- <Key
- latin:keyLabel="ك"
- latin:popupCharacters="ك,گ" />
- <Key
- latin:keyLabel="ط" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.65%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="8.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ئ" />
- <Key
- latin:keyLabel="ء" />
- <Key
- latin:keyLabel="ؤ" />
- <Key
- latin:keyLabel="ر" />
- <Key
- latin:keyLabel="ذ" />
- <Key
- latin:keyLabel="ى" />
- <Key
- latin:keyLabel="ة" />
- <Key
- latin:keyLabel="و" />
- <Key
- latin:keyLabel="ز"
- latin:popupCharacters="ز,ژ" />
- <Key
- latin:keyLabel="ظ" />
- <Key
- latin:keyLabel="د" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_azerty.xml b/java/res/xml-large/kbd_rows_azerty.xml
deleted file mode 100644
index 7ba716bc5..000000000
--- a/java/res/xml-large/kbd_rows_azerty.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="8.5%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.5%p"
- >
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyXPos="5.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="m" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.5%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="\'" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_hebrew.xml b/java/res/xml-large/kbd_rows_hebrew.xml
deleted file mode 100644
index a1475376b..000000000
--- a/java/res/xml-large/kbd_rows_hebrew.xml
+++ /dev/null
@@ -1,122 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="8.600%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- <Key
- latin:keyLabel="ק" />
- <Key
- latin:keyLabel="ר" />
- <Key
- latin:keyLabel="א" />
- <Key
- latin:keyLabel="ט" />
- <Key
- latin:keyLabel="ו" />
- <Key
- latin:keyLabel="ן" />
- <Key
- latin:keyLabel="ם" />
- <Key
- latin:keyLabel="פ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-12.000%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.600%p"
- >
- <Key
- latin:keyLabel="ש"
- latin:keyXPos="4.000%p" />
- <Key
- latin:keyLabel="ד" />
- <Key
- latin:keyLabel="ג"
- latin:popupCharacters="ג,ג׳" />
- <Key
- latin:keyLabel="כ" />
- <Key
- latin:keyLabel="ע" />
- <Key
- latin:keyLabel="י"
- latin:popupCharacters="י,ײַ" />
- <Key
- latin:keyLabel="ח"
- latin:popupCharacters="ח,ח׳" />
- <Key
- latin:keyLabel="ל" />
- <Key
- latin:keyLabel="ך" />
- <Key
- latin:keyLabel="ף" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-10.400%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.600%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="10.000%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ז"
- latin:popupCharacters="ז,ז׳" />
- <Key
- latin:keyLabel="ס" />
- <Key
- latin:keyLabel="ב" />
- <Key
- latin:keyLabel="ה" />
- <Key
- latin:keyLabel="נ" />
- <Key
- latin:keyLabel="מ" />
- <Key
- latin:keyLabel="צ"
- latin:popupCharacters="צ,צ׳" />
- <Key
- latin:keyLabel="ת"
- latin:popupCharacters="ת,ת׳" />
- <Key
- latin:keyLabel="ץ"
- latin:popupCharacters="ץ,ץ׳" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_qwertz.xml b/java/res/xml-large/kbd_rows_qwertz.xml
deleted file mode 100644
index 7f85fe778..000000000
--- a/java/res/xml-large/kbd_rows_qwertz.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="9.0%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row2" />
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_russian.xml b/java/res/xml-large/kbd_rows_russian.xml
deleted file mode 100644
index b72324745..000000000
--- a/java/res/xml-large/kbd_rows_russian.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="8.0%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="й"
- latin:keyXPos="2.15%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ц" />
- <Key
- latin:keyLabel="у" />
- <Key
- latin:keyLabel="к" />
- <Key
- latin:keyLabel="е"
- latin:popupCharacters="@string/alternates_for_cyrillic_e" />
- <Key
- latin:keyLabel="н" />
- <Key
- latin:keyLabel="г" />
- <Key
- latin:keyLabel="ш" />
- <Key
- latin:keyLabel="щ" />
- <Key
- latin:keyLabel="з" />
- <Key
- latin:keyLabel="х" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.0%p"
- >
- <Key
- latin:keyLabel="ф"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ы" />
- <Key
- latin:keyLabel="в" />
- <Key
- latin:keyLabel="а" />
- <Key
- latin:keyLabel="п" />
- <Key
- latin:keyLabel="р" />
- <Key
- latin:keyLabel="о" />
- <Key
- latin:keyLabel="л" />
- <Key
- latin:keyLabel="д" />
- <Key
- latin:keyLabel="ж" />
- <Key
- latin:keyLabel="э" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.0%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="я" />
- <Key
- latin:keyLabel="ч" />
- <Key
- latin:keyLabel="с" />
- <Key
- latin:keyLabel="м" />
- <Key
- latin:keyLabel="и" />
- <Key
- latin:keyLabel="т" />
- <Key
- latin:keyLabel="ь"
- latin:popupCharacters="@string/alternates_for_cyrillic_soft_sign" />
- <Key
- latin:keyLabel="б" />
- <Key
- latin:keyLabel="ю" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel=","
- latin:popupCharacters="," />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_scandinavian.xml b/java/res/xml-large/kbd_rows_scandinavian.xml
deleted file mode 100644
index 645ef625a..000000000
--- a/java/res/xml-large/kbd_rows_scandinavian.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="7.9%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyLabel="å" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.9%p"
- >
- <Key
- latin:keyLabel="a"
- latin:keyXPos="3.5%p"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="@string/keylabel_for_scandinavia_row2_10"
- latin:popupCharacters="@string/alternates_for_scandinavia_row2_10" />
- <Key
- latin:keyLabel="@string/keylabel_for_scandinavia_row2_11"
- latin:popupCharacters="@string/alternates_for_scandinavia_row2_11" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.9%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Spacer
- latin:keyWidth="4.35%p" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <Spacer
- latin:keyWidth="4.35%p" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_serbian.xml b/java/res/xml-large/kbd_rows_serbian.xml
deleted file mode 100644
index 4dfe94400..000000000
--- a/java/res/xml-large/kbd_rows_serbian.xml
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="8.0%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="љ"
- latin:keyXPos="2.15%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="њ" />
- <Key
- latin:keyLabel="е" />
- <Key
- latin:keyLabel="р" />
- <Key
- latin:keyLabel="т" />
- <Key
- latin:keyLabel="з" />
- <Key
- latin:keyLabel="у" />
- <Key
- latin:keyLabel="и" />
- <Key
- latin:keyLabel="о" />
- <Key
- latin:keyLabel="п" />
- <Key
- latin:keyLabel="ш" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.9%p"
- >
- <Key
- latin:keyLabel="а"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="с" />
- <Key
- latin:keyLabel="д" />
- <Key
- latin:keyLabel="ф" />
- <Key
- latin:keyLabel="г" />
- <Key
- latin:keyLabel="х" />
- <Key
- latin:keyLabel="ј" />
- <Key
- latin:keyLabel="к" />
- <Key
- latin:keyLabel="л" />
- <Key
- latin:keyLabel="ч" />
- <Key
- latin:keyLabel="ћ" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.5%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="8.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ѕ" />
- <Key
- latin:keyLabel="џ" />
- <Key
- latin:keyLabel="ц" />
- <Key
- latin:keyLabel="в" />
- <Key
- latin:keyLabel="б" />
- <Key
- latin:keyLabel="н" />
- <Key
- latin:keyLabel="м" />
- <Key
- latin:keyLabel="ђ" />
- <Key
- latin:keyLabel="ж" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <include
- latin:keyboardLayout="@xml/kbd_row3_right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_rows_spanish.xml b/java/res/xml-large/kbd_rows_spanish.xml
deleted file mode 100644
index 7ef44bb53..000000000
--- a/java/res/xml-large/kbd_rows_spanish.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row1" />
- <Row
- latin:keyWidth="8.5%p"
- >
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyXPos="5.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="ñ" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-large/kbd_symbols.xml b/java/res/xml-large/kbd_symbols.xml
deleted file mode 100644
index 77849f6fd..000000000
--- a/java/res/xml-large/kbd_symbols.xml
+++ /dev/null
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_currency_key_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="9.0%p"
- >
- <Key
- latin:keyLabel="1"
- latin:popupCharacters="¹,½,⅓,¼,⅛" />
- <Key
- latin:keyLabel="2"
- latin:popupCharacters="²,⅔" />
- <Key
- latin:keyLabel="3"
- latin:popupCharacters="³,¾,⅜" />
- <Key
- latin:keyLabel="4"
- latin:popupCharacters="⁴" />
- <Key
- latin:keyLabel="5"
- latin:popupCharacters="⅝" />
- <Key
- latin:keyLabel="6" />
- <Key
- latin:keyLabel="7"
- latin:popupCharacters="⅞" />
- <Key
- latin:keyLabel="8" />
- <Key
- latin:keyLabel="9" />
- <Key
- latin:keyLabel="0"
- latin:popupCharacters="ⁿ,∅" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="9.0%p"
- >
- <Key
- latin:keyLabel="#"
- latin:keyXPos="4.5%p" />
- <Key
- latin:keyStyle="currencyKeyStyle" />
- <Key
- latin:keyLabel="%"
- latin:popupCharacters="‰" />
- <Key
- latin:keyLabel="&amp;" />
- <Key
- latin:keyLabel="*"
- latin:popupCharacters="†,‡,★" />
- <Key
- latin:keyLabel="-"
- latin:popupCharacters="_,–,—" />
- <Key
- latin:keyLabel="+"
- latin:popupCharacters="±" />
- <Key
- latin:keyLabel="("
- latin:popupCharacters="[,{,&lt;" />
- <Key
- latin:keyLabel=")"
- latin:popupCharacters="],},&gt;" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="&lt;"
- latin:popupCharacters="≤,«,‹" />
- <Key
- latin:keyLabel="&gt;"
- latin:popupCharacters="≥,»,›" />
- <Key
- latin:keyLabel="="
- latin:popupCharacters="≠,≈" />
- <switch>
- <case
- latin:languageCode="ru"
- >
- <Key
- latin:keyLabel=":" />
- </case>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="\'"
- latin:popupCharacters="‘,’,‚,‛" />
- </case>
- <default>
- <Key
- latin:keyLabel=":" />
- </default>
- </switch>
- <Key
- latin:keyLabel=";" />
- <switch>
- <case
- latin:languageCode="ru"
- >
- <Key
- latin:keyLabel="\'"
- latin:popupCharacters="‘,’,‚,‛" />
- <!-- Note: DroidSans doesn't have double-high-reversed-quotation
- '\u201f' glyph. -->
- <!-- latin:popupCharacters="“,”,„,‟,«,»" -->
- <Key
- latin:keyLabel="&quot;"
- latin:popupCharacters="“,”,«,»" />
- <Key
- latin:keyLabel="." />
- <Key
- latin:keyLabel="," />
- </case>
- <default>
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- <Key
- latin:keyLabel="!"
- latin:popupCharacters="¡" />
- <Key
- latin:keyLabel="\?"
- latin:popupCharacters="¿" />
- </default>
- </switch>
- <Key
- latin:keyLabel="/"
- latin:keyWidth="fillRight" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="13.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="tabKeyStyle" />
- <Key
- latin:keyLabel="\@" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyXPos="30.750%p"
- latin:keyWidth="39.750%p" />
- <switch>
- <case
- latin:languageCode="ru"
- >
- <Key
- latin:keyLabel="_"
- latin:keyWidth="9.750%p" />
- <Key
- latin:keyLabel="-"
- latin:keyWidth="9.750%p" />
- </case>
- <default>
- <!-- Note: DroidSans doesn't have double-high-reversed-quotation
- '\u201f' glyph. -->
- <!-- latin:popupCharacters="“,”,„,‟,«,»,‘,’,‚,‛" -->
- <Key
- latin:keyLabel="&quot;"
- latin:popupCharacters="“,”,«,»,‘,’,‚,‛"
- latin:keyWidth="9.750%p" />
- <Key
- latin:keyLabel="_"
- latin:keyWidth="9.750%p" />
- </default>
- </switch>
- <Spacer
- latin:keyXPos="-10.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
-</Keyboard>
diff --git a/java/res/xml-large/kbd_symbols_shift.xml b/java/res/xml-large/kbd_symbols_shift.xml
deleted file mode 100644
index b25292f27..000000000
--- a/java/res/xml-large/kbd_symbols_shift.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="9.0%p"
- >
- <Key
- latin:keyLabel="~" />
- <Key
- latin:keyLabel="`" />
- <Key
- latin:keyLabel="|" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="•"
- latin:popupCharacters="♪,♥,♠,♦,♣" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="√" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="π"
- latin:popupCharacters="Π" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="÷" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="×" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="§"
- latin:popupCharacters="¶" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="Δ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-10.0%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="9.0%p"
- >
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="£"
- latin:keyXPos="4.5%p" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¢" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="€" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¥" />
- <Key
- latin:keyLabel="^"
- latin:popupCharacters="↑,↓,←,→" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="°"
- latin:popupCharacters="′,″" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="±"
- latin:popupCharacters="∞" />
- <Key
- latin:keyLabel="{" />
- <Key
- latin:keyLabel="}" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-14.6%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="10.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="\\" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="©" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="®" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="™" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="℅" />
- <Key
- latin:keyLabel="[" />
- <Key
- latin:keyLabel="]" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¡" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¿" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row
- latin:keyWidth="8.9%p"
- >
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="13.0%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="tabKeyStyle" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyXPos="30.750%p"
- latin:keyWidth="39.750%p" />
- <Spacer
- latin:keyXPos="-10.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
- </Row>
-</Keyboard>
diff --git a/java/res/xml-pl/kbd_qwerty.xml b/java/res/xml-pl/kbd_qwerty.xml
deleted file mode 100644
index 44312c52c..000000000
--- a/java/res/xml-pl/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="pl"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
diff --git a/java/res/xml-pt/kbd_qwerty.xml b/java/res/xml-pt/kbd_qwerty.xml
deleted file mode 100644
index f5dcbc61b..000000000
--- a/java/res/xml-pt/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="pt"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
diff --git a/java/res/xml-ru/kbd_qwerty.xml b/java/res/xml-ru/kbd_qwerty.xml
deleted file mode 100644
index aee1b1bfc..000000000
--- a/java/res/xml-ru/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="ru"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_russian" />
-</Keyboard>
diff --git a/java/res/xml-sr/kbd_qwerty.xml b/java/res/xml-sr/kbd_qwerty.xml
deleted file mode 100644
index 58fc187c2..000000000
--- a/java/res/xml-sr/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="sr"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_serbian" />
-</Keyboard>
diff --git a/java/res/xml-sv/kbd_qwerty.xml b/java/res/xml-sv/kbd_qwerty.xml
deleted file mode 100644
index e29d9abce..000000000
--- a/java/res/xml-sv/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="sv"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
-</Keyboard>
diff --git a/java/res/xml-large-land/kbd_popup_template.xml b/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml
index 2c1d1902e..4d8b446a2 100644
--- a/java/res/xml-large-land/kbd_popup_template.xml
+++ b/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml
@@ -20,8 +20,7 @@
<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
latin:keyWidth="5%p"
- latin:horizontalGap="0px"
- latin:verticalGap="0px"
latin:rowHeight="@dimen/popup_key_height"
+ style="?attr/moreKeysKeyboardStyle"
>
</Keyboard>
diff --git a/java/res/xml-sw600dp-land/kbd_number.xml b/java/res/xml-sw600dp-land/kbd_number.xml
new file mode 100644
index 000000000..cb86b3b2f
--- /dev/null
+++ b/java/res/xml-sw600dp-land/kbd_number.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="18%p"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_number" />
+</Keyboard>
diff --git a/java/res/xml-es/kbd_qwerty.xml b/java/res/xml-sw600dp-land/kbd_phone.xml
index 568f4d652..71c7c04a1 100644
--- a/java/res/xml-es/kbd_qwerty.xml
+++ b/java/res/xml-sw600dp-land/kbd_phone.xml
@@ -20,8 +20,9 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="es,es_US"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="18%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_spanish" />
+ latin:keyboardLayout="@xml/rows_phone" />
</Keyboard>
diff --git a/java/res/xml-sw600dp-land/kbd_phone_symbols.xml b/java/res/xml-sw600dp-land/kbd_phone_symbols.xml
new file mode 100644
index 000000000..39bdae3c7
--- /dev/null
+++ b/java/res/xml-sw600dp-land/kbd_phone_symbols.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="18%p"
+>
+ <!-- Tablet doesn't have phone symbols keyboard -->
+ <include
+ latin:keyboardLayout="@xml/rows_phone" />
+</Keyboard>
diff --git a/java/res/xml-sw600dp-land/kbd_thai.xml b/java/res/xml-sw600dp-land/kbd_thai.xml
new file mode 100644
index 000000000..b75980f2f
--- /dev/null
+++ b/java/res/xml-sw600dp-land/kbd_thai.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="3.20%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai" />
+</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_10_10_7_symbols.xml b/java/res/xml-sw600dp/kbd_10_10_7_symbols.xml
new file mode 100644
index 000000000..66254dea0
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_10_10_7_symbols.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_10_10_7_symbols" />
+</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_10_10_7_symbols_shift.xml b/java/res/xml-sw600dp/kbd_10_10_7_symbols_shift.xml
new file mode 100644
index 000000000..3c5ed5e09
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_10_10_7_symbols_shift.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_10_10_7_symbols_shift" />
+</Keyboard>
diff --git a/java/res/xml-large/kbd_popup_template.xml b/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml
index fff2659be..d90a5884e 100644
--- a/java/res/xml-large/kbd_popup_template.xml
+++ b/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml
@@ -20,8 +20,7 @@
<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
latin:keyWidth="8%p"
- latin:horizontalGap="@dimen/key_horizontal_gap"
- latin:verticalGap="0px"
latin:rowHeight="@dimen/popup_key_height"
+ style="?attr/moreKeysKeyboardStyle"
>
</Keyboard>
diff --git a/java/res/xml-de-rZZ/kbd_qwerty.xml b/java/res/xml-sw600dp/kbd_number.xml
index d5fd8ef7a..4a8b08c2a 100644
--- a/java/res/xml-de-rZZ/kbd_qwerty.xml
+++ b/java/res/xml-sw600dp/kbd_number.xml
@@ -20,8 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="de"
+ latin:keyWidth="18%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
+ latin:keyboardLayout="@xml/rows_number" />
</Keyboard>
diff --git a/java/res/xml-cs/kbd_qwerty.xml b/java/res/xml-sw600dp/kbd_phone.xml
index 9991ea2d2..f63f1c648 100644
--- a/java/res/xml-cs/kbd_qwerty.xml
+++ b/java/res/xml-sw600dp/kbd_phone.xml
@@ -20,8 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="cs"
+ latin:keyWidth="18%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
+ latin:keyboardLayout="@xml/rows_phone" />
</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_phone_symbols.xml b/java/res/xml-sw600dp/kbd_phone_symbols.xml
new file mode 100644
index 000000000..a0f55b732
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_phone_symbols.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="18%p"
+>
+ <!-- Tablet doesn't have phone symbols keyboard -->
+ <include
+ latin:keyboardLayout="@xml/rows_phone" />
+</Keyboard>
diff --git a/java/res/xml-sw600dp/kbd_thai.xml b/java/res/xml-sw600dp/kbd_thai.xml
new file mode 100644
index 000000000..b75980f2f
--- /dev/null
+++ b/java/res/xml-sw600dp/kbd_thai.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="3.20%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai" />
+</Keyboard>
diff --git a/java/res/xml-sw600dp/key_apostrophe.xml b/java/res/xml-sw600dp/key_apostrophe.xml
new file mode 100644
index 000000000..2aec34729
--- /dev/null
+++ b/java/res/xml-sw600dp/key_apostrophe.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:mode="email|url"
+ >
+ <Key
+ latin:keyLabel="-" />
+ </case>
+ <case
+ latin:languageCode="fa"
+ >
+ <Key
+ latin:keyLabel="!text/keylabel_for_apostrophe"
+ latin:keyHintLabel="!text/keyhintlabel_for_apostrophe"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_apostrophe"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="!text/keylabel_for_apostrophe"
+ latin:keyHintLabel="!text/keyhintlabel_for_apostrophe"
+ latin:moreKeys="!text/more_keys_for_apostrophe"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_azerty_quote.xml b/java/res/xml-sw600dp/key_azerty_quote.xml
new file mode 100644
index 000000000..0e4a8ecdd
--- /dev/null
+++ b/java/res/xml-sw600dp/key_azerty_quote.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="\'"
+ latin:keyHintLabel=":"
+ latin:moreKeys=":"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+</merge>
diff --git a/java/res/xml-sw600dp/key_colemak_colon.xml b/java/res/xml-sw600dp/key_colemak_colon.xml
new file mode 100644
index 000000000..a5a6e9526
--- /dev/null
+++ b/java/res/xml-sw600dp/key_colemak_colon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel=":"
+ latin:keyHintLabel=";"
+ latin:moreKeys=";"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+</merge>
diff --git a/java/res/xml-sw600dp/key_dash.xml b/java/res/xml-sw600dp/key_dash.xml
new file mode 100644
index 000000000..b139c29c8
--- /dev/null
+++ b/java/res/xml-sw600dp/key_dash.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:mode="email|url"
+ >
+ <Key
+ latin:keyLabel="_" />
+ </case>
+ <case
+ latin:languageCode="ar|fa"
+ >
+ <Key
+ latin:keyLabel="."
+ latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_arabic_diacritics"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="-"
+ latin:keyHintLabel="_"
+ latin:moreKeys="_"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_f1.xml b/java/res/xml-sw600dp/key_f1.xml
new file mode 100644
index 000000000..77afe4e64
--- /dev/null
+++ b/java/res/xml-sw600dp/key_f1.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols"
+ latin:mode="url"
+ >
+ <Key
+ latin:keyLabel=":" />
+ </case>
+ <case
+ latin:keyboardLayoutSetElement="symbols"
+ >
+ <Key
+ latin:keyLabel="\@" />
+ </case>
+ <!-- keyboardLayoutSetElement != "symbols" -->
+ <case
+ latin:mode="email"
+ >
+ <Key
+ latin:keyLabel="\@" />
+ </case>
+ <case
+ latin:mode="url"
+ >
+ <Key
+ latin:keyLabel="/"
+ latin:keyHintLabel=":"
+ latin:moreKeys=":"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="/"
+ latin:keyHintLabel="\@"
+ latin:moreKeys="\@"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_f2.xml b/java/res/xml-sw600dp/key_f2.xml
new file mode 100644
index 000000000..ca3b30b54
--- /dev/null
+++ b/java/res/xml-sw600dp/key_f2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:mode="email|url"
+ >
+ <Key
+ latin:keyStyle="comKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionSearch"
+ >
+ <Key
+ latin:keyLabel=":"
+ latin:keyHintLabel="+"
+ latin:moreKeys="+"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyStyle="smileyKeyStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_greek_semicolon.xml b/java/res/xml-sw600dp/key_greek_semicolon.xml
new file mode 100644
index 000000000..3f09419b1
--- /dev/null
+++ b/java/res/xml-sw600dp/key_greek_semicolon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel=";"
+ latin:keyHintLabel=":"
+ latin:moreKeys=":"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+</merge>
diff --git a/java/res/xml-sw600dp/key_question_exclamation.xml b/java/res/xml-sw600dp/key_question_exclamation.xml
new file mode 100644
index 000000000..860a0be77
--- /dev/null
+++ b/java/res/xml-sw600dp/key_question_exclamation.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:mode="email|url"
+ >
+ <Key
+ latin:keyLabel="-" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="\?"
+ latin:keyHintLabel="!"
+ latin:moreKeys="!"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_shortcut.xml b/java/res/xml-sw600dp/key_shortcut.xml
new file mode 100644
index 000000000..87fc75cd5
--- /dev/null
+++ b/java/res/xml-sw600dp/key_shortcut.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:shortcutKeyEnabled="true"
+ latin:clobberSettingsKey="false"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/settings_as_more_key" />
+ </case>
+ <case
+ latin:shortcutKeyEnabled="true"
+ latin:clobberSettingsKey="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle" />
+ </case>
+ <case
+ latin:shortcutKeyEnabled="false"
+ latin:clobberSettingsKey="false"
+ >
+ <Key
+ latin:keyStyle="settingsKeyStyle" />
+ </case>
+ <!-- shortcutKeyEnabled="false" clobberSettingsKey="true" -->
+ <default>
+ <Spacer />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_space.xml b/java/res/xml-sw600dp/key_space.xml
new file mode 100644
index 000000000..86af89f50
--- /dev/null
+++ b/java/res/xml-sw600dp/key_space.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:languageCode="fa"
+ latin:languageSwitchKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="languageSwitchKeyStyle" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="27.0%p" />
+ <Key
+ latin:keyStyle="zwnjKeyStyle" />
+ </case>
+ <case
+ latin:languageCode="fa"
+ latin:languageSwitchKeyEnabled="false"
+ >
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="36.0%p" />
+ <Key
+ latin:keyStyle="zwnjKeyStyle" />
+ </case>
+ <case
+ latin:languageSwitchKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="languageSwitchKeyStyle" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="36.0%p" />
+ </case>
+ <!-- languageSwitchKeyEnabled="false" -->
+ <default>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="45.0%p" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
new file mode 100644
index 000000000..a1b2eb475
--- /dev/null
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="hasShiftedLetterHintStyle"
+ latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="hasShiftedLetterHintStyle"
+ latin:keyLabelFlags="hasShiftedLetterHint" />
+ </default>
+ </switch>
+ <!-- Functional key styles -->
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+ >
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key_shifted"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOff" />
+ </case>
+ <case
+ latin:keyboardLayoutSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key_shifted"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOn" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOff" />
+ </default>
+ </switch>
+ <key-style
+ latin:styleName="deleteKeyStyle"
+ latin:code="!code/key_delete"
+ latin:keyIcon="!icon/delete_key"
+ latin:keyActionFlags="isRepeatable|noKeyPreview"
+ latin:backgroundType="functional" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_enter" />
+ <!-- Override defaultEnterKeyStyle in key_styles_enter.xml -->
+ <key-style
+ latin:styleName="defaultEnterKeyStyle"
+ latin:code="!code/key_enter"
+ latin:keyIcon="!icon/enter_key"
+ latin:keyLabelFlags="preserveCase|autoXScale|followKeyLargeLabelRatio"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional"
+ latin:parentStyle="navigateMoreKeysStyle" />
+ <key-style
+ latin:styleName="spaceKeyStyle"
+ latin:code="!code/key_space"
+ latin:keyActionFlags="noKeyPreview|enableLongPress" />
+ <!-- U+200C: ZERO WIDTH NON-JOINER
+ U+200D: ZERO WIDTH JOINER -->
+ <key-style
+ latin:styleName="zwnjKeyStyle"
+ latin:code="0x200C"
+ latin:keyIcon="!icon/zwnj_key"
+ latin:moreKeys="!icon/zwj_key|&#x200D;"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:keyActionFlags="noKeyPreview" />
+ <key-style
+ latin:styleName="smileyKeyStyle"
+ latin:keyLabel=":-)"
+ latin:keyOutputText=":-) "
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/more_keys_for_smiley" />
+ <key-style
+ latin:styleName="shortcutKeyStyle"
+ latin:code="!code/key_shortcut"
+ latin:keyIcon="!icon/shortcut_key"
+ latin:keyIconDisabled="!icon/shortcut_key_disabled"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="languageSwitchKeyStyle"
+ latin:code="!code/key_language_switch"
+ latin:keyIcon="!icon/language_switch_key"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping|enableLongPress"
+ latin:altCode="!code/key_space" />
+ <key-style
+ latin:styleName="settingsKeyStyle"
+ latin:code="!code/key_settings"
+ latin:keyIcon="!icon/settings_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ latin:navigatePrevious="true"
+ >
+ <key-style
+ latin:styleName="tabKeyStyle"
+ latin:code="!code/key_action_previous"
+ latin:keyIcon="!icon/tab_key"
+ latin:keyIconPreview="!icon/tab_key_preview"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="tabKeyStyle"
+ latin:code="!code/key_tab"
+ latin:keyIcon="!icon/tab_key"
+ latin:keyIconPreview="!icon/tab_key_preview"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <key-style
+ latin:styleName="toSymbolKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_symbol_key"
+ latin:keyLabelFlags="preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="toAlphaKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_alpha_key"
+ latin:keyLabelFlags="preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="toMoreSymbolKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyLabel="!text/label_to_more_symbol_for_tablet_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="backFromMoreSymbolKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyLabel="!text/label_to_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="comKeyStyle"
+ latin:keyLabel="!text/keylabel_for_popular_domain"
+ latin:keyLabelFlags="autoXScale|fontNormal|hasPopupHint|preserveCase"
+ latin:keyOutputText="!text/keylabel_for_popular_domain"
+ latin:moreKeys="!text/more_keys_for_popular_domain" />
+</merge>
diff --git a/java/res/xml-xlarge/kbd_row3_right2.xml b/java/res/xml-sw600dp/keys_comma_period.xml
index 25453160f..752f75b5f 100644
--- a/java/res/xml-xlarge/kbd_row3_right2.xml
+++ b/java/res/xml-sw600dp/keys_comma_period.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2011, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -32,15 +32,15 @@
</case>
<default>
<Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
+ latin:keyLabel="!text/keylabel_for_tablet_comma"
+ latin:keyHintLabel="!text/keyhintlabel_for_tablet_comma"
+ latin:moreKeys="!text/more_keys_for_tablet_comma"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
<Key
latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
+ latin:keyHintLabel="!text/keyhintlabel_for_tablet_period"
+ latin:moreKeys="!text/more_keys_for_tablet_period"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
</default>
</switch>
</merge>
diff --git a/java/res/xml-sw600dp/keys_dvorak_123.xml b/java/res/xml-sw600dp/keys_dvorak_123.xml
new file mode 100644
index 000000000..635ea0476
--- /dev/null
+++ b/java/res/xml-sw600dp/keys_dvorak_123.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="\'"
+ latin:keyHintLabel="&quot;"
+ latin:moreKeys="!"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel=","
+ latin:keyHintLabel="&lt;"
+ latin:moreKeys="\?"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="."
+ latin:keyHintLabel="&gt;"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/more_keys_for_punctuation"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+</merge>
diff --git a/java/res/xml-sw600dp/keys_pcqwerty2_right3.xml b/java/res/xml-sw600dp/keys_pcqwerty2_right3.xml
new file mode 100644
index 000000000..0a27ca70c
--- /dev/null
+++ b/java/res/xml-sw600dp/keys_pcqwerty2_right3.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <Key
+ latin:keyLabel="["
+ latin:moreKeys="{" />
+ <Key
+ latin:keyLabel="]"
+ latin:moreKeys="}" />
+ <!-- U+00A6: "¦" BROKEN BAR -->
+ <Key
+ latin:keyLabel="\\"
+ latin:moreKeys="\\|,&#x00A6;" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="["
+ latin:keyHintLabel="{"
+ latin:moreKeys="{"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="]"
+ latin:keyHintLabel="}"
+ latin:moreKeys="}"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <!-- U+00A6: "¦" BROKEN BAR -->
+ <Key
+ latin:keyLabel="\\"
+ latin:keyHintLabel="|"
+ latin:moreKeys="\\|,&#x00A6;"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml b/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml
new file mode 100644
index 000000000..a0e5cbb92
--- /dev/null
+++ b/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <Key
+ latin:keyLabel=";"
+ latin:moreKeys=":" />
+ <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
+ <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" -->
+ <Key
+ latin:keyLabel="\'"
+ latin:moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x2018;,&#x2019;,&#x201A;,&#x201B;,&quot;" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=";"
+ latin:keyHintLabel=":"
+ latin:moreKeys=":"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
+ <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" -->
+ <Key
+ latin:keyLabel="\'"
+ latin:keyHintLabel="&quot;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x2018;,&#x2019;,&#x201A;,&#x201B;,&quot;"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml b/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml
new file mode 100644
index 000000000..ee5271abe
--- /dev/null
+++ b/java/res/xml-sw600dp/keys_pcqwerty4_right3.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <!-- 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 -->
+ <Key
+ latin:keyLabel=","
+ latin:additionalMoreKeys="&lt;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x2039;,&#x2064;,&#x00AB;" />
+ <Key
+ latin:keyLabel="."
+ latin:additionalMoreKeys="&gt;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x203A;,&#x2065;,&#x00BB;" />
+ <!-- U+00BF: "¿" INVERTED QUESTION MARK -->
+ <Key
+ latin:keyLabel="/"
+ latin:additionalMoreKeys="\?"
+ latin:moreKeys="&#x00BF;" />
+ </case>
+ <default>
+ <!-- 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 -->
+ <Key
+ latin:keyLabel=","
+ latin:keyHintLabel="&lt;"
+ latin:additionalMoreKeys="&lt;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x2039;,&#x2264;,&#x00AB;"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="."
+ latin:keyHintLabel="&gt;"
+ latin:additionalMoreKeys="&gt;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x203A;,&#x2265;,&#x00BB;"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <!-- U+00BF: "¿" INVERTED QUESTION MARK -->
+ <Key
+ latin:keyLabel="/"
+ latin:keyHintLabel="\?"
+ latin:additionalMoreKeys="\?"
+ latin:moreKeys="&#x00BF;"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/row_dvorak4.xml b/java/res/xml-sw600dp/row_dvorak4.xml
new file mode 100644
index 000000000..969cc145e
--- /dev/null
+++ b/java/res/xml-sw600dp/row_dvorak4.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="9.0%p"
+ latin:backgroundType="functional"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/key_shortcut" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="28.0%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <include
+ latin:keyboardLayout="@xml/key_question_exclamation" />
+ <include
+ latin:keyboardLayout="@xml/key_dash" />
+ <include
+ latin:keyboardLayout="@xml/key_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/row_hebrew4.xml b/java/res/xml-sw600dp/row_hebrew4.xml
new file mode 100644
index 000000000..f429f97fb
--- /dev/null
+++ b/java/res/xml-sw600dp/row_hebrew4.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="9.0%p"
+ latin:backgroundType="functional"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/key_shortcut" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="28.0%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <include
+ latin:keyboardLayout="@xml/key_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/row_pcqwerty5.xml b/java/res/xml-sw600dp/row_pcqwerty5.xml
new file mode 100644
index 000000000..3c4a46660
--- /dev/null
+++ b/java/res/xml-sw600dp/row_pcqwerty5.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <switch>
+ <case
+ latin:languageSwitchKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="languageSwitchKeyStyle"
+ latin:keyWidth="9.0%p"
+ latin:backgroundType="functional" />
+ </case>
+ </switch>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyXPos="25.5%p"
+ latin:keyWidth="49.0%p" />
+ <include
+ latin:keyXPos="-9.0%p"
+ latin:keyWidth="fillRight"
+ latin:keyboardLayout="@xml/key_shortcut" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml
new file mode 100644
index 000000000..fa433635e
--- /dev/null
+++ b/java/res/xml-sw600dp/row_qwerty4.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="9.0%p"
+ latin:backgroundType="functional"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/key_shortcut" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="28.0%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <include
+ latin:keyboardLayout="@xml/key_apostrophe" />
+ <include
+ latin:keyboardLayout="@xml/key_dash" />
+ <include
+ latin:keyboardLayout="@xml/key_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/row_symbols4.xml b/java/res/xml-sw600dp/row_symbols4.xml
new file mode 100644
index 000000000..73a5b1703
--- /dev/null
+++ b/java/res/xml-sw600dp/row_symbols4.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="9.0%p"
+ latin:backgroundType="functional"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <Key
+ latin:keyLabel="/" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="28.0%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <Key
+ latin:keyLabel="&quot;"
+ latin:moreKeys="!text/more_keys_for_tablet_double_quote" />
+ <Key
+ latin:keyLabel="_" />
+ <!-- Here is empty space. -->
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/row_symbols_shift4.xml b/java/res/xml-sw600dp/row_symbols_shift4.xml
new file mode 100644
index 000000000..6f3aac7c6
--- /dev/null
+++ b/java/res/xml-sw600dp/row_symbols_shift4.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="9.0%p"
+ latin:backgroundType="functional"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <!-- Here is empty space. -->
+ <include
+ latin:keyXPos="28.0%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <!-- Here is empty space. -->
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_arabic1.xml b/java/res/xml-sw600dp/rowkeys_arabic1.xml
new file mode 100644
index 000000000..44fdc676d
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_arabic1.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0636: "ض" ARABIC LETTER DAD -->
+ <Key
+ latin:keyLabel="&#x0636;" />
+ <!-- U+0635: "ص" ARABIC LETTER SAD -->
+ <Key
+ latin:keyLabel="&#x0635;" />
+ <!-- U+062B: "ث" ARABIC LETTER THEH -->
+ <Key
+ latin:keyLabel="&#x062B;" />
+ <!-- U+0642: "ق" ARABIC LETTER QAF
+ U+06A8: "ڨ" ARABIC LETTER QAF WITH THREE DOTS ABOVE -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+06A8 ARABIC LETTER QAF WITH THREE DOTS ABOVE -->
+ <Key
+ latin:keyLabel="&#x0642;"
+ latin:moreKeys="&#x06A8;" />
+ <!-- U+0641: "ف" ARABIC LETTER FEH
+ U+06A4: "ڤ" ARABIC LETTER VEH
+ U+06A2: "ڢ" ARABIC LETTER FEH WITH DOT MOVED BELOW
+ U+06A5: "ڥ" ARABIC LETTER FEH WITH THREE DOTS BELOW -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+06A2 ARABIC LETTER FEH WITH DOT MOVED BELOW -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+06A5 ARABIC LETTER FEH WITH THREE DOTS BELOW -->
+ <Key
+ latin:keyLabel="&#x0641;"
+ latin:moreKeys="&#x06A4;,&#x06A2;,&#x06A5;" />
+ <!-- U+063A: "غ" ARABIC LETTER GHAIN -->
+ <Key
+ latin:keyLabel="&#x063A;" />
+ <!-- U+0639: "ع" ARABIC LETTER AIN -->
+ <Key
+ latin:keyLabel="&#x0639;" />
+ <!-- U+0647: "ه" ARABIC LETTER HEH
+ U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM
+ U+0647 U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER -->
+ <Key
+ latin:keyLabel="&#x0647;"
+ latin:moreKeys="&#xFEEB;|&#x0647;&#x200D;" />
+ <!-- U+062E: "خ" ARABIC LETTER KHAH -->
+ <Key
+ latin:keyLabel="&#x062E;" />
+ <!-- U+062D: "ح" ARABIC LETTER HAH -->
+ <Key
+ latin:keyLabel="&#x062D;" />
+ <!-- U+062C: "ج" ARABIC LETTER JEEM
+ U+0686: "چ" ARABIC LETTER TCHEH -->
+ <Key
+ latin:keyLabel="&#x062C;"
+ latin:moreKeys="&#x0686;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_arabic2.xml b/java/res/xml-sw600dp/rowkeys_arabic2.xml
new file mode 100644
index 000000000..3eba2fbf3
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_arabic2.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0634: "ش" ARABIC LETTER SHEEN
+ U+069C: "ڜ" ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+069C ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE -->
+ <Key
+ latin:keyLabel="&#x0634;"
+ latin:moreKeys="&#x069C;" />
+ <!-- U+0633: "س" ARABIC LETTER SEEN -->
+ <Key
+ latin:keyLabel="&#x0633;" />
+ <!-- U+064A: "ي" ARABIC LETTER YEH
+ U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE
+ U+0649: "ى" ARABIC LETTER ALEF MAKSURA -->
+ <Key
+ latin:keyLabel="&#x064A;"
+ latin:moreKeys="&#x0626;,&#x0649;" />
+ <!-- U+0628: "ب" ARABIC LETTER BEH
+ U+067E: "پ" ARABIC LETTER PEH -->
+ <Key
+ latin:keyLabel="&#x0628;"
+ latin:moreKeys="&#x067E;" />
+ <!-- U+0644: "ل" ARABIC LETTER LAM
+ U+FEFB: "ﻻ" ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+ U+0627: "ا" ARABIC LETTER ALEF
+ U+FEF7: "ﻷ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+ U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
+ U+FEF9: "ﻹ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
+ U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW
+ U+FEF5: "ﻵ" ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+ U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0644;"
+ latin:moreKeys="&#xFEFB;|&#x0644;&#x0627;,&#xFEF7;|&#x0644;&#x0623;,&#xFEF9;|&#x0644;&#x0625;,&#xFEF5;|&#x0644;&#x0622;" />
+ <!-- U+0627: "ا" ARABIC LETTER ALEF
+ U+0621: "ء" ARABIC LETTER HAMZA
+ U+0671: "ٱ" ARABIC LETTER ALEF WASLA
+ U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
+ U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW
+ U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0627;"
+ latin:moreKeys="&#x0621;,&#x0671;,&#x0623;,&#x0625;,&#x0622;" />
+ <!-- U+062A: "ت" ARABIC LETTER TEH -->
+ <Key
+ latin:keyLabel="&#x062A;" />
+ <!-- U+0646: "ن" ARABIC LETTER NOON -->
+ <Key
+ latin:keyLabel="&#x0646;" />
+ <!-- U+0645: "م" ARABIC LETTER MEEM -->
+ <Key
+ latin:keyLabel="&#x0645;" />
+ <!-- U+0643: "ك" ARABIC LETTER KAF
+ U+06AF: "گ" ARABIC LETTER GAF
+ U+06A9: "ک" ARABIC LETTER KEHEH -->
+ <Key
+ latin:keyLabel="&#x0643;"
+ latin:moreKeys="&#x06AF;,&#x06A9;" />
+ <!-- U+0637: "ط" ARABIC LETTER TAH -->
+ <Key
+ latin:keyLabel="&#x0637;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_arabic3.xml b/java/res/xml-sw600dp/rowkeys_arabic3.xml
new file mode 100644
index 000000000..911550f4a
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_arabic3.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0626;" />
+ <!-- U+0621: "ء" ARABIC LETTER HAMZA -->
+ <Key
+ latin:keyLabel="&#x0621;" />
+ <!-- U+0624: "ؤ" ARABIC LETTER WAW WITH HAMZA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0624;" />
+ <!-- U+0631: "ر" ARABIC LETTER REH -->
+ <Key
+ latin:keyLabel="&#x0631;" />
+ <!-- U+0630: "ذ" ARABIC LETTER THAL -->
+ <Key
+ latin:keyLabel="&#x0630;" />
+ <!-- U+0649: "ى" ARABIC LETTER ALEF MAKSURA -->
+ <Key
+ latin:keyLabel="&#x0649;" />
+ <!-- U+0629: "ة" ARABIC LETTER TEH MARBUTA -->
+ <Key
+ latin:keyLabel="&#x0629;" />
+ <!-- U+0648: "و" ARABIC LETTER WAW -->
+ <Key
+ latin:keyLabel="&#x0648;" />
+ <!-- U+0632: "ز" ARABIC LETTER ZAIN
+ U+0698: "ژ" ARABIC LETTER JEH -->
+ <Key
+ latin:keyLabel="&#x0632;"
+ latin:moreKeys="&#x0698;" />
+ <!-- U+0638: "ظ" ARABIC LETTER ZAH -->
+ <Key
+ latin:keyLabel="&#x0638;" />
+ <!-- U+062F: "د" ARABIC LETTER DAL -->
+ <Key
+ latin:keyLabel="&#x062F;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_dvorak3.xml b/java/res/xml-sw600dp/rowkeys_dvorak3.xml
new file mode 100644
index 000000000..2148bb2c7
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_dvorak3.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="q" />
+ <Key
+ latin:keyLabel="j"
+ latin:moreKeys="!text/more_keys_for_j" />
+ <Key
+ latin:keyLabel="k"
+ latin:moreKeys="!text/more_keys_for_k" />
+ <Key
+ latin:keyLabel="x" />
+ <Key
+ latin:keyLabel="b" />
+ <Key
+ latin:keyLabel="m" />
+ <Key
+ latin:keyLabel="w"
+ latin:moreKeys="!text/more_keys_for_w" />
+ <Key
+ latin:keyLabel="v"
+ latin:moreKeys="!text/more_keys_for_v" />
+ <Key
+ latin:keyLabel="z"
+ latin:moreKeys="!text/more_keys_for_z" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_farsi1.xml b/java/res/xml-sw600dp/rowkeys_farsi1.xml
new file mode 100644
index 000000000..53208f286
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_farsi1.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0636: "ض" ARABIC LETTER DAD -->
+ <Key
+ latin:keyLabel="&#x0636;" />
+ <!-- U+0635: "ص" ARABIC LETTER SAD -->
+ <Key
+ latin:keyLabel="&#x0635;" />
+ <!-- U+062B: "ث" ARABIC LETTER THEH -->
+ <Key
+ latin:keyLabel="&#x062B;" />
+ <!-- U+0642: "ق" ARABIC LETTER QAF -->
+ <Key
+ latin:keyLabel="&#x0642;" />
+ <!-- U+0641: "ف" ARABIC LETTER FEH -->
+ <Key
+ latin:keyLabel="&#x0641;" />
+ <!-- U+063A: "غ" ARABIC LETTER GHAIN -->
+ <Key
+ latin:keyLabel="&#x063A;" />
+ <!-- U+0639: "ع" ARABIC LETTER AIN -->
+ <Key
+ latin:keyLabel="&#x0639;" />
+ <!-- U+0647: "ه" ARABIC LETTER HEH
+ U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM
+ U+0647/U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER
+ U+0647/U+0654: ARABIC LETTER HEH + ARABIC HAMZA ABOVE
+ U+0629: "ة" ARABIC LETTER TEH MARBUTA -->
+ <Key
+ latin:keyLabel="&#x0647;"
+ latin:moreKeys="&#xFEEB;|&#x0647;&#x200D;,&#x0647;&#x0654;,&#x0629;,%" />
+ <!-- U+062E: "خ" ARABIC LETTER KHAH -->
+ <Key
+ latin:keyLabel="&#x062E;" />
+ <!-- U+062D: "ح" ARABIC LETTER HAH -->
+ <Key
+ latin:keyLabel="&#x062D;" />
+ <!-- U+062C: "ج" ARABIC LETTER JEEM -->
+ <Key
+ latin:keyLabel="&#x062C;" />
+ <!-- U+0686: "چ" ARABIC LETTER TCHEH -->
+ <Key
+ latin:keyLabel="&#x0686;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_farsi2.xml b/java/res/xml-sw600dp/rowkeys_farsi2.xml
new file mode 100644
index 000000000..234f98430
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_farsi2.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0634: "ش" ARABIC LETTER SHEEN -->
+ <Key
+ latin:keyLabel="&#x0634;" />
+ <!-- U+0633: "س" ARABIC LETTER SEEN -->
+ <Key
+ latin:keyLabel="&#x0633;" />
+ <!-- U+06CC: "ی" ARABIC LETTER FARSI YEH
+ U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE
+ U+064A: "ي" ARABIC LETTER YEH
+ U+FBE8: "ﯨ" ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM
+ U+0649: "ى" ARABIC LETTER ALEF MAKSURA -->
+ <Key
+ latin:keyLabel="&#x06CC;"
+ latin:moreKeys="&#x0626;,&#x064A;,&#xFBE8;|&#x0649;" />
+ <!-- U+0628: "ب" ARABIC LETTER BEH -->
+ <Key
+ latin:keyLabel="&#x0628;" />
+ <!-- U+0644: "ل" ARABIC LETTER LAM -->
+ <Key
+ latin:keyLabel="&#x0644;" />
+ <!-- U+0627: "ا" ARABIC LETTER ALEF
+ U+0621: "ء" ARABIC LETTER HAMZA
+ U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE
+ U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
+ U+0671: "ٱ" ARABIC LETTER ALEF WASLA
+ U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW -->
+ <Key
+ latin:keyLabel="&#x0627;"
+ latin:moreKeys="&#x0621;,&#x0622;,&#x0623;,&#x0671;,&#x0625;" />
+ <!-- U+062A: "ت" ARABIC LETTER TEH
+ U+062B: "ﺙ" ARABIC LETTER THEH
+ U+0629: "ة": ARABIC LETTER TEH MARBUTA -->
+ <Key
+ latin:keyLabel="&#x062A;"
+ latin:moreKeys="&#x062B;,&#x0629;" />
+ <!-- U+0646: "ن" ARABIC LETTER NOON -->
+ <Key
+ latin:keyLabel="&#x0646;" />
+ <!-- U+0645: "م" ARABIC LETTER MEEM -->
+ <Key
+ latin:keyLabel="&#x0645;" />
+ <!-- U+06A9: "ک" ARABIC LETTER KEHEH
+ U+0643: "ك" ARABIC LETTER KAF -->
+ <Key
+ latin:keyLabel="&#x06A9;"
+ latin:moreKeys="&#x0643;" />
+ <!-- U+06AF: "گ" ARABIC LETTER GAF -->
+ <Key
+ latin:keyLabel="&#x06AF;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_farsi3.xml b/java/res/xml-sw600dp/rowkeys_farsi3.xml
new file mode 100644
index 000000000..998ba72d6
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_farsi3.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0638: "ظ" ARABIC LETTER ZAH -->
+ <Key
+ latin:keyLabel="&#x0638;" />
+ <!-- U+0637: "ط" ARABIC LETTER TAH -->
+ <Key
+ latin:keyLabel="&#x0637;" />
+ <!-- U+0698: "ژ" ARABIC LETTER JEH -->
+ <Key
+ latin:keyLabel="&#x0698;" />
+ <!-- U+0632: "ز" ARABIC LETTER ZAIN -->
+ <Key
+ latin:keyLabel="&#x0632;" />
+ <!-- U+0631: "ر" ARABIC LETTER REH -->
+ <Key
+ latin:keyLabel="&#x0631;" />
+ <!-- U+0630: "ذ" ARABIC LETTER THAL -->
+ <Key
+ latin:keyLabel="&#x0630;" />
+ <!-- U+062F: "د" ARABIC LETTER DAL -->
+ <Key
+ latin:keyLabel="&#x062F;" />
+ <!-- U+067E: "پ" ARABIC LETTER PEH -->
+ <Key
+ latin:keyLabel="&#x067E;" />
+ <!-- U+0648: "و" ARABIC LETTER WAW
+ U+0624: "ؤ" ARABIC LETTER WAW WITH HAMZA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0648;"
+ latin:moreKeys="&#x0624;" />
+ <!-- U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0622;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml b/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml
new file mode 100644
index 000000000..d486b9df0
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_pcqwerty1.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty_symbols1" />
+ </case>
+ <!-- keyboardLayoutSetElement="alphabet*" -->
+ <default>
+ <!-- U+00AC: "¬" NOT SIGN -->
+ <Key
+ latin:keyLabel="`"
+ latin:keyHintLabel="~"
+ latin:additionalMoreKeys="~"
+ latin:moreKeys="&#x00AC;"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <!-- U+00A1: "¡" NVERTED EXCLAMATION MARK -->
+ <Key
+ latin:keyLabel="1"
+ latin:keyHintLabel="!"
+ latin:additionalMoreKeys="!"
+ latin:moreKeys="&#x00A1;,!text/more_keys_for_symbols_1"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="2"
+ latin:keyHintLabel="\@"
+ latin:additionalMoreKeys="\@"
+ latin:moreKeys="!text/more_keys_for_symbols_2"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="3"
+ latin:keyHintLabel="#"
+ latin:additionalMoreKeys="#"
+ latin:moreKeys="!text/more_keys_for_symbols_3"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="4"
+ latin:keyHintLabel="$"
+ latin:additionalMoreKeys="$"
+ latin:moreKeys="!text/more_keys_for_symbols_4"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="5"
+ latin:keyHintLabel="%"
+ latin:additionalMoreKeys="\\%"
+ latin:moreKeys="!text/more_keys_for_symbols_5"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="6"
+ latin:keyHintLabel="^"
+ latin:additionalMoreKeys="^"
+ latin:moreKeys="!text/more_keys_for_symbols_6"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="7"
+ latin:keyHintLabel="&amp;"
+ latin:additionalMoreKeys="&amp;"
+ latin:moreKeys="!text/more_keys_for_symbols_7"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="8"
+ latin:keyHintLabel="*"
+ latin:additionalMoreKeys="*"
+ latin:moreKeys="!text/more_keys_for_symbols_8"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="9"
+ latin:keyHintLabel="("
+ latin:additionalMoreKeys="("
+ latin:moreKeys="!text/more_keys_for_symbols_9"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="0"
+ latin:keyHintLabel=")"
+ latin:additionalMoreKeys=")"
+ latin:moreKeys="!text/more_keys_for_symbols_0"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyHintLabel="_"
+ latin:moreKeys="_"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ <Key
+ latin:keyLabel="="
+ latin:keyHintLabel="+"
+ latin:moreKeys="+"
+ latin:keyStyle="hasShiftedLetterHintStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_symbols2.xml b/java/res/xml-sw600dp/rowkeys_symbols2.xml
new file mode 100644
index 000000000..d7067e0cf
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_symbols2.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:languageCode="fa"
+ >
+ <!-- U+066C: "٬" ARABIC THOUSANDS SEPARATOR -->
+ <Key
+ latin:keyLabel="&#x066C;"
+ latin:keyHintLabel="&amp;"
+ latin:keyLabelFlags="hasPopupHint|hasShiftedLetterHint"
+ latin:moreKeys="&amp;" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="#" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="currencyKeyStyle" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_percent"
+ latin:moreKeys="!text/more_keys_for_symbols_percent" />
+ <switch>
+ <case
+ latin:languageCode="fa"
+ >
+ <!-- U+066B: "٫" ARABIC DECIMAL SEPARATOR -->
+ <Key
+ latin:keyLabel="&#x066B;"
+ latin:keyHintLabel="#"
+ latin:keyLabelFlags="hasPopupHint|hasShiftedLetterHint"
+ latin:moreKeys="#" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="&amp;" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel="*"
+ latin:moreKeys="!text/more_keys_for_star" />
+ <!-- U+2013: "–" EN DASH
+ U+2014: "—" EM DASH -->
+ <Key
+ latin:keyLabel="-"
+ latin:moreKeys="_,&#x2013;,&#x2014;" />
+ <Key
+ latin:keyLabel="+"
+ latin:moreKeys="!text/more_keys_for_plus" />
+ <include
+ latin:keyboardLayout="@xml/keys_parentheses" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_symbols3.xml b/java/res/xml-sw600dp/rowkeys_symbols3.xml
new file mode 100644
index 000000000..4bfa0d730
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_symbols3.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/keys_less_greater" />
+ <!-- U+2260: "≠" NOT EQUAL TO
+ U+2248: "≈" ALMOST EQUAL TO -->
+ <Key
+ latin:keyLabel="="
+ latin:moreKeys="&#x2260;,&#x2248;" />
+ <switch>
+ <case
+ latin:mode="url"
+ >
+ <Key
+ latin:keyLabel="\'" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=":" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_semicolon"
+ latin:moreKeys="!text/more_keys_for_symbols_semicolon" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_comma"
+ latin:moreKeys="!text/more_keys_for_comma" />
+ <Key
+ latin:keyLabel="." />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_exclamation"
+ latin:moreKeys="!text/more_keys_for_symbols_exclamation" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_question"
+ latin:moreKeys="!text/more_keys_for_symbols_question" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_symbols_shift1.xml b/java/res/xml-sw600dp/rowkeys_symbols_shift1.xml
new file mode 100644
index 000000000..3549fdda4
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_symbols_shift1.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="~" />
+ <Key
+ latin:keyLabel="`" />
+ <Key
+ latin:keyLabel="|" />
+ <!-- U+2022: "•" BULLET -->
+ <Key
+ latin:keyLabel="&#x2022;"
+ latin:moreKeys="!text/more_keys_for_bullet" />
+ <!-- U+221A: "√" SQUARE ROOT -->
+ <Key
+ latin:keyLabel="&#x221A;" />
+ <!-- U+03C0: "π" GREEK SMALL LETTER PI
+ U+03A0: "Π" GREEK CAPITAL LETTER PI -->
+ <Key
+ latin:keyLabel="&#x03C0;"
+ latin:moreKeys="&#x03A0;" />
+ <!-- U+00F7: "÷" DIVISION SIGN -->
+ <Key
+ latin:keyLabel="&#x00F7;" />
+ <!-- U+00D7: "×" MULTIPLICATION SIGN -->
+ <Key
+ latin:keyLabel="&#x00D7;" />
+ <!-- U+00A7: "§" SECTION SIGN
+ U+00B6: "¶" PILCROW SIGN -->
+ <Key
+ latin:keyLabel="&#x00A7;"
+ latin:moreKeys="&#x00B6;" />
+ <!-- U+0394: "Δ" GREEK CAPITAL LETTER DELTA -->
+ <Key
+ latin:keyLabel="&#x0394;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_symbols_shift2.xml b/java/res/xml-sw600dp/rowkeys_symbols_shift2.xml
new file mode 100644
index 000000000..2048b7335
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_symbols_shift2.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyStyle="moreCurrency1KeyStyle" />
+ <Key
+ latin:keyStyle="moreCurrency2KeyStyle" />
+ <Key
+ latin:keyStyle="moreCurrency3KeyStyle" />
+ <Key
+ latin:keyStyle="moreCurrency4KeyStyle" />
+ <!-- U+2191: "↑" UPWARDS ARROW
+ U+2193: "↓" DOWNWARDS ARROW
+ U+2190: "←" LEFTWARDS ARROW
+ U+2192: "→" RIGHTWARDS ARROW -->
+ <Key
+ latin:keyLabel="^"
+ latin:moreKeys="&#x2191;,&#x2193;,&#x2190;,&#x2192;" />
+ <!-- U+00B0: "°" DEGREE SIGN
+ U+2032: "′" PRIME
+ U+2033: "″" DOUBLE PRIME -->
+ <Key
+ latin:keyLabel="&#x00B0;"
+ latin:moreKeys="&#x2032;,&#x2033;" />
+ <!-- U+00B1: "±" PLUS-MINUS SIGN
+ U+221E: "∞" INFINITY -->
+ <Key
+ latin:keyLabel="&#x00B1;"
+ latin:moreKeys="&#x221E;" />
+ <include
+ latin:keyboardLayout="@xml/keys_curly_brackets" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_symbols_shift3.xml b/java/res/xml-sw600dp/rowkeys_symbols_shift3.xml
new file mode 100644
index 000000000..8bd865639
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_symbols_shift3.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="\\" />
+ <!-- U+00A9: "©" COPYRIGHT SIGN -->
+ <Key
+ latin:keyLabel="&#x00A9;" />
+ <!-- U+00AE: "®" REGISTERED SIGN -->
+ <Key
+ latin:keyLabel="&#x00AE;" />
+ <!-- U+2122: "™" TRADE MARK SIGN -->
+ <Key
+ latin:keyLabel="&#x2122;" />
+ <!-- U+2105: "℅" CARE OF -->
+ <Key
+ latin:keyLabel="&#x2105;" />
+ <include
+ latin:keyboardLayout="@xml/keys_square_brackets" />
+ <!-- U+00A1: "¡" INVERTED EXCLAMATION MARK -->
+ <Key
+ latin:keyLabel="&#x00A1;" />
+ <!-- U+00BF: "¿" INVERTED QUESTION MARK -->
+ <Key
+ latin:keyLabel="&#x00BF;" />
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_thai1.xml b/java/res/xml-sw600dp/rowkeys_thai1.xml
new file mode 100644
index 000000000..6aec7c2c5
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_thai1.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0E51: "๑" THAI DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x0E51;" />
+ <!-- U+0E52: "๒" THAI DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x0E52;" />
+ <!-- U+0E53: "๓" THAI DIGIT THREE -->
+ <Key
+ latin:keyLabel="&#x0E53;" />
+ <!-- U+0E54: "๔" THAI DIGIT FOUR -->
+ <Key
+ latin:keyLabel="&#x0E54;" />
+ <!-- U+0E39: " ู" THAI CHARACTER SARA UU -->
+ <Key
+ latin:keyLabel="&#x0E39;" />
+ <!-- U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT -->
+ <Key
+ latin:keyLabel="&#x0E3F;" />
+ <!-- U+0E55: "๕" THAI DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x0E55;" />
+ <!-- U+0E56: "๖" THAI DIGIT SIX -->
+ <Key
+ latin:keyLabel="&#x0E56;" />
+ <!-- U+0E57: "๗" THAI DIGIT SEVEN -->
+ <Key
+ latin:keyLabel="&#x0E57;" />
+ <!-- U+0E58: "๘" THAI DIGIT EIGHT -->
+ <Key
+ latin:keyLabel="&#x0E58;" />
+ <!-- U+0E59: "๙" THAI DIGIT NINE -->
+ <Key
+ latin:keyLabel="&#x0E59;" />
+ </case>
+ <default>
+ <!-- U+0E45: "ๅ" THAI CHARACTER LAKKHANGYAO -->
+ <Key
+ latin:keyLabel="&#x0E45;" />
+ <Key
+ latin:keyLabel="/" />
+ <!-- U+0E20: "ภ" THAI CHARACTER PHO SAMPHAO -->
+ <Key
+ latin:keyLabel="&#x0E20;" />
+ <!-- U+0E16: "ถ" THAI CHARACTER THO THUNG -->
+ <Key
+ latin:keyLabel="&#x0E16;" />
+ <!-- U+0E38: " ุ" THAI CHARACTER SARA U -->
+ <Key
+ latin:keyLabel="&#x0E38;" />
+ <!-- U+0E36: " ึ" THAI CHARACTER SARA UE -->
+ <Key
+ latin:keyLabel="&#x0E36;" />
+ <!-- U+0E04: "ค" THAI CHARACTER KHO KHWAI -->
+ <Key
+ latin:keyLabel="&#x0E04;" />
+ <!-- U+0E15: "ต" THAI CHARACTER TO TAO -->
+ <Key
+ latin:keyLabel="&#x0E15;" />
+ <!-- U+0E08: "จ" THAI CHARACTER CHO CHAN -->
+ <Key
+ latin:keyLabel="&#x0E08;" />
+ <!-- U+0E02: "ข" THAI CHARACTER KHO KHAI -->
+ <Key
+ latin:keyLabel="&#x0E02;" />
+ <!-- U+0E0A: "ช" THAI CHARACTER CHO CHANG -->
+ <Key
+ latin:keyLabel="&#x0E0A;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_thai2.xml b/java/res/xml-sw600dp/rowkeys_thai2.xml
new file mode 100644
index 000000000..edb759a89
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_thai2.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0E50: "๐" THAI DIGIT ZERO -->
+ <Key
+ latin:keyLabel="&#x0E50;" />
+ <Key
+ latin:keyLabel="&quot;" />
+ <!-- U+0E0E: "ฎ" THAI CHARACTER DO CHADA -->
+ <Key
+ latin:keyLabel="&#x0E0E;" />
+ <!-- U+0E11: "ฑ" THAI CHARACTER THO NANGMONTHO -->
+ <Key
+ latin:keyLabel="&#x0E11;" />
+ <!-- U+0E18: "ธ" THAI CHARACTER THO THONG -->
+ <Key
+ latin:keyLabel="&#x0E18;" />
+ <!-- U+0E4D: " ํ" THAI CHARACTER THANTHAKHAT -->
+ <Key
+ latin:keyLabel="&#x0E4D;" />
+ <!-- U+0E4A: " ๊" THAI CHARACTER MAI TRI -->
+ <Key
+ latin:keyLabel="&#x0E4A;" />
+ <!-- U+0E13: "ณ" THAI CHARACTER NO NEN -->
+ <Key
+ latin:keyLabel="&#x0E13;" />
+ <!-- U+0E2F: "ฯ" THAI CHARACTER PAIYANNOI -->
+ <Key
+ latin:keyLabel="&#x0E2F;" />
+ <!-- U+0E0D: "ญ" THAI CHARACTER YO YING -->
+ <Key
+ latin:keyLabel="&#x0E0D;" />
+ <!-- U+0E10: "ฐ" THAI CHARACTER THO THAN -->
+ <Key
+ latin:keyLabel="&#x0E10;" />
+ <Key
+ latin:keyLabel="," />
+ <!-- U+0E05: "ฅ" THAI CHARACTER KHO KHON -->
+ <Key
+ latin:keyLabel="&#x0E05;" />
+ </case>
+ <default>
+ <!-- U+0E46: "ๆ" THAI CHARACTER MAIYAMOK -->
+ <Key
+ latin:keyLabel="&#x0E46;" />
+ <!-- U+0E44: "ไ" THAI CHARACTER SARA AI MAIMALAI -->
+ <Key
+ latin:keyLabel="&#x0E44;" />
+ <!-- U+0E33: "ำ" THAI CHARACTER SARA AM -->
+ <Key
+ latin:keyLabel="&#x0E33;" />
+ <!-- U+0E1E: "พ" THAI CHARACTER PHO PHAN -->
+ <Key
+ latin:keyLabel="&#x0E1E;" />
+ <!-- U+0E30: "ะ" THAI CHARACTER SARA A -->
+ <Key
+ latin:keyLabel="&#x0E30;" />
+ <!-- U+0E31: " ั" THAI CHARACTER MAI HAN-AKAT -->
+ <Key
+ latin:keyLabel="&#x0E31;" />
+ <!-- U+0E35: " ี" HAI CHARACTER SARA II -->
+ <Key
+ latin:keyLabel="&#x0E35;" />
+ <!-- U+0E23: "ร" THAI CHARACTER RO RUA -->
+ <Key
+ latin:keyLabel="&#x0E23;" />
+ <!-- U+0E19: "น" THAI CHARACTER NO NU -->
+ <Key
+ latin:keyLabel="&#x0E19;" />
+ <!-- U+0E22: "ย" THAI CHARACTER YO YAK -->
+ <Key
+ latin:keyLabel="&#x0E22;" />
+ <!-- U+0E1A: "บ" THAI CHARACTER BO BAIMAI -->
+ <Key
+ latin:keyLabel="&#x0E1A;" />
+ <!-- U+0E25: "ล" THAI CHARACTER LO LING -->
+ <Key
+ latin:keyLabel="&#x0E25;" />
+ <!-- U+0E03: "ฃ" THAI CHARACTER KHO KHUAT -->
+ <Key
+ latin:keyLabel="&#x0E03;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_thai3.xml b/java/res/xml-sw600dp/rowkeys_thai3.xml
new file mode 100644
index 000000000..7507dde86
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_thai3.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0E24: "ฤ" THAI CHARACTER RU -->
+ <Key
+ latin:keyLabel="&#x0E24;" />
+ <!-- U+0E06: "ฆ" THAI CHARACTER KHO RAKHANG -->
+ <Key
+ latin:keyLabel="&#x0E06;" />
+ <!-- U+0E0F: "ฏ" THAI CHARACTER TO PATAK -->
+ <Key
+ latin:keyLabel="&#x0E0F;" />
+ <!-- U+0E42: "โ" THAI CHARACTER SARA O -->
+ <Key
+ latin:keyLabel="&#x0E42;" />
+ <!-- U+0E0C: "ฌ" THAI CHARACTER CHO CHOE -->
+ <Key
+ latin:keyLabel="&#x0E0C;" />
+ <!-- U+0E47: " ็" THAI CHARACTER MAITAIKHU -->
+ <Key
+ latin:keyLabel="&#x0E47;" />
+ <!-- U+0E4B: " ๋" THAI CHARACTER MAI CHATTAWA -->
+ <Key
+ latin:keyLabel="&#x0E4B;" />
+ <!-- U+0E29: "ษ" THAI CHARACTER SO RUSI -->
+ <Key
+ latin:keyLabel="&#x0E29;" />
+ <!-- U+0E28: "ศ" THAI CHARACTER SO SALA -->
+ <Key
+ latin:keyLabel="&#x0E28;" />
+ <!-- U+0E0B: "ซ" THAI CHARACTER SO SO -->
+ <Key
+ latin:keyLabel="&#x0E0B;" />
+ <Key
+ latin:keyLabel="." />
+ </case>
+ <default>
+ <!-- U+0E1F: "ฟ" THAI CHARACTER FO FAN -->
+ <Key
+ latin:keyLabel="&#x0E1F;" />
+ <!-- U+0E2B: "ห" THAI CHARACTER HO HIP -->
+ <Key
+ latin:keyLabel="&#x0E2B;" />
+ <!-- U+0E01: "ก" THAI CHARACTER KO KAI -->
+ <Key
+ latin:keyLabel="&#x0E01;" />
+ <!-- U+0E14: "ด" THAI CHARACTER DO DEK -->
+ <Key
+ latin:keyLabel="&#x0E14;" />
+ <!-- U+0E40: "เ" THAI CHARACTER SARA E -->
+ <Key
+ latin:keyLabel="&#x0E40;" />
+ <!-- U+0E49: " ้" THAI CHARACTER MAI THO -->
+ <Key
+ latin:keyLabel="&#x0E49;" />
+ <!-- U+0E48: " ฺ" THAI CHARACTER MAI EK -->
+ <Key
+ latin:keyLabel="&#x0E48;" />
+ <!-- U+0E32: "า" THAI CHARACTER SARA AA -->
+ <Key
+ latin:keyLabel="&#x0E32;" />
+ <!-- U+0E2A: "ส" THAI CHARACTER SO SUA -->
+ <Key
+ latin:keyLabel="&#x0E2A;" />
+ <!-- U+0E27: "ว" THAI CHARACTER WO WAEN -->
+ <Key
+ latin:keyLabel="&#x0E27;" />
+ <!-- U+0E07: "ง" THAI CHARACTER NGO NGU -->
+ <Key
+ latin:keyLabel="&#x0E07;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/rowkeys_thai4.xml b/java/res/xml-sw600dp/rowkeys_thai4.xml
new file mode 100644
index 000000000..64549bdce
--- /dev/null
+++ b/java/res/xml-sw600dp/rowkeys_thai4.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel="(" />
+ <Key
+ latin:keyLabel=")" />
+ <!-- U+0E09: "ฉ" THAI CHARACTER CHO CHING -->
+ <Key
+ latin:keyLabel="&#x0E09;" />
+ <!-- U+0E2E: "ฮ" THAI CHARACTER HO NOKHUK -->
+ <Key
+ latin:keyLabel="&#x0E2E;" />
+ <!-- U+0E3A: " ฺ" THAI CHARACTER PHINTHU -->
+ <Key
+ latin:keyLabel="&#x0E3A;" />
+ <!-- U+0E4C: " ์" THAI CHARACTER THANTHAKHAT -->
+ <Key
+ latin:keyLabel="&#x0E4C;" />
+ <Key
+ latin:keyLabel="\?" />
+ <!-- U+0E12: "ฒ" THAI CHARACTER THO PHUTHAO -->
+ <Key
+ latin:keyLabel="&#x0E12;" />
+ <!-- U+0E2C: "ฬ" THAI CHARACTER LO CHULA -->
+ <Key
+ latin:keyLabel="&#x0E2C;" />
+ <!-- U+0E26: "ฦ" THAI CHARACTER LU -->
+ <Key
+ latin:keyLabel="&#x0E26;" />
+ </case>
+ <default>
+ <!-- U+0E1C: "ผ" THAI CHARACTER PHO PHUNG -->
+ <Key
+ latin:keyLabel="&#x0E1C;" />
+ <!-- U+0E1B: "ป" THAI CHARACTER PO PLA -->
+ <Key
+ latin:keyLabel="&#x0E1B;" />
+ <!-- U+0E41: "แ" THAI CHARACTER SARA AE -->
+ <Key
+ latin:keyLabel="&#x0E41;" />
+ <!-- U+0E2D: "อ" THAI CHARACTER O ANG -->
+ <Key
+ latin:keyLabel="&#x0E2D;" />
+ <!-- U+0E34: " ิ" THAI CHARACTER SARA I -->
+ <Key
+ latin:keyLabel="&#x0E34;" />
+ <!-- U+0E37: " ื" THAI CHARACTER SARA UEE -->
+ <Key
+ latin:keyLabel="&#x0E37;" />
+ <!-- U+0E17: "ท" THAI CHARACTER THO THAHAN -->
+ <Key
+ latin:keyLabel="&#x0E17;" />
+ <!-- U+0E21: "ม" THAI CHARACTER MO MA -->
+ <Key
+ latin:keyLabel="&#x0E21;" />
+ <!-- U+0E43: "ใ" THAI CHARACTER SARA AI MAIMUAN -->
+ <Key
+ latin:keyLabel="&#x0E43;" />
+ <!-- U+0E1D: "ฝ" THAI CHARACTER FO FA -->
+ <Key
+ latin:keyLabel="&#x0E1D;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/rows_10_10_7_symbols.xml b/java/res/xml-sw600dp/rows_10_10_7_symbols.xml
new file mode 100644
index 000000000..44c967c04
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_10_10_7_symbols.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols3" />
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml b/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml
new file mode 100644
index 000000000..3d3b59f22
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols_shift4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_arabic.xml b/java/res/xml-sw600dp/rows_arabic.xml
new file mode 100644
index 000000000..ec7c2ad96
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_arabic.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<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_arabic1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic3"
+ latin:keyXPos="4.091%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_azerty.xml b/java/res/xml-sw600dp/rows_azerty.xml
new file mode 100644
index 000000000..824ee38f3
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_azerty.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_bulgarian.xml b/java/res/xml-sw600dp/rows_bulgarian.xml
new file mode 100644
index 000000000..72532369c
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_bulgarian.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_bulgarian_bds.xml b/java/res/xml-sw600dp/rows_bulgarian_bds.xml
new file mode 100644
index 000000000..db6220e8e
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_bulgarian_bds.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_colemak.xml b/java/res/xml-sw600dp/rows_colemak.xml
new file mode 100644
index 000000000..f7e903bb5
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_colemak.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <include
+ latin:keyboardLayout="@xml/key_colemak_colon" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_dvorak.xml b/java/res/xml-sw600dp/rows_dvorak.xml
new file mode 100644
index 000000000..2fa8eb205
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_dvorak.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/keys_dvorak_123" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak3" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_dvorak4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_east_slavic.xml b/java/res/xml-sw600dp/rows_east_slavic.xml
new file mode 100644
index 000000000..309625516
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_east_slavic.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<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_east_slavic1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_farsi.xml b/java/res/xml-sw600dp/rows_farsi.xml
new file mode 100644
index 000000000..52c2d9329
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_farsi.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi1" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi2" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi3"
+ latin:keyXPos="4.091%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_georgian.xml b/java/res/xml-sw600dp/rows_georgian.xml
new file mode 100644
index 000000000..61d3eb05a
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_georgian.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian2"
+ latin:keyXPos="4.5%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_greek.xml b/java/res/xml-sw600dp/rows_greek.xml
new file mode 100644
index 000000000..6a10228fb
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_greek.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_greek_semicolon" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek2"
+ latin:keyXPos="4.5%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_hebrew.xml b/java/res/xml-sw600dp/rows_hebrew.xml
new file mode 100644
index 000000000..f9e6f51ab
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_hebrew.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_apostrophe" />
+ <include
+ latin:keyboardLayout="@xml/key_dash" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew3"
+ latin:keyXPos="10.0%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_hebrew4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_hindi.xml b/java/res/xml-sw600dp/rows_hindi.xml
new file mode 100644
index 000000000..967846519
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_hindi.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_nordic.xml b/java/res/xml-sw600dp/rows_nordic.xml
new file mode 100644
index 000000000..43144030f
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_nordic.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<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_nordic1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_nordic2" />
+ <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_qwerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <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-sw600dp/rows_number_normal.xml b/java/res/xml-sw600dp/rows_number_normal.xml
new file mode 100644
index 000000000..48b304089
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_number_normal.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row>
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="1"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="31%p" />
+ <Key
+ latin:keyLabel="2"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="3"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-14%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="/"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <switch>
+ <case
+ latin:mode="time|datetime"
+ >
+ <Key
+ latin:keyLabel=","
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_am_pm"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel="4"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="31%p" />
+ <Key
+ latin:keyLabel="5"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="6"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyXPos="-14%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <switch>
+ <case
+ latin:mode="time|datetime"
+ >
+ <Key
+ latin:keyLabel=":"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="="
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel="7"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="31%p" />
+ <Key
+ latin:keyLabel="8"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="9"
+ latin:keyStyle="numKeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="30%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="31%p" />
+ <Key
+ latin:keyLabel="0"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/rows_number_password.xml b/java/res/xml-sw600dp/rows_number_password.xml
new file mode 100644
index 000000000..6c3855a01
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_number_password.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="23%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="23%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="23%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="23%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw600dp/rows_pcqwerty.xml b/java/res/xml-sw600dp/rows_pcqwerty.xml
new file mode 100644
index 000000000..fa6080a19
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_pcqwerty.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyWidth="9.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabel="!text/label_to_symbol_key_pcqwerty"
+ latin:keyWidth="12.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty4" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyXPos="-15.0%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_pcqwerty5" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml b/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml
new file mode 100644
index 000000000..5e1aa6382
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_pcqwerty_symbols.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyWidth="9.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="12.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty4"
+ latin:keyXPos="15.0%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_pcqwerty5" />
+</merge>
diff --git a/java/res/xml-large/kbd_phone.xml b/java/res/xml-sw600dp/rows_phone.xml
index dd53a206a..dcc4fde7d 100644
--- a/java/res/xml-large/kbd_phone.xml
+++ b/java/res/xml-sw600dp/rows_phone.xml
@@ -18,107 +18,105 @@
*/
-->
-<Keyboard
+<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="16.75%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
+ latin:keyboardLayout="@xml/key_styles_common" />
<include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <!-- This row is intentionally not marked as a top row -->
+ latin:keyboardLayout="@xml/key_styles_number" />
<Row>
<Key
latin:keyLabel="-"
latin:keyStyle="numKeyStyle"
- latin:keyXPos="15.625%p"
- latin:keyWidth="9.25%p" />
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel="+"
latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyStyle="numPauseKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="num1KeyStyle"
- latin:keyXPos="38.867%p" />
+ latin:keyXPos="31%p" />
<Key
latin:keyStyle="num2KeyStyle" />
<Key
latin:keyStyle="num3KeyStyle" />
<Key
latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
+ latin:keyXPos="-14%p"
+ latin:keyWidth="fillRight" />
</Row>
<Row>
<Key
latin:keyLabel=","
latin:keyStyle="numKeyStyle"
- latin:keyXPos="15.625%p"
- latin:keyWidth="9.25%p" />
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel="."
latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyStyle="numWaitKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="num4KeyStyle"
- latin:keyXPos="38.867%p" />
+ latin:keyXPos="31%p" />
<Key
latin:keyStyle="num5KeyStyle" />
<Key
latin:keyStyle="num6KeyStyle" />
<Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.00%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
+ latin:keyStyle="enterKeyStyle"
+ latin:keyXPos="-14%p"
+ latin:keyWidth="fillRight" />
</Row>
<Row>
<Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="11.0%p"
- latin:keyEdgeFlags="left" />
- <!-- There is an empty area below the "More" key and left of the "(" key. To ignore
- the touch event on the area, "(" is intentionally not marked as a left edge key. -->
- <Key
latin:keyLabel="("
latin:keyStyle="numKeyStyle"
- latin:keyXPos="15.625%p"
- latin:keyWidth="9.25%p" />
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel=")"
latin:keyStyle="numKeyStyle"
- latin:keyWidth="9.25%p" />
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="N"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="10%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="num7KeyStyle"
- latin:keyXPos="38.867%p" />
+ latin:keyXPos="31%p" />
<Key
latin:keyStyle="num8KeyStyle" />
<Key
latin:keyStyle="num9KeyStyle" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer />
+ </Row>
<Row>
<Key
- latin:keyStyle="tabKeyStyle"
- latin:keyWidth="11.00%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="15.625%p"
- latin:keyWidth="18.67%p" />
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="30%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="38.867%p" />
+ latin:keyXPos="31%p" />
<Key
latin:keyStyle="num0KeyStyle" />
<Key
latin:keyLabel="#"
latin:keyStyle="numKeyStyle" />
- <Spacer
- latin:keyXPos="-11.00%p"
- latin:keyWidth="0%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f2" />
</Row>
-</Keyboard>
+</merge>
diff --git a/java/res/xml-sw600dp/rows_qwerty.xml b/java/res/xml-sw600dp/rows_qwerty.xml
new file mode 100644
index 000000000..bac02fd9a
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_qwerty.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2"
+ latin:keyXPos="4.5%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_qwertz.xml b/java/res/xml-sw600dp/rows_qwertz.xml
new file mode 100644
index 000000000..98ddd0843
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_qwertz.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2"
+ latin:keyXPos="4.5%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_south_slavic.xml b/java/res/xml-sw600dp/rows_south_slavic.xml
new file mode 100644
index 000000000..e53a2ee92
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_south_slavic.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<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_south_slavic1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_spanish.xml b/java/res/xml-sw600dp/rows_spanish.xml
new file mode 100644
index 000000000..b48ee0155
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_spanish.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_spanish2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_symbols.xml b/java/res/xml-sw600dp/rows_symbols.xml
new file mode 100644
index 000000000..3d0593dab
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_symbols.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols2"
+ latin:keyXPos="4.5%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols3" />
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_symbols_shift.xml b/java/res/xml-sw600dp/rows_symbols_shift.xml
new file mode 100644
index 000000000..0050c0c15
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_symbols_shift.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift2"
+ latin:keyXPos="4.5%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="9.0%p"
+ >
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols_shift4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_thai.xml b/java/res/xml-sw600dp/rows_thai.xml
new file mode 100644
index 000000000..c1fe55b39
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_thai.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.5%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai1"
+ latin:keyXPos="3.75%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.5%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai2"
+ latin:keyXPos="0.719%p" />
+ </Row>
+ <Row
+ latin:keyWidth="7.5%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai3"
+ latin:keyXPos="3.75%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.5%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai4" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-xlarge-land/kbd_popup_template.xml b/java/res/xml-sw768dp-land/kbd_more_keys_keyboard_template.xml
index 3caae1a60..f593fa944 100644
--- a/java/res/xml-xlarge-land/kbd_popup_template.xml
+++ b/java/res/xml-sw768dp-land/kbd_more_keys_keyboard_template.xml
@@ -20,8 +20,7 @@
<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
latin:keyWidth="3.5%p"
- latin:horizontalGap="0px"
- latin:verticalGap="0px"
latin:rowHeight="@dimen/popup_key_height"
+ style="?attr/moreKeysKeyboardStyle"
>
</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_number.xml b/java/res/xml-sw768dp-land/kbd_number.xml
new file mode 100644
index 000000000..3ad25a392
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_number.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="13.250%p"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_number" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_phone.xml b/java/res/xml-sw768dp-land/kbd_phone.xml
new file mode 100644
index 000000000..abe7e7c41
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_phone.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="13.250%p"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_phone" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_phone_symbols.xml b/java/res/xml-sw768dp-land/kbd_phone_symbols.xml
new file mode 100644
index 000000000..641464dbe
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_phone_symbols.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyboardHorizontalEdgesPadding="10%p"
+ latin:keyWidth="13.250%p"
+>
+ <!-- Tablet doesn't have phone symbols keyboard -->
+ <include
+ latin:keyboardLayout="@xml/rows_phone" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_thai.xml b/java/res/xml-sw768dp-land/kbd_thai.xml
new file mode 100644
index 000000000..b2cdbc373
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_thai.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="2.65%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_thai_symbols.xml b/java/res/xml-sw768dp-land/kbd_thai_symbols.xml
new file mode 100644
index 000000000..1531458ea
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_thai_symbols.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="2.65%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai_symbols" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml b/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml
new file mode 100644
index 000000000..fa30f24c0
--- /dev/null
+++ b/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="2.65%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai_symbols_shift" />
+</Keyboard>
diff --git a/java/res/xml-xlarge/kbd_popup_template.xml b/java/res/xml-sw768dp/kbd_more_keys_keyboard_template.xml
index 7d39d1a3a..f89a0a673 100644
--- a/java/res/xml-xlarge/kbd_popup_template.xml
+++ b/java/res/xml-sw768dp/kbd_more_keys_keyboard_template.xml
@@ -20,8 +20,7 @@
<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
latin:keyWidth="5.0%p"
- latin:horizontalGap="0px"
- latin:verticalGap="0px"
latin:rowHeight="@dimen/popup_key_height"
+ style="?attr/moreKeysKeyboardStyle"
>
</Keyboard>
diff --git a/java/res/xml-iw/kbd_qwerty.xml b/java/res/xml-sw768dp/kbd_number.xml
index dc2c5d35a..b20123c80 100644
--- a/java/res/xml-iw/kbd_qwerty.xml
+++ b/java/res/xml-sw768dp/kbd_number.xml
@@ -20,8 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="iw"
+ latin:keyWidth="13.250%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_hebrew" />
+ latin:keyboardLayout="@xml/rows_number" />
</Keyboard>
diff --git a/java/res/xml-nb/kbd_qwerty.xml b/java/res/xml-sw768dp/kbd_phone.xml
index 1f4e86e89..fa9bf1bf4 100644
--- a/java/res/xml-nb/kbd_qwerty.xml
+++ b/java/res/xml-sw768dp/kbd_phone.xml
@@ -20,8 +20,8 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="nb"
+ latin:keyWidth="13.250%p"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
+ latin:keyboardLayout="@xml/rows_phone" />
</Keyboard>
diff --git a/java/res/xml-da/kbd_qwerty.xml b/java/res/xml-sw768dp/kbd_phone_symbols.xml
index 37a50fdfd..e1a359e84 100644
--- a/java/res/xml-da/kbd_qwerty.xml
+++ b/java/res/xml-sw768dp/kbd_phone_symbols.xml
@@ -20,8 +20,9 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="da"
+ latin:keyWidth="13.250%p"
>
+ <!-- Tablet doesn't have phone symbols keyboard -->
<include
- latin:keyboardLayout="@xml/kbd_rows_scandinavian" />
+ latin:keyboardLayout="@xml/rows_phone" />
</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_thai.xml b/java/res/xml-sw768dp/kbd_thai.xml
new file mode 100644
index 000000000..593ccbd48
--- /dev/null
+++ b/java/res/xml-sw768dp/kbd_thai.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="2.95%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_thai_symbols.xml b/java/res/xml-sw768dp/kbd_thai_symbols.xml
new file mode 100644
index 000000000..e2e5f5d56
--- /dev/null
+++ b/java/res/xml-sw768dp/kbd_thai_symbols.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="2.95%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai_symbols" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml b/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml
new file mode 100644
index 000000000..a1358d4a2
--- /dev/null
+++ b/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="2.95%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai_symbols_shift" />
+</Keyboard>
diff --git a/java/res/xml-sw768dp/key_settings.xml b/java/res/xml-sw768dp/key_settings.xml
new file mode 100644
index 000000000..0d3bb59a4
--- /dev/null
+++ b/java/res/xml-sw768dp/key_settings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:clobberSettingsKey="false"
+ >
+ <Key
+ latin:keyStyle="settingsKeyStyle" />
+ </case>
+ <default>
+ <Spacer />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw768dp/key_shortcut.xml b/java/res/xml-sw768dp/key_shortcut.xml
new file mode 100644
index 000000000..2d09ebbfc
--- /dev/null
+++ b/java/res/xml-sw768dp/key_shortcut.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:shortcutKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle" />
+ </case>
+ <default>
+ <!-- The empty space instead of shortcut key. -->
+ <Spacer />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw768dp/key_space.xml b/java/res/xml-sw768dp/key_space.xml
new file mode 100644
index 000000000..8968f080a
--- /dev/null
+++ b/java/res/xml-sw768dp/key_space.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:languageCode="fa"
+ >
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="32.188%p" />
+ <!-- U+200C: "" ZERO WIDTH NON-JOINER
+ U+200D: "" ZERO WIDTH JOINER -->
+ <Key
+ latin:keyStyle="zwnjKeyStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="40.235%p" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml
new file mode 100644
index 000000000..40082ac35
--- /dev/null
+++ b/java/res/xml-sw768dp/key_styles_common.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="hasShiftedLetterHintStyle"
+ latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="hasShiftedLetterHintStyle"
+ latin:keyLabelFlags="hasShiftedLetterHint" />
+ </default>
+ </switch>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+ >
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key_shifted"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOff" />
+ </case>
+ <case
+ latin:keyboardLayoutSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key_shifted"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOn" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOff" />
+ </default>
+ </switch>
+ <key-style
+ latin:styleName="deleteKeyStyle"
+ latin:code="!code/key_delete"
+ latin:keyIcon="!icon/delete_key"
+ latin:keyActionFlags="isRepeatable|noKeyPreview"
+ latin:backgroundType="functional" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_enter" />
+ <key-style
+ latin:styleName="spaceKeyStyle"
+ latin:code="!code/key_space"
+ latin:keyActionFlags="noKeyPreview" />
+ <!-- U+200C: ZERO WIDTH NON-JOINER
+ U+200D: ZERO WIDTH JOINER -->
+ <key-style
+ latin:styleName="zwnjKeyStyle"
+ latin:code="0x200C"
+ latin:keyIcon="!icon/zwnj_key"
+ latin:moreKeys="!icon/zwj_key|&#x200D;"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:keyActionFlags="noKeyPreview" />
+ <key-style
+ latin:styleName="smileyKeyStyle"
+ latin:keyLabel=":-)"
+ latin:keyOutputText=":-) "
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/more_keys_for_smiley" />
+ <key-style
+ latin:styleName="shortcutKeyStyle"
+ latin:code="!code/key_shortcut"
+ latin:keyIcon="!icon/shortcut_key"
+ latin:keyIconDisabled="!icon/shortcut_key_disabled"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="settingsKeyStyle"
+ latin:code="!code/key_settings"
+ latin:keyIcon="!icon/settings_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ latin:navigatePrevious="true"
+ >
+ <key-style
+ latin:styleName="tabKeyStyle"
+ latin:code="!code/key_action_previous"
+ latin:keyLabel="!text/label_tab_key"
+ latin:keyLabelFlags="fontNormal|preserveCase"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="tabKeyStyle"
+ latin:code="!code/key_tab"
+ latin:keyLabel="!text/label_tab_key"
+ latin:keyLabelFlags="fontNormal|preserveCase"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <key-style
+ latin:styleName="toSymbolKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_symbol_key"
+ latin:keyLabelFlags="fontNormal|preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="toAlphaKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_alpha_key"
+ latin:keyLabelFlags="fontNormal|preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="toMoreSymbolKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyLabel="!text/label_to_more_symbol_for_tablet_key"
+ latin:keyLabelFlags="fontNormal"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="backFromMoreSymbolKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyLabel="!text/label_to_symbol_key"
+ latin:keyLabelFlags="fontNormal"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="comKeyStyle"
+ latin:keyLabel="!text/keylabel_for_popular_domain"
+ latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase"
+ latin:keyOutputText="!text/keylabel_for_popular_domain"
+ latin:moreKeys="!text/more_keys_for_popular_domain" />
+</merge>
diff --git a/java/res/xml-sw768dp/row_dvorak4.xml b/java/res/xml-sw768dp/row_dvorak4.xml
new file mode 100644
index 000000000..0827815c9
--- /dev/null
+++ b/java/res/xml-sw768dp/row_dvorak4.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional"
+ >
+ <include
+ latin:keyXPos="5.782%p"
+ latin:keyboardLayout="@xml/key_settings" />
+ <include
+ latin:keyboardLayout="@xml/key_shortcut" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="29.923%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <include
+ latin:keyboardLayout="@xml/key_question_exclamation" />
+ <include
+ latin:keyboardLayout="@xml/key_dash" />
+ <include
+ latin:keyboardLayout="@xml/key_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/row_hebrew4.xml b/java/res/xml-sw768dp/row_hebrew4.xml
new file mode 100644
index 000000000..180c5641d
--- /dev/null
+++ b/java/res/xml-sw768dp/row_hebrew4.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional"
+ >
+ <include
+ latin:keyXPos="5.782%p"
+ latin:keyboardLayout="@xml/key_settings" />
+ <include
+ latin:keyboardLayout="@xml/key_shortcut" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="29.923%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <include
+ latin:keyboardLayout="@xml/key_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/row_pcqwerty5.xml b/java/res/xml-sw768dp/row_pcqwerty5.xml
new file mode 100644
index 000000000..e27ec878b
--- /dev/null
+++ b/java/res/xml-sw768dp/row_pcqwerty5.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_settings" />
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <Spacer
+ latin:keyXPos="15.0%p"
+ latin:keyWidth="10.5%p" />
+ </case>
+ <case
+ latin:mode="email|url"
+ >
+ <Key
+ latin:keyStyle="comKeyStyle"
+ latin:keyXPos="15.0%p"
+ latin:keyWidth="10.5%p" />
+ </case>
+ <default>
+ <Spacer
+ latin:keyXPos="15.0%p"
+ latin:keyWidth="10.5%p" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="49.0%p" />
+ <include
+ latin:keyXPos="-8.047%p"
+ latin:keyWidth="fillRight"
+ latin:keyboardLayout="@xml/key_shortcut" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/row_qwerty4.xml b/java/res/xml-sw768dp/row_qwerty4.xml
new file mode 100644
index 000000000..92411f54e
--- /dev/null
+++ b/java/res/xml-sw768dp/row_qwerty4.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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"
+>
+ <Row
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional"
+ >
+ <include
+ latin:keyXPos="5.782%p"
+ latin:keyboardLayout="@xml/key_settings" />
+ <include
+ latin:keyboardLayout="@xml/key_shortcut" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="29.923%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <include
+ latin:keyboardLayout="@xml/key_apostrophe" />
+ <include
+ latin:keyboardLayout="@xml/key_dash" />
+ <include
+ latin:keyboardLayout="@xml/key_f2" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/row_symbols4.xml b/java/res/xml-sw768dp/row_symbols4.xml
new file mode 100644
index 000000000..4e1c11994
--- /dev/null
+++ b/java/res/xml-sw768dp/row_symbols4.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional"
+ >
+ <Key
+ latin:keyXPos="13.829%p"
+ latin:keyLabel="/" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="29.923%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <Key
+ latin:keyLabel="&quot;"
+ latin:moreKeys="!text/more_keys_for_tablet_double_quote" />
+ <Key
+ latin:keyLabel="_" />
+ <!-- Here is empty space. -->
+ </Row>
+</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_qwerty.xml b/java/res/xml-sw768dp/row_symbols_shift4.xml
index 6237712f6..561351cab 100644
--- a/java/res/xml-xlarge/kbd_rows_qwerty.xml
+++ b/java/res/xml-sw768dp/row_symbols_shift4.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -21,14 +21,15 @@
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row1" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row2" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
+ <Row
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional"
+ >
+ <!-- Here is empty space. -->
+ <include
+ latin:keyXPos="29.923%p"
+ latin:keyboardLayout="@xml/key_space"
+ latin:backgroundType="normal" />
+ <!-- Here is empty space. -->
+ </Row>
</merge>
diff --git a/java/res/xml-sw768dp/rowkeys_thai_digits.xml b/java/res/xml-sw768dp/rowkeys_thai_digits.xml
new file mode 100644
index 000000000..512283096
--- /dev/null
+++ b/java/res/xml-sw768dp/rowkeys_thai_digits.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0E51: "๑" THAI DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x0E51;" />
+ <!-- U+0E52: "๒" THAI DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x0E52;" />
+ <!-- U+0E53: "๓" THAI DIGIT THREE -->
+ <Key
+ latin:keyLabel="&#x0E53;" />
+ <!-- U+0E54: "๔" THAI DIGIT FOUR -->
+ <Key
+ latin:keyLabel="&#x0E54;" />
+ <!-- U+0E55: "๕" THAI DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x0E55;" />
+ <!-- U+0E56: "๖" THAI DIGIT SIX -->
+ <Key
+ latin:keyLabel="&#x0E56;" />
+ <!-- U+0E57: "๗" THAI DIGIT SEVEN -->
+ <Key
+ latin:keyLabel="&#x0E57;" />
+ <!-- U+0E58: "๘" THAI DIGIT EIGHT -->
+ <Key
+ latin:keyLabel="&#x0E58;" />
+ <!-- U+0E59: "๙" THAI DIGIT NINE -->
+ <Key
+ latin:keyLabel="&#x0E59;" />
+ <!-- U+0E50: "๐" THAI DIGIT ZERO -->
+ <Key
+ latin:keyLabel="&#x0E50;" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_10_10_7_symbols.xml b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml
new file mode 100644
index 000000000..d9b0d2383
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols3" />
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyXPos="-13.750%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml
new file mode 100644
index 000000000..a317dbf84
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyXPos="-13.750%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols_shift4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_arabic.xml b/java/res/xml-sw768dp/rows_arabic.xml
new file mode 100644
index 000000000..8b05d9376
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_arabic.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic3"
+ latin:keyXPos="13.829%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_azerty.xml b/java/res/xml-sw768dp/rows_azerty.xml
new file mode 100644
index 000000000..dcc403b59
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_azerty.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_bulgarian.xml b/java/res/xml-sw768dp/rows_bulgarian.xml
new file mode 100644
index 000000000..64534144a
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_bulgarian.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.186%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_bulgarian_bds.xml b/java/res/xml-sw768dp/rows_bulgarian_bds.xml
new file mode 100644
index 000000000..8acb4d259
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_bulgarian_bds.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.000%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_colemak.xml b/java/res/xml-sw768dp/rows_colemak.xml
new file mode 100644
index 000000000..db9b0c247
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_colemak.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <include
+ latin:keyboardLayout="@xml/key_colemak_colon" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_dvorak.xml b/java/res/xml-sw768dp/rows_dvorak.xml
new file mode 100644
index 000000000..941647815
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_dvorak.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/keys_dvorak_123" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak3" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_dvorak4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_east_slavic.xml b/java/res/xml-sw768dp/rows_east_slavic.xml
new file mode 100644
index 000000000..0316c76f6
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_east_slavic.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.000%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN -->
+ <Key
+ latin:keyLabel="&#x044A;" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.000%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.000%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_farsi.xml b/java/res/xml-sw768dp/rows_farsi.xml
new file mode 100644
index 000000000..4b4c970fd
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_farsi.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi1" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi2" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.186%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi3"
+ latin:keyXPos="13.829%p" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_georgian.xml b/java/res/xml-sw768dp/rows_georgian.xml
new file mode 100644
index 000000000..74f1a07c1
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_georgian.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"/>
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_greek.xml b/java/res/xml-sw768dp/rows_greek.xml
new file mode 100644
index 000000000..aebe12928
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_greek.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/key_greek_semicolon" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"/>
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_hebrew.xml b/java/res/xml-sw768dp/rows_hebrew.xml
new file mode 100644
index 000000000..e588b830c
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_hebrew.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/key_apostrophe" />
+ <include
+ latin:keyboardLayout="@xml/key_dash" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew3"
+ latin:keyXPos="13.829%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_hebrew4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_hindi.xml b/java/res/xml-sw768dp/rows_hindi.xml
new file mode 100644
index 000000000..510772b13
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_hindi.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.000%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_nordic.xml b/java/res/xml-sw768dp/rows_nordic.xml
new file mode 100644
index 000000000..06591a66e
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_nordic.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_nordic1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_nordic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <Spacer
+ latin:keyWidth="3.689%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyXPos="-13.750%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_number_normal.xml b/java/res/xml-sw768dp/rows_number_normal.xml
new file mode 100644
index 000000000..84910a88f
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_number_normal.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row>
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="1"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="2"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="3"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel="/"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <switch>
+ <case
+ latin:mode="time|datetime"
+ >
+ <Key
+ latin:keyLabel=","
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_am_pm"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel="4"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="5"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="6"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ <switch>
+ <case
+ latin:mode="time|datetime"
+ >
+ <Key
+ latin:keyLabel=":"
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="="
+ latin:keyStyle="numKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel="7"
+ latin:keyStyle="numKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="8"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="9"
+ latin:keyStyle="numKeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer />
+ </Row>
+ <Row>
+ <include
+ latin:keyboardLayout="@xml/key_settings"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyXPos="13.829%p"
+ latin:keyWidth="24.140%p"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyStyle="numStarKeyStyle"
+ latin:keyXPos="43.125%p" />
+ <Key
+ latin:keyLabel="0"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/rows_number_password.xml b/java/res/xml-sw768dp/rows_number_password.xml
new file mode 100644
index 000000000..cfa221491
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_number_password.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row>
+ <Key
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle"
+ latin:keyXPos="32.076%p" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="32.076%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyXPos="-11.172%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="32.076%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer />
+ </Row>
+ <Row>
+ <include
+ latin:keyboardLayout="@xml/key_settings"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyXPos="45.326%p"
+ latin:keyStyle="num0KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer />
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/rows_pcqwerty.xml b/java/res/xml-sw768dp/rows_pcqwerty.xml
new file mode 100644
index 000000000..a8447288f
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_pcqwerty.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyWidth="9.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabel="!text/label_to_symbol_key_pcqwerty"
+ latin:keyWidth="12.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty4" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_pcqwerty5" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml b/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml
new file mode 100644
index 000000000..956da97fb
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_pcqwerty_symbols.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyWidth="9.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="12.0%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty3" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.0%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty4"
+ latin:keyXPos="15.0%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_pcqwerty5" />
+</merge>
diff --git a/java/res/xml-xlarge/kbd_phone_symbols.xml b/java/res/xml-sw768dp/rows_phone.xml
index 6ee57d6a5..2f718db62 100644
--- a/java/res/xml-xlarge/kbd_phone_symbols.xml
+++ b/java/res/xml-sw768dp/rows_phone.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2011, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -18,34 +18,33 @@
*/
-->
-<Keyboard
+<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyWidth="13.250%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
+ latin:keyboardLayout="@xml/key_styles_common" />
<include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <!-- This row is intentionally not marked as a top row -->
+ latin:keyboardLayout="@xml/key_styles_number" />
<Row>
<Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
+ latin:keyStyle="numTabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
<Key
latin:keyLabel="-"
latin:keyStyle="numKeyStyle"
latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel="+"
latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
- latin:code="44"
- latin:keyLabel="@string/label_pause_key"
- latin:keyWidth="8.047%p" />
+ latin:keyStyle="numPauseKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="num1KeyStyle"
latin:keyXPos="43.125%p" />
@@ -56,27 +55,27 @@
<Key
latin:keyStyle="deleteKeyStyle"
latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
+ latin:keyWidth="fillRight" />
</Row>
<Row>
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
<Key
latin:keyLabel=","
latin:keyStyle="numKeyStyle"
latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel="."
latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
- latin:code="59"
- latin:keyLabel="@string/label_wait_key"
- latin:keyWidth="8.047%p" />
+ latin:keyStyle="numWaitKeyStyle"
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="num4KeyStyle"
latin:keyXPos="43.125%p" />
@@ -85,27 +84,29 @@
<Key
latin:keyStyle="num6KeyStyle" />
<Key
- latin:keyStyle="returnKeyStyle"
+ latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
+ latin:keyWidth="fillRight" />
</Row>
<Row>
- <!-- There is an empty area below the "More" key and left of the "(" key. To ignore
- the touch event on the area, "(" is intentionally not marked as a left edge key. -->
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="13.829%p" />
<Key
latin:keyLabel="("
latin:keyStyle="numKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel=")"
latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyLabel="N"
latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
+ latin:keyWidth="8.047%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="num7KeyStyle"
latin:keyXPos="43.125%p" />
@@ -113,22 +114,18 @@
latin:keyStyle="num8KeyStyle" />
<Key
latin:keyStyle="num9KeyStyle" />
- <!-- There is an empty area below the "Enter" key and right of the "9" key. To ignore
- the touch event on the area, "9" is intentionally not marked as a right edge key. -->
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer />
</Row>
- <!-- This row is intentionally not marked as a bottom row -->
<Row>
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- </switch>
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
+ <include
+ latin:keyboardLayout="@xml/key_settings"
+ latin:keyWidth="8.047%p" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
latin:keyXPos="13.829%p"
- latin:keyWidth="24.140%p" />
+ latin:keyWidth="24.140%p"
+ latin:backgroundType="functional" />
<Key
latin:keyStyle="numStarKeyStyle"
latin:keyXPos="43.125%p" />
@@ -137,15 +134,5 @@
<Key
latin:keyLabel="#"
latin:keyStyle="numKeyStyle" />
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- </switch>
- </Row>
-</Keyboard>
+ </Row>
+</merge>
diff --git a/java/res/xml-sw768dp/rows_qwerty.xml b/java/res/xml-sw768dp/rows_qwerty.xml
new file mode 100644
index 000000000..a1deabd3b
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_qwerty.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"/>
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_qwertz.xml b/java/res/xml-sw768dp/rows_qwertz.xml
new file mode 100644
index 000000000..801dd38b6
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_qwertz.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"/>
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_south_slavic.xml b/java/res/xml-sw768dp/rows_south_slavic.xml
new file mode 100644
index 000000000..b55685330
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_south_slavic.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.375%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.227%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.000%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_spanish.xml b/java/res/xml-sw768dp/rows_spanish.xml
new file mode 100644
index 000000000..8b8033288
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_spanish.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"/>
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="10.167%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_spanish2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyXPos="-13.750%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_symbols.xml b/java/res/xml-sw768dp/rows_symbols.xml
new file mode 100644
index 000000000..efd77352b
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_symbols.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols3" />
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_symbols_shift.xml b/java/res/xml-sw768dp/rows_symbols_shift.xml
new file mode 100644
index 000000000..fd1b93d51
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_symbols_shift.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols_shift4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_thai.xml b/java/res/xml-sw768dp/rows_thai.xml
new file mode 100644
index 000000000..7721bc5a9
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_thai.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.079%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai1"
+ latin:keyXPos="11.508%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"/>
+ </Row>
+ <Row
+ latin:keyWidth="7.079%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.125%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai3" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="7.181%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.829%p"/>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai4" />
+ <include
+ latin:keyboardLayout="@xml/keys_comma_period" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_thai_symbols.xml b/java/res/xml-sw768dp/rows_thai_symbols.xml
new file mode 100644
index 000000000..528514182
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_thai_symbols.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai_digits"
+ latin:keyXPos="7.969%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols1" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols3" />
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyXPos="-13.750%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols4" />
+</merge>
diff --git a/java/res/xml-sw768dp/rows_thai_symbols_shift.xml b/java/res/xml-sw768dp/rows_thai_symbols_shift.xml
new file mode 100644
index 000000000..9d2694b86
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_thai_symbols_shift.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai_digits"
+ latin:keyXPos="7.969%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.282%p"
+ >
+ <Key
+ latin:keyStyle="tabKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="7.969%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
+ </Row>
+ <Row
+ latin:keyWidth="8.125%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyLabelFlags="alignLeft"
+ latin:keyWidth="11.172%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.047%p"
+ >
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="13.829%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyXPos="-13.750%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols_shift4" />
+</merge>
diff --git a/java/res/xml-tr/kbd_qwerty.xml b/java/res/xml-tr/kbd_qwerty.xml
deleted file mode 100644
index d2c38f60a..000000000
--- a/java/res/xml-tr/kbd_qwerty.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="tr"
->
- <include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
diff --git a/java/res/xml-xlarge/kbd_key_styles.xml b/java/res/xml-xlarge/kbd_key_styles.xml
deleted file mode 100644
index 4c1e3b63e..000000000
--- a/java/res/xml-xlarge/kbd_key_styles.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <!-- Functional key styles -->
- <key-style
- latin:styleName="functionalKeyStyle"
- latin:isFunctional="true" />
- <key-style
- latin:styleName="shiftKeyStyle"
- latin:code="@integer/key_shift"
- latin:keyIcon="iconShiftKey"
- latin:keyIconShifted="iconShiftedShiftKey"
- latin:parentStyle="functionalKeyStyle"
- latin:isSticky="true" />
- <key-style
- latin:styleName="deleteKeyStyle"
- latin:code="@integer/key_delete"
- latin:keyIcon="iconDeleteKey"
- latin:parentStyle="functionalKeyStyle"
- latin:isRepeatable="true" />
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyIcon="iconReturnKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="spaceKeyStyle"
- latin:code="@integer/key_space"
- latin:keyIconPreview="iconPreviewSpaceKey" />
- <key-style
- latin:styleName="nonSpecialBackgroundSpaceKeyStyle"
- latin:code="@integer/key_space"
- latin:keyIconPreview="iconPreviewSpaceKey" />
- <key-style
- latin:styleName="smileyKeyStyle"
- latin:keyLabel=":-)"
- latin:keyOutputText=":-) "
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_smiley"
- latin:maxPopupKeyboardColumn="5" />
- <key-style
- latin:styleName="settingsKeyStyle"
- latin:code="@integer/key_settings"
- latin:keyIcon="iconSettingsKey"
- latin:keyIconPreview="iconPreviewSettingsKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="shortcutKeyStyle"
- latin:code="@integer/key_shortcut"
- latin:keyIcon="iconShortcutKey"
- latin:keyIconPreview="iconPreviewShortcutKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="tabKeyStyle"
- latin:code="@integer/key_tab"
- latin:keyLabel="@string/label_tab_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="toSymbolKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_symbol_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="toAlphaKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_alpha_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="moreKeyStyle"
- latin:code="@integer/key_shift"
- latin:keyLabel="@string/label_more_key"
- latin:keyLabelOption="fontNormal"
- latin:parentStyle="functionalKeyStyle"
- latin:isSticky="true" />
- <key-style
- latin:styleName="comKeyStyle"
- latin:keyLabel="@string/keylabel_for_popular_domain"
- latin:keyLabelOption="fontNormal|hasPopupHint"
- latin:keyOutputText="@string/keylabel_for_popular_domain"
- latin:popupCharacters="@string/alternates_for_popular_domain" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <key-style
- latin:styleName="nonPasswordSymbolKeyStyle"
- latin:enabled="false" />
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <key-style
- latin:styleName="nonPasswordSymbolKeyStyle"
- latin:enabled="true" />
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml-xlarge/kbd_number.xml b/java/res/xml-xlarge/kbd_number.xml
deleted file mode 100644
index a3bed2f3a..000000000
--- a/java/res/xml-xlarge/kbd_number.xml
+++ /dev/null
@@ -1,223 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
- latin:keyWidth="13.250%p"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <!-- This row is intentionally not marked as a top row -->
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="32.076%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="32.076%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="32.076%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- There is an empty area below the "Enter" key and right of the "9" key. To
- ignore the touch event on the area, "9" is intentionally not marked as a right
- edge key. -->
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row>
- <Spacer
- latin:keyXPos="32.076%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <!-- There is an empty area below the "Enter" key and right of the "#" key. To
- ignore the touch event on the area, "#" is intentionally not marked as a right
- edge key. -->
- </Row>
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <!-- This row is intentionally not marked as a top row -->
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="1"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="2"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="3"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="/"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="4"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="5"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="6"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <!-- There is an empty area below the "More" key and left of the "(" key. To
- ignore the touch event on the area, "(" is intentionally not marked as a left
- edge key. -->
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="="
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="7"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="8"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="9"
- latin:keyStyle="numKeyStyle" />
- <!-- There is an empty area below the "Enter" key and right of the "9" key. To
- ignore the touch event on the area, "9" is intentionally not marked as a right
- edge key. -->
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row>
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- </switch>
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="13.829%p"
- latin:keyWidth="24.140%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyLabel="0"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- </switch>
- </Row>
- </default>
- </switch>
-</Keyboard>
diff --git a/java/res/xml-xlarge/kbd_phone.xml b/java/res/xml-xlarge/kbd_phone.xml
deleted file mode 100644
index 0935992fd..000000000
--- a/java/res/xml-xlarge/kbd_phone.xml
+++ /dev/null
@@ -1,139 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
- latin:keyWidth="13.250%p"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row>
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-11.172%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <!-- There is an empty area below the "More" key and left of the "(" key. To ignore
- the touch event on the area, "(" is intentionally not marked as a left edge key. -->
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle"
- latin:keyWidth="8.047%p" />
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <!-- There is an empty area below the "Enter" key and right of the "9" key. To ignore
- the touch event on the area, "9" is intentionally not marked as a right edge key. -->
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row>
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- </switch>
- <Key
- latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle"
- latin:keyXPos="20.400%p"
- latin:keyWidth="16.084%p" />
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyXPos="43.125%p" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- </switch>
- </Row>
-</Keyboard>
diff --git a/java/res/xml-xlarge/kbd_qwerty_row1.xml b/java/res/xml-xlarge/kbd_qwerty_row1.xml
deleted file mode 100644
index 3727cf34e..000000000
--- a/java/res/xml-xlarge/kbd_qwerty_row1.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="8.282%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.969%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-9.219%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
-</merge>
diff --git a/java/res/xml-xlarge/kbd_qwerty_row2.xml b/java/res/xml-xlarge/kbd_qwerty_row2.xml
deleted file mode 100644
index 45af120e2..000000000
--- a/java/res/xml-xlarge/kbd_qwerty_row2.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="8.125%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-15.704%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
-</merge>
diff --git a/java/res/xml-xlarge/kbd_qwerty_row3.xml b/java/res/xml-xlarge/kbd_qwerty_row3.xml
deleted file mode 100644
index 7297ea512..000000000
--- a/java/res/xml-xlarge/kbd_qwerty_row3.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="8.047%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="13.829%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right2" />
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyXPos="-13.750%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
-</merge>
diff --git a/java/res/xml-xlarge/kbd_qwerty_row4.xml b/java/res/xml-xlarge/kbd_qwerty_row4.xml
deleted file mode 100644
index bdef89dcc..000000000
--- a/java/res/xml-xlarge/kbd_qwerty_row4.xml
+++ /dev/null
@@ -1,141 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <!-- This row is intentionally not marked as a bottom row -->
- <Row
- latin:keyWidth="8.047%p"
- >
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- </switch>
- <Spacer
- latin:keyXPos="15.157%p"
- latin:keyWidth="fillRight" />
- <switch>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyStyle="comKeyStyle"
- latin:keyWidth="16.084%p" />
- </case>
- <default>
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyStyle="comKeyStyle" />
- </case>
- <case
- latin:imeAction="actionSearch"
- >
- <Key
- latin:keyLabel=":"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="+"
- latin:popupCharacters="+" />
- </case>
- <default>
- <Key
- latin:keyStyle="smileyKeyStyle" />
- </default>
- </switch>
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="\@" />
- </case>
- <default>
- <Key
- latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\@"
- latin:popupCharacters="\@" />
- </default>
- </switch>
- </default>
- </switch>
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyXPos="31.250%p"
- latin:keyWidth="37.500%p" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="-" />
- </case>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="/"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel=":"
- latin:popupCharacters=":" />
- </case>
- <default>
- <Key
- latin:keyLabel="\'"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="&quot;"
- latin:popupCharacters="&quot;" />
- </default>
- </switch>
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="_" />
- </case>
- <default>
- <Key
- latin:keyLabel="-"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="_"
- latin:popupCharacters="_" />
- </default>
- </switch>
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- </switch>
- </Row>
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_arabic.xml b/java/res/xml-xlarge/kbd_rows_arabic.xml
deleted file mode 100644
index c1810026b..000000000
--- a/java/res/xml-xlarge/kbd_rows_arabic.xml
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This file for Arabic layout is an alpha version. It allows to enter -->
-<!-- some right-to-left text, but it has gone through no study whatsoever, -->
-<!-- and needs to be run through UX. -->
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="7.375%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.500%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ض" />
- <Key
- latin:keyLabel="ص" />
- <Key
- latin:keyLabel="ث" />
- <Key
- latin:keyLabel="ق" />
- <Key
- latin:keyLabel="ف"
- latin:popupCharacters="ف,ڤ" />
- <Key
- latin:keyLabel="غ" />
- <Key
- latin:keyLabel="ع" />
- <Key
- latin:keyLabel="ه"
- latin:popupCharacters="ه,هـ" />
- <Key
- latin:keyLabel="خ" />
- <Key
- latin:keyLabel="ح" />
- <Key
- latin:keyLabel="ج"
- latin:popupCharacters="ج,چ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.500%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.375%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="9.375%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ش" />
- <Key
- latin:keyLabel="س" />
- <Key
- latin:keyLabel="ي" />
- <Key
- latin:keyLabel="ب"
- latin:popupCharacters="ب,پ" />
- <Key
- latin:keyLabel="ل"
- latin:popupCharacters="ل,لا" />
- <Key
- latin:keyLabel="ا"
- latin:popupCharacters="ا,أ,إ,آ" />
- <Key
- latin:keyLabel="ت" />
- <Key
- latin:keyLabel="ن" />
- <Key
- latin:keyLabel="م" />
- <Key
- latin:keyLabel="ك"
- latin:popupCharacters="ك,گ" />
- <Key
- latin:keyLabel="ط" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-9.375%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.375%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="12.750%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ئ" />
- <Key
- latin:keyLabel="ء" />
- <Key
- latin:keyLabel="ؤ" />
- <Key
- latin:keyLabel="ر" />
- <Key
- latin:keyLabel="ذ" />
- <Key
- latin:keyLabel="ى" />
- <Key
- latin:keyLabel="ة" />
- <Key
- latin:keyLabel="و" />
- <Key
- latin:keyLabel="ز"
- latin:popupCharacters="ز,ژ" />
- <Key
- latin:keyLabel="ظ" />
- <Key
- latin:keyLabel="د" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_azerty.xml b/java/res/xml-xlarge/kbd_rows_azerty.xml
deleted file mode 100644
index 373bda9ce..000000000
--- a/java/res/xml-xlarge/kbd_rows_azerty.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <Row
- latin:keyWidth="8.282%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.969%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-9.219%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.125%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="10.167%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="m"
- latin:keyEdgeFlags="right" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-15.704%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.047%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="13.829%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="\'"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel=":"
- latin:popupCharacters=":" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyXPos="-13.750%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_hebrew.xml b/java/res/xml-xlarge/kbd_rows_hebrew.xml
deleted file mode 100644
index 5275a1f15..000000000
--- a/java/res/xml-xlarge/kbd_rows_hebrew.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="8.000%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- <Key
- latin:keyLabel="ק" />
- <Key
- latin:keyLabel="ר" />
- <Key
- latin:keyLabel="א" />
- <Key
- latin:keyLabel="ט" />
- <Key
- latin:keyLabel="ו" />
- <Key
- latin:keyLabel="ן" />
- <Key
- latin:keyLabel="ם" />
- <Key
- latin:keyLabel="פ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-12.000%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.000%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="9.600%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ש" />
- <Key
- latin:keyLabel="ד" />
- <Key
- latin:keyLabel="ג"
- latin:popupCharacters="ג,ג׳" />
- <Key
- latin:keyLabel="כ" />
- <Key
- latin:keyLabel="ע" />
- <Key
- latin:keyLabel="י"
- latin:popupCharacters="י,ײַ" />
- <Key
- latin:keyLabel="ח"
- latin:popupCharacters="ח,ח׳" />
- <Key
- latin:keyLabel="ל" />
- <Key
- latin:keyLabel="ך" />
- <Key
- latin:keyLabel="ף" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-10.400%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.000%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="13.200%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ז"
- latin:popupCharacters="ז,ז׳" />
- <Key
- latin:keyLabel="ס" />
- <Key
- latin:keyLabel="ב" />
- <Key
- latin:keyLabel="ה" />
- <Key
- latin:keyLabel="נ" />
- <Key
- latin:keyLabel="מ" />
- <Key
- latin:keyLabel="צ"
- latin:popupCharacters="צ,צ׳" />
- <Key
- latin:keyLabel="ת"
- latin:popupCharacters="ת,ת׳" />
- <Key
- latin:keyLabel="ץ"
- latin:popupCharacters="ץ,ץ׳" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_qwertz.xml b/java/res/xml-xlarge/kbd_rows_qwertz.xml
deleted file mode 100644
index 6567c3166..000000000
--- a/java/res/xml-xlarge/kbd_rows_qwertz.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <Row
- latin:keyWidth="8.282%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.969%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-9.219%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row2" />
- <Row
- latin:keyWidth="8.047%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="13.829%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <switch>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="!"
- latin:popupCharacters="!" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="\?"
- latin:popupCharacters="\?" />
- </default>
- </switch>
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyXPos="-13.750%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_russian.xml b/java/res/xml-xlarge/kbd_rows_russian.xml
deleted file mode 100644
index ee91481c1..000000000
--- a/java/res/xml-xlarge/kbd_rows_russian.xml
+++ /dev/null
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="7.125%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="й" />
- <Key
- latin:keyLabel="ц" />
- <Key
- latin:keyLabel="у" />
- <Key
- latin:keyLabel="к" />
- <Key
- latin:keyLabel="е"
- latin:popupCharacters="@string/alternates_for_cyrillic_e" />
- <Key
- latin:keyLabel="н" />
- <Key
- latin:keyLabel="г" />
- <Key
- latin:keyLabel="ш" />
- <Key
- latin:keyLabel="щ" />
- <Key
- latin:keyLabel="з" />
- <Key
- latin:keyLabel="х" />
- <Key
- latin:keyLabel="ъ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.125%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="9.375%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ф" />
- <Key
- latin:keyLabel="ы" />
- <Key
- latin:keyLabel="в" />
- <Key
- latin:keyLabel="а" />
- <Key
- latin:keyLabel="п" />
- <Key
- latin:keyLabel="р" />
- <Key
- latin:keyLabel="о" />
- <Key
- latin:keyLabel="л" />
- <Key
- latin:keyLabel="д" />
- <Key
- latin:keyLabel="ж" />
- <Key
- latin:keyLabel="э" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-9.375%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.125%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="12.750%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="я" />
- <Key
- latin:keyLabel="ч" />
- <Key
- latin:keyLabel="с" />
- <Key
- latin:keyLabel="м" />
- <Key
- latin:keyLabel="и" />
- <Key
- latin:keyLabel="т" />
- <Key
- latin:keyLabel="ь" />
- <Key
- latin:keyLabel="б" />
- <Key
- latin:keyLabel="ю" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right2" />
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_scandinavian.xml b/java/res/xml-xlarge/kbd_rows_scandinavian.xml
deleted file mode 100644
index 7e9f604f5..000000000
--- a/java/res/xml-xlarge/kbd_rows_scandinavian.xml
+++ /dev/null
@@ -1,151 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <Row
- latin:keyWidth="7.375%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.500%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyLabel="å" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-11.500%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.375%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="9.375%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="@string/keylabel_for_scandinavia_row2_10"
- latin:popupCharacters="@string/alternates_for_scandinavia_row2_10" />
- <Key
- latin:keyLabel="@string/keylabel_for_scandinavia_row2_11"
- latin:popupCharacters="@string/alternates_for_scandinavia_row2_11" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-9.375%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.375%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="12.750%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right2" />
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyXPos="-12.750%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_serbian.xml b/java/res/xml-xlarge/kbd_rows_serbian.xml
deleted file mode 100644
index 4997dabb9..000000000
--- a/java/res/xml-xlarge/kbd_rows_serbian.xml
+++ /dev/null
@@ -1,130 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="7.125%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="љ" />
- <Key
- latin:keyLabel="њ" />
- <Key
- latin:keyLabel="е" />
- <Key
- latin:keyLabel="р" />
- <Key
- latin:keyLabel="т" />
- <Key
- latin:keyLabel="з" />
- <Key
- latin:keyLabel="у" />
- <Key
- latin:keyLabel="и" />
- <Key
- latin:keyLabel="о" />
- <Key
- latin:keyLabel="п" />
- <Key
- latin:keyLabel="ш" />
- <Key
- latin:keyLabel="ђ" />
- <Key
- latin:keyLabel="ж"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right"/>
- </Row>
- <Row
- latin:keyWidth="7.250%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="а" />
- <Key
- latin:keyLabel="с" />
- <Key
- latin:keyLabel="д" />
- <Key
- latin:keyLabel="ф" />
- <Key
- latin:keyLabel="г" />
- <Key
- latin:keyLabel="х" />
- <Key
- latin:keyLabel="ј" />
- <Key
- latin:keyLabel="к" />
- <Key
- latin:keyLabel="л" />
- <Key
- latin:keyLabel="ч" />
- <Key
- latin:keyLabel="ћ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-9.219%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="7.250%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="13.829%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ѕ" />
- <Key
- latin:keyLabel="џ" />
- <Key
- latin:keyLabel="ц" />
- <Key
- latin:keyLabel="в" />
- <Key
- latin:keyLabel="б" />
- <Key
- latin:keyLabel="н" />
- <Key
- latin:keyLabel="м" />
- <include
- latin:keyboardLayout="@xml/kbd_row3_right2" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-13.750%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_rows_spanish.xml b/java/res/xml-xlarge/kbd_rows_spanish.xml
deleted file mode 100644
index 300592e6a..000000000
--- a/java/res/xml-xlarge/kbd_rows_spanish.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row1" />
- <Row
- latin:keyWidth="8.125%p"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="10.167%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="ñ" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-15.704%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml-xlarge/kbd_symbols.xml b/java/res/xml-xlarge/kbd_symbols.xml
deleted file mode 100644
index 0e6103ab9..000000000
--- a/java/res/xml-xlarge/kbd_symbols.xml
+++ /dev/null
@@ -1,195 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_currency_key_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="8.282%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.969%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="1"
- latin:popupCharacters="¹,½,⅓,¼,⅛" />
- <Key
- latin:keyLabel="2"
- latin:popupCharacters="²,⅔" />
- <Key
- latin:keyLabel="3"
- latin:popupCharacters="³,¾,⅜" />
- <Key
- latin:keyLabel="4"
- latin:popupCharacters="⁴" />
- <Key
- latin:keyLabel="5"
- latin:popupCharacters="⅝" />
- <Key
- latin:keyLabel="6" />
- <Key
- latin:keyLabel="7"
- latin:popupCharacters="⅞" />
- <Key
- latin:keyLabel="8" />
- <Key
- latin:keyLabel="9" />
- <Key
- latin:keyLabel="0"
- latin:popupCharacters="ⁿ,∅" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-9.219%p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.125%p"
- >
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="#" />
- <Key
- latin:keyStyle="currencyKeyStyle" />
- <Key
- latin:keyLabel="%"
- latin:popupCharacters="‰" />
- <Key
- latin:keyLabel="&amp;" />
- <Key
- latin:keyLabel="*"
- latin:popupCharacters="†,‡,★" />
- <Key
- latin:keyLabel="-"
- latin:popupCharacters="_,–,—" />
- <Key
- latin:keyLabel="+"
- latin:popupCharacters="±" />
- <Key
- latin:keyLabel="("
- latin:popupCharacters="[,{,&lt;" />
- <Key
- latin:keyLabel=")"
- latin:popupCharacters="],},&gt;" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-15.704%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.047%p"
- >
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="13.829%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="&lt;"
- latin:popupCharacters="≤,«,‹" />
- <Key
- latin:keyLabel="&gt;"
- latin:popupCharacters="≥,»,›" />
- <Key
- latin:keyLabel="="
- latin:popupCharacters="≠,≈" />
- <switch>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="\'"
- latin:popupCharacters="‘,’,‚,‛" />
- </case>
- <default>
- <Key
- latin:keyLabel=":" />
- </default>
- </switch>
- <Key
- latin:keyLabel=";" />
- <Key
- latin:keyLabel="," />
- <Key
- latin:keyLabel="." />
- <Key
- latin:keyLabel="!"
- latin:popupCharacters="¡" />
- <Key
- latin:keyLabel="\?"
- latin:popupCharacters="¿" />
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyXPos="-13.750%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row
- latin:keyWidth="8.047%p"
- >
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- </switch>
- <Key
- latin:keyLabel="/"
- latin:keyXPos="15.157%p" />
- <Key
- latin:keyLabel="\@" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyXPos="31.250%p"
- latin:keyWidth="37.500%p" />
- <!-- Note: DroidSans doesn't have double-high-reversed-quotation '\u201f' glyph. -->
- <!-- latin:popupCharacters="“,”,„,‟,«,»,‘,’,‚,‛" -->
- <Key
- latin:keyLabel="&quot;"
- latin:popupCharacters="“,”,«,»,‘,’,‚,‛" />
- <Key
- latin:keyLabel="_" />
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- </switch>
- </Row>
-</Keyboard>
diff --git a/java/res/xml-xlarge/kbd_symbols_shift.xml b/java/res/xml-xlarge/kbd_symbols_shift.xml
deleted file mode 100644
index b36814104..000000000
--- a/java/res/xml-xlarge/kbd_symbols_shift.xml
+++ /dev/null
@@ -1,175 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <!-- This row is intentionally not marked as a top row -->
- <Row
- latin:keyWidth="8.282%p"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="7.969%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="~" />
- <Key
- latin:keyLabel="`" />
- <Key
- latin:keyLabel="|" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="•"
- latin:popupCharacters="♪,♥,♠,♦,♣" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="√" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="π"
- latin:popupCharacters="Π" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="÷" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="×" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="§"
- latin:popupCharacters="¶" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="Δ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyXPos="-9.219%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.125%p"
- >
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyLabelOption="alignLeft"
- latin:keyWidth="11.172%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="£" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¢" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="€" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¥" />
- <Key
- latin:keyLabel="^"
- latin:popupCharacters="↑,↓,←,→" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="°"
- latin:popupCharacters="′,″" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="±"
- latin:popupCharacters="∞" />
- <Key
- latin:keyLabel="{" />
- <Key
- latin:keyLabel="}" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyXPos="-15.704%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.047%p"
- >
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyWidth="13.829%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="\\" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="©" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="®" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="™" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="℅" />
- <Key
- latin:keyLabel="[" />
- <Key
- latin:keyLabel="]" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¡" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¿" />
- <Key
- latin:keyStyle="moreKeyStyle"
- latin:keyXPos="-13.750%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
- </Row>
- <!-- This row is intentionally not marked as a bottom row -->
- <Row
- latin:keyWidth="8.047%p"
- >
- <switch>
- <case latin:hasSettingsKey="true">
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="8.047%p" />
- </case>
- </switch>
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyXPos="31.250%p"
- latin:keyWidth="37.500%p" />
- <switch>
- <case
- latin:voiceKeyEnabled="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyXPos="-8.047%p"
- latin:keyWidth="fillRight" />
- </case>
- </switch>
- </Row>
-</Keyboard>
diff --git a/java/res/xml/language_prefs.xml b/java/res/xml/additional_subtype_settings.xml
index b7a4c07db..ad280c146 100644
--- a/java/res/xml/language_prefs.xml
+++ b/java/res/xml/additional_subtype_settings.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -14,6 +14,6 @@
limitations under the License.
-->
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/language_selection_title">
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Items will be added at runtime -->
</PreferenceScreen>
diff --git a/java/res/xml/kbd_10_10_7_symbols.xml b/java/res/xml/kbd_10_10_7_symbols.xml
new file mode 100644
index 000000000..7e075df48
--- /dev/null
+++ b/java/res/xml/kbd_10_10_7_symbols.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_symbols" />
+</Keyboard>
diff --git a/java/res/xml/kbd_10_10_7_symbols_shift.xml b/java/res/xml/kbd_10_10_7_symbols_shift.xml
new file mode 100644
index 000000000..25db3c84d
--- /dev/null
+++ b/java/res/xml/kbd_10_10_7_symbols_shift.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_symbols_shift" />
+</Keyboard>
diff --git a/java/res/xml-hu/kbd_qwerty.xml b/java/res/xml/kbd_arabic.xml
index 3195d5b1f..ce5f30b2f 100644
--- a/java/res/xml-hu/kbd_qwerty.xml
+++ b/java/res/xml/kbd_arabic.xml
@@ -20,8 +20,7 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="hu"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwertz" />
+ latin:keyboardLayout="@xml/rows_arabic" />
</Keyboard>
diff --git a/java/res/xml-ar/kbd_qwerty.xml b/java/res/xml/kbd_azerty.xml
index 57a6d2caf..7bafe5bca 100644
--- a/java/res/xml-ar/kbd_qwerty.xml
+++ b/java/res/xml/kbd_azerty.xml
@@ -20,8 +20,7 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="ar"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_arabic" />
+ latin:keyboardLayout="@xml/rows_azerty" />
</Keyboard>
diff --git a/java/res/xml/kbd_bulgarian.xml b/java/res/xml/kbd_bulgarian.xml
new file mode 100644
index 000000000..a651991c0
--- /dev/null
+++ b/java/res/xml/kbd_bulgarian.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"):
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_bulgarian" />
+</Keyboard>
diff --git a/java/res/xml/kbd_bulgarian_bds.xml b/java/res/xml/kbd_bulgarian_bds.xml
new file mode 100644
index 000000000..a8d770c04
--- /dev/null
+++ b/java/res/xml/kbd_bulgarian_bds.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"):
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_bulgarian_bds" />
+</Keyboard>
diff --git a/java/res/xml/kbd_colemak.xml b/java/res/xml/kbd_colemak.xml
new file mode 100644
index 000000000..ee1d5e86e
--- /dev/null
+++ b/java/res/xml/kbd_colemak.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_colemak" />
+</Keyboard>
diff --git a/java/res/xml/kbd_currency_key_styles.xml b/java/res/xml/kbd_currency_key_styles.xml
deleted file mode 100644
index 9d3bb4725..000000000
--- a/java/res/xml/kbd_currency_key_styles.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <switch>
- <case
- latin:passwordInput="true"
- >
- <key-style
- latin:styleName="currencyKeyStyle"
- latin:keyLabel="$" />
- </case>
- <!-- Countries using Euro currency, 23 countries as for January 2011. -->
- 1. Andorra (ca_AD, ca_ES)
- 2. Austria (de_AT)
- 3. Belgium (nl_BE, fr_BE, de_BE)
- 4. Cyprus (el_CY, tr_CY)
- 5. Estonia (et_EE)
- 6. Finland (fi_FI, sv_FI)
- 7. France (fr_FR)
- 8. Germany (de_DE)
- 9. Greece (el_GR)
- 10. Ireland (ga_IE, en_IE)
- 11. Italy (it_IT)
- 12. Kosovo (??_XK) ??
- 13. Luxembourg (lb_LU, fr_LU, de_LU)
- 14. Malta (mt_MT, en_MT)
- 15. Monaco (fr_MO)
- 16. Montenegro (sla_ME)
- 17. Netherlands (nl_NL)
- 18. Portugal (pt_PT)
- 19. San Marino (it_SM)
- 20. Slovakia (sk_SK)
- 21. Slovenia (sl_SI)
- 22. Spain (es_ES, ca_ES)
- 23. Vatican City (it_VA)
- -->
- <!-- Note: Some locales may not have country code, and it it supposed to indicate the
- country where the language originally/mainly spoken. -->
- <case
- latin:localeCode="de|es|el|fi|fr|it|nl|sk|sl|pt_PT"
- >
- <key-style
- latin:styleName="currencyKeyStyle"
- latin:keyLabel="€"
- latin:popupCharacters="@string/alternates_for_currency_euro" />
- </case>
- <case
- latin:languageCode="ca|et|lb|mt|sla"
- >
- <key-style
- latin:styleName="currencyKeyStyle"
- latin:keyLabel="€"
- latin:popupCharacters="@string/alternates_for_currency_euro" />
- </case>
- <case
- latin:countryCode="AD|AT|BE|CY|EE|FI|FR|DE|GR|IE|IT|XK|LU|MT|MO|ME|NL|PT|SM|SK|SI|ES|VA"
- >
- <key-style
- latin:styleName="currencyKeyStyle"
- latin:keyLabel="€"
- latin:popupCharacters="@string/alternates_for_currency_euro" />
- </case>
- <!-- United Kingdom -->
- <case
- latin:countryCode="GB"
- >
- <key-style
- latin:styleName="currencyKeyStyle"
- latin:keyLabel="£"
- latin:popupCharacters="@string/alternates_for_currency_pound" />
- </case>
- <default>
- <key-style
- latin:styleName="currencyKeyStyle"
- latin:keyLabel="$"
- latin:popupCharacters="@string/alternates_for_currency_dollar" />
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml/kbd_dvorak.xml b/java/res/xml/kbd_dvorak.xml
new file mode 100644
index 000000000..27c6a5084
--- /dev/null
+++ b/java/res/xml/kbd_dvorak.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_dvorak" />
+</Keyboard>
diff --git a/java/res/xml/kbd_east_slavic.xml b/java/res/xml/kbd_east_slavic.xml
new file mode 100644
index 000000000..3bc233953
--- /dev/null
+++ b/java/res/xml/kbd_east_slavic.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"):
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_east_slavic" />
+</Keyboard>
diff --git a/java/res/xml/kbd_farsi.xml b/java/res/xml/kbd_farsi.xml
new file mode 100644
index 000000000..1af4e61ca
--- /dev/null
+++ b/java/res/xml/kbd_farsi.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_farsi" />
+</Keyboard>
diff --git a/java/res/xml/kbd_georgian.xml b/java/res/xml/kbd_georgian.xml
new file mode 100644
index 000000000..2dc6bf0ee
--- /dev/null
+++ b/java/res/xml/kbd_georgian.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_georgian" />
+</Keyboard>
diff --git a/java/res/xml/kbd_greek.xml b/java/res/xml/kbd_greek.xml
new file mode 100644
index 000000000..7056efb00
--- /dev/null
+++ b/java/res/xml/kbd_greek.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_greek" />
+</Keyboard>
diff --git a/java/res/xml/kbd_hebrew.xml b/java/res/xml/kbd_hebrew.xml
new file mode 100644
index 000000000..74836f342
--- /dev/null
+++ b/java/res/xml/kbd_hebrew.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_hebrew" />
+</Keyboard>
diff --git a/java/res/xml/kbd_hindi.xml b/java/res/xml/kbd_hindi.xml
new file mode 100644
index 000000000..0e69e3ae2
--- /dev/null
+++ b/java/res/xml/kbd_hindi.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_hindi" />
+</Keyboard>
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
deleted file mode 100644
index 3d8600391..000000000
--- a/java/res/xml/kbd_key_styles.xml
+++ /dev/null
@@ -1,216 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <!-- Base key style for the functional key -->
- <key-style
- latin:styleName="functionalKeyStyle"
- latin:isFunctional="true" />
- <!-- Base key style for the key which may have settings key as popup key -->
- <switch>
- <case
- latin:clobberSettingsKey="true"
- >
- <key-style
- latin:styleName="settingsPopupStyle"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <case
- latin:clobberSettingsKey="false"
- latin:hasSettingsKey="true"
- >
- <key-style
- latin:styleName="settingsPopupStyle"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <!-- clobberSettingsKey="false" and hasSettingsKey="false" -->
- <default>
- <key-style
- latin:styleName="settingsPopupStyle"
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="\@icon/5|\@integer/key_settings"
- latin:parentStyle="functionalKeyStyle" />
- </default>
- </switch>
- <!-- Functional key styles -->
- <key-style
- latin:styleName="shiftKeyStyle"
- latin:code="@integer/key_shift"
- latin:keyIcon="iconShiftKey"
- latin:keyIconShifted="iconShiftedShiftKey"
- latin:parentStyle="functionalKeyStyle"
- latin:isSticky="true" />
- <key-style
- latin:styleName="deleteKeyStyle"
- latin:code="@integer/key_delete"
- latin:keyIcon="iconDeleteKey"
- latin:parentStyle="functionalKeyStyle"
- latin:isRepeatable="true" />
- <!-- Return key style -->
- <switch>
- <case
- latin:imeAction="actionGo"
- >
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyLabel="@string/label_go_key"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <case
- latin:imeAction="actionNext"
- >
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyLabel="@string/label_next_key"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <case
- latin:imeAction="actionDone"
- >
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyLabel="@string/label_done_key"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <case
- latin:imeAction="actionSend"
- >
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyLabel="@string/label_send_key"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <case
- latin:imeAction="actionSearch"
- >
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyIcon="iconSearchKey"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <default>
- <key-style
- latin:styleName="returnKeyStyle"
- latin:code="@integer/key_return"
- latin:keyIcon="iconReturnKey"
- latin:parentStyle="functionalKeyStyle" />
- </default>
- </switch>
- <key-style
- latin:styleName="spaceKeyStyle"
- latin:code="@integer/key_space"
- latin:keyIconPreview="iconPreviewSpaceKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="smileyKeyStyle"
- latin:keyLabel=":-)"
- latin:keyOutputText=":-) "
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_smiley"
- latin:maxPopupKeyboardColumn="5"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="shortcutKeyStyle"
- latin:code="@integer/key_shortcut"
- latin:keyIcon="iconShortcutKey"
- latin:keyIconPreview="iconPreviewShortcutKey"
- latin:parentStyle="settingsPopupStyle" />
- <key-style
- latin:styleName="settingsKeyStyle"
- latin:code="@integer/key_settings"
- latin:keyIcon="iconSettingsKey"
- latin:keyIconPreview="iconPreviewSettingsKey"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="tabKeyStyle"
- latin:code="@integer/key_tab"
- latin:keyIcon="iconTabKey"
- latin:keyIconPreview="iconPreviewTabKey"
- latin:parentStyle="functionalKeyStyle" />
- <!-- Note: This key style is not for functional tab key. This is used for the tab key which is
- laid out as normal letter key. -->
- <key-style
- latin:styleName="nonSpecialBackgroundTabKeyStyle"
- latin:code="@integer/key_tab"
- latin:keyIcon="iconTabKey"
- latin:keyIconPreview="iconPreviewTabKey" />
- <switch>
- <!-- When this qwerty keyboard has no voice key but voice key is enabled, then symbol
- keyboard will have mic key. That means we should use "?123mic" key here. -->
- <case
- latin:voiceKeyEnabled="true"
- latin:hasVoiceKey="false"
- >
- <key-style
- latin:styleName="toSymbolKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyIcon="iconToSymbolKeyWithShortcut"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <default>
- <key-style
- latin:styleName="toSymbolKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_symbol_key"
- latin:parentStyle="functionalKeyStyle" />
- </default>
- </switch>
- <key-style
- latin:styleName="toAlphaKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_alpha_key"
- latin:parentStyle="functionalKeyStyle" />
- <key-style
- latin:styleName="altKeyStyle"
- latin:code="@integer/key_shift"
- latin:keyLabel="@string/label_alt_key"
- latin:parentStyle="functionalKeyStyle"
- latin:isSticky="true" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <key-style
- latin:styleName="nonPasswordSymbolKeyStyle"
- latin:enabled="false" />
- <key-style
- latin:styleName="nonPasswordFunctionalKeyStyle"
- latin:enabled="false"
- latin:parentStyle="functionalKeyStyle" />
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <key-style
- latin:styleName="nonPasswordSymbolKeyStyle"
- latin:enabled="true" />
- <key-style
- latin:styleName="nonPasswordFunctionalKeyStyle"
- latin:enabled="true"
- latin:parentStyle="functionalKeyStyle" />
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml/kbd_popup_template.xml b/java/res/xml/kbd_more_keys_keyboard_template.xml
index 9ee27493d..8e977c5ad 100644
--- a/java/res/xml/kbd_popup_template.xml
+++ b/java/res/xml/kbd_more_keys_keyboard_template.xml
@@ -20,8 +20,7 @@
<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
latin:keyWidth="10%p"
- latin:horizontalGap="@dimen/key_horizontal_gap"
- latin:verticalGap="0px"
latin:rowHeight="@dimen/popup_key_height"
+ style="?attr/moreKeysKeyboardStyle"
>
</Keyboard>
diff --git a/java/res/xml/kbd_nordic.xml b/java/res/xml/kbd_nordic.xml
new file mode 100644
index 000000000..a2196c926
--- /dev/null
+++ b/java/res/xml/kbd_nordic.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_nordic" />
+</Keyboard>
diff --git a/java/res/xml/kbd_number.xml b/java/res/xml/kbd_number.xml
index 4d7b6d9a9..8b0deea97 100644
--- a/java/res/xml/kbd_number.xml
+++ b/java/res/xml/kbd_number.xml
@@ -23,130 +23,5 @@
latin:keyWidth="26.67%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <switch>
- <case
- latin:passwordInput="true"
- >
- <Row
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:rowEdgeFlags="bottom"
- >
- <Spacer />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Spacer />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- </case>
- <!-- latin:passwordInput="false" -->
- <default>
- <Row
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="1"
- latin:keyStyle="numKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="2"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="3"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numFunctionalKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyLabel="4"
- latin:keyStyle="numKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="5"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="6"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numFunctionalKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyLabel="7"
- latin:keyStyle="numKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="8"
- latin:keyStyle="numKeyStyle"/>
- <Key
- latin:keyLabel="9"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:rowEdgeFlags="bottom"
- >
- <Key
- latin:keyStyle="numSpaceKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="0"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- </default>
- </switch>
+ latin:keyboardLayout="@xml/rows_number" />
</Keyboard>
diff --git a/java/res/xml/kbd_pcqwerty.xml b/java/res/xml/kbd_pcqwerty.xml
new file mode 100644
index 000000000..cebca4ff7
--- /dev/null
+++ b/java/res/xml/kbd_pcqwerty.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="3.20%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_pcqwerty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_pcqwerty_symbols.xml b/java/res/xml/kbd_pcqwerty_symbols.xml
new file mode 100644
index 000000000..fd64e5bf4
--- /dev/null
+++ b/java/res/xml/kbd_pcqwerty_symbols.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:rowHeight="20%p"
+ latin:verticalGap="3.20%p"
+ latin:touchPositionCorrectionData="@null"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_pcqwerty_symbols" />
+</Keyboard>
diff --git a/java/res/xml/kbd_phone.xml b/java/res/xml/kbd_phone.xml
index c6508fb03..91637b62c 100644
--- a/java/res/xml/kbd_phone.xml
+++ b/java/res/xml/kbd_phone.xml
@@ -1,19 +1,19 @@
<?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
+** 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
+** 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
+** 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.
*/
-->
@@ -23,65 +23,5 @@
latin:keyWidth="26.67%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <Row
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyStyle="num1KeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num2KeyStyle" />
- <Key
- latin:keyStyle="num3KeyStyle" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numFunctionalKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num4KeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num5KeyStyle" />
- <Key
- latin:keyStyle="num6KeyStyle" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numFunctionalKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="num7KeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num8KeyStyle" />
- <Key
- latin:keyStyle="num9KeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:rowEdgeFlags="bottom"
- >
- <Key
- latin:keyStyle="numSwitchToAltKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="num0KeyStyle" />
- <Key
- latin:keyStyle="numSpaceKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
+ latin:keyboardLayout="@xml/rows_phone" />
</Keyboard>
diff --git a/java/res/xml/kbd_phone_symbols.xml b/java/res/xml/kbd_phone_symbols.xml
index 5d9912229..7f59a855a 100644
--- a/java/res/xml/kbd_phone_symbols.xml
+++ b/java/res/xml/kbd_phone_symbols.xml
@@ -1,19 +1,19 @@
<?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
+** 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
+** 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
+** 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.
*/
-->
@@ -23,78 +23,5 @@
latin:keyWidth="26.67%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_numkey_styles" />
- <Row
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="("
- latin:keyStyle="numKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="/"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel=")"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="-"
- latin:keyStyle="numFunctionalKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyLabel="N"
- latin:keyEdgeFlags="left" />
- <!-- Pause is a comma. Check PhoneNumberUtils.java to see if this
- has changed. -->
- <Key
- latin:code="44"
- latin:keyLabel="@string/label_pause_key"
- latin:keyLabelOption="followKeyHintLabelRatio" />
- <Key
- latin:keyLabel=","
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyLabel="."
- latin:keyStyle="numFunctionalKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="numStarKeyStyle"
- latin:keyEdgeFlags="left" />
- <!-- Wait is a semicolon. -->
- <Key
- latin:code="59"
- latin:keyLabel="@string/label_wait_key"
- latin:keyLabelOption="followKeyHintLabelRatio" />
- <Key
- latin:keyLabel="#"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:rowEdgeFlags="bottom"
- >
- <Key
- latin:keyStyle="numSwitchToNumericKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="+"
- latin:keyStyle="numKeyStyle" />
- <Key
- latin:keyStyle="numSpaceKeyStyle" />
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
+ latin:keyboardLayout="@xml/rows_phone_symbols" />
</Keyboard>
diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml
index 40917b921..2f49b943a 100644
--- a/java/res/xml/kbd_qwerty.xml
+++ b/java/res/xml/kbd_qwerty.xml
@@ -20,8 +20,7 @@
<Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="en_GB,en_US"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
+ latin:keyboardLayout="@xml/rows_qwerty" />
</Keyboard>
diff --git a/java/res/xml/kbd_qwerty_f1.xml b/java/res/xml/kbd_qwerty_f1.xml
deleted file mode 100644
index 51b9800e0..000000000
--- a/java/res/xml/kbd_qwerty_f1.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <switch>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="/"
- latin:keyWidth="9.2%p"
- latin:keyStyle="settingsPopupStyle" />
- </case>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="\@"
- latin:keyWidth="9.2%p"
- latin:keyStyle="settingsPopupStyle" />
- </case>
- <default>
- <switch>
- <case
- latin:hasVoiceKey="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyWidth="9.2%p" />
- </case>
- <!-- latin:hasVoiceKey="false" -->
- <case
- latin:navigateAction="true"
- >
- <Key
- latin:keyLabel="."
- latin:keyWidth="9.2%p"
- latin:keyStyle="settingsPopupStyle" />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyWidth="9.2%p"
- latin:keyStyle="settingsPopupStyle" />
- </default>
- </switch>
- </default>
- </switch>
- </case>
- <!-- hasSettingsKey="false" -->
- <default>
- <switch>
- <case
- latin:mode="url"
- >
- <Key
- latin:keyLabel="/"
- latin:keyStyle="settingsPopupStyle" />
- </case>
- <case
- latin:mode="email"
- >
- <Key
- latin:keyLabel="\@"
- latin:keyStyle="settingsPopupStyle" />
- </case>
- <default>
- <switch>
- <case
- latin:hasVoiceKey="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle" />
- </case>
- <!-- latin:hasVoiceKey="false" -->
- <case
- latin:navigateAction="true"
- >
- <Key
- latin:keyLabel="."
- latin:keyStyle="settingsPopupStyle" />
- </case>
- <default>
- <Key
- latin:keyLabel=","
- latin:keyStyle="settingsPopupStyle" />
- </default>
- </switch>
- </default>
- </switch>
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml/kbd_qwerty_row1.xml b/java/res/xml/kbd_qwerty_row1.xml
deleted file mode 100644
index cfd2efd2a..000000000
--- a/java/res/xml/kbd_qwerty_row1.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="q"
- latin:keyHintLabel="1"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:keyHintLabel="2"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:keyHintLabel="3"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:keyHintLabel="4"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:keyHintLabel="5"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:keyHintLabel="6"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:keyHintLabel="7"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:keyHintLabel="8"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:keyHintLabel="9"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:keyHintLabel="0"
- latin:popupCharacters="@string/alternates_for_p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
-</merge>
diff --git a/java/res/xml/kbd_qwerty_row2.xml b/java/res/xml/kbd_qwerty_row2.xml
deleted file mode 100644
index 57bbad75a..000000000
--- a/java/res/xml/kbd_qwerty_row2.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyXPos="5%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l"
- latin:keyEdgeFlags="right" />
- <!-- Here is 5%p space -->
- </Row>
-</merge>
diff --git a/java/res/xml/kbd_qwerty_row4.xml b/java/res/xml/kbd_qwerty_row4.xml
deleted file mode 100644
index ff2ef3acd..000000000
--- a/java/res/xml/kbd_qwerty_row4.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="bottom"
- >
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyWidth="13.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="9.2%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f1" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyWidth="35.83%p" />
- <switch>
- <case
- latin:navigateAction="true"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_web_tab_punctuation"
- latin:keyWidth="9.2%p"
- latin:maxPopupKeyboardColumn="8" />
- </case>
- <default>
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_punctuation"
- latin:keyWidth="9.2%p"
- latin:maxPopupKeyboardColumn="7"
- latin:keyStyle="functionalKeyStyle" />
- </default>
- </switch>
- </case>
- <!-- latin:hasSettingsKey="false" -->
- <default>
- <Key
- latin:keyStyle="toSymbolKeyStyle"
- latin:keyWidth="15%p"
- latin:keyEdgeFlags="left" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f1" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyWidth="50%p" />
- <switch>
- <case
- latin:navigateAction="true"
- >
- <Key
- latin:keyStyle="tabKeyStyle"
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_web_tab_punctuation"
- latin:maxPopupKeyboardColumn="8" />
- </case>
- <default>
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_punctuation"
- latin:maxPopupKeyboardColumn="7"
- latin:keyStyle="functionalKeyStyle" />
- </default>
- </switch>
- </default>
- </switch>
- <switch>
- <case
- latin:mode="im"
- >
- <Key
- latin:keyStyle="smileyKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </case>
- <default>
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </default>
- </switch>
- </Row>
-</merge>
diff --git a/java/res/xml/kbd_qwertz.xml b/java/res/xml/kbd_qwertz.xml
new file mode 100644
index 000000000..9f7e9019c
--- /dev/null
+++ b/java/res/xml/kbd_qwertz.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_qwertz" />
+</Keyboard>
diff --git a/java/res/xml/kbd_rows_arabic.xml b/java/res/xml/kbd_rows_arabic.xml
deleted file mode 100644
index a548775a4..000000000
--- a/java/res/xml/kbd_rows_arabic.xml
+++ /dev/null
@@ -1,122 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This file for Arabic layout is an alpha version. It allows to enter -->
-<!-- some right-to-left text, but it has gone through no study whatsoever, -->
-<!-- and needs to be run through UX. -->
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="ض"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ص" />
- <Key
- latin:keyLabel="ق" />
- <Key
- latin:keyLabel="ف"
- latin:popupCharacters="ڤ" />
- <Key
- latin:keyLabel="غ" />
- <Key
- latin:keyLabel="ع" />
- <Key
- latin:keyLabel="ه"
- latin:popupCharacters="هـ" />
- <Key
- latin:keyLabel="خ" />
- <Key
- latin:keyLabel="ح" />
- <Key
- latin:keyLabel="ج"
- latin:popupCharacters="چ"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="ش"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="س" />
- <Key
- latin:keyLabel="ي"
- latin:popupCharacters="ى,ئ" />
- <Key
- latin:keyLabel="ب"
- latin:popupCharacters="پ" />
- <Key
- latin:keyLabel="ل"
- latin:popupCharacters="لا" />
- <Key
- latin:keyLabel="ا"
- latin:popupCharacters="أ,إ,آ,ء" />
- <Key
- latin:keyLabel="ت" />
- <Key
- latin:keyLabel="ن" />
- <Key
- latin:keyLabel="م" />
- <Key
- latin:keyLabel="ك"
- latin:popupCharacters="گ"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="9.7%p"
- >
- <Key
- latin:keyLabel="ظ"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ط" />
- <Key
- latin:keyLabel="ذ" />
- <Key
- latin:keyLabel="د" />
- <Key
- latin:keyLabel="ز"
- latin:popupCharacters="ژ" />
- <Key
- latin:keyLabel="ر" />
- <Key
- latin:keyLabel="و"
- latin:popupCharacters="ؤ" />
- <Key
- latin:keyLabel="ة" />
- <Key
- latin:keyLabel="ث" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_azerty.xml b/java/res/xml/kbd_rows_azerty.xml
deleted file mode 100644
index 96efb6646..000000000
--- a/java/res/xml/kbd_rows_azerty.xml
+++ /dev/null
@@ -1,143 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="a"
- latin:keyHintLabel="1"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="z"
- latin:keyHintLabel="2"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="e"
- latin:keyHintLabel="3"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:keyHintLabel="4"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:keyHintLabel="5"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:keyHintLabel="6"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:keyHintLabel="7"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:keyHintLabel="8"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:keyHintLabel="9"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:keyHintLabel="0"
- latin:popupCharacters="@string/alternates_for_p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="q"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="m"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="15%p"
- latin:visualInsetsRight="1%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
-
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="\'"
- latin:popupCharacters="‘,’,‚,‛" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_hebrew.xml b/java/res/xml/kbd_rows_hebrew.xml
deleted file mode 100644
index c3c8f7d3e..000000000
--- a/java/res/xml/kbd_rows_hebrew.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This file for Hebrew layout is an alpha version. It allows to enter -->
-<!-- some right-to-left text, but it has gone through no study whatsoever, -->
-<!-- and needs to be run through UX. -->
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="ק"
- latin:keyXPos="5%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ר" />
- <Key
- latin:keyLabel="א" />
- <Key
- latin:keyLabel="ט" />
- <Key
- latin:keyLabel="ו" />
- <Key
- latin:keyLabel="ן" />
- <Key
- latin:keyLabel="ם" />
- <Key
- latin:keyLabel="פ" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="ש"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ד" />
- <Key
- latin:keyLabel="ג" />
- <Key
- latin:keyLabel="כ" />
- <Key
- latin:keyLabel="ע" />
- <Key
- latin:keyLabel="י" />
- <Key
- latin:keyLabel="ח" />
- <Key
- latin:keyLabel="ל" />
- <Key
- latin:keyLabel="ך" />
- <Key
- latin:keyLabel="ף"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="ז"
- latin:keyXPos="5%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ס" />
- <Key
- latin:keyLabel="ב" />
- <Key
- latin:keyLabel="ה" />
- <Key
- latin:keyLabel="נ" />
- <Key
- latin:keyLabel="מ" />
- <Key
- latin:keyLabel="צ" />
- <Key
- latin:keyLabel="ת" />
- <Key
- latin:keyLabel="ץ"
- latin:keyEdgeFlags="right" />
- <!-- Here is 5%p space -->
- </Row>
- <include latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_qwertz.xml b/java/res/xml/kbd_rows_qwertz.xml
deleted file mode 100644
index 347ef60ad..000000000
--- a/java/res/xml/kbd_rows_qwertz.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="q"
- latin:keyHintLabel="1"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:keyHintLabel="2"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:keyHintLabel="3"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:keyHintLabel="4"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:keyHintLabel="5"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="z"
- latin:keyHintLabel="6"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="u"
- latin:keyHintLabel="7"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:keyHintLabel="8"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:keyHintLabel="9"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:keyHintLabel="0"
- latin:popupCharacters="@string/alternates_for_p"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row2" />
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="15%p"
- latin:visualInsetsRight="1%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="y"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_russian.xml b/java/res/xml/kbd_rows_russian.xml
deleted file mode 100644
index 2c10c3141..000000000
--- a/java/res/xml/kbd_rows_russian.xml
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="9.091%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="й"
- latin:keyHintLabel="1"
- latin:popupCharacters="1"
- latin:keyWidth="8.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ц"
- latin:keyHintLabel="2"
- latin:popupCharacters="2" />
- <Key
- latin:keyLabel="у"
- latin:keyHintLabel="3"
- latin:popupCharacters="3" />
- <Key
- latin:keyLabel="к"
- latin:keyHintLabel="4"
- latin:popupCharacters="4" />
- <Key
- latin:keyLabel="е"
- latin:keyHintLabel="5"
- latin:popupCharacters="@string/alternates_for_cyrillic_e" />
- <Key
- latin:keyLabel="н"
- latin:keyHintLabel="6"
- latin:popupCharacters="6" />
- <Key
- latin:keyLabel="г"
- latin:keyHintLabel="7"
- latin:popupCharacters="7" />
- <Key
- latin:keyLabel="ш"
- latin:keyHintLabel="8"
- latin:popupCharacters="8" />
- <Key
- latin:keyLabel="щ"
- latin:keyHintLabel="9"
- latin:popupCharacters="9" />
- <Key
- latin:keyLabel="з"
- latin:keyHintLabel="0"
- latin:popupCharacters="0" />
- <Key
- latin:keyLabel="х"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="9.091%p"
- >
- <Key
- latin:keyLabel="ф"
- latin:keyWidth="8.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ы" />
- <Key
- latin:keyLabel="в" />
- <Key
- latin:keyLabel="а" />
- <Key
- latin:keyLabel="п" />
- <Key
- latin:keyLabel="р" />
- <Key
- latin:keyLabel="о" />
- <Key
- latin:keyLabel="л" />
- <Key
- latin:keyLabel="д" />
- <Key
- latin:keyLabel="ж" />
- <Key
- latin:keyLabel="э"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.5%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="11.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="я" />
- <Key
- latin:keyLabel="ч" />
- <Key
- latin:keyLabel="с" />
- <Key
- latin:keyLabel="м" />
- <Key
- latin:keyLabel="и" />
- <Key
- latin:keyLabel="т" />
- <Key
- latin:keyLabel="ь"
- latin:popupCharacters="@string/alternates_for_cyrillic_soft_sign" />
- <Key
- latin:keyLabel="б" />
- <Key
- latin:keyLabel="ю" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_scandinavian.xml b/java/res/xml/kbd_rows_scandinavian.xml
deleted file mode 100644
index 3f2560128..000000000
--- a/java/res/xml/kbd_rows_scandinavian.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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/kbd_key_styles" />
- <Row
- latin:keyWidth="9.09%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="q"
- latin:keyHintLabel="1"
- latin:popupCharacters="@string/alternates_for_q"
- latin:keyWidth="8.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="w"
- latin:keyHintLabel="2"
- latin:popupCharacters="@string/alternates_for_w" />
- <Key
- latin:keyLabel="e"
- latin:keyHintLabel="3"
- latin:popupCharacters="@string/alternates_for_e" />
- <Key
- latin:keyLabel="r"
- latin:keyHintLabel="4"
- latin:popupCharacters="@string/alternates_for_r" />
- <Key
- latin:keyLabel="t"
- latin:keyHintLabel="5"
- latin:popupCharacters="@string/alternates_for_t" />
- <Key
- latin:keyLabel="y"
- latin:keyHintLabel="6"
- latin:popupCharacters="@string/alternates_for_y" />
- <Key
- latin:keyLabel="u"
- latin:keyHintLabel="7"
- latin:popupCharacters="@string/alternates_for_u" />
- <Key
- latin:keyLabel="i"
- latin:keyHintLabel="8"
- latin:popupCharacters="@string/alternates_for_i" />
- <Key
- latin:keyLabel="o"
- latin:keyHintLabel="9"
- latin:popupCharacters="@string/alternates_for_o" />
- <Key
- latin:keyLabel="p"
- latin:keyHintLabel="0"
- latin:popupCharacters="@string/alternates_for_p" />
- <Key
- latin:keyLabel="å"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="9.09%p"
- >
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyWidth="8.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="@string/keylabel_for_scandinavia_row2_10"
- latin:popupCharacters="@string/alternates_for_scandinavia_row2_10" />
- <Key
- latin:keyLabel="@string/keylabel_for_scandinavia_row2_11"
- latin:popupCharacters="@string/alternates_for_scandinavia_row2_11"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_serbian.xml b/java/res/xml/kbd_rows_serbian.xml
deleted file mode 100644
index 2bed276d3..000000000
--- a/java/res/xml/kbd_rows_serbian.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:keyWidth="9.09%p"
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="љ"
- latin:keyHintLabel="1"
- latin:popupCharacters="1"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="њ"
- latin:keyHintLabel="2"
- latin:popupCharacters="2" />
- <Key
- latin:keyLabel="е"
- latin:keyHintLabel="3"
- latin:popupCharacters="3" />
- <Key
- latin:keyLabel="р"
- latin:keyHintLabel="4"
- latin:popupCharacters="4" />
- <Key
- latin:keyLabel="т"
- latin:keyHintLabel="5"
- latin:popupCharacters="5" />
- <Key
- latin:keyLabel="з"
- latin:keyHintLabel="6"
- latin:popupCharacters="6" />
- <Key
- latin:keyLabel="у"
- latin:keyHintLabel="7"
- latin:popupCharacters="7" />
- <Key
- latin:keyLabel="и"
- latin:keyHintLabel="8"
- latin:popupCharacters="8" />
- <Key
- latin:keyLabel="о"
- latin:keyHintLabel="9"
- latin:popupCharacters="9" />
- <Key
- latin:keyLabel="п"
- latin:keyHintLabel="0"
- latin:popupCharacters="0" />
- <Key
- latin:keyLabel="ш"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="9.09%p"
- >
- <Key
- latin:keyLabel="а"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="с" />
- <Key
- latin:keyLabel="д" />
- <Key
- latin:keyLabel="ф" />
- <Key
- latin:keyLabel="г" />
- <Key
- latin:keyLabel="х" />
- <Key
- latin:keyLabel="ј" />
- <Key
- latin:keyLabel="к" />
- <Key
- latin:keyLabel="л" />
- <Key
- latin:keyLabel="ч" />
- <Key
- latin:keyLabel="ћ"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row
- latin:keyWidth="8.90%p"
- >
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="ѕ" />
- <Key
- latin:keyLabel="џ" />
- <Key
- latin:keyLabel="ц" />
- <Key
- latin:keyLabel="в" />
- <Key
- latin:keyLabel="б" />
- <Key
- latin:keyLabel="н" />
- <Key
- latin:keyLabel="м" />
- <Key
- latin:keyLabel="ђ" />
- <Key
- latin:keyLabel="ж" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_rows_spanish.xml b/java/res/xml/kbd_rows_spanish.xml
deleted file mode 100644
index c5ead10da..000000000
--- a/java/res/xml/kbd_rows_spanish.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge
- xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row1" />
- <Row
- latin:keyWidth="10%p"
- >
- <Key
- latin:keyLabel="a"
- latin:popupCharacters="@string/alternates_for_a"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="s"
- latin:popupCharacters="@string/alternates_for_s" />
- <Key
- latin:keyLabel="d"
- latin:popupCharacters="@string/alternates_for_d" />
- <Key
- latin:keyLabel="f" />
- <Key
- latin:keyLabel="g"
- latin:popupCharacters="@string/alternates_for_g" />
- <Key
- latin:keyLabel="h" />
- <Key
- latin:keyLabel="j" />
- <Key
- latin:keyLabel="k"
- latin:popupCharacters="@string/alternates_for_k" />
- <Key
- latin:keyLabel="l"
- latin:popupCharacters="@string/alternates_for_l" />
- <Key
- latin:keyLabel="ñ"
- latin:keyEdgeFlags="right" />
- </Row>
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
-</merge>
diff --git a/java/res/xml/kbd_south_slavic.xml b/java/res/xml/kbd_south_slavic.xml
new file mode 100644
index 000000000..f3ad02c7b
--- /dev/null
+++ b/java/res/xml/kbd_south_slavic.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_south_slavic" />
+</Keyboard>
diff --git a/java/res/xml/kbd_spanish.xml b/java/res/xml/kbd_spanish.xml
new file mode 100644
index 000000000..6ce2b5d24
--- /dev/null
+++ b/java/res/xml/kbd_spanish.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_spanish" />
+</Keyboard>
diff --git a/java/res/xml/kbd_suggestions_pane_template.xml b/java/res/xml/kbd_suggestions_pane_template.xml
new file mode 100644
index 000000000..21316e6bb
--- /dev/null
+++ b/java/res/xml/kbd_suggestions_pane_template.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="10%p"
+ latin:rowHeight="@dimen/more_suggestions_row_height"
+ >
+</Keyboard>
diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml
index 8e9124f74..f6612a2f7 100644
--- a/java/res/xml/kbd_symbols.xml
+++ b/java/res/xml/kbd_symbols.xml
@@ -1,128 +1,26 @@
<?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
+** 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
+** 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
+** 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"
- latin:keyWidth="10%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_currency_key_styles" />
- <Row
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="1"
- latin:popupCharacters="¹,½,⅓,¼,⅛"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="2"
- latin:popupCharacters="²,⅔" />
- <Key
- latin:keyLabel="3"
- latin:popupCharacters="³,¾,⅜" />
- <Key
- latin:keyLabel="4"
- latin:popupCharacters="⁴" />
- <Key
- latin:keyLabel="5"
- latin:popupCharacters="⅝" />
- <Key
- latin:keyLabel="6" />
- <Key
- latin:keyLabel="7"
- latin:popupCharacters="⅞" />
- <Key
- latin:keyLabel="8" />
- <Key
- latin:keyLabel="9" />
- <Key
- latin:keyLabel="0"
- latin:popupCharacters="ⁿ,∅"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyLabel="\@"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="\#" />
- <Key
- latin:keyStyle="currencyKeyStyle" />
- <Key
- latin:keyLabel="%"
- latin:popupCharacters="‰" />
- <Key
- latin:keyLabel="&amp;" />
- <Key
- latin:keyLabel="*"
- latin:popupCharacters="†,‡,★" />
- <Key
- latin:keyLabel="-"
- latin:popupCharacters="_,–,—" />
- <Key
- latin:keyLabel="+"
- latin:popupCharacters="±" />
- <Key
- latin:keyLabel="("
- latin:popupCharacters="[,{,&lt;" />
- <Key
- latin:keyLabel=")"
- latin:popupCharacters="],},&gt;"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="altKeyStyle"
- latin:keyWidth="15%p"
- latin:visualInsetsRight="1%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="!"
- latin:popupCharacters="¡" />
- <!-- Note: DroidSans doesn't have double-high-reversed-quotation '\u201f' glyph. -->
- <!-- latin:popupCharacters="“,”,„,‟,«,»" -->
- <Key
- latin:keyLabel="&quot;"
- latin:popupCharacters="“,”,«,»"
- latin:maxPopupKeyboardColumn="6" />
- <Key
- latin:keyLabel="\'"
- latin:popupCharacters="‘,’,‚,‛" />
- <Key
- latin:keyLabel=":" />
- <Key
- latin:keyLabel=";" />
- <Key
- latin:keyLabel="/" />
- <Key
- latin:keyLabel="\?"
- latin:popupCharacters="¿" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_symbols_row4" />
+ latin:keyboardLayout="@xml/rows_symbols" />
</Keyboard>
diff --git a/java/res/xml/kbd_symbols_f1.xml b/java/res/xml/kbd_symbols_f1.xml
deleted file mode 100644
index da5b5fc8d..000000000
--- a/java/res/xml/kbd_symbols_f1.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <switch>
- <case
- latin:hasVoiceKey="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle"
- latin:keyWidth="9.2%p" />
- </case>
- <!-- latin:hasVoiceKey="false" -->
- <default>
- <Key
- latin:keyLabel=","
- latin:keyWidth="9.2%p"
- latin:keyStyle="settingsPopupStyle" />
- </default>
- </switch>
- </case>
- <!-- hasSettingsKey="false" -->
- <default>
- <switch>
- <case
- latin:hasVoiceKey="true"
- >
- <Key
- latin:keyStyle="shortcutKeyStyle" />
- </case>
- <!-- latin:hasVoiceKey="false" -->
- <default>
- <Key
- latin:keyLabel=","
- latin:keyStyle="settingsPopupStyle" />
- </default>
- </switch>
- </default>
- </switch>
-</merge>
diff --git a/java/res/xml/kbd_symbols_row4.xml b/java/res/xml/kbd_symbols_row4.xml
deleted file mode 100644
index 68b79e84d..000000000
--- a/java/res/xml/kbd_symbols_row4.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="bottom"
- >
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyWidth="13.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="9.2%p" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_f1" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyWidth="35.83%p" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_punctuation"
- latin:keyWidth="9.2%p"
- latin:maxPopupKeyboardColumn="7"
- latin:keyStyle="functionalKeyStyle" />
- </case>
- <!-- latin:hasSettingsKey="false" -->
- <default>
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyWidth="15%p"
- latin:keyEdgeFlags="left" />
- <include
- latin:keyboardLayout="@xml/kbd_symbols_f1" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyWidth="50%p" />
- <Key
- latin:keyLabel="."
- latin:keyLabelOption="hasPopupHint"
- latin:popupCharacters="@string/alternates_for_punctuation"
- latin:maxPopupKeyboardColumn="7"
- latin:keyStyle="functionalKeyStyle" />
- </default>
- </switch>
- <switch>
- <case
- latin:mode="im"
- >
- <Key
- latin:keyStyle="smileyKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </case>
- <default>
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </default>
- </switch>
- </Row>
-</merge>
diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml
index f22d45aff..41a5571ef 100644
--- a/java/res/xml/kbd_symbols_shift.xml
+++ b/java/res/xml/kbd_symbols_shift.xml
@@ -1,127 +1,26 @@
<?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
+** 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
+** 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
+** 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"
- latin:keyWidth="10%p"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <Row
- latin:rowEdgeFlags="top"
- >
- <Key
- latin:keyLabel="~"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="`" />
- <Key
- latin:keyLabel="|" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="•"
- latin:popupCharacters="♪,♥,♠,♦,♣" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="√" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="π"
- latin:popupCharacters="Π" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="÷" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="×" />
- <Key
- latin:keyLabel="{" />
- <Key
- latin:keyLabel="}"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="nonSpecialBackgroundTabKeyStyle"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="£" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¢" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="€" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="°"
- latin:popupCharacters="′,″" />
- <Key
- latin:keyLabel="^"
- latin:popupCharacters="↑,↓,←,→" />
- <Key
- latin:keyLabel="_" />
- <Key
- latin:keyLabel="="
- latin:popupCharacters="≠,≈,∞" />
- <Key
- latin:keyLabel="[" />
- <Key
- latin:keyLabel="]"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </Row>
- <Row>
- <Key
- latin:keyStyle="shiftKeyStyle"
- latin:keyWidth="15%p"
- latin:visualInsetsRight="1%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="™" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="®" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="©" />
- <Key
- latin:keyStyle="nonPasswordSymbolKeyStyle"
- latin:keyLabel="¶"
- latin:popupCharacters="§" />
- <Key
- latin:keyLabel="\\" />
- <Key
- latin:keyLabel="&lt;"
- latin:popupCharacters="≤,«,‹" />
- <Key
- latin:keyLabel="&gt;"
- latin:popupCharacters="≥,»,›" />
- <Key
- latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillRight"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
- </Row>
- <include latin:keyboardLayout="@xml/kbd_symbols_shift_row4" />
+ latin:keyboardLayout="@xml/rows_symbols_shift" />
</Keyboard>
diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml
deleted file mode 100644
index 90a96e4bc..000000000
--- a/java/res/xml/kbd_symbols_shift_row4.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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"
->
- <Row
- latin:keyWidth="10%p"
- latin:rowEdgeFlags="bottom"
- >
- <switch>
- <case
- latin:hasSettingsKey="true"
- >
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyWidth="13.75%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyStyle="settingsKeyStyle"
- latin:keyWidth="9.2%p" />
- <Key
- latin:keyLabel="„"
- latin:popupCharacters="“,”,„,‟,«,»,‘,’,‚,‛"
- latin:keyWidth="9.2%p"
- latin:keyStyle="nonPasswordFunctionalKeyStyle" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyWidth="35.83%p" />
- <Key
- latin:keyLabel="…"
- latin:keyWidth="9.2%p"
- latin:keyStyle="nonPasswordFunctionalKeyStyle" />
- </case>
- <!-- latin:hasSettingsKey="false" -->
- <default>
- <Key
- latin:keyStyle="toAlphaKeyStyle"
- latin:keyWidth="15%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="„"
- latin:popupCharacters="“,”,„,‟,«,»,‘,’,‚,‛"
- latin:keyStyle="nonPasswordFunctionalKeyStyle" />
- <Key
- latin:keyStyle="spaceKeyStyle"
- latin:keyWidth="50%p" />
- <Key
- latin:keyLabel="…"
- latin:keyStyle="nonPasswordFunctionalKeyStyle" />
- </default>
- </switch>
- <switch>
- <case
- latin:mode="im"
- >
- <Key
- latin:keyStyle="smileyKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </case>
- <default>
- <Key
- latin:keyStyle="returnKeyStyle"
- latin:keyWidth="fillRight"
- latin:keyEdgeFlags="right" />
- </default>
- </switch>
- </Row>
-</merge>
diff --git a/java/res/xml/kbd_thai.xml b/java/res/xml/kbd_thai.xml
new file mode 100644
index 000000000..058ca16a3
--- /dev/null
+++ b/java/res/xml/kbd_thai.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_thai" />
+</Keyboard>
diff --git a/java/res/xml/kbd_thai_symbols.xml b/java/res/xml/kbd_thai_symbols.xml
new file mode 100644
index 000000000..7e075df48
--- /dev/null
+++ b/java/res/xml/kbd_thai_symbols.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_symbols" />
+</Keyboard>
diff --git a/java/res/xml/kbd_thai_symbols_shift.xml b/java/res/xml/kbd_thai_symbols_shift.xml
new file mode 100644
index 000000000..25db3c84d
--- /dev/null
+++ b/java/res/xml/kbd_thai_symbols_shift.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_symbols_shift" />
+</Keyboard>
diff --git a/java/res/xml/kbd_rows_qwerty.xml b/java/res/xml/key_azerty_quote.xml
index 6237712f6..65789ea69 100644
--- a/java/res/xml/kbd_rows_qwerty.xml
+++ b/java/res/xml/key_azerty_quote.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2010, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -21,14 +21,17 @@
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
- <include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row1" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row2" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel="\?" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="\'"
+ latin:moreKeys="!text/more_keys_for_single_quote" />
+ </default>
+ </switch>
</merge>
diff --git a/java/res/xml/key_colemak_colon.xml b/java/res/xml/key_colemak_colon.xml
new file mode 100644
index 000000000..307b4ebca
--- /dev/null
+++ b/java/res/xml/key_colemak_colon.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel=";"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=":"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0"
+ latin:moreKeys=";" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml-large/kbd_row3_right.xml b/java/res/xml/key_f1.xml
index 5e9584f2d..455f9ef59 100644
--- a/java/res/xml-large/kbd_row3_right.xml
+++ b/java/res/xml/key_f1.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2011, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -23,44 +23,32 @@
>
<switch>
<case
- latin:mode="email"
+ latin:mode="url"
>
<Key
- latin:keyLabel="\@"
- latin:keyXPos="-8.9%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
+ latin:keyLabel="/"
+ latin:keyStyle="f1MoreKeysStyle" />
</case>
<case
- latin:mode="url"
+ latin:mode="email"
>
<Key
- latin:keyLabel="-"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="_"
- latin:popupCharacters="_"
- latin:keyXPos="-8.9%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
+ latin:keyLabel="\@"
+ latin:keyStyle="f1MoreKeysStyle" />
</case>
<case
- latin:imeAction="actionSearch"
+ latin:hasShortcutKey="true"
>
<Key
- latin:keyLabel=":"
- latin:keyLabelOption="hasUppercaseLetter"
- latin:keyHintLabel="+"
- latin:popupCharacters="+"
- latin:keyXPos="-8.9%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
+ latin:keyStyle="shortcutKeyStyle" />
</case>
+ <!-- latin:hasShortcutKey="false" -->
<default>
<Key
- latin:keyStyle="smileyKeyStyle"
- latin:keyXPos="-8.9%p"
- latin:keyWidth="fillBoth"
- latin:keyEdgeFlags="right" />
+ latin:keyLabel="!text/keylabel_for_comma"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:additionalMoreKeys="!text/more_keys_for_comma"
+ latin:keyStyle="f1MoreKeysStyle" />
</default>
</switch>
</merge>
diff --git a/java/res/xml/key_greek_semicolon.xml b/java/res/xml/key_greek_semicolon.xml
new file mode 100644
index 000000000..ae73a59f6
--- /dev/null
+++ b/java/res/xml/key_greek_semicolon.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel=":"
+ latin:keyHintLabel="1"
+ latin:moreKeys=";"
+ latin:additionalMoreKeys="1" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=";"
+ latin:keyHintLabel="1"
+ latin:moreKeys=":"
+ latin:additionalMoreKeys="1" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/key_space.xml b/java/res/xml/key_space.xml
new file mode 100644
index 000000000..02ee42fd2
--- /dev/null
+++ b/java/res/xml/key_space.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:languageCode="fa"
+ latin:languageSwitchKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="languageSwitchKeyStyle" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="30%p" />
+ <Key
+ latin:keyStyle="zwnjKeyStyle" />
+ </case>
+ <case
+ latin:languageCode="fa"
+ latin:languageSwitchKeyEnabled="false"
+ >
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="40%p" />
+ <Key
+ latin:keyStyle="zwnjKeyStyle" />
+ </case>
+ <case
+ latin:languageSwitchKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="languageSwitchKeyStyle" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="40%p" />
+ </case>
+ <!-- languageSwitchKeyEnabled="false" -->
+ <default>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="50%p" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
new file mode 100644
index 000000000..162119dab
--- /dev/null
+++ b/java/res/xml/key_styles_common.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- Base key style for the key which may have settings or tab key as popup key. -->
+ <include
+ latin:keyboardLayout="@xml/key_styles_f1" />
+ <!-- Functional key styles -->
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetAutomaticShifted"
+ >
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key_shifted"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOff" />
+ </case>
+ <case
+ latin:keyboardLayoutSetElement="alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key_shifted"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOn" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="shiftKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyIcon="!icon/shift_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="stickyOff" />
+ </default>
+ </switch>
+ <key-style
+ latin:styleName="deleteKeyStyle"
+ latin:code="!code/key_delete"
+ latin:keyIcon="!icon/delete_key"
+ latin:keyActionFlags="isRepeatable|noKeyPreview"
+ latin:backgroundType="functional" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_enter" />
+ <switch>
+ <!-- Shift + Enter in textMultiLine field. -->
+ <case
+ latin:isMultiLine="true"
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <!-- Smiley in textShortMessage field.
+ Overrides common enter key style. -->
+ <case
+ latin:mode="im"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabel=":-)"
+ latin:keyOutputText=":-) "
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_smiley"
+ latin:backgroundType="functional" />
+ </case>
+ </switch>
+ <key-style
+ latin:styleName="spaceKeyStyle"
+ latin:code="!code/key_space"
+ latin:keyActionFlags="noKeyPreview|enableLongPress" />
+ <!-- U+200C: ZERO WIDTH NON-JOINER
+ U+200D: ZERO WIDTH JOINER -->
+ <key-style
+ latin:styleName="zwnjKeyStyle"
+ latin:code="0x200C"
+ latin:keyIcon="!icon/zwnj_key"
+ latin:moreKeys="!icon/zwj_key|&#x200D;"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:keyActionFlags="noKeyPreview" />
+ <key-style
+ latin:styleName="shortcutKeyStyle"
+ latin:code="!code/key_shortcut"
+ latin:keyIcon="!icon/shortcut_key"
+ latin:keyIconDisabled="!icon/shortcut_key_disabled"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
+ latin:altCode="!code/key_space"
+ latin:parentStyle="f1MoreKeysStyle" />
+ <key-style
+ latin:styleName="settingsKeyStyle"
+ latin:code="!code/key_settings"
+ latin:keyIcon="!icon/settings_key"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
+ latin:altCode="!code/key_space"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="languageSwitchKeyStyle"
+ latin:code="!code/key_language_switch"
+ latin:keyIcon="!icon/language_switch_key"
+ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping|enableLongPress"
+ latin:altCode="!code/key_space" />
+ <key-style
+ latin:styleName="tabKeyStyle"
+ latin:code="!code/key_tab"
+ latin:keyIcon="!icon/tab_key"
+ latin:keyIconPreview="!icon/tab_key_preview"
+ latin:backgroundType="functional" />
+ <!-- Note: This key style is not for functional tab key. This is used for the tab key which is
+ laid out as normal letter key. -->
+ <key-style
+ latin:styleName="nonSpecialBackgroundTabKeyStyle"
+ latin:code="!code/key_tab"
+ latin:keyIcon="!icon/tab_key"
+ latin:keyIconPreview="!icon/tab_key_preview" />
+ <switch>
+ <!-- When this qwerty keyboard has no shortcut keys but shortcut key is enabled, then symbol
+ keyboard will have a shortcut key. That means we should use label_to_symbol_key label
+ and shortcut_for_label icon. -->
+ <case
+ latin:shortcutKeyEnabled="true"
+ latin:hasShortcutKey="false"
+ >
+ <key-style
+ latin:styleName="toSymbolKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyIcon="!icon/shortcut_for_label"
+ latin:keyLabel="!text/label_to_symbol_with_microphone_key"
+ latin:keyLabelFlags="withIconRight|preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ </case>
+ <default>
+ <key-style
+ latin:styleName="toSymbolKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_symbol_key"
+ latin:keyLabelFlags="preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+ <key-style
+ latin:styleName="toAlphaKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_alpha_key"
+ latin:keyLabelFlags="preserveCase"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="toMoreSymbolKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyLabel="!text/label_to_more_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="backFromMoreSymbolKeyStyle"
+ latin:code="!code/key_shift"
+ latin:keyLabel="!text/label_to_symbol_key"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional" />
+ <key-style
+ latin:styleName="punctuationKeyStyle"
+ latin:keyLabel="."
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_punctuation"
+ latin:backgroundType="functional" />
+</merge>
diff --git a/java/res/xml/key_styles_currency.xml b/java/res/xml/key_styles_currency.xml
new file mode 100644
index 000000000..6dea16f89
--- /dev/null
+++ b/java/res/xml/key_styles_currency.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:passwordInput="true"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency_dollar" />
+ </case>
+ <!-- Countries using Euro currency, 23 countries as for January 2011. -->
+ 1. Andorra (ca_AD, ca_ES)
+ 2. Austria (de_AT)
+ 3. Belgium (nl_BE, fr_BE, de_BE)
+ 4. Cyprus (el_CY, tr_CY)
+ 5. Estonia (et_EE)
+ 6. Finland (fi_FI, sv_FI)
+ 7. France (fr_FR)
+ 8. Germany (de_DE)
+ 9. Greece (el_GR)
+ 10. Ireland (ga_IE, en_IE)
+ 11. Italy (it_IT)
+ 12. Kosovo (??_XK) ??
+ 13. Luxembourg (lb_LU, fr_LU, de_LU)
+ 14. Malta (mt_MT, en_MT)
+ 15. Monaco (fr_MO)
+ 16. Montenegro (sla_ME)
+ 17. Netherlands (nl_NL)
+ 18. Portugal (pt_PT)
+ 19. San Marino (it_SM)
+ 20. Slovakia (sk_SK)
+ 21. Slovenia (sl_SI)
+ 22. Spain (es_ES, ca_ES)
+ 23. Vatican City (it_VA)
+ -->
+ <!-- Though Denmark and Turkey don't using Euro as their currencies, but having Euro sign on
+ the symbol keyboard might be useful. Especially Danish krone (kr) and Turkish lira
+ (TL) can be represented by usual alphabet letters. -->
+ <!-- Note: Some locales may not have country code, and it it supposed to indicate the
+ country where the language originally/mainly spoken. -->
+ <case
+ latin:localeCode="da|de|es|el|fi|fr|it|nl|sk|sl|pt_PT|tr"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency_euro" />
+ </case>
+ <case
+ latin:languageCode="ca|et|lb|mt|sla"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency_euro" />
+ </case>
+ <case
+ latin:countryCode="AD|AT|BE|CY|EE|FI|FR|DE|GR|IE|IT|XK|LU|MT|MO|ME|NL|PT|SM|SK|SI|ES|VA"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency_euro" />
+ </case>
+ <case
+ latin:languageCode="iw"
+ >
+ <!-- U+20AA: "₪" NEW SHEQEL SIGN
+ U+00A3: "£" POUND SIGN
+ U+20AC: "€" EURO SIGN
+ U+00A2: "¢" CENT SIGN -->
+ <key-style
+ latin:styleName="currencyKeyStyle"
+ latin:keyLabel="&#x20AA;"
+ latin:moreKeys="!text/more_keys_for_currency_general" />
+ <key-style
+ latin:styleName="moreCurrency1KeyStyle"
+ latin:keyLabel="&#x00A3;" />
+ <key-style
+ latin:styleName="moreCurrency2KeyStyle"
+ latin:keyLabel="&#x20AC;" />
+ <key-style
+ latin:styleName="moreCurrency3KeyStyle"
+ latin:keyLabel="$"
+ latin:moreKeys="&#x00A2;" />
+ <key-style
+ latin:styleName="moreCurrency4KeyStyle"
+ latin:keyLabel="&#x00A2;" />
+ </case>
+ <case
+ latin:languageCode="fa"
+ >
+ <!-- U+FDFC: "﷼" RIAL SIGN
+ U+060B: "؋" AFGHANI SIGN
+ U+00A3: "£" POUND SIGN
+ U+20AC: "€" EURO SIGN
+ U+00A2: "¢" CENT SIGN -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+FCDC: RIAL SIGN -->
+ <key-style
+ latin:styleName="currencyKeyStyle"
+ latin:keyLabel="&#xFDFC;"
+ latin:moreKeys="!text/more_keys_for_currency_general,&#x060B;" />
+ <key-style
+ latin:styleName="moreCurrency1KeyStyle"
+ latin:keyLabel="&#x00A3;" />
+ <key-style
+ latin:styleName="moreCurrency2KeyStyle"
+ latin:keyLabel="&#x20AC;" />
+ <key-style
+ latin:styleName="moreCurrency3KeyStyle"
+ latin:keyLabel="$"
+ latin:moreKeys="&#x00A2;" />
+ <key-style
+ latin:styleName="moreCurrency4KeyStyle"
+ latin:keyLabel="&#x00A2;" />
+ </case>
+ <!-- United Kingdom -->
+ <case
+ latin:countryCode="GB"
+ >
+ <!-- U+00A3: "£" POUND SIGN
+ U+20AC: "€" EURO SIGN
+ U+00A5: "¥" YEN SIGN
+ U+00A2: "¢" CENT SIGN -->
+ <key-style
+ latin:styleName="currencyKeyStyle"
+ latin:keyLabel="&#x00A3;"
+ latin:moreKeys="!text/more_keys_for_currency_pound" />
+ <key-style
+ latin:styleName="moreCurrency1KeyStyle"
+ latin:keyLabel="&#x20AC;" />
+ <key-style
+ latin:styleName="moreCurrency2KeyStyle"
+ latin:keyLabel="&#x00A5;" />
+ <key-style
+ latin:styleName="moreCurrency3KeyStyle"
+ latin:keyLabel="$"
+ latin:moreKeys="&#x00A2;" />
+ <key-style
+ latin:styleName="moreCurrency4KeyStyle"
+ latin:keyLabel="&#x00A2;" />
+ </case>
+ <default>
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency_dollar" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/key_styles_currency_dollar.xml b/java/res/xml/key_styles_currency_dollar.xml
new file mode 100644
index 000000000..674a3966d
--- /dev/null
+++ b/java/res/xml/key_styles_currency_dollar.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <!-- U+00A3: "£" POUND SIGN
+ U+00A2: "¢" CENT SIGN
+ U+20AC: "€" EURO SIGN
+ U+00A5: "¥" YEN SIGN -->
+ <key-style
+ latin:styleName="currencyKeyStyle"
+ latin:keyLabel="$"
+ latin:moreKeys="!text/more_keys_for_currency_dollar" />
+ <key-style
+ latin:styleName="moreCurrency1KeyStyle"
+ latin:keyLabel="&#x00A3;" />
+ <key-style
+ latin:styleName="moreCurrency2KeyStyle"
+ latin:keyLabel="&#x00A2;" />
+ <key-style
+ latin:styleName="moreCurrency3KeyStyle"
+ latin:keyLabel="&#x20AC;" />
+ <key-style
+ latin:styleName="moreCurrency4KeyStyle"
+ latin:keyLabel="&#x00A5;" />
+</merge>
diff --git a/java/res/xml/key_styles_currency_euro.xml b/java/res/xml/key_styles_currency_euro.xml
new file mode 100644
index 000000000..686fb3033
--- /dev/null
+++ b/java/res/xml/key_styles_currency_euro.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <!-- U+20AC: "€" EURO SIGN
+ U+00A3: "£" POUND SIGN
+ U+00A5: "¥" YEN SIGN
+ U+00A2: "¢" CENT SIGN -->
+ <key-style
+ latin:styleName="currencyKeyStyle"
+ latin:keyLabel="&#x20AC;"
+ latin:moreKeys="!text/more_keys_for_currency_euro" />
+ <key-style
+ latin:styleName="moreCurrency1KeyStyle"
+ latin:keyLabel="&#x00A3;" />
+ <key-style
+ latin:styleName="moreCurrency2KeyStyle"
+ latin:keyLabel="&#x00A5;" />
+ <key-style
+ latin:styleName="moreCurrency3KeyStyle"
+ latin:keyLabel="$"
+ latin:moreKeys="&#x00A2;" />
+ <key-style
+ latin:styleName="moreCurrency4KeyStyle"
+ latin:keyLabel="&#x00A2;" />
+</merge>
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
new file mode 100644
index 000000000..3788ca8ba
--- /dev/null
+++ b/java/res/xml/key_styles_enter.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- Navigate more keys style -->
+ <switch>
+ <case
+ latin:imeAction="actionNext"
+ latin:navigatePrevious="true"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/action_previous_as_more_key" />
+ </case>
+ <case
+ latin:imeAction="actionNext"
+ latin:navigatePrevious="false"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle" />
+ </case>
+ <case
+ latin:imeAction="actionPrevious"
+ latin:navigateNext="true"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/action_next_as_more_key" />
+ </case>
+ <case
+ latin:imeAction="actionPrevious"
+ latin:navigateNext="false"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle" />
+ </case>
+ <!-- imeAction!="actionNext" and imeAction!="actionPrevious" -->
+ <case
+ latin:navigateNext="true"
+ latin:navigatePrevious="true"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,!text/action_previous_as_more_key,!text/action_next_as_more_key" />
+ </case>
+ <case
+ latin:navigateNext="true"
+ latin:navigatePrevious="false"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/action_next_as_more_key" />
+ </case>
+ <case
+ latin:navigateNext="false"
+ latin:navigatePrevious="true"
+ >
+ <key-style
+ latin:styleName="navigateMoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/action_previous_as_more_key" />
+ </case>
+ <!-- naviagteNext="false" and navigatePrevious="false" -->
+ <default>
+ <key-style
+ latin:styleName="navigateMoreKeysStyle" />
+ </default>
+ </switch>
+ <!-- Enter key style -->
+ <key-style
+ latin:styleName="defaultEnterKeyStyle"
+ latin:code="!code/key_enter"
+ latin:keyIcon="!icon/enter_key"
+ latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional"
+ latin:parentStyle="navigateMoreKeysStyle" />
+ <key-style
+ latin:styleName="defaultActionKeyStyle"
+ latin:code="!code/key_action_enter"
+ latin:keyIcon="!icon/undefined"
+ latin:backgroundType="action"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ <switch>
+ <!-- Shift + Enter in textMultiLine field. -->
+ <case
+ latin:isMultiLine="true"
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionGo"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabel="!text/label_go_key"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionNext"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabel="!text/label_next_key"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionPrevious"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabel="!text/label_previous_key"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionDone"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabel="!text/label_done_key"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionSend"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabel="!text/label_send_key"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionSearch"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyIcon="!icon/search_key"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <case
+ latin:imeAction="actionCustomLabel"
+ >
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:keyLabelFlags="fromCustomActionLabel"
+ latin:parentStyle="defaultActionKeyStyle" />
+ </case>
+ <!-- imeAction is either actionNone or actionUnspecified. -->
+ <default>
+ <key-style
+ latin:styleName="enterKeyStyle"
+ latin:parentStyle="defaultEnterKeyStyle" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/key_styles_f1.xml b/java/res/xml/key_styles_f1.xml
new file mode 100644
index 000000000..8dfc3cb84
--- /dev/null
+++ b/java/res/xml/key_styles_f1.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- Base key style for the key which may have settings or tab key as popup key. -->
+ <!-- Kept as a separate file for cleaner overriding by an overlay. -->
+ <switch>
+ <case
+ latin:clobberSettingsKey="true"
+ >
+ <key-style
+ latin:styleName="f1MoreKeysStyle"
+ latin:backgroundType="functional" />
+ </case>
+ <!-- clobberSettingsKey="false" -->
+ <default>
+ <key-style
+ latin:styleName="f1MoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/settings_as_more_key"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/kbd_numkey_styles.xml b/java/res/xml/key_styles_number.xml
index 657bfbcbf..2e5a601b0 100644
--- a/java/res/xml/kbd_numkey_styles.xml
+++ b/java/res/xml/key_styles_number.xml
@@ -22,23 +22,28 @@
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<key-style
+ latin:styleName="numKeyBaseStyle"
+ latin:keyActionFlags="noKeyPreview" />
+ <key-style
latin:styleName="numKeyStyle"
- latin:keyLabelOption="largeLetter|followKeyLetterRatio" />
+ latin:keyLabelFlags="followKeyLargeLetterRatio"
+ latin:parentStyle="numKeyBaseStyle" />
<key-style
latin:styleName="numModeKeyStyle"
- latin:keyLabelOption="fontNormal|followKeyLetterRatio" />
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio"
+ latin:parentStyle="numKeyBaseStyle" />
<key-style
latin:styleName="numFunctionalKeyStyle"
- latin:keyLabelOption="largeLetter|followKeyLetterRatio"
- latin:parentStyle="functionalKeyStyle" />
+ latin:keyLabelFlags="followKeyLargeLetterRatio"
+ latin:backgroundType="functional"
+ latin:parentStyle="numKeyBaseStyle" />
<key-style
latin:styleName="numberKeyStyle"
- latin:keyLabelOption="alignLeftOfCenter|hasHintLabel"
+ latin:keyLabelFlags="alignLeftOfCenter|hasHintLabel"
latin:parentStyle="numKeyStyle" />
<key-style
latin:styleName="num0KeyStyle"
- latin:code="48"
- latin:keyLabel="0 +"
+ latin:keyLabel="0"
latin:parentStyle="numberKeyStyle" />
<key-style
latin:styleName="num1KeyStyle"
@@ -84,24 +89,55 @@
latin:keyLabel="9"
latin:keyHintLabel="WXYZ"
latin:parentStyle="numberKeyStyle" />
+ <!-- U+002A: "*" ASTERISK
+ U+FF0A: "*" FULLWIDTH ASTERISK -->
<key-style
latin:styleName="numStarKeyStyle"
- latin:code="42"
- latin:keyLabel="\uff0a"
+ latin:code="0x002A"
+ latin:keyLabel="&#xFF0A;"
latin:parentStyle="numKeyStyle" />
+ <!-- Only for non-tablet device -->
<key-style
- latin:styleName="numSwitchToAltKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_phone_symbols_key"
+ latin:styleName="numPhoneToSymbolKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_phone_symbols_key"
latin:parentStyle="numModeKeyStyle" />
<key-style
- latin:styleName="numSwitchToNumericKeyStyle"
- latin:code="@integer/key_switch_alpha_symbol"
- latin:keyLabel="@string/label_to_phone_numeric_key"
+ latin:styleName="numPhoneToNumericKeyStyle"
+ latin:code="!code/key_switch_alpha_symbol"
+ latin:keyLabel="!text/label_to_phone_numeric_key"
latin:parentStyle="numModeKeyStyle" />
+ <!-- U+002C: "," COMMA -->
+ <key-style
+ latin:styleName="numPauseKeyStyle"
+ latin:code="0x002C"
+ latin:keyLabel="!text/label_pause_key"
+ latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale"
+ latin:parentStyle="numKeyBaseStyle" />
+ <!-- U+003B: ";" SEMICOLON -->
+ <key-style
+ latin:styleName="numWaitKeyStyle"
+ latin:code="0x003B"
+ latin:keyLabel="!text/label_wait_key"
+ latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale"
+ latin:parentStyle="numKeyBaseStyle" />
+ <key-style
+ latin:styleName="numTabKeyStyle"
+ latin:keyActionFlags="noKeyPreview"
+ latin:parentStyle="tabKeyStyle" />
<key-style
latin:styleName="numSpaceKeyStyle"
- latin:code="@integer/key_space"
- latin:keyIcon="iconSpaceKey"
- latin:keyIconPreview="iconPreviewSpaceKey" />
+ latin:code="!code/key_space"
+ latin:keyIcon="!icon/space_key_for_number_layout"
+ latin:keyActionFlags="enableLongPress"
+ latin:parentStyle="numKeyBaseStyle" />
+ <!-- Override defaultEnterKeyStyle in key_styles_enter.xml -->
+ <key-style
+ latin:styleName="defaultEnterKeyStyle"
+ latin:code="!code/key_enter"
+ latin:keyIcon="!icon/enter_key"
+ latin:keyLabelFlags="preserveCase|autoXScale|followKeyLargeLabelRatio"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional"
+ latin:parentStyle="navigateMoreKeysStyle" />
</merge>
diff --git a/java/res/xml/keyboard_layout_set_arabic.xml b/java/res/xml/keyboard_layout_set_arabic.xml
new file mode 100644
index 000000000..10e95bd30
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_arabic.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_arabic"
+ 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/keyboard_layout_set_azerty.xml b/java/res/xml/keyboard_layout_set_azerty.xml
new file mode 100644
index 000000000..4d144edbc
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_azerty.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_azerty"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_10_10_7_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_10_10_7_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/keyboard_layout_set_bulgarian.xml b/java/res/xml/keyboard_layout_set_bulgarian.xml
new file mode 100644
index 000000000..c6fdff9a2
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_bulgarian.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_bulgarian"
+ 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/keyboard_layout_set_bulgarian_bds.xml b/java/res/xml/keyboard_layout_set_bulgarian_bds.xml
new file mode 100644
index 000000000..a36b3bd52
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_bulgarian_bds.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_bulgarian_bds"
+ 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/keyboard_layout_set_colemak.xml b/java/res/xml/keyboard_layout_set_colemak.xml
new file mode 100644
index 000000000..c18f13225
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_colemak.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_colemak"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_10_10_7_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_10_10_7_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/keyboard_layout_set_dvorak.xml b/java/res/xml/keyboard_layout_set_dvorak.xml
new file mode 100644
index 000000000..eb8e0c539
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_dvorak.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_dvorak"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_10_10_7_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_10_10_7_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/keyboard_layout_set_east_slavic.xml b/java/res/xml/keyboard_layout_set_east_slavic.xml
new file mode 100644
index 000000000..8d66faf8f
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_east_slavic.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_east_slavic"
+ 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/keyboard_layout_set_farsi.xml b/java/res/xml/keyboard_layout_set_farsi.xml
new file mode 100644
index 000000000..b9a91e3a8
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_farsi.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_farsi"
+ 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/keyboard_layout_set_georgian.xml b/java/res/xml/keyboard_layout_set_georgian.xml
new file mode 100644
index 000000000..36d091653
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_georgian.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_georgian"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="alphabetAutomaticShifted"
+ latin:elementKeyboard="@xml/kbd_georgian"
+ latin:enableProximityCharsCorrection="true" />
+ <!-- On these shifted alphabet layouts the proximity characters correction should be disabled
+ because the letters on these layouts aren't the ones in different case of the above
+ unshifted layouts. -->
+ <Element
+ latin:elementName="alphabetManualShifted"
+ latin:elementKeyboard="@xml/kbd_georgian" />
+ <Element
+ latin:elementName="alphabetShiftLocked"
+ latin:elementKeyboard="@xml/kbd_georgian" />
+ <Element
+ latin:elementName="alphabetShiftLockShifted"
+ latin:elementKeyboard="@xml/kbd_georgian" />
+ <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/keyboard_layout_set_greek.xml b/java/res/xml/keyboard_layout_set_greek.xml
new file mode 100644
index 000000000..b376e4fe3
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_greek.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_greek"
+ 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/keyboard_layout_set_hebrew.xml b/java/res/xml/keyboard_layout_set_hebrew.xml
new file mode 100644
index 000000000..212816dfe
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_hebrew.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_hebrew"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_10_10_7_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_10_10_7_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/keyboard_layout_set_hindi.xml b/java/res/xml/keyboard_layout_set_hindi.xml
new file mode 100644
index 000000000..e850c7ebc
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_hindi.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_hindi"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="alphabetAutomaticShifted"
+ latin:elementKeyboard="@xml/kbd_hindi"
+ latin:enableProximityCharsCorrection="true" />
+ <!-- On these shifted alphabet layouts the proximity characters correction should be disabled
+ because the letters on these layouts aren't the ones in different case of the above
+ unshifted layouts. -->
+ <Element
+ latin:elementName="alphabetManualShifted"
+ latin:elementKeyboard="@xml/kbd_hindi" />
+ <Element
+ latin:elementName="alphabetShiftLocked"
+ latin:elementKeyboard="@xml/kbd_hindi" />
+ <Element
+ latin:elementName="alphabetShiftLockShifted"
+ latin:elementKeyboard="@xml/kbd_hindi" />
+ <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/keyboard_layout_set_nordic.xml b/java/res/xml/keyboard_layout_set_nordic.xml
new file mode 100644
index 000000000..1f00f440e
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_nordic.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_nordic"
+ 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/keyboard_layout_set_pcqwerty.xml b/java/res/xml/keyboard_layout_set_pcqwerty.xml
new file mode 100644
index 000000000..9367ed00c
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_pcqwerty.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_pcqwerty"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_pcqwerty_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_pcqwerty_symbols" />
+ <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/keyboard_layout_set_qwerty.xml b/java/res/xml/keyboard_layout_set_qwerty.xml
new file mode 100644
index 000000000..821517081
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_qwerty.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwerty"
+ 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/keyboard_layout_set_qwertz.xml b/java/res/xml/keyboard_layout_set_qwertz.xml
new file mode 100644
index 000000000..f9e87a66f
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_qwertz.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_qwertz"
+ 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/keyboard_layout_set_south_slavic.xml b/java/res/xml/keyboard_layout_set_south_slavic.xml
new file mode 100644
index 000000000..36666b91b
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_south_slavic.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_south_slavic"
+ 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/keyboard_layout_set_spanish.xml b/java/res/xml/keyboard_layout_set_spanish.xml
new file mode 100644
index 000000000..57cef5234
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_spanish.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_spanish"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_10_10_7_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_10_10_7_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/keyboard_layout_set_thai.xml b/java/res/xml/keyboard_layout_set_thai.xml
new file mode 100644
index 000000000..94713e3d4
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_thai.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_thai"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="alphabetAutomaticShifted"
+ latin:elementKeyboard="@xml/kbd_thai"
+ latin:enableProximityCharsCorrection="true" />
+ <!-- On these shifted alphabet layouts the proximity characters correction should be disabled
+ because the letters on these layouts aren't the ones in different case of the above
+ unshifted layouts. -->
+ <Element
+ latin:elementName="alphabetManualShifted"
+ latin:elementKeyboard="@xml/kbd_thai" />
+ <Element
+ latin:elementName="alphabetShiftLocked"
+ latin:elementKeyboard="@xml/kbd_thai" />
+ <Element
+ latin:elementName="alphabetShiftLockShifted"
+ latin:elementKeyboard="@xml/kbd_thai" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_thai_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_thai_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/keys_curly_brackets.xml b/java/res/xml/keys_curly_brackets.xml
new file mode 100644
index 000000000..6a4b1a945
--- /dev/null
+++ b/java/res/xml/keys_curly_brackets.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="{"
+ latin:code="!code/key_left_curly_bracket" />
+ <Key
+ latin:keyLabel="}"
+ latin:code="!code/key_right_curly_bracket" />
+</merge>
diff --git a/java/res/xml/keys_dvorak_123.xml b/java/res/xml/keys_dvorak_123.xml
new file mode 100644
index 000000000..60e6b6f0d
--- /dev/null
+++ b/java/res/xml/keys_dvorak_123.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel="&quot;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ </case>
+ <case
+ latin:mode="url"
+ >
+ <Key
+ latin:keyLabel="/"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ </case>
+ <case
+ latin:mode="email"
+ >
+ <Key
+ latin:keyLabel="\@"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="\'"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1"
+ latin:moreKeys="!" />
+ </default>
+ </switch>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel="&lt;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <Key
+ latin:keyLabel="&gt;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=","
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2"
+ latin:moreKeys="\?" />
+ <Key
+ latin:keyLabel="."
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:keyLabelFlags="hasPopupHint|preserveCase"
+ latin:moreKeys="!text/more_keys_for_punctuation,%" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/keys_less_greater.xml b/java/res/xml/keys_less_greater.xml
new file mode 100644
index 000000000..bc9ecdf2f
--- /dev/null
+++ b/java/res/xml/keys_less_greater.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:languageCode="fa"
+ >
+ <!-- U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+ <Key
+ latin:keyLabel="&#x00AB;"
+ latin:code="0x00BB"
+ latin:moreKeys="!text/more_keys_for_less_than" />
+ <Key
+ latin:keyLabel="&#x00BB;"
+ latin:code="0x00AB"
+ latin:moreKeys="!text/more_keys_for_greater_than" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="&lt;"
+ latin:code="!code/key_less_than"
+ latin:moreKeys="!text/more_keys_for_less_than" />
+ <Key
+ latin:keyLabel="&gt;"
+ latin:code="!code/key_greater_than"
+ latin:moreKeys="!text/more_keys_for_greater_than" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/keys_parentheses.xml b/java/res/xml/keys_parentheses.xml
new file mode 100644
index 000000000..25e89c930
--- /dev/null
+++ b/java/res/xml/keys_parentheses.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="("
+ latin:code="!code/key_left_parenthesis"
+ latin:moreKeys="!text/more_keys_for_left_parenthesis" />
+ <Key
+ latin:keyLabel=")"
+ latin:code="!code/key_right_parenthesis"
+ latin:moreKeys="!text/more_keys_for_right_parenthesis" />
+</merge>
diff --git a/java/res/xml/keys_pcqwerty2_right3.xml b/java/res/xml/keys_pcqwerty2_right3.xml
new file mode 100644
index 000000000..2065e6b46
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty2_right3.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted"
+ >
+ <Key
+ latin:keyLabel="["
+ latin:moreKeys="{" />
+ <Key
+ latin:keyLabel="]"
+ latin:moreKeys="}" />
+ <!-- U+00A6: "¦" BROKEN BAR -->
+ <Key
+ latin:keyLabel="\\"
+ latin:moreKeys="\\|,&#x00A6;" />
+ </case>
+ <!-- keyboardLayoutSetElement="alphabet*Shifted|symbols*" -->
+ <default>
+ <Key
+ latin:keyLabel="{" />
+ <Key
+ latin:keyLabel="}" />
+ <!-- U+00A6: "¦" BROKEN BAR -->
+ <Key
+ latin:keyLabel="|"
+ latin:moreKeys="&#x00A6;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/keys_pcqwerty3_right2.xml b/java/res/xml/keys_pcqwerty3_right2.xml
new file mode 100644
index 000000000..fd9d3b8b0
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty3_right2.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted"
+ >
+ <Key
+ latin:keyLabel=";"
+ latin:moreKeys=":" />
+ <Key
+ latin:keyLabel="\'"
+ latin:moreKeys="&quot;" />
+ </case>
+ <!-- keyboardLayoutSetElement="alphabet*Shifted|symbols*" -->
+ <default>
+ <Key
+ latin:keyLabel=":" />
+ <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
+ <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" -->
+ <Key
+ latin:keyLabel="&quot;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/keys_pcqwerty4_right3.xml b/java/res/xml/keys_pcqwerty4_right3.xml
new file mode 100644
index 000000000..7795b3d8b
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty4_right3.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted"
+ >
+ <Key
+ latin:keyLabel=","
+ latin:moreKeys="&lt;" />
+ <Key
+ latin:keyLabel="."
+ latin:moreKeys="&gt;" />
+ <!-- U+00BF: "¿" INVERTED QUESTION MARK -->
+ <Key
+ latin:keyLabel="/"
+ latin:moreKeys="\?,&#x00BF;" />
+ </case>
+ <!-- keyboardLayoutSetElement="alphabet*Shifted|symbols*" -->
+ <default>
+ <!-- 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 -->
+ <Key
+ latin:keyLabel="&lt;"
+ latin:moreKeys="!fixedColumnOrder!3,&#x2039;,&#x2264;,&#x00AB;" />
+ <Key
+ latin:keyLabel="&gt;"
+ latin:moreKeys="!fixedColumnOrder!3,&#x203A;,&#x2265;,&#x00BB;" />
+ <!-- U+00BF: "¿" INVERTED QUESTION MARK -->
+ <Key
+ latin:keyLabel="\?"
+ latin:moreKeys="&#x00BF;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/keys_pcqwerty_symbols1.xml b/java/res/xml/keys_pcqwerty_symbols1.xml
new file mode 100644
index 000000000..bf48b1f17
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty_symbols1.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+00AC: "¬" NOT SIGN -->
+ <Key
+ latin:keyLabel="~"
+ latin:moreKeys="&#x00AC;" />
+ <!-- U+00A1: "¡" NVERTED EXCLAMATION MARK -->
+ <Key
+ latin:keyLabel="!"
+ latin:moreKeys="&#x00A1;" />
+ <Key
+ latin:keyLabel="\@" />
+ <Key
+ latin:keyLabel="#" />
+ <Key
+ latin:keyLabel="$" />
+ <!-- U+2030: "‰" PER MILLE SIGN -->
+ <Key
+ latin:keyLabel="%"
+ latin:moreKeys="&#x2030;" />
+ <Key
+ latin:keyLabel="^" />
+ <Key
+ latin:keyLabel="&amp;" />
+ <Key
+ latin:keyLabel="*"
+ latin:moreKeys="!text/more_keys_for_star" />
+ <Key
+ latin:keyLabel="(" />
+ <Key
+ latin:keyLabel=")" />
+ <Key
+ latin:keyLabel="_" />
+ <Key
+ latin:keyLabel="+" />
+</merge>
diff --git a/java/res/xml/keys_pcqwerty_symbols2.xml b/java/res/xml/keys_pcqwerty_symbols2.xml
new file mode 100644
index 000000000..d0ea984e8
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty_symbols2.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+2022: "•" BULLET -->
+ <Key
+ latin:keyLabel="&#x2022;"
+ latin:moreKeys="!text/more_keys_for_bullet" />
+ <!-- U+00B1: "±" PLUS-MINUS SIGN -->
+ <Key
+ latin:keyLabel="&#x00B1;" />
+ <!-- U+00AC: "¬" NOT SIGN -->
+ <Key
+ latin:keyLabel="&#x00AC;" />
+ <!-- U+00A6: "¦" BROKEN BAR -->
+ <Key
+ latin:keyLabel="&#x00A6;" />
+ <!-- U+221A: "√" SQUARE ROOT -->
+ <Key
+ latin:keyLabel="&#x221A;" />
+ <!-- U+03C0: "π" GREEK SMALL LETTER PI
+ U+03A0: "Π" GREEK CAPITAL LETTER PI -->
+ <Key
+ latin:keyLabel="&#x03C0;"
+ latin:moreKeys="&#x03A0;" />
+ <!-- U+03CC: "σ" GREEK SMALL LETTER SIGMA
+ U+03A3: "Σ" GREEK CAPITAL LETTER SIGMA -->
+ <Key
+ latin:keyLabel="&#x03C3;"
+ latin:moreKeys="&#x03A3;" />
+ <!-- U+00B5: "µ" MICRO SIGN -->
+ <Key
+ latin:keyLabel="&#x00B5;" />
+ <!-- U+00F7: "÷" DIVISION SIGN -->
+ <Key
+ latin:keyLabel="&#x00F7;" />
+ <!-- U+00D7: "×" MULTIPLICATION SIGN -->
+ <Key
+ latin:keyLabel="&#x00D7;" />
+</merge>
diff --git a/java/res/xml/keys_pcqwerty_symbols3.xml b/java/res/xml/keys_pcqwerty_symbols3.xml
new file mode 100644
index 000000000..35279deaf
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty_symbols3.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+00A3: "£" POUND SIGN; -->
+ <Key
+ latin:keyLabel="&#x00A3;" />
+ <!-- U+00A2: "¢" CENT SIGN -->
+ <Key
+ latin:keyLabel="&#x00A2;" />
+ <!-- U+20AC: "€" EURO SIGN -->
+ <Key
+ latin:keyLabel="&#x20AC;" />
+ <!-- U+00A5: "¥" YEN SIGN -->
+ <Key
+ latin:keyLabel="&#x00A5;" />
+ <!-- U+00A4: "¤" CURRENCY SIGN -->
+ <Key
+ latin:keyLabel="&#x00A4;" />
+ <!-- U+00B0: "°" DEGREE SIGN
+ U+2032: "′" PRIME
+ U+2033: "″" DOUBLE PRIME -->
+ <Key
+ latin:keyLabel="&#x00B0;"
+ latin:moreKeys="&#x2032;,&#x2033;" />
+ <!-- U+2260: "≠" NOT EQUAL TO -->
+ <Key
+ latin:keyLabel="&#x2260;" />
+ <!-- U+2248: "≈" ALMOST EQUAL TO -->
+ <Key
+ latin:keyLabel="&#x2248;" />
+ <!-- U+221E: "∞" INFINITY -->
+ <Key
+ latin:keyLabel="&#x221E;" />
+</merge>
diff --git a/java/res/xml/keys_pcqwerty_symbols4.xml b/java/res/xml/keys_pcqwerty_symbols4.xml
new file mode 100644
index 000000000..3c628f0e0
--- /dev/null
+++ b/java/res/xml/keys_pcqwerty_symbols4.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+2122: "™" TRADE MARK SIGN -->
+ <Key
+ latin:keyLabel="&#x2122;" />
+ <!-- U+00AE: "®" REGISTERED SIGN -->
+ <Key
+ latin:keyLabel="&#x00AE;" />
+ <!-- U+00A9: "©" COPYRIGHT SIGN -->
+ <Key
+ latin:keyLabel="&#x00A9;" />
+ <!-- U+00B6: "¶" PILCROW SIGN -->
+ <Key
+ latin:keyLabel="&#x00B6;" />
+ <!-- U+00A7: "§" SECTION SIGN -->
+ <Key
+ latin:keyLabel="&#x00A7;" />
+ <!-- U+2191: "↑" UPWARDS ARROW
+ U+2193: "↓" DOWNWARDS ARROW
+ U+2190: "←" LEFTWARDS ARROW
+ U+2192: "→" RIGHTWARDS ARROW -->
+ <Key
+ latin:keyLabel="&#x2191;"
+ latin:moreKeys="&#x2193;" />
+ <Key
+ latin:keyLabel="&#x2190;"
+ latin:moreKeys="&#x2192;" />
+</merge>
diff --git a/java/res/xml/keys_square_brackets.xml b/java/res/xml/keys_square_brackets.xml
new file mode 100644
index 000000000..5c128fd0c
--- /dev/null
+++ b/java/res/xml/keys_square_brackets.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="["
+ latin:code="!code/key_left_square_bracket" />
+ <Key
+ latin:keyLabel="]"
+ latin:code="!code/key_right_square_bracket" />
+</merge>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 3b700b136..07bff098b 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -3,16 +3,16 @@
/**
* Copyright (c) 2008, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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
+ * 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
+ * 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.
*/
-->
@@ -20,14 +20,315 @@
<!-- The attributes in this XML file provide configuration information -->
<!-- for the Input Method Manager. -->
-<!-- Keyboard: en_US, en_GB, ar, cs, da, de, es, es_US, fi, fr, fr_CA, fr_CH, hr, hu, it, iw, nb, nl, pl, pt, ru, sr, sv, tr -->
-<!-- Voice: af, cs, da, de, en, es, fr, it, ja, ko, nl, pl, pt, ru, tr, yue, zh, zu -->
+<!-- Supported subtypes
+ keyboard_locale: script_name/keyboard_layout_set[:keyboard_locale]
+ ar: Arabic/arabic
+ be: Belarusian/east_slavic
+ bg: Bulgarian/bulgarian
+ bg: Bulgarian/bulgarian_bds
+ cs: Czech/qwertz
+ da: Danish/nordic
+ de: German/qwertz
+ el: Greek/greek
+ en_US: English United States/qwerty
+ en_GB: English Great Britain/qwerty
+ es: Spanish/spanish
+ et: Estonian/nordic
+ fa: Persian/arabic
+ fi: Finnish/nordic
+ fr: French/azerty
+ fr_CA: French Canada/qwerty
+ hi: Hindi/hindi
+ hr: Croatian/qwertz
+ hu: Hungarian/qwertz
+ is: Icelandic/qwerty
+ it: Italian/qwerty
+ iw: Hebrew/hebrew
+ ka: Georgian/georgian
+ ky: Kyrgyz/east_slavic
+ lt: Lithuanian/qwerty
+ lv: Latvian/qwerty
+ mk: Macedonian/south_slavic
+ nb: Norwegian Bokmål/nordic
+ nl: Dutch/qwerty
+ pl: Polish/qwerty
+ pt_BR: Portuguese Brazil/qwerty
+ pt_PT: Portuguese Portugal/qwerty
+ ro: Romanian/qwerty
+ ru: Russian/east_slavic
+ sk: Slovak/qwerty
+ sl: Slovenian/qwerty
+ sr: Serbian/south_slavic
+ sv: Swedish/nordic
+ th: Thai/thai
+ tr: Turkish/qwerty
+ uk: Ukrainian/east_slavic
+ vi: Vietnamese/qwerty
+ zz: QWERTY/qwerty
+ -->
<!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. -->
-<!-- TODO: use <lang>_mic icon instead of a common mic icon. -->
-<!-- TODO: remove all comment outed voice subtypes -->
<!-- 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"
+ android:settingsActivity="com.android.inputmethod.latin.SettingsActivity"
android:isDefault="@bool/im_is_default">
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_en_US"
+ android:imeSubtypeLocale="en_US"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,TrySuppressingImeSwitcher,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_en_GB"
+ android:imeSubtypeLocale="en_GB"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,TrySuppressingImeSwitcher,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ar"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=arabic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="be"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="bg"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_bulgarian_bds"
+ android:imeSubtypeLocale="bg"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian_bds"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="cs"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="da"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="de"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="el"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=greek"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="es"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="et"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="fa"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=farsi"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="fi"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="fr"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=azerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="fr_CA"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="hi"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="hr"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="hu"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="is"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="it"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. -->
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="iw"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=hebrew"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ka"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=georgian"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ky"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="lt"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="lv"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="mk"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=south_slavic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="nb"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="nl"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="pl"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="pt_BR"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="pt_PT"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ro"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="ru"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="sk"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="sl"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="sr"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=south_slavic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="sv"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="th"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=thai"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="tr"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="uk"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_generic"
+ android:imeSubtypeLocale="vi"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+ />
+ <subtype android:icon="@drawable/ic_subtype_keyboard"
+ android:label="@string/subtype_no_language_qwerty"
+ android:imeSubtypeLocale="zz"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable"
+ />
</input-method>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index f68ee0168..d8bf7847e 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -29,6 +29,7 @@
<CheckBoxPreference
android:key="vibrate_on"
android:title="@string/vibrate_on_keypress"
+ android:defaultValue="@bool/config_default_vibration_enabled"
android:persistent="true" />
<CheckBoxPreference
android:key="sound_on"
@@ -40,19 +41,6 @@
android:title="@string/popup_on_keypress"
android:persistent="true"
android:defaultValue="@bool/config_default_popup_preview" />
- <CheckBoxPreference
- android:key="recorrection_enabled"
- android:title="@string/prefs_enable_recorrection"
- android:summary="@string/prefs_enable_recorrection_summary"
- android:persistent="true"
- android:defaultValue="@bool/config_default_recorrection_enabled" />
- <ListPreference
- android:key="settings_key"
- android:title="@string/prefs_settings_key"
- android:persistent="true"
- android:entryValues="@array/settings_key_modes_values"
- android:entries="@array/settings_key_modes"
- android:defaultValue="@string/settings_key_mode_auto" />
<ListPreference
android:key="voice_mode"
android:title="@string/voice_input"
@@ -60,10 +48,6 @@
android:entryValues="@array/voice_input_modes_values"
android:entries="@array/voice_input_modes"
android:defaultValue="@string/voice_mode_main" />
- <PreferenceScreen
- android:key="subtype_settings"
- android:title="@string/language_selection_title"
- android:summary="@string/language_selection_summary" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/correction_category"
@@ -73,15 +57,9 @@
android:title="@string/configure_dictionaries_title">
<intent
android:action="android.intent.action.MAIN"
- android:targetPackage="com.google.android.inputmethod.latin.dictionarypack"
- android:targetClass="com.google.android.inputmethod.latin.dictionarypack.DictionarySettings" />
+ android:targetPackage="@string/dictionary_pack_package_name"
+ android:targetClass="@string/dictionary_pack_settings_activity" />
</PreferenceScreen>
- <CheckBoxPreference
- android:key="quick_fixes"
- android:title="@string/quick_fixes"
- android:summary="@string/quick_fixes_summary"
- android:persistent="true"
- android:defaultValue="true" />
<ListPreference
android:key="auto_correction_threshold"
android:title="@string/auto_correction"
@@ -100,65 +78,54 @@
android:defaultValue="@string/prefs_suggestion_visibility_default_value" />
</PreferenceCategory>
<PreferenceCategory
- android:title="@string/ngram_category"
- android:key="ngram_settings">
- <CheckBoxPreference
- android:key="bigram_suggestion"
- android:title="@string/bigram_suggestion"
- android:summary="@string/bigram_suggestion_summary"
- android:persistent="true"
- android:defaultValue="true" />
+ android:title="@string/misc_category"
+ android:key="misc_settings">
<CheckBoxPreference
- android:key="bigram_prediction"
- android:dependency="bigram_suggestion"
- android:title="@string/bigram_prediction"
- android:summary="@string/bigram_prediction_summary"
+ android:key="usability_study_mode"
+ android:title="@string/prefs_usability_study_mode"
android:persistent="true"
android:defaultValue="false" />
+ <PreferenceScreen
+ android:key="pref_advanced_settings"
+ android:title="@string/advanced_settings"
+ android:summary="@string/advanced_settings_summary">
+ <CheckBoxPreference
+ android:key="pref_suppress_language_switch_key"
+ android:title="@string/suppress_language_switch_key"
+ android:persistent="true"
+ android:defaultValue="false" />
+ <CheckBoxPreference
+ android:key="pref_include_other_imes_in_language_switch_list"
+ android:title="@string/include_other_imes_in_language_switch_list"
+ android:summary="@string/include_other_imes_in_language_switch_list_summary"
+ android:persistent="true"
+ android:defaultValue="false" />
+ <PreferenceScreen
+ android:fragment="com.android.inputmethod.latin.AdditionalSubtypeSettings"
+ android:key="custom_input_styles"
+ android:title="@string/custom_input_styles_title" />
+ <!-- Values for popup dismiss delay are added programatically -->
+ <ListPreference
+ android:key="pref_key_preview_popup_dismiss_delay"
+ android:title="@string/key_preview_popup_dismiss_delay" />
+ <CheckBoxPreference
+ android:key="pref_key_use_contacts_dict"
+ android:title="@string/use_contacts_dict"
+ android:summary="@string/use_contacts_dict_summary"
+ android:persistent="true"
+ android:defaultValue="true" />
+ <CheckBoxPreference
+ android:key="next_word_prediction"
+ android:title="@string/bigram_prediction"
+ android:summary="@string/bigram_prediction_summary"
+ android:persistent="true"
+ android:defaultValue="true" />
+ <PreferenceScreen
+ android:key="pref_vibration_duration_settings"
+ android:title="@string/prefs_keypress_vibration_duration_settings"/>
+ <PreferenceScreen
+ android:key="pref_keypress_sound_volume"
+ android:title="@string/prefs_keypress_sound_volume_settings" />
+ </PreferenceScreen>
</PreferenceCategory>
- <PreferenceCategory
- android:title="@string/misc_category"
- android:key="misc_settings">
- <CheckBoxPreference
- android:key="usability_study_mode"
- android:title="@string/prefs_usability_study_mode"
- android:persistent="true"
- android:defaultValue="false" />
- <CheckBoxPreference
- android:key="enable_logging"
- android:title="@string/prefs_enable_log"
- android:summary="@string/prefs_description_log"
- android:persistent="true"
- android:defaultValue="true" />
- <ListPreference
- android:key="pref_keyboard_layout_20100902"
- android:title="@string/keyboard_layout"
- android:persistent="true"
- android:entryValues="@array/keyboard_layout_modes_values"
- android:entries="@array/keyboard_layout_modes"
- android:defaultValue="@string/config_default_keyboard_theme_id" />
- </PreferenceCategory>
- <PreferenceScreen
- android:key="pref_advanced_settings"
- android:title="@string/advanced_settings"
- android:summary="@string/advanced_settings_summary">
- <!-- Values for popup dismiss delay are added programatically -->
- <ListPreference
- android:key="pref_key_preview_popup_dismiss_delay"
- android:title="@string/key_preview_popup_dismiss_delay" />
- <CheckBoxPreference
- android:key="pref_key_use_contacts_dict"
- android:title="@string/use_contacts_dict"
- android:summary="@string/use_contacts_dict_summary"
- android:persistent="true"
- android:defaultValue="true" />
- </PreferenceScreen>
- <!-- <Preference
- android:title="Debug Settings"
- android:key="debug_settings">
- <intent
- android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.inputmethod.latin"
- android:targetClass="com.android.inputmethod.latin.DebugSettings" />
- </Preference>-->
</PreferenceScreen>
diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml
index 477461df4..b926ed065 100644
--- a/java/res/xml/prefs_for_debug.xml
+++ b/java/res/xml/prefs_for_debug.xml
@@ -27,26 +27,25 @@
/>
<ListPreference
- android:key="pref_keyboard_layout_20100902"
+ android:key="pref_keyboard_layout_20110916"
android:title="@string/keyboard_layout"
android:persistent="true"
android:entryValues="@array/keyboard_layout_modes_values"
android:entries="@array/keyboard_layout_modes"
- android:defaultValue="@string/config_default_keyboard_theme_id"
+ android:defaultValue="@string/config_default_keyboard_theme_index"
/>
<CheckBoxPreference
- android:key="use_spacebar_language_switch"
- android:title="@string/prefs_use_spacebar_language_switch"
+ android:key="debug_mode"
+ android:title="@string/prefs_debug_mode"
android:persistent="true"
android:defaultValue="false"
/>
<CheckBoxPreference
- android:key="debug_mode"
- android:title="@string/prefs_debug_mode"
+ android:key="force_non_distinct_multitouch"
+ android:title="@string/prefs_force_non_distinct_multitouch"
android:persistent="true"
android:defaultValue="false"
/>
-
</PreferenceScreen>
diff --git a/java/res/xml/row_dvorak4.xml b/java/res/xml/row_dvorak4.xml
new file mode 100644
index 000000000..69bac1358
--- /dev/null
+++ b/java/res/xml/row_dvorak4.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <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>
+ <include
+ latin:keyXPos="25%p"
+ latin:keyboardLayout="@xml/key_space" />
+ <Key
+ latin:keyLabel="z"
+ latin:moreKeys="!text/more_keys_for_z" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/row_pcqwerty5.xml b/java/res/xml/row_pcqwerty5.xml
new file mode 100644
index 000000000..a8940af6e
--- /dev/null
+++ b/java/res/xml/row_pcqwerty5.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="11.538%p" />
+ </case>
+ <!-- keyboardLayoutSetElement="alphabet*" -->
+ <default>
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyIcon="!icon/undefined"
+ latin:keyLabel="!text/label_to_symbol_key_pcqwerty"
+ latin:keyWidth="11.538%p" />
+ </default>
+ </switch>
+ <switch>
+ <case
+ latin:shortcutKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle" />
+ </case>
+ <case
+ latin:clobberSettingsKey="false"
+ >
+ <Key
+ latin:keyStyle="settingsKeyStyle" />
+ </case>
+ </switch>
+ <switch>
+ <case
+ latin:languageSwitchKeyEnabled="true"
+ >
+ <Key
+ latin:keyStyle="languageSwitchKeyStyle"
+ latin:keyXPos="19.230%p" />
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyWidth="53.844%p" />
+ </case>
+ <!-- languageSwitchKeyEnabled="false" -->
+ <default>
+ <Key
+ latin:keyStyle="spaceKeyStyle"
+ latin:keyXPos="19.230%p"
+ latin:keyWidth="61.536%p" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/row_qwerty4.xml b/java/res/xml/row_qwerty4.xml
new file mode 100644
index 000000000..c29fbf2f1
--- /dev/null
+++ b/java/res/xml/row_qwerty4.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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"
+>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="toSymbolKeyStyle"
+ latin:keyWidth="15%p" />
+ <include
+ latin:keyboardLayout="@xml/key_f1" />
+ <include
+ latin:keyXPos="25%p"
+ latin:keyboardLayout="@xml/key_space" />
+ <switch>
+ <case
+ latin:languageCode="ar|fa"
+ >
+ <Key
+ latin:keyHintLabel="!text/keyhintlabel_for_arabic_diacritics"
+ latin:keyLabelFlags="hasPopupHint|hasShiftedLetterHint"
+ latin:moreKeys="!text/more_keys_for_arabic_diacritics"
+ latin:keyStyle="punctuationKeyStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyStyle="punctuationKeyStyle" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/row_symbols4.xml b/java/res/xml/row_symbols4.xml
new file mode 100644
index 000000000..150ad486c
--- /dev/null
+++ b/java/res/xml/row_symbols4.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="15%p" />
+ <switch>
+ <case
+ latin:hasShortcutKey="true"
+ >
+ <Key
+ latin:keyStyle="shortcutKeyStyle" />
+ </case>
+ <!-- latin:hasShortcutKey="false" -->
+ <default>
+ <Key
+ latin:keyLabel="!text/keylabel_for_comma"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:additionalMoreKeys="!text/more_keys_for_comma"
+ latin:keyStyle="f1MoreKeysStyle" />
+ </default>
+ </switch>
+ <include
+ latin:keyXPos="25%p"
+ latin:keyboardLayout="@xml/key_space" />
+ <Key
+ latin:keyStyle="punctuationKeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/row_symbols_shift4.xml b/java/res/xml/row_symbols_shift4.xml
new file mode 100644
index 000000000..1bfb5ecd1
--- /dev/null
+++ b/java/res/xml/row_symbols_shift4.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="toAlphaKeyStyle"
+ latin:keyWidth="15%p" />
+ <!-- U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
+ <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. -->
+ <!-- latin:keyLabelFlags="hasPopupHint" -->
+ <!-- latin:moreKeys="&#x201F;" -->
+ <!-- U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
+ <Key
+ latin:keyLabel="&#x201E;"
+ latin:backgroundType="functional" />
+ <include
+ latin:keyXPos="25%p"
+ latin:keyboardLayout="@xml/key_space" />
+ <!-- U+2026: "…" HORIZONTAL ELLIPSIS -->
+ <Key
+ latin:keyLabel="&#x2026;"
+ latin:backgroundType="functional" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/rowkeys_arabic1.xml b/java/res/xml/rowkeys_arabic1.xml
new file mode 100644
index 000000000..b1bf790e4
--- /dev/null
+++ b/java/res/xml/rowkeys_arabic1.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0636: "ض" ARABIC LETTER DAD
+ U+0661: "١" ARABIC-INDIC DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x0636;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1,&#x0661;" />
+ <!-- U+0635: "ص" ARABIC LETTER SAD
+ U+0662: "٢" ARABIC-INDIC DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x0635;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2,&#x0662;" />
+ <!-- U+0642: "ق" ARABIC LETTER QAF
+ U+06A8: "ڨ" ARABIC LETTER QAF WITH THREE DOTS ABOVE
+ U+0663: "٣" ARABIC-INDIC DIGIT THREE -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+06A8 ARABIC LETTER QAF WITH THREE DOTS ABOVE -->
+ <Key
+ latin:keyLabel="&#x0642;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3,&#x0663;"
+ latin:moreKeys="&#x06A8;" />
+ <!-- U+0641: "ف" ARABIC LETTER FEH
+ U+06A4: "ڤ" ARABIC LETTER VEH
+ U+06A2: "ڢ" ARABIC LETTER FEH WITH DOT MOVED BELOW
+ U+06A5: "ڥ" ARABIC LETTER FEH WITH THREE DOTS BELOW
+ U+0664: "٤" ARABIC-INDIC DIGIT FOUR -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+06A2 ARABIC LETTER FEH WITH DOT MOVED BELOW -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+06A5 ARABIC LETTER FEH WITH THREE DOTS BELOW -->
+ <Key
+ latin:keyLabel="&#x0641;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4,&#x0664;"
+ latin:moreKeys="&#x06A4;,&#x06A2;,&#x06A5;" />
+ <!-- U+063A: "غ" ARABIC LETTER GHAIN
+ U+0665: "٥" ARABIC-INDIC DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x063A;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5,&#x0665;" />
+ <!-- U+0639: "ع" ARABIC LETTER AIN
+ U+0666: "٦" ARABIC-INDIC DIGIT SIX -->
+ <Key
+ latin:keyLabel="&#x0639;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6,&#x0666;" />
+ <!-- U+0647: "ه" ARABIC LETTER HEH
+ U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM
+ U+0647 U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER
+ U+0667: "٧" ARABIC-INDIC DIGIT SEVEN -->
+ <Key
+ latin:keyLabel="&#x0647;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7,&#x0667;"
+ latin:moreKeys="&#xFEEB;|&#x0647;&#x200D;" />
+ <!-- U+062E: "خ" ARABIC LETTER KHAH
+ U+0668: "٨" ARABIC-INDIC DIGIT EIGHT -->
+ <Key
+ latin:keyLabel="&#x062E;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8,&#x0668;" />
+ <!-- U+062D: "ح" ARABIC LETTER HAH
+ U+0669: "٩" ARABIC-INDIC DIGIT NINE -->
+ <Key
+ latin:keyLabel="&#x062D;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9,&#x0669;" />
+ <!-- U+062C: "ج" ARABIC LETTER JEEM
+ U+0686: "چ" ARABIC LETTER TCHEH
+ U+0660: "٠" ARABIC-INDIC DIGIT ZERO -->
+ <Key
+ latin:keyLabel="&#x062C;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0,&#x0660;"
+ latin:moreKeys="&#x0686;" />
+</merge>
diff --git a/java/res/xml/rowkeys_arabic2.xml b/java/res/xml/rowkeys_arabic2.xml
new file mode 100644
index 000000000..f86aae014
--- /dev/null
+++ b/java/res/xml/rowkeys_arabic2.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0634: "ش" ARABIC LETTER SHEEN
+ U+069C: "ڜ" ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE -->
+ <!-- TODO: DroidSansArabic lacks the glyph of U+069C ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE -->
+ <Key
+ latin:keyLabel="&#x0634;"
+ latin:moreKeys="&#x069C;" />
+ <!-- U+0633: "س" ARABIC LETTER SEEN -->
+ <Key
+ latin:keyLabel="&#x0633;" />
+ <!-- U+064A: "ي" ARABIC LETTER YEH
+ U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE
+ U+0649: "ى" ARABIC LETTER ALEF MAKSURA -->
+ <Key
+ latin:keyLabel="&#x064A;"
+ latin:moreKeys="&#x0626;,&#x0649;" />
+ <!-- U+0628: "ب" ARABIC LETTER BEH
+ U+067E: "پ" ARABIC LETTER PEH -->
+ <Key
+ latin:keyLabel="&#x0628;"
+ latin:moreKeys="&#x067E;" />
+ <!-- U+0644: "ل" ARABIC LETTER LAM
+ U+FEFB: "ﻻ" ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+ U+0627: "ا" ARABIC LETTER ALEF
+ U+FEF7: "ﻷ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+ U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
+ U+FEF9: "ﻹ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM
+ U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW
+ U+FEF5: "ﻵ" ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+ U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0644;"
+ latin:moreKeys="&#xFEFB;|&#x0644;&#x0627;,&#xFEF7;|&#x0644;&#x0623;,&#xFEF9;|&#x0644;&#x0625;,&#xFEF5;|&#x0644;&#x0622;" />
+ <!-- U+0627: "ا" ARABIC LETTER ALEF
+ U+0621: "ء" ARABIC LETTER HAMZA
+ U+0671: "ٱ" ARABIC LETTER ALEF WASLA
+ U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
+ U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW
+ U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0627;"
+ latin:moreKeys="&#x0621;,&#x0671;,&#x0623;,&#x0625;,&#x0622;" />
+ <!-- U+062A: "ت" ARABIC LETTER TEH
+ U+062B: "ﺙ" ARABIC LETTER THEH -->
+ <Key
+ latin:keyLabel="&#x062A;"
+ latin:moreKeys="&#x062B;" />
+ <!-- U+0646: "ن" ARABIC LETTER NOON -->
+ <Key
+ latin:keyLabel="&#x0646;" />
+ <!-- U+0645: "م" ARABIC LETTER MEEM -->
+ <Key
+ latin:keyLabel="&#x0645;" />
+ <!-- U+0643: "ك" ARABIC LETTER KAF
+ U+06AF: "گ" ARABIC LETTER GAF
+ U+06A9: "ک" ARABIC LETTER KEHEH -->
+ <Key
+ latin:keyLabel="&#x0643;"
+ latin:moreKeys="&#x06AF;,&#x06A9;"
+ latin:keyWidth="fillRight" />
+</merge>
diff --git a/java/res/xml/rowkeys_arabic3.xml b/java/res/xml/rowkeys_arabic3.xml
new file mode 100644
index 000000000..9e9eac0d9
--- /dev/null
+++ b/java/res/xml/rowkeys_arabic3.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0638: "ظ" ARABIC LETTER ZAH -->
+ <Key
+ latin:keyLabel="&#x0638;" />
+ <!-- U+0637: "ط" ARABIC LETTER TAH -->
+ <Key
+ latin:keyLabel="&#x0637;" />
+ <!-- U+0630: "ذ" ARABIC LETTER THAL -->
+ <Key
+ latin:keyLabel="&#x0630;" />
+ <!-- U+062F: "د" ARABIC LETTER DAL -->
+ <Key
+ latin:keyLabel="&#x062F;" />
+ <!-- U+0632: "ز" ARABIC LETTER ZAIN
+ U+0698: "ژ" ARABIC LETTER JEH -->
+ <Key
+ latin:keyLabel="&#x0632;"
+ latin:moreKeys="&#x0698;" />
+ <!-- U+0631: "ر" ARABIC LETTER REH -->
+ <Key
+ latin:keyLabel="&#x0631;" />
+ <!-- U+0629: "ة" ARABIC LETTER TEH MARBUTA -->
+ <Key
+ latin:keyLabel="&#x0629;" />
+ <!-- U+0648: "و" ARABIC LETTER WAW
+ U+0624: "ﺅ" ARABIC LETTER WAW WITH HAMZA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0648;"
+ latin:moreKeys="&#x0624;" />
+</merge>
diff --git a/java/res/xml/rowkeys_azerty1.xml b/java/res/xml/rowkeys_azerty1.xml
new file mode 100644
index 000000000..42b27463f
--- /dev/null
+++ b/java/res/xml/rowkeys_azerty1.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="a"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1"
+ latin:moreKeys="!text/more_keys_for_a" />
+ <Key
+ latin:keyLabel="z"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2"
+ latin:moreKeys="!text/more_keys_for_z" />
+ <Key
+ latin:keyLabel="e"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="!text/more_keys_for_e" />
+ <Key
+ latin:keyLabel="r"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4"
+ latin:moreKeys="!text/more_keys_for_r" />
+ <Key
+ latin:keyLabel="t"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5"
+ latin:moreKeys="!text/more_keys_for_t" />
+ <Key
+ latin:keyLabel="y"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6"
+ latin:moreKeys="!text/more_keys_for_y" />
+ <Key
+ latin:keyLabel="u"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7"
+ latin:moreKeys="!text/more_keys_for_u" />
+ <Key
+ latin:keyLabel="i"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="!text/more_keys_for_i" />
+ <Key
+ latin:keyLabel="o"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9"
+ latin:moreKeys="!text/more_keys_for_o" />
+ <Key
+ latin:keyLabel="p"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+</merge>
diff --git a/java/res/xml/rowkeys_azerty2.xml b/java/res/xml/rowkeys_azerty2.xml
new file mode 100644
index 000000000..2eee214e5
--- /dev/null
+++ b/java/res/xml/rowkeys_azerty2.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="q" />
+ <Key
+ latin:keyLabel="s"
+ latin:moreKeys="!text/more_keys_for_s" />
+ <Key
+ latin:keyLabel="d"
+ latin:moreKeys="!text/more_keys_for_d" />
+ <Key
+ latin:keyLabel="f" />
+ <Key
+ latin:keyLabel="g"
+ latin:moreKeys="!text/more_keys_for_g" />
+ <Key
+ latin:keyLabel="h"
+ latin:moreKeys="!text/more_keys_for_h" />
+ <Key
+ latin:keyLabel="j"
+ latin:moreKeys="!text/more_keys_for_j" />
+ <Key
+ latin:keyLabel="k"
+ latin:moreKeys="!text/more_keys_for_k" />
+ <Key
+ latin:keyLabel="l"
+ latin:moreKeys="!text/more_keys_for_l" />
+ <Key
+ latin:keyLabel="m" />
+</merge>
diff --git a/java/res/xml/rowkeys_azerty3.xml b/java/res/xml/rowkeys_azerty3.xml
new file mode 100644
index 000000000..9f4c608f8
--- /dev/null
+++ b/java/res/xml/rowkeys_azerty3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="w"
+ latin:moreKeys="!text/more_keys_for_w" />
+ <Key
+ latin:keyLabel="x" />
+ <Key
+ latin:keyLabel="c"
+ latin:moreKeys="!text/more_keys_for_c" />
+ <Key
+ latin:keyLabel="v"
+ latin:moreKeys="!text/more_keys_for_v" />
+ <Key
+ latin:keyLabel="b" />
+ <Key
+ latin:keyLabel="n"
+ latin:moreKeys="!text/more_keys_for_n" />
+ <include
+ latin:keyboardLayout="@xml/key_azerty_quote" />
+</merge>
diff --git a/java/res/xml/rowkeys_bulgarian1.xml b/java/res/xml/rowkeys_bulgarian1.xml
new file mode 100644
index 000000000..441b079f1
--- /dev/null
+++ b/java/res/xml/rowkeys_bulgarian1.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+044F: "я" CYRILLIC SMALL LETTER YA -->
+ <Key
+ latin:keyLabel="&#x044F;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
+ <Key
+ latin:keyLabel="&#x0432;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
+ <Key
+ latin:keyLabel="&#x0435;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3" />
+ <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
+ <Key
+ latin:keyLabel="&#x0440;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
+ <Key
+ latin:keyLabel="&#x0442;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5" />
+ <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN -->
+ <Key
+ latin:keyLabel="&#x044A;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6" />
+ <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
+ <Key
+ latin:keyLabel="&#x0443;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <!-- U+0438: "и" CYRILLIC SMALL LETTER I
+ U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE -->
+ <Key
+ latin:keyLabel="&#x0438;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="&#x045D;" />
+ <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
+ <Key
+ latin:keyLabel="&#x043E;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <!-- U+043F: "п" CYRILLIC SMALL LETTER PE -->
+ <Key
+ latin:keyLabel="&#x043F;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
+ <Key
+ latin:keyLabel="&#x0447;" />
+</merge>
diff --git a/java/res/xml/rowkeys_bulgarian2.xml b/java/res/xml/rowkeys_bulgarian2.xml
new file mode 100644
index 000000000..a4e93d862
--- /dev/null
+++ b/java/res/xml/rowkeys_bulgarian2.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0430: "а" CYRILLIC SMALL LETTER A -->
+ <Key
+ latin:keyLabel="&#x0430;" />
+ <!-- U+0441: "с" CYRILLIC SMALL LETTER ES -->
+ <Key
+ latin:keyLabel="&#x0441;" />
+ <!-- U+0434: "д" CYRILLIC SMALL LETTER DE -->
+ <Key
+ latin:keyLabel="&#x0434;" />
+ <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF -->
+ <Key
+ latin:keyLabel="&#x0444;" />
+ <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
+ <Key
+ latin:keyLabel="&#x0433;" />
+ <!-- U+0445: "х" CYRILLIC SMALL LETTER HA -->
+ <Key
+ latin:keyLabel="&#x0445;" />
+ <!-- U+0439: "й" CYRILLIC SMALL LETTER SHORT I -->
+ <Key
+ latin:keyLabel="&#x0439;" />
+ <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
+ <Key
+ latin:keyLabel="&#x043A;" />
+ <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
+ <Key
+ latin:keyLabel="&#x043B;" />
+ <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA -->
+ <Key
+ latin:keyLabel="&#x0448;" />
+ <!-- U+0449: "щ" CYRILLIC SMALL LETTER SHCHA -->
+ <Key
+ latin:keyLabel="&#x0449;" />
+</merge>
diff --git a/java/res/xml/rowkeys_bulgarian3.xml b/java/res/xml/rowkeys_bulgarian3.xml
new file mode 100644
index 000000000..258219c27
--- /dev/null
+++ b/java/res/xml/rowkeys_bulgarian3.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
+ <Key
+ latin:keyLabel="&#x0437;" />
+ <!-- U+044C: "ь" CYRILLIC SMALL LETTER SOFT SIGN -->
+ <Key
+ latin:keyLabel="&#x044C;" />
+ <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE -->
+ <Key
+ latin:keyLabel="&#x0446;" />
+ <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
+ <Key
+ latin:keyLabel="&#x0436;" />
+ <!-- U+0431: "б" CYRILLIC SMALL LETTER BE -->
+ <Key
+ latin:keyLabel="&#x0431;" />
+ <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
+ <Key
+ latin:keyLabel="&#x043D;" />
+ <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
+ <Key
+ latin:keyLabel="&#x043C;" />
+ <!-- U+044E: "ю" CYRILLIC SMALL LETTER YU -->
+ <Key
+ latin:keyLabel="&#x044E;" />
+</merge>
diff --git a/java/res/xml/rowkeys_bulgarian_bds1.xml b/java/res/xml/rowkeys_bulgarian_bds1.xml
new file mode 100644
index 000000000..eed1fcb8f
--- /dev/null
+++ b/java/res/xml/rowkeys_bulgarian_bds1.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
+ <Key
+ latin:keyLabel="&#x0443;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
+ <Key
+ latin:keyLabel="&#x0435;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <!-- U+0438: "и" CYRILLIC SMALL LETTER I
+ U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE -->
+ <Key
+ latin:keyLabel="&#x0438;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="&#x045D;" />
+ <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA -->
+ <Key
+ latin:keyLabel="&#x0448;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+0449: "щ" CYRILLIC SMALL LETTER SHCHA -->
+ <Key
+ latin:keyLabel="&#x0449;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5" />
+ <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
+ <Key
+ latin:keyLabel="&#x043A;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6" />
+ <!-- U+0441: "с" CYRILLIC SMALL LETTER ES -->
+ <Key
+ latin:keyLabel="&#x0441;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <!-- U+0434: "д" CYRILLIC SMALL LETTER DE -->
+ <Key
+ latin:keyLabel="&#x0434;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8" />
+ <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
+ <Key
+ latin:keyLabel="&#x0437;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE -->
+ <Key
+ latin:keyLabel="&#x0446;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ <!-- U+0431: "б" CYRILLIC SMALL LETTER BE -->
+ <Key
+ latin:keyLabel="&#x0431;" />
+</merge>
diff --git a/java/res/xml/rowkeys_bulgarian_bds2.xml b/java/res/xml/rowkeys_bulgarian_bds2.xml
new file mode 100644
index 000000000..ff1bff895
--- /dev/null
+++ b/java/res/xml/rowkeys_bulgarian_bds2.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+044C: "ь" CYRILLIC SMALL LETTER SOFT SIGN -->
+ <Key
+ latin:keyLabel="&#x044C;" />
+ <!-- U+044F: "я" CYRILLIC SMALL LETTER YA -->
+ <Key
+ latin:keyLabel="&#x044F;" />
+ <!-- U+0430: "а" CYRILLIC SMALL LETTER A -->
+ <Key
+ latin:keyLabel="&#x0430;" />
+ <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
+ <Key
+ latin:keyLabel="&#x043E;" />
+ <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
+ <Key
+ latin:keyLabel="&#x0436;" />
+ <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
+ <Key
+ latin:keyLabel="&#x0433;" />
+ <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
+ <Key
+ latin:keyLabel="&#x0442;" />
+ <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
+ <Key
+ latin:keyLabel="&#x043D;" />
+ <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
+ <Key
+ latin:keyLabel="&#x0432;" />
+ <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
+ <Key
+ latin:keyLabel="&#x043C;" />
+ <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
+ <Key
+ latin:keyLabel="&#x0447;" />
+</merge>
diff --git a/java/res/xml/rowkeys_bulgarian_bds3.xml b/java/res/xml/rowkeys_bulgarian_bds3.xml
new file mode 100644
index 000000000..7bb780ac7
--- /dev/null
+++ b/java/res/xml/rowkeys_bulgarian_bds3.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+044E: "ю" CYRILLIC SMALL LETTER YU -->
+ <Key
+ latin:keyLabel="&#x044E;" />
+ <!-- U+0439: "й" CYRILLIC SMALL LETTER SHORT I -->
+ <Key
+ latin:keyLabel="&#x0439;" />
+ <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN -->
+ <Key
+ latin:keyLabel="&#x044A;" />
+ <!-- U+044D: "э" CYRILLIC SMALL LETTER E -->
+ <Key
+ latin:keyLabel="&#x044D;" />
+ <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF -->
+ <Key
+ latin:keyLabel="&#x0444;" />
+ <!-- U+0445: "х" CYRILLIC SMALL LETTER HA -->
+ <Key
+ latin:keyLabel="&#x0445;" />
+ <!-- U+043F: "п" CYRILLIC SMALL LETTER PE -->
+ <Key
+ latin:keyLabel="&#x043F;" />
+ <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
+ <Key
+ latin:keyLabel="&#x0440;" />
+ <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
+ <Key
+ latin:keyLabel="&#x043B;" />
+</merge>
diff --git a/java/res/xml/rowkeys_colemak1.xml b/java/res/xml/rowkeys_colemak1.xml
new file mode 100644
index 000000000..f1c30756b
--- /dev/null
+++ b/java/res/xml/rowkeys_colemak1.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="q"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <Key
+ latin:keyLabel="w"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2"
+ latin:moreKeys="!text/more_keys_for_w" />
+ <Key
+ latin:keyLabel="f"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3" />
+ <Key
+ latin:keyLabel="p"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <Key
+ latin:keyLabel="g"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5"
+ latin:moreKeys="!text/more_keys_for_g" />
+ <Key
+ latin:keyLabel="j"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6"
+ latin:moreKeys="!text/more_keys_for_j" />
+ <Key
+ latin:keyLabel="l"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7"
+ latin:moreKeys="!text/more_keys_for_l" />
+ <Key
+ latin:keyLabel="u"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="!text/more_keys_for_u" />
+ <Key
+ latin:keyLabel="y"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9"
+ latin:moreKeys="!text/more_keys_for_y" />
+</merge>
diff --git a/java/res/xml/rowkeys_colemak2.xml b/java/res/xml/rowkeys_colemak2.xml
new file mode 100644
index 000000000..f73d7e95f
--- /dev/null
+++ b/java/res/xml/rowkeys_colemak2.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="a"
+ latin:moreKeys="!text/more_keys_for_a" />
+ <Key
+ latin:keyLabel="r"
+ latin:moreKeys="!text/more_keys_for_r" />
+ <Key
+ latin:keyLabel="s"
+ latin:moreKeys="!text/more_keys_for_s" />
+ <Key
+ latin:keyLabel="t"
+ latin:moreKeys="!text/more_keys_for_t" />
+ <Key
+ latin:keyLabel="d"
+ latin:moreKeys="!text/more_keys_for_d" />
+ <Key
+ latin:keyLabel="h"
+ latin:moreKeys="!text/more_keys_for_h" />
+ <Key
+ latin:keyLabel="n"
+ latin:moreKeys="!text/more_keys_for_n" />
+ <Key
+ latin:keyLabel="e"
+ latin:moreKeys="!text/more_keys_for_e" />
+ <Key
+ latin:keyLabel="i"
+ latin:moreKeys="!text/more_keys_for_i" />
+ <Key
+ latin:keyLabel="o"
+ latin:moreKeys="!text/more_keys_for_o" />
+</merge>
diff --git a/java/res/xml/rowkeys_colemak3.xml b/java/res/xml/rowkeys_colemak3.xml
new file mode 100644
index 000000000..f0f915142
--- /dev/null
+++ b/java/res/xml/rowkeys_colemak3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="z"
+ latin:moreKeys="!text/more_keys_for_z" />
+ <Key
+ latin:keyLabel="x" />
+ <Key
+ latin:keyLabel="c"
+ latin:moreKeys="!text/more_keys_for_c" />
+ <Key
+ latin:keyLabel="v"
+ latin:moreKeys="!text/more_keys_for_v" />
+ <Key
+ latin:keyLabel="b" />
+ <Key
+ latin:keyLabel="k"
+ latin:moreKeys="!text/more_keys_for_k" />
+ <Key
+ latin:keyLabel="m" />
+</merge>
diff --git a/java/res/xml/rowkeys_dvorak1.xml b/java/res/xml/rowkeys_dvorak1.xml
new file mode 100644
index 000000000..7e0eb6e71
--- /dev/null
+++ b/java/res/xml/rowkeys_dvorak1.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="p"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <Key
+ latin:keyLabel="y"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5"
+ latin:moreKeys="!text/more_keys_for_y" />
+ <Key
+ latin:keyLabel="f"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6" />
+ <Key
+ latin:keyLabel="g"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7"
+ latin:moreKeys="!text/more_keys_for_g" />
+ <Key
+ latin:keyLabel="c"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="!text/more_keys_for_c" />
+ <Key
+ latin:keyLabel="r"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9"
+ latin:moreKeys="!text/more_keys_for_r" />
+ <Key
+ latin:keyLabel="l"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0"
+ latin:moreKeys="!text/more_keys_for_l" />
+</merge>
diff --git a/java/res/xml/rowkeys_dvorak2.xml b/java/res/xml/rowkeys_dvorak2.xml
new file mode 100644
index 000000000..943e3f549
--- /dev/null
+++ b/java/res/xml/rowkeys_dvorak2.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="a"
+ latin:moreKeys="!text/more_keys_for_a" />
+ <Key
+ latin:keyLabel="o"
+ latin:moreKeys="!text/more_keys_for_o" />
+ <Key
+ latin:keyLabel="e"
+ latin:moreKeys="!text/more_keys_for_e" />
+ <Key
+ latin:keyLabel="u"
+ latin:moreKeys="!text/more_keys_for_u" />
+ <Key
+ latin:keyLabel="i"
+ latin:moreKeys="!text/more_keys_for_i" />
+ <Key
+ latin:keyLabel="d"
+ latin:moreKeys="!text/more_keys_for_d" />
+ <Key
+ latin:keyLabel="h"
+ latin:moreKeys="!text/more_keys_for_h" />
+ <Key
+ latin:keyLabel="t"
+ latin:moreKeys="!text/more_keys_for_t" />
+ <Key
+ latin:keyLabel="n"
+ latin:moreKeys="!text/more_keys_for_n" />
+ <Key
+ latin:keyLabel="s"
+ latin:moreKeys="!text/more_keys_for_s" />
+</merge>
diff --git a/java/res/xml/rowkeys_dvorak3.xml b/java/res/xml/rowkeys_dvorak3.xml
new file mode 100644
index 000000000..b035f41cd
--- /dev/null
+++ b/java/res/xml/rowkeys_dvorak3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="j"
+ latin:moreKeys="!text/more_keys_for_j" />
+ <Key
+ latin:keyLabel="k"
+ latin:moreKeys="!text/more_keys_for_k" />
+ <Key
+ latin:keyLabel="x" />
+ <Key
+ latin:keyLabel="b" />
+ <Key
+ latin:keyLabel="m" />
+ <Key
+ latin:keyLabel="w"
+ latin:moreKeys="!text/more_keys_for_w" />
+ <Key
+ latin:keyLabel="v"
+ latin:moreKeys="!text/more_keys_for_v" />
+</merge>
diff --git a/java/res/xml/rowkeys_east_slavic1.xml b/java/res/xml/rowkeys_east_slavic1.xml
new file mode 100644
index 000000000..00cb6a973
--- /dev/null
+++ b/java/res/xml/rowkeys_east_slavic1.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0439: "й" CYRILLIC SMALL LETTER SHORT I -->
+ <Key
+ latin:keyLabel="&#x0439;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE -->
+ <Key
+ latin:keyLabel="&#x0446;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
+ <Key
+ latin:keyLabel="&#x0443;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="!text/more_keys_for_cyrillic_u" />
+ <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
+ <Key
+ latin:keyLabel="&#x043A;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
+ <Key
+ latin:keyLabel="&#x0435;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5"
+ latin:moreKeys="!text/more_keys_for_cyrillic_ye" />
+ <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
+ <Key
+ latin:keyLabel="&#x043D;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6"
+ latin:moreKeys="!text/more_keys_for_cyrillic_en" />
+ <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
+ <Key
+ latin:keyLabel="&#x0433;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA -->
+ <Key
+ latin:keyLabel="&#x0448;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_east_slavic_row1_9"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE -->
+ <Key
+ latin:keyLabel="&#x0437;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ <!-- U+0445: "х" CYRILLIC SMALL LETTER HA -->
+ <Key
+ latin:keyLabel="&#x0445;"
+ latin:moreKeys="!text/more_keys_for_cyrillic_ha" />
+</merge>
diff --git a/java/res/xml/rowkeys_east_slavic2.xml b/java/res/xml/rowkeys_east_slavic2.xml
new file mode 100644
index 000000000..c635af2d9
--- /dev/null
+++ b/java/res/xml/rowkeys_east_slavic2.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF -->
+ <Key
+ latin:keyLabel="&#x0444;" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_east_slavic_row2_1"
+ latin:moreKeys="!text/more_keys_for_east_slavic_row2_1" />
+ <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
+ <Key
+ latin:keyLabel="&#x0432;" />
+ <!-- U+0430: "а" CYRILLIC SMALL LETTER A -->
+ <Key
+ latin:keyLabel="&#x0430;" />
+ <!-- U+043F: "п" CYRILLIC SMALL LETTER PE -->
+ <Key
+ latin:keyLabel="&#x043F;" />
+ <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
+ <Key
+ latin:keyLabel="&#x0440;" />
+ <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
+ <Key
+ latin:keyLabel="&#x043E;"
+ latin:moreKeys="!text/more_keys_for_cyrillic_o" />
+ <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
+ <Key
+ latin:keyLabel="&#x043B;" />
+ <!-- U+0434: "д" CYRILLIC SMALL LETTER DE -->
+ <Key
+ latin:keyLabel="&#x0434;" />
+ <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
+ <Key
+ latin:keyLabel="&#x0436;" />
+ <!-- U+044D: "э" CYRILLIC SMALL LETTER E -->
+ <Key
+ latin:keyLabel="&#x044D;" />
+</merge>
diff --git a/java/res/xml/rowkeys_east_slavic3.xml b/java/res/xml/rowkeys_east_slavic3.xml
new file mode 100644
index 000000000..c3a171b49
--- /dev/null
+++ b/java/res/xml/rowkeys_east_slavic3.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+044F: "я" CYRILLIC SMALL LETTER YA -->
+ <Key
+ latin:keyLabel="&#x044F;" />
+ <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
+ <Key
+ latin:keyLabel="&#x0447;" />
+ <!-- U+0441: "с" CYRILLIC SMALL LETTER ES -->
+ <Key
+ latin:keyLabel="&#x0441;" />
+ <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
+ <Key
+ latin:keyLabel="&#x043C;" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_east_slavic_row3_5" />
+ <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
+ <Key
+ latin:keyLabel="&#x0442;" />
+ <!-- U+044C: "ь" CYRILLIC SMALL LETTER SOFT SIGN -->
+ <Key
+ latin:keyLabel="&#x044C;"
+ latin:moreKeys="!text/more_keys_for_cyrillic_soft_sign" />
+ <!-- U+0431: "б" CYRILLIC SMALL LETTER BE -->
+ <Key
+ latin:keyLabel="&#x0431;" />
+ <!-- U+044E: "ю" CYRILLIC SMALL LETTER YU -->
+ <Key
+ latin:keyLabel="&#x044E;" />
+</merge>
diff --git a/java/res/xml/rowkeys_farsi1.xml b/java/res/xml/rowkeys_farsi1.xml
new file mode 100644
index 000000000..840b048f7
--- /dev/null
+++ b/java/res/xml/rowkeys_farsi1.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0635: "ص" ARABIC LETTER SAD
+ U+0636: "ض" ARABIC LETTER DAD
+ U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x0635;"
+ latin:moreKeys="&#x0636;,%"
+ latin:keyHintLabel="&#x06F1;"
+ latin:additionalMoreKeys="&#x06F1;,1" />
+ <!-- U+0642: "ق" ARABIC LETTER QAF
+ U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x0642;"
+ latin:keyHintLabel="&#x06F2;"
+ latin:additionalMoreKeys="&#x06F2;,2" />
+ <!-- U+0641: "ف" ARABIC LETTER FEH
+ U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE -->
+ <Key
+ latin:keyLabel="&#x0641;"
+ latin:keyHintLabel="&#x06F3;"
+ latin:additionalMoreKeys="&#x06F3;,3" />
+ <!-- U+063A: "غ" ARABIC LETTER GHAIN
+ U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR -->
+ <Key
+ latin:keyLabel="&#x063A;"
+ latin:keyHintLabel="&#x06F4;"
+ latin:additionalMoreKeys="&#x06F4;,4" />
+ <!-- U+0639: "ع" ARABIC LETTER AIN
+ U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x0639;"
+ latin:keyHintLabel="&#x06F5;"
+ latin:additionalMoreKeys="&#x06F5;,5" />
+ <!-- U+0647: "ه" ARABIC LETTER HEH
+ U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM
+ U+0647/U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER
+ U+0647/U+0654: ARABIC LETTER HEH + ARABIC HAMZA ABOVE
+ U+0629: "ة" ARABIC LETTER TEH MARBUTA
+ U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX -->
+ <Key
+ latin:keyLabel="&#x0647;"
+ latin:moreKeys="&#xFEEB;|&#x0647;&#x200D;,&#x0647;&#x0654;,&#x0629;,%"
+ latin:keyHintLabel="&#x06F6;"
+ latin:additionalMoreKeys="&#x06F6;,6" />
+ <!-- U+062E: "خ" ARABIC LETTER KHAH
+ U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN -->
+ <Key
+ latin:keyLabel="&#x062E;"
+ latin:keyHintLabel="&#x06F7;"
+ latin:additionalMoreKeys="&#x06F7;,7" />
+ <!-- U+062D: "ح" ARABIC LETTER HAH
+ U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT -->
+ <Key
+ latin:keyLabel="&#x062D;"
+ latin:keyHintLabel="&#x06F8;"
+ latin:additionalMoreKeys="&#x06F8;,8" />
+ <!-- U+062C: "ج" ARABIC LETTER JEEM
+ U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE -->
+ <Key
+ latin:keyLabel="&#x062C;"
+ latin:keyHintLabel="&#x06F9;"
+ latin:additionalMoreKeys="&#x06F9;,9" />
+ <!-- U+0686: "چ" ARABIC LETTER TCHEH
+ U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO -->
+ <Key
+ latin:keyLabel="&#x0686;"
+ latin:keyHintLabel="&#x06F0;"
+ latin:additionalMoreKeys="&#x06F0;,0" />
+</merge>
diff --git a/java/res/xml/rowkeys_farsi2.xml b/java/res/xml/rowkeys_farsi2.xml
new file mode 100644
index 000000000..21548936e
--- /dev/null
+++ b/java/res/xml/rowkeys_farsi2.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0634: "ش" ARABIC LETTER SHEEN -->
+ <Key
+ latin:keyLabel="&#x0634;" />
+ <!-- U+0633: "س" ARABIC LETTER SEEN
+ U+0636: "ض" ARABIC LETTER DAD -->
+ <Key
+ latin:keyLabel="&#x0633;"
+ latin:moreKeys="&#x0636;" />
+ <!-- U+06CC: "ی" ARABIC LETTER FARSI YEH
+ U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE
+ U+064A: "ي" ARABIC LETTER YEH
+ U+FBE8: "ﯨ" ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM
+ U+0649: "ى" ARABIC LETTER ALEF MAKSURA -->
+ <Key
+ latin:keyLabel="&#x06CC;"
+ latin:moreKeys="&#x0626;,&#x064A;,&#xFBE8;|&#x0649;" />
+ <!-- U+0628: "ب" ARABIC LETTER BEH -->
+ <Key
+ latin:keyLabel="&#x0628;" />
+ <!-- U+0644: "ل" ARABIC LETTER LAM -->
+ <Key
+ latin:keyLabel="&#x0644;" />
+ <!-- U+0627: "ا" ARABIC LETTER ALEF
+ U+0621: "ء" ARABIC LETTER HAMZA
+ U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE
+ U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
+ U+0671: "ٱ" ARABIC LETTER ALEF WASLA
+ U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW -->
+ <Key
+ latin:keyLabel="&#x0627;"
+ latin:moreKeys="&#x0621;,&#x0622;,&#x0623;,&#x0671;,&#x0625;" />
+ <!-- U+062A: "ت" ARABIC LETTER TEH
+ U+062B: "ﺙ" ARABIC LETTER THEH
+ U+0629: "ة": ARABIC LETTER TEH MARBUTA -->
+ <Key
+ latin:keyLabel="&#x062A;"
+ latin:moreKeys="&#x062B;,&#x0629;" />
+ <!-- U+0646: "ن" ARABIC LETTER NOON -->
+ <Key
+ latin:keyLabel="&#x0646;" />
+ <!-- U+0645: "م" ARABIC LETTER MEEM -->
+ <Key
+ latin:keyLabel="&#x0645;" />
+ <!-- U+06A9: "ک" ARABIC LETTER KEHEH
+ U+0643: "ك" ARABIC LETTER KAF -->
+ <Key
+ latin:keyLabel="&#x06A9;"
+ latin:moreKeys="&#x0643;" />
+</merge>
diff --git a/java/res/xml/rowkeys_farsi3.xml b/java/res/xml/rowkeys_farsi3.xml
new file mode 100644
index 000000000..29c35134c
--- /dev/null
+++ b/java/res/xml/rowkeys_farsi3.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0637: "ط" ARABIC LETTER TAH
+ U+0638: "ظ" ARABIC LETTER ZAH -->
+ <Key
+ latin:keyLabel="&#x0637;"
+ latin:moreKeys="&#x0638;" />
+ <!-- U+0632: "ز" ARABIC LETTER ZAIN
+ U+0698: "ژ" ARABIC LETTER JEH -->
+ <Key
+ latin:keyLabel="&#x0632;"
+ latin:moreKeys="&#x0698;" />
+ <!-- U+0631: "ر" ARABIC LETTER REH -->
+ <Key
+ latin:keyLabel="&#x0631;" />
+ <!-- U+0630: "ذ" ARABIC LETTER THAL -->
+ <Key
+ latin:keyLabel="&#x0630;" />
+ <!-- U+062F: "د" ARABIC LETTER DAL -->
+ <Key
+ latin:keyLabel="&#x062F;" />
+ <!-- U+067E: "پ" ARABIC LETTER PEH -->
+ <Key
+ latin:keyLabel="&#x067E;" />
+ <!-- U+0648: "و" ARABIC LETTER WAW
+ U+0624: "ؤ" ARABIC LETTER WAW WITH HAMZA ABOVE -->
+ <Key
+ latin:keyLabel="&#x0648;"
+ latin:moreKeys="&#x0624;" />
+ <!-- U+06AF: "گ" ARABIC LETTER GAF -->
+ <Key
+ latin:keyLabel="&#x06AF;" />
+</merge>
diff --git a/java/res/xml/rowkeys_georgian1.xml b/java/res/xml/rowkeys_georgian1.xml
new file mode 100644
index 000000000..d31a4c79c
--- /dev/null
+++ b/java/res/xml/rowkeys_georgian1.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel="Q"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <!-- U+10ED: "ჭ" GEORGIAN LETTER CHAR -->
+ <Key
+ latin:keyLabel="&#x10ED;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <Key
+ latin:keyLabel="E"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3" />
+ <!-- U+10E6: "ღ" GEORGIAN LETTER GHAN -->
+ <Key
+ latin:keyLabel="&#x10E6;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+10D7: "თ" GEORGIAN LETTER TAN -->
+ <Key
+ latin:keyLabel="&#x10D7;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5" />
+ <Key
+ latin:keyLabel="Y"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6" />
+ <Key
+ latin:keyLabel="U"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <Key
+ latin:keyLabel="I"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8" />
+ <Key
+ latin:keyLabel="O"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <Key
+ latin:keyLabel="P"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ </case>
+ <default>
+ <!-- U+10E5: "ქ" GEORGIAN LETTER GHAN -->
+ <Key
+ latin:keyLabel="&#x10E5;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <!-- U+10EC: "წ" GEORGIAN LETTER CIL -->
+ <Key
+ latin:keyLabel="&#x10EC;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <!-- U+10D4: "ე" GEORGIAN LETTER EN
+ U+10F1: "ჱ" GEORGIAN LETTER HE -->
+ <Key
+ latin:keyLabel="&#x10D4;"
+ latin:moreKeys="&#x10F1;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3" />
+ <!-- U+10E0: "რ" GEORGIAN LETTER RAE -->
+ <Key
+ latin:keyLabel="&#x10E0;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+10E2: "ტ" GEORGIAN LETTER TAR -->
+ <Key
+ latin:keyLabel="&#x10E2;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5" />
+ <!-- U+10E7: "ყ" GEORGIAN LETTER QAR
+ U+10F8: "ჸ" GEORGIAN LETTER ELIFI -->
+ <Key
+ latin:keyLabel="&#x10E7;"
+ latin:moreKeys="&#x10F8;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6" />
+ <!-- U+10E3: "უ" GEORGIAN LETTER UN -->
+ <Key
+ latin:keyLabel="&#x10E3;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <!-- U+10D8: "ი" GEORGIAN LETTER IN
+ U+10F2: "ჲ" GEORGIAN LETTER HIE -->
+ <Key
+ latin:keyLabel="&#x10D8;"
+ latin:moreKeys="&#x10F2;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8" />
+ <!-- U+10DD: "ო" GEORGIAN LETTER ON -->
+ <Key
+ latin:keyLabel="&#x10DD;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <!-- U+10DE: "პ" GEORGIAN LETTER PAR -->
+ <Key
+ latin:keyLabel="&#x10DE;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_georgian2.xml b/java/res/xml/rowkeys_georgian2.xml
new file mode 100644
index 000000000..cdccda31f
--- /dev/null
+++ b/java/res/xml/rowkeys_georgian2.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <Key
+ latin:keyLabel="A" />
+ <!-- U+10E8: "შ" GEORGIAN LETTER SHIN -->
+ <Key
+ latin:keyLabel="&#x10E8;" />
+ <Key
+ latin:keyLabel="D" />
+ <Key
+ latin:keyLabel="F" />
+ <Key
+ latin:keyLabel="G" />
+ <Key
+ latin:keyLabel="H" />
+ <!-- U+10DF: "ჟ" GEORGIAN LETTER ZHAR -->
+ <Key
+ latin:keyLabel="&#x10DF;" />
+ <Key
+ latin:keyLabel="K" />
+ <Key
+ latin:keyLabel="L" />
+ </case>
+ <default>
+ <!-- U+10D0: "ა" GEORGIAN LETTER AN
+ U+10FA: "ჺ" GEORGIAN LETTER AIN -->
+ <Key
+ latin:keyLabel="&#x10D0;"
+ latin:moreKeys="&#x10FA;" />
+ <!-- U+10E1: "ს" GEORGIAN LETTER SAN -->
+ <Key
+ latin:keyLabel="&#x10E1;" />
+ <!-- U+10D3: "დ" GEORGIAN LETTER DON -->
+ <Key
+ latin:keyLabel="&#x10D3;" />
+ <!-- U+10E4: "ფ" GEORGIAN LETTER PHAR
+ U+10F6: "ჶ" GEORGIAN LETTER FI -->
+ <Key
+ latin:keyLabel="&#x10E4;"
+ latin:moreKeys="&#x10F6;" />
+ <!-- U+10D2: "გ" GEORGIAN LETTER GAN
+ U+10F9: "ჹ" GEORGIAN LETTER TURNED GAN -->
+ <Key
+ latin:keyLabel="&#x10D2;"
+ latin:moreKeys="&#x10F9;" />
+ <!-- U+10F0: "ჰ" GEORGIAN LETTER HAE
+ U+10F5: "ჵ" GEORGIAN LETTER HOE -->
+ <Key
+ latin:keyLabel="&#x10F0;"
+ latin:moreKeys="&#x10F5;" />
+ <!-- U+10EF: "ჯ" GEORGIAN LETTER JHAN
+ U+10F7: "ჷ" GEORGIAN LETTER YN -->
+ <Key
+ latin:keyLabel="&#x10EF;"
+ latin:moreKeys="&#x10F7;" />
+ <!-- U+10D9: "კ" GEORGIAN LETTER KAN -->
+ <Key
+ latin:keyLabel="&#x10D9;" />
+ <!-- U+10DA: "ლ" GEORGIAN LETTER LAS -->
+ <Key
+ latin:keyLabel="&#x10DA;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_georgian3.xml b/java/res/xml/rowkeys_georgian3.xml
new file mode 100644
index 000000000..a3714586f
--- /dev/null
+++ b/java/res/xml/rowkeys_georgian3.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+10EB: "ძ" GEORGIAN LETTER JIL -->
+ <Key
+ latin:keyLabel="&#x10EB;" />
+ <Key
+ latin:keyLabel="X" />
+ <!-- U+10E9: "ჩ" GEORGIAN LETTER CHIN -->
+ <Key
+ latin:keyLabel="&#x10E9;" />
+ <Key
+ latin:keyLabel="V" />
+ <Key
+ latin:keyLabel="B" />
+ <Key
+ latin:keyLabel="N" />
+ <Key
+ latin:keyLabel="M" />
+ </case>
+ <default>
+ <!-- U+10D6: "ზ" GEORGIAN LETTER ZEN -->
+ <Key
+ latin:keyLabel="&#x10D6;" />
+ <!-- U+10EE: "ხ" GEORGIAN LETTER XAN
+ U+10F4: "ჴ" GEORGIAN LETTER HAR -->
+ <Key
+ latin:keyLabel="&#x10EE;"
+ latin:moreKeys="&#x10F4;" />
+ <!-- U+10EA: "ც" GEORGIAN LETTER CAN -->
+ <Key
+ latin:keyLabel="&#x10EA;" />
+ <!-- U+10D5: "ვ" GEORGIAN LETTER VIN
+ U+10F3: "ჳ" GEORGIAN LETTER WE -->
+ <Key
+ latin:keyLabel="&#x10D5;"
+ latin:moreKeys="&#x10F3;" />
+ <!-- U+10D1: "ბ" GEORGIAN LETTER BAN -->
+ <Key
+ latin:keyLabel="&#x10D1;" />
+ <!-- U+10DC: "ნ" GEORGIAN LETTER NAR
+ U+10FC: "ჼ" MODIFIER LETTER GEORGIAN NAR -->
+ <Key
+ latin:keyLabel="&#x10DC;"
+ latin:moreKeys="&#x10FC;" />
+ <!-- U+10DB: "მ" GEORGIAN LETTER MAN -->
+ <Key
+ latin:keyLabel="&#x10DB;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_greek1.xml b/java/res/xml/rowkeys_greek1.xml
new file mode 100644
index 000000000..5777d3b85
--- /dev/null
+++ b/java/res/xml/rowkeys_greek1.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- TODO: Should find a way to compound Greek dialytika tonos and other Greek letters. -->
+ <!--
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+ >
+ U+0385: "΅" GREEK DIALYTIKA TONOS
+ <Key
+ latin:keyLabel="&#x0385;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ </case>
+ <default>
+ -->
+ <!-- U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA -->
+ <Key
+ latin:keyLabel="&#x03C2;"
+ latin:keyLabelFlags="preserveCase"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <!--
+ </default>
+ </switch>
+ -->
+ <!-- U+03B5: "ε" GREEK SMALL LETTER EPSILON
+ U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS -->
+ <Key
+ latin:keyLabel="&#x03B5;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="&#x03AD;" />
+ <!-- U+03C1: "ρ" GREEK SMALL LETTER RHO -->
+ <Key
+ latin:keyLabel="&#x03C1;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+03C4: "τ" GREEK SMALL LETTER TAU -->
+ <Key
+ latin:keyLabel="&#x03C4;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5" />
+ <!-- U+03C5: "υ" GREEK SMALL LETTER UPSILON
+ U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
+ U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+ U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS -->
+ <Key
+ latin:keyLabel="&#x03C5;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6"
+ latin:moreKeys="&#x03CD;,&#x03CB;,&#x03B0;" />
+ <!-- U+03B8: "θ" GREEK SMALL LETTER THETA -->
+ <Key
+ latin:keyLabel="&#x03B8;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <!-- U+03B9: "ι" GREEK SMALL LETTER IOTA
+ U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
+ U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+ U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS -->
+ <Key
+ latin:keyLabel="&#x03B9;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="&#x03AF;,&#x03CA;,&#x0390;" />
+ <!-- U+03BF: "ο" GREEK SMALL LETTER OMICRON
+ U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS -->
+ <Key
+ latin:keyLabel="&#x03BF;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9"
+ latin:moreKeys="&#x03CC;" />
+ <!-- U+03C0: "π" GREEK SMALL LETTER PI -->
+ <Key
+ latin:keyLabel="&#x03C0;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+</merge>
diff --git a/java/res/xml/rowkeys_greek2.xml b/java/res/xml/rowkeys_greek2.xml
new file mode 100644
index 000000000..91bdc1165
--- /dev/null
+++ b/java/res/xml/rowkeys_greek2.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+03B1: "α" GREEK SMALL LETTER ALPHA
+ U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS -->
+ <Key
+ latin:keyLabel="&#x03B1;"
+ latin:moreKeys="&#x03AC;" />
+ <!-- U+03C3: "σ" GREEK SMALL LETTER SIGMA -->
+ <Key
+ latin:keyLabel="&#x03C3;" />
+ <!-- U+03B4: "δ" GREEK SMALL LETTER DELTA -->
+ <Key
+ latin:keyLabel="&#x03B4;" />
+ <!-- U+03C6: "φ" GREEK SMALL LETTER PHI -->
+ <Key
+ latin:keyLabel="&#x03C6;" />
+ <!-- U+03B3: "γ" GREEK SMALL LETTER GAMMA -->
+ <Key
+ latin:keyLabel="&#x03B3;" />
+ <!-- U+03B7: "η" GREEK SMALL LETTER ETA
+ U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS -->
+ <Key
+ latin:keyLabel="&#x03B7;"
+ latin:moreKeys="&#x03AE;" />
+ <!-- U+03BE: "ξ" GREEK SMALL LETTER XI -->
+ <Key
+ latin:keyLabel="&#x03BE;" />
+ <!-- U+03BA: "κ" GREEK SMALL LETTER KAPPA -->
+ <Key
+ latin:keyLabel="&#x03BA;" />
+ <!-- U+03BB: "λ" GREEK SMALL LETTER LAMDA -->
+ <Key
+ latin:keyLabel="&#x03BB;" />
+</merge>
diff --git a/java/res/xml/rowkeys_greek3.xml b/java/res/xml/rowkeys_greek3.xml
new file mode 100644
index 000000000..8a99db925
--- /dev/null
+++ b/java/res/xml/rowkeys_greek3.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+03B6: "ζ" GREEK SMALL LETTER ZETA -->
+ <Key
+ latin:keyLabel="&#x03B6;" />
+ <!-- U+03C7: "χ" GREEK SMALL LETTER CHI -->
+ <Key
+ latin:keyLabel="&#x03C7;" />
+ <!-- U+03C8: "ψ" GREEK SMALL LETTER PSI -->
+ <Key
+ latin:keyLabel="&#x03C8;" />
+ <!-- U+03C9: "ω" GREEK SMALL LETTER OMEGA
+ U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS -->
+ <Key
+ latin:keyLabel="&#x03C9;"
+ latin:moreKeys="&#x03CE;" />
+ <!-- U+03B2: "β" GREEK SMALL LETTER BETA -->
+ <Key
+ latin:keyLabel="&#x03B2;" />
+ <!-- U+03BD: "ν" GREEK SMALL LETTER NU -->
+ <Key
+ latin:keyLabel="&#x03BD;" />
+ <!-- U+03BC: "μ" GREEK SMALL LETTER MU -->
+ <Key
+ latin:keyLabel="&#x03BC;" />
+</merge>
diff --git a/java/res/xml/rowkeys_hebrew1.xml b/java/res/xml/rowkeys_hebrew1.xml
new file mode 100644
index 000000000..396da785e
--- /dev/null
+++ b/java/res/xml/rowkeys_hebrew1.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+05E7: "ק" HEBREW LETTER QOF -->
+ <Key
+ latin:keyLabel="&#x05E7;" />
+ <!-- U+05E8: "ר" HEBREW LETTER RESH -->
+ <Key
+ latin:keyLabel="&#x05E8;" />
+ <!-- U+05D0: "א" HEBREW LETTER ALEF -->
+ <Key
+ latin:keyLabel="&#x05D0;" />
+ <!-- U+05D8: "ט" HEBREW LETTER TET -->
+ <Key
+ latin:keyLabel="&#x05D8;" />
+ <!-- U+05D5: "ו" HEBREW LETTER VAV -->
+ <Key
+ latin:keyLabel="&#x05D5;" />
+ <!-- U+05DF: "ן" HEBREW LETTER FINAL NUN -->
+ <Key
+ latin:keyLabel="&#x05DF;" />
+ <!-- U+05DD: "ם" HEBREW LETTER FINAL MEM -->
+ <Key
+ latin:keyLabel="&#x05DD;" />
+ <!-- U+05E4: "פ" HEBREW LETTER PE -->
+ <Key
+ latin:keyLabel="&#x05E4;" />
+</merge>
diff --git a/java/res/xml/rowkeys_hebrew2.xml b/java/res/xml/rowkeys_hebrew2.xml
new file mode 100644
index 000000000..e4ecac335
--- /dev/null
+++ b/java/res/xml/rowkeys_hebrew2.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+05E9: "ש" HEBREW LETTER SHIN -->
+ <Key
+ latin:keyLabel="&#x05E9;" />
+ <!-- U+05D3: "ד" HEBREW LETTER DALET -->
+ <Key
+ latin:keyLabel="&#x05D3;" />
+ <!-- U+05D2: "ג" HEBREW LETTER GIMEL
+ U+05D2 U+05F3: "ג׳" HEBREW LETTER GIMEL + HEBREW PUNCTUATION GERESH -->
+ <Key
+ latin:keyLabel="&#x05D2;"
+ latin:moreKeys="&#x05D2;&#x05F3;" />
+ <!-- U+05DB: "כ" HEBREW LETTER KAF -->
+ <Key
+ latin:keyLabel="&#x05DB;" />
+ <!-- U+05E2: "ע" HEBREW LETTER AYIN -->
+ <Key
+ latin:keyLabel="&#x05E2;" />
+ <!-- U+05D9: "י" HEBREW LETTER YOD
+ U+05F2 U+05B7: "ײַ" HEBREW LIGATURE YIDDISH DOUBLE YOD + HEBREW POINT PATAH -->
+ <Key
+ latin:keyLabel="&#x05D9;"
+ latin:moreKeys="&#x05F2;&#x05B7;" />
+ <!-- U+05D7: "ח" HEBREW LETTER HET
+ U+05D7 U+05F3: "ח׳" HEBREW LETTER HET + HEBREW PUNCTUATION GERESH -->
+ <Key
+ latin:keyLabel="&#x05D7;"
+ latin:moreKeys="&#x05D7;&#x05F3;" />
+ <!-- U+05DC: "ל" HEBREW LETTER LAMED -->
+ <Key
+ latin:keyLabel="&#x05DC;" />
+ <!-- U+05DA: "ך" HEBREW LETTER FINAL KAF -->
+ <Key
+ latin:keyLabel="&#x05DA;" />
+ <!-- U+05E3: "ף" HEBREW LETTER FINAL PE -->
+ <Key
+ latin:keyLabel="&#x05E3;" />
+</merge>
diff --git a/java/res/xml/rowkeys_hebrew3.xml b/java/res/xml/rowkeys_hebrew3.xml
new file mode 100644
index 000000000..805a7a596
--- /dev/null
+++ b/java/res/xml/rowkeys_hebrew3.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+05D6: "ז" HEBREW LETTER ZAYIN
+ U+05D6 U+05F3: "ז׳" HEBREW LETTER ZAYIN + HEBREW PUNCTUATION GERESH -->
+ <Key
+ latin:keyLabel="&#x05D6;"
+ latin:moreKeys="&#x05D6;&#x05F3;" />
+ <!-- U+05E1: "ס" HEBREW LETTER SAMEKH -->
+ <Key
+ latin:keyLabel="&#x05E1;" />
+ <!-- U+05D1: "ב" HEBREW LETTER BET -->
+ <Key
+ latin:keyLabel="&#x05D1;" />
+ <!-- U+05D4: "ה" HEBREW LETTER HE -->
+ <Key
+ latin:keyLabel="&#x05D4;" />
+ <!-- U+05E0: "נ" HEBREW LETTER NUN -->
+ <Key
+ latin:keyLabel="&#x05E0;" />
+ <!-- U+05DE: "מ" HEBREW LETTER MEM -->
+ <Key
+ latin:keyLabel="&#x05DE;" />
+ <!-- U+05E6: "צ" HEBREW LETTER TSADI
+ U+05E6 U+05F3: "צ׳" HEBREW LETTER TSADI + HEBREW PUNCTUATION GERESH -->
+ <Key
+ latin:keyLabel="&#x05E6;"
+ latin:moreKeys="&#x05E6;&#x05F3;" />
+ <!-- U+05EA: "ת" HEBREW LETTER TAV
+ U+05EA U+05F3: "ת׳" HEBREW LETTER TAV + HEBREW PUNCTUATION GERESH -->
+ <Key
+ latin:keyLabel="&#x05EA;"
+ latin:moreKeys="&#x05EA;&#x05F3;" />
+ <!-- U+05E5: "ץ" HEBREW LETTER FINAL TSADI
+ U+05E5 U+05F3: "ץ׳" HEBREW LETTER FINAL TSADI + HEBREW PUNCTUATION GERESH -->
+ <Key
+ latin:keyLabel="&#x05E5;"
+ latin:moreKeys="&#x05E5;&#x05F3;" />
+</merge>
diff --git a/java/res/xml/rowkeys_hindi1.xml b/java/res/xml/rowkeys_hindi1.xml
new file mode 100644
index 000000000..656ba01c4
--- /dev/null
+++ b/java/res/xml/rowkeys_hindi1.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0914: "औ" DEVANAGARI LETTER AU
+ U+0912/U+0902: "ऒं" DEVANAGARI LETTER SHORT O//DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0914;"
+ latin:moreKeys="&#x0912;&#x0902;" />
+ <!-- U+0910: "ऐ" DEVANAGARI LETTER AI
+ U+0910/U+0902: "ऐं" DEVANAGARI LETTER AI/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0910;"
+ latin:moreKeys="&#x0910;&#x0902;" />
+ <!-- U+0906: "आ" DEVANAGARI LETTER AA
+ U+0906/U+0902: "आं" DEVANAGARI LETTER AA/DEVANAGARI SIGN ANUSVARA
+ U+0906/U+0901: "आँ" DEVANAGARI LETTER AA/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x0906;"
+ latin:moreKeys="&#x0906;&#x0902;,&#x0906;&#x0901;" />
+ <!-- U+0908: "ई" DEVANAGARI LETTER II
+ U+0908/U+0902: "ईं" DEVANAGARI LETTER II/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0908;"
+ latin:moreKeys="&#x0908;&#x0902;" />
+ <!-- U+090A: "ऊ" DEVANAGARI LETTER UU
+ U+090A/U+0902: "ऊं" DEVANAGARI LETTER UU/DEVANAGARI SIGN ANUSVARA
+ U+090A/U+0901: "ऊँ" DEVANAGARI LETTER UU/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x090A;"
+ latin:moreKeys="&#x090A;&#x0902;,&#x090A;&#x0901;" />
+ <!-- U+092D: "भ" DEVANAGARI LETTER BHA -->
+ <Key
+ latin:keyLabel="&#x092D;" />
+ <!-- U+0903: "ः" DEVANAGARI SIGN VISARGA -->
+ <Key
+ latin:keyLabel="&#x0903;" />
+ <!-- U+0918: "घ" DEVANAGARI LETTER GHA -->
+ <Key
+ latin:keyLabel="&#x0918;" />
+ <!-- U+0927: "ध" DEVANAGARI LETTER DHA
+ U+0915/U+094D/U+0937: "क्ष" DEVANAGARI LETTER KA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER SSA
+ U+0936/U+094D/U+0930: "श्र" DEVANAGARI LETTER SHA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA -->
+ <Key
+ latin:keyLabel="&#x0927;"
+ latin:moreKeys="&#x0915;&#x094D;&#x0937;,&#x0936;&#x094D;&#x0930;" />
+ <!-- U+091D: "झ" DEVANAGARI LETTER JHA -->
+ <Key
+ latin:keyLabel="&#x091D;" />
+ <!-- U+0922: "ढ" DEVANAGARI LETTER DDHA -->
+ <Key
+ latin:keyLabel="&#x0922;" />
+ </case>
+ <default>
+ <!-- U+094C: "ौ" DEVANAGARI VOWEL SIGN AU
+ U+094C/U+0902: "ौं" DEVANAGARI VOWEL SIGN AU/DEVANAGARI SIGN ANUSVARA
+ U+0967: "१" DEVANAGARI DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x094C;"
+ latin:moreKeys="&#x094C;&#x0902;,%"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="&#x0967;,1" />
+ <!-- U+0948: "ै" DEVANAGARI VOWEL SIGN AI
+ U+0948/U+0902: "ैं" DEVANAGARI VOWEL SIGN AI/DEVANAGARI SIGN ANUSVARA
+ U+0968: "२" DEVANAGARI DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x0948;"
+ latin:moreKeys="&#x0948;&#x0902;,%"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="&#x0968;,2" />
+ <!-- U+093E: "ा" DEVANAGARI VOWEL SIGN AA
+ U+093E/U+0902: "ां" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN ANUSVARA
+ U+093E/U+0901: "ाँ" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN CANDRABINDU
+ U+0969: "३" DEVANAGARI DIGIT THREE -->
+ <Key
+ latin:keyLabel="&#x093E;"
+ latin:moreKeys="&#x093E;&#x0902;,&#x093E;&#x0901;,%"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="&#x0969;,3" />
+ <!-- U+0940: "ी" DEVANAGARI VOWEL SIGN II
+ U+0940/U+0902: "ीं" DEVANAGARI VOWEL SIGN II/DEVANAGARI SIGN ANUSVARA
+ U+096A: "४" DEVANAGARI DIGIT FOUR -->
+ <Key
+ latin:keyLabel="&#x0940;"
+ latin:moreKeys="&#x0940;&#x0902;,%"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="&#x096A;,4" />
+ <!-- U+0942: "ू" DEVANAGARI VOWEL SIGN UU
+ U+0942/U+0902: "ूं" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN ANUSVARA
+ U+0942/U+0901: "ूँ" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN CANDRABINDU
+ U+096B: "५" DEVANAGARI DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x0942;"
+ latin:moreKeys="&#x0942;&#x0902;,&#x0942;&#x0901;,%"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="&#x096B;,5" />
+ <!-- U+092C: "ब" DEVANAGARI LETTER BA
+ U+092C/U+0952: "ब॒" DEVANAGARI LETTER BA/DEVANAGARI STRESS SIGN ANUDATTA -->
+ <Key
+ latin:keyLabel="&#x092C;"
+ latin:moreKeys="&#x092C;&#x0952;,%"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="&#x096C;,6" />
+ <!-- U+0939: "ह" DEVANAGARI LETTER HA
+ U+096D: "७" DEVANAGARI DIGIT SEVEN -->
+ <Key
+ latin:keyLabel="&#x0939;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="&#x096D;,7" />
+ <!-- U+0917: "ग" DEVANAGARI LETTER GA
+ U+091C/U+094D/U+091E: "ज्ञ" DEVANAGARI LETTER JA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER NYA
+ U+0917/U+093C: "ग़" DEVANAGARI LETTER GA/DEVANAGARI SIGN NUKTA
+ U+0917/U+0952: "ग॒" DEVANAGARI LETTER GA/DEVANAGARI STRESS SIGN ANUDATTA
+ U+096E: "८" DEVANAGARI DIGIT EIGHT -->
+ <Key
+ latin:keyLabel="&#x0917;"
+ latin:moreKeys="&#x091C;&#x094D;&#x091E;,&#x0917;&#x093C;,&#x0917;&#x0952;,%"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="&#x096E;,8" />
+ <!-- U+0926: "द" DEVANAGARI LETTER DA
+ U+096F: "९" DEVANAGARI DIGIT NINE -->
+ <Key
+ latin:keyLabel="&#x0926;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <!-- U+091C: "ज" DEVANAGARI LETTER JA
+ U+091C/U+0952: "ज॒" DEVANAGARI LETTER JA/DEVANAGARI STRESS SIGN ANUDATTA
+ U+091C/U+094D/U+091E: "ज्ञ" DEVANAGARI LETTER JA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER NYA
+ U+091C/U+093C: "ज़" DEVANAGARI LETTER JA/DEVANAGARI SIGN NUKTA
+ U+0966: "०" DEVANAGARI DIGIT ZERO -->
+ <Key
+ latin:keyLabel="&#x091C;"
+ latin:moreKeys="&#x091C;&#x0952;,&#x091C;&#x094D;&#x091E;,&#x091C;&#x093C;,%"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="&#x0966;,0" />
+ <!-- U+0921: "ड" DEVANAGARI LETTER DDA
+ U+0921/U+0952: "ड॒" DEVANAGARI LETTER DDA/DEVANAGARI STRESS SIGN ANUDATTA
+ U+0921/U+093C: "ड़" DEVANAGARI LETTER DDA/DEVANAGARI SIGN NUKTA -->
+ <Key
+ latin:keyLabel="&#x0921;"
+ latin:moreKeys="&#x0921;&#x0952;,&#x0921;&#x093C;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_hindi2.xml b/java/res/xml/rowkeys_hindi2.xml
new file mode 100644
index 000000000..05e3db202
--- /dev/null
+++ b/java/res/xml/rowkeys_hindi2.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0913: "ओ" DEVANAGARI LETTER O
+ U+0913/U+0902: "ओं" DEVANAGARI LETTER O/DEVANAGARI SIGN ANUSVARA
+ U+0911: "ऑ" DEVANAGARI LETTER CANDRA O
+ U+0912: "ऒ" DEVANAGARI LETTER SHORT O -->
+ <Key
+ latin:keyLabel="&#x0913;"
+ latin:moreKeys="&#x0913;&#x0902;,&#x0911;,&#x0912;" />
+ <!-- U+090F: "ए" DEVANAGARI LETTER E
+ U+090F/U+0902: "एं" DEVANAGARI LETTER E/DEVANAGARI SIGN ANUSVARA
+ U+090F/U+0901: "एँ" DEVANAGARI LETTER E/DEVANAGARI SIGN CANDRABINDU
+ U+090D: "ऍ" DEVANAGARI LETTER CANDRA E
+ U+090E: "ऎ" DEVANAGARI LETTER SHORT E -->
+ <Key
+ latin:keyLabel="&#x090F;"
+ latin:moreKeys="&#x090F;&#x0902;,&#x090F;&#x0901;,&#x090D;,&#x090E;" />
+ <!-- U+0905: "अ" DEVANAGARI LETTER A
+ U+0905/U+0902: "अं" DEVANAGARI LETTER A/DEVANAGARI SIGN ANUSVARA
+ U+0905/U+0901: "अँ" DEVANAGARI LETTER A/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x0905;"
+ latin:moreKeys="&#x0905;&#x0902;,&#x0905;&#x0901;" />
+ <!-- U+0907: "इ" DEVANAGARI LETTER I
+ U+0907/U+0902: "इं" DEVANAGARI LETTER I/DEVANAGARI SIGN ANUSVARA
+ U+0907/U+0901: "इं" DEVANAGARI LETTER I/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x0907;"
+ latin:moreKeys="&#x0907;&#x0902;,&#x0907;&#x0901;" />
+ <!-- U+0909: "उ" DEVANAGARI LETTER U
+ U+0909/U+0902: "उं" DEVANAGARI LETTER U/DEVANAGARI SIGN ANUSVARA
+ U+0909/U+0901: "उँ" DEVANAGARI LETTER U/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x0909;"
+ latin:moreKeys="&#x0909;&#x0902;,&#x0909;&#x0901;" />
+ <!-- U+092B: "फ" DEVANAGARI LETTER PHA
+ U+092B/U+093C: "फ़" DEVANAGARI LETTER PHA/DEVANAGARI SIGN NUKTA -->
+ <Key
+ latin:keyLabel="&#x092B;"
+ latin:moreKeys="&#x092B;&#x093C;" />
+ <!-- U+0931: "ऱ" DEVANAGARI LETTER RRA
+ U+094D/U+0930: "्र" DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA
+ U+0930/U+094D: "र्" DEVANAGARI LETTER RA/DEVANAGARI SIGN VIRAMA -->
+ <Key
+ latin:keyLabel="&#x0931;"
+ latin:moreKeys="&#x094D;&#x0930;,&#x0930;&#x094D;" />
+ <!-- U+0916: "ख" DEVANAGARI LETTER KHA
+ U+0916/U+093C: "ख़" DEVANAGARI LETTER KHA/DEVANAGARI SIGN NUKTA -->
+ <Key
+ latin:keyLabel="&#x0916;"
+ latin:moreKeys="&#x0916;&#x093C;" />
+ <!-- U+0925: "थ" DEVANAGARI LETTER THA -->
+ <Key
+ latin:keyLabel="&#x0925;" />
+ <!-- U+091B: "छ" DEVANAGARI LETTER CHA -->
+ <Key
+ latin:keyLabel="&#x091B;" />
+ <!-- U+0920: "ठ" DEVANAGARI LETTER TTHA -->
+ <Key
+ latin:keyLabel="&#x0920;" />
+ </case>
+ <default>
+ <!-- U+094B: "ो" DEVANAGARI VOWEL SIGN O
+ U+094B/U+0902: "қं" DEVANAGARI VOWEL SIGN O/DEVANAGARI SIGN ANUSVARA
+ U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O
+ U+094A: "ॊ" DEVANAGARI VOWEL SIGN SHORT O -->
+ <Key
+ latin:keyLabel="&#x094B;"
+ latin:moreKeys="&#x094B;&#x0902;,&#x0949;,&#x094A;" />
+ <!-- U+0947: "े" DEVANAGARI VOWEL SIGN E
+ U+0947/U+0902: "ें" DEVANAGARI VOWEL SIGN E/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0947;"
+ latin:moreKeys="&#x0947;&#x0902;" />
+ <!-- U+094D: "्" DEVANAGARI SIGN VIRAMA -->
+ <Key
+ latin:keyLabel="&#x094D;" />
+ <!-- U+093F: "ि" DEVANAGARI VOWEL SIGN I
+ U+093F/U+0902: "िं" DEVANAGARI VOWEL SIGN I/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x093F;"
+ latin:moreKeys="&#x093F;&#x0902;" />
+ <!-- U+0941: "ु" DEVANAGARI VOWEL SIGN U
+ U+0941/U+0902: "ुं" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN ANUSVARA
+ U+0941/U+0901: "ुँ" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x0941;"
+ latin:moreKeys="&#x0941;&#x0902;,&#x0941;&#x0901;" />
+ <!-- U+092A: "प" DEVANAGARI LETTER PA -->
+ <Key
+ latin:keyLabel="&#x092A;" />
+ <!-- U+0930: "र" DEVANAGARI LETTER RA
+ U+090B: "ऋ" DEVANAGARI LETTER VOCALIC R
+ U+0930/U+093C: "ऱ" DEVANAGARI LETTER RA/DEVANAGARI SIGN NUKTA
+ U+0960: "ॠ" DEVANAGARI LETTER VOCALIC RR -->
+ <Key
+ latin:keyLabel="&#x0930;"
+ latin:moreKeys="&#x090B;,&#x0930;&#x093C;,&#x0960;" />
+ <!-- U+0915: "क" DEVANAGARI LETTER KA
+ U+0915/U+093C: "क़" DEVANAGARI LETTER KA/DEVANAGARI SIGN NUKTA -->
+ <Key
+ latin:keyLabel="&#x0915;"
+ latin:moreKeys="&#x0915;&#x093C;" />
+ <!-- U+0924: "त" DEVANAGARI LETTER TA
+ U+0924/U+094D/U+0930: "त्र" DEVANAGARI LETTER TA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA -->
+ <Key
+ latin:keyLabel="&#x0924;"
+ latin:moreKeys="&#x0924;&#x094D;&#x0930;" />
+ <!-- U+091A: "च" DEVANAGARI LETTER CA -->
+ <Key
+ latin:keyLabel="&#x091A;" />
+ <!-- U+091F: "ट" DEVANAGARI LETTER TTA -->
+ <Key
+ latin:keyLabel="&#x091F;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_hindi3.xml b/java/res/xml/rowkeys_hindi3.xml
new file mode 100644
index 000000000..92bcb56b3
--- /dev/null
+++ b/java/res/xml/rowkeys_hindi3.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0911: "ऑ" DEVANAGARI LETTER CANDRA O -->
+ <Key
+ latin:keyLabel="&#x0911;" />
+ <!-- U+0901: "ँ" DEVANAGARI SIGN CANDRABINDU
+ U+0945: "ॅ" DEVANAGARI VOWEL SIGN CANDRA E-->
+ <Key
+ latin:keyLabel="&#x0901;"
+ latin:moreKeys="&#x0945;" />
+ <!-- U+0923: "ण" DEVANAGARI LETTER NNA -->
+ <Key
+ latin:keyLabel="&#x0923;" />
+ <!-- U+0929: "ऩ" DEVANAGARI LETTER NNNA -->
+ <Key
+ latin:keyLabel="&#x0929;" />
+ <!-- U+0933: "ळ" DEVANAGARI LETTER LLA
+ U+0934: "ऴ" DEVANAGARI LETTER LLLA -->
+ <Key
+ latin:keyLabel="&#x0933;"
+ latin:moreKeys="&#x0934;" />
+ <!-- U+0936: "श" DEVANAGARI LETTER SHA -->
+ <Key
+ latin:keyLabel="&#x0936;" />
+ <!-- U+0937: "ष" DEVANAGARI LETTER SSA -->
+ <Key
+ latin:keyLabel="&#x0937;" />
+ <!-- U+0943: "ृ" DEVANAGARI VOWEL SIGN VOCALIC R
+ U+0944: "ॄ" DEVANAGARI VOWEL SIGN VOCALIC RR -->
+ <Key
+ latin:keyLabel="&#x0943;"
+ latin:moreKeys="&#x0944;" />
+ <!-- U+091E: "ञ" DEVANAGARI LETTER NYA -->
+ <Key
+ latin:keyLabel="&#x091E;" />
+ </case>
+ <default>
+ <!-- U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O -->
+ <Key
+ latin:keyLabel="&#x0949;" />
+ <!-- U+0902: "ं" DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0902;" />
+ <!-- U+092E: "म" DEVANAGARI LETTER MA
+ U+0950: "ॐ" DEVANAGARI OM -->
+ <Key
+ latin:keyLabel="&#x092E;"
+ latin:moreKeys="&#x0950;" />
+ <!-- U+0928: "न" DEVANAGARI LETTER NA
+ U+091E: "ञ" DEVANAGARI LETTER NYA
+ U+0919: "ङ" DEVANAGARI LETTER NGA
+ U+0928/U+093C: "ऩ" DEVANAGARI LETTER NA/DEVANAGARI SIGN NUKTA -->
+ <Key
+ latin:keyLabel="&#x0928;"
+ latin:moreKeys="&#x091E;,&#x0919;,&#x0928;&#x093C;" />
+ <!-- U+0935: "व" DEVANAGARI LETTER VA -->
+ <Key
+ latin:keyLabel="&#x0935;" />
+ <!-- U+0932: "ल" DEVANAGARI LETTER LA
+ U+090C: "ऌ" DEVANAGARI LETTER VOCALIC L
+ U+0961: "ॡ" DEVANAGARI LETTER VOCALIC LL -->
+ <Key
+ latin:keyLabel="&#x0932;"
+ latin:moreKeys="&#x090C;,&#x0961;" />
+ <!-- U+0938: "स" DEVANAGARI LETTER SA -->
+ <Key
+ latin:keyLabel="&#x0938;" />
+ <!-- U+092F: "य" DEVANAGARI LETTER YA
+ U+095F: "य़" DEVANAGARI LETTER YYA -->
+ <Key
+ latin:keyLabel="&#x092F;"
+ latin:moreKeys="&#x095F;" />
+ <!-- U+093C: "़" DEVANAGARI SIGN NUKTA
+ U+097D: "ॽ" DEVANAGARI LETTER GLOTTAL STOP
+ U+0970: "॰" DEVANAGARI ABBREVIATION SIGN
+ U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
+ <Key
+ latin:keyLabel="&#x093C;"
+ latin:moreKeys="&#x097D;,&#x0970;,&#x093D;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_nordic1.xml b/java/res/xml/rowkeys_nordic1.xml
new file mode 100644
index 000000000..72ac86b2e
--- /dev/null
+++ b/java/res/xml/rowkeys_nordic1.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_nordic_row1_11" />
+</merge>
diff --git a/java/res/xml-large/kbd_rows_qwerty.xml b/java/res/xml/rowkeys_nordic2.xml
index a2d26b3de..836214abf 100644
--- a/java/res/xml-large/kbd_rows_qwerty.xml
+++ b/java/res/xml/rowkeys_nordic2.xml
@@ -2,7 +2,7 @@
<!--
/*
**
-** Copyright 2011, The Android Open Source Project
+** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -22,13 +22,11 @@
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<include
- latin:keyboardLayout="@xml/kbd_key_styles" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row1" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row2" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row3" />
- <include
- latin:keyboardLayout="@xml/kbd_qwerty_row4" />
+ latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_nordic_row2_10"
+ latin:moreKeys="!text/more_keys_for_nordic_row2_10" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_nordic_row2_11"
+ latin:moreKeys="!text/more_keys_for_nordic_row2_11" />
</merge>
diff --git a/java/res/xml/rowkeys_pcqwerty1.xml b/java/res/xml/rowkeys_pcqwerty1.xml
new file mode 100644
index 000000000..0ecda3550
--- /dev/null
+++ b/java/res/xml/rowkeys_pcqwerty1.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted"
+ >
+ <!-- U+00AC: "¬" NOT SIGN -->
+ <Key
+ latin:keyLabel="`"
+ latin:moreKeys="~"
+ latin:additionalMoreKeys="&#x00AC;" />
+ <!-- U+00A1: "¡" NVERTED EXCLAMATION MARK -->
+ <Key
+ latin:keyLabel="1"
+ latin:additionalMoreKeys="!"
+ latin:moreKeys="&#x00A1;,!text/more_keys_for_symbols_1" />
+ <Key
+ latin:keyLabel="2"
+ latin:additionalMoreKeys="\@"
+ latin:moreKeys="!text/more_keys_for_symbols_2" />
+ <Key
+ latin:keyLabel="3"
+ latin:additionalMoreKeys="#"
+ latin:moreKeys="!text/more_keys_for_symbols_3" />
+ <Key
+ latin:keyLabel="4"
+ latin:additionalMoreKeys="$"
+ latin:moreKeys="!text/more_keys_for_symbols_4" />
+ <Key
+ latin:keyLabel="5"
+ latin:additionalMoreKeys="\\%"
+ latin:moreKeys="!text/more_keys_for_symbols_5" />
+ <Key
+ latin:keyLabel="6"
+ latin:additionalMoreKeys="^"
+ latin:moreKeys="!text/more_keys_for_symbols_6" />
+ <Key
+ latin:keyLabel="7"
+ latin:additionalMoreKeys="&amp;"
+ latin:moreKeys="!text/more_keys_for_symbols_7" />
+ <Key
+ latin:keyLabel="8"
+ latin:additionalMoreKeys="*,%"
+ latin:moreKeys="!text/more_keys_for_symbols_8" />
+ <Key
+ latin:keyLabel="9"
+ latin:additionalMoreKeys="("
+ latin:moreKeys="!text/more_keys_for_symbols_9" />
+ <Key
+ latin:keyLabel="0"
+ latin:additionalMoreKeys=")"
+ latin:moreKeys="!text/more_keys_for_symbols_0" />
+ <Key
+ latin:keyLabel="-"
+ latin:moreKeys="_" />
+ <Key
+ latin:keyLabel="="
+ latin:moreKeys="+" />
+ </case>
+ <!-- keyboardLayoutSetElement="alphabet*Shifted|symbols*" -->
+ <default>
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty_symbols1" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_pcqwerty2.xml b/java/res/xml/rowkeys_pcqwerty2.xml
new file mode 100644
index 000000000..cedf47559
--- /dev/null
+++ b/java/res/xml/rowkeys_pcqwerty2.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty_symbols2" />
+ </case>
+ <default>
+ <!-- The keys on this PC layout row2 consist of the letters of QWERTY layout row1 and
+ some symbols keys. -->
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1"
+ latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" />
+ </default>
+ </switch>
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty2_right3" />
+</merge>
diff --git a/java/res/xml/rowkeys_pcqwerty3.xml b/java/res/xml/rowkeys_pcqwerty3.xml
new file mode 100644
index 000000000..5044e5feb
--- /dev/null
+++ b/java/res/xml/rowkeys_pcqwerty3.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty_symbols3" />
+ </case>
+ <default>
+ <!-- The keys on this PC layout row3 consist of the letters of QWERTY layout row2 and
+ some symbols keys. -->
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+ </default>
+ </switch>
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty3_right2" />
+</merge>
diff --git a/java/res/xml/rowkeys_pcqwerty4.xml b/java/res/xml/rowkeys_pcqwerty4.xml
new file mode 100644
index 000000000..4071e8c09
--- /dev/null
+++ b/java/res/xml/rowkeys_pcqwerty4.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="symbols|symbolsShifted"
+ >
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty_symbols4" />
+ </case>
+ <default>
+ <!-- The keys on this PC layout row4 consist of the letters of QWERTY layout row3 and
+ some symbols keys. -->
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ </default>
+ </switch>
+ <include
+ latin:keyboardLayout="@xml/keys_pcqwerty4_right3" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty1.xml b/java/res/xml/rowkeys_qwerty1.xml
new file mode 100644
index 000000000..84d613460
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty1.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="q"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <Key
+ latin:keyLabel="w"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2"
+ latin:moreKeys="!text/more_keys_for_w" />
+ <Key
+ latin:keyLabel="e"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="!text/more_keys_for_e" />
+ <Key
+ latin:keyLabel="r"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4"
+ latin:moreKeys="!text/more_keys_for_r" />
+ <Key
+ latin:keyLabel="t"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5"
+ latin:moreKeys="!text/more_keys_for_t" />
+ <Key
+ latin:keyLabel="y"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6"
+ latin:moreKeys="!text/more_keys_for_y" />
+ <Key
+ latin:keyLabel="u"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7"
+ latin:moreKeys="!text/more_keys_for_u" />
+ <Key
+ latin:keyLabel="i"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="!text/more_keys_for_i" />
+ <Key
+ latin:keyLabel="o"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9"
+ latin:moreKeys="!text/more_keys_for_o" />
+ <Key
+ latin:keyLabel="p"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty2.xml b/java/res/xml/rowkeys_qwerty2.xml
new file mode 100644
index 000000000..d9777d920
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty2.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="a"
+ latin:moreKeys="!text/more_keys_for_a" />
+ <Key
+ latin:keyLabel="s"
+ latin:moreKeys="!text/more_keys_for_s" />
+ <Key
+ latin:keyLabel="d"
+ latin:moreKeys="!text/more_keys_for_d" />
+ <Key
+ latin:keyLabel="f" />
+ <Key
+ latin:keyLabel="g"
+ latin:moreKeys="!text/more_keys_for_g" />
+ <Key
+ latin:keyLabel="h"
+ latin:moreKeys="!text/more_keys_for_h" />
+ <Key
+ latin:keyLabel="j"
+ latin:moreKeys="!text/more_keys_for_j" />
+ <Key
+ latin:keyLabel="k"
+ latin:moreKeys="!text/more_keys_for_k" />
+ <Key
+ latin:keyLabel="l"
+ latin:moreKeys="!text/more_keys_for_l" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty3.xml b/java/res/xml/rowkeys_qwerty3.xml
new file mode 100644
index 000000000..a74aeb842
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="z"
+ latin:moreKeys="!text/more_keys_for_z" />
+ <Key
+ latin:keyLabel="x" />
+ <Key
+ latin:keyLabel="c"
+ latin:moreKeys="!text/more_keys_for_c" />
+ <Key
+ latin:keyLabel="v"
+ latin:moreKeys="!text/more_keys_for_v" />
+ <Key
+ latin:keyLabel="b" />
+ <Key
+ latin:keyLabel="n"
+ latin:moreKeys="!text/more_keys_for_n" />
+ <Key
+ latin:keyLabel="m" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwertz1.xml b/java/res/xml/rowkeys_qwertz1.xml
new file mode 100644
index 000000000..d87f03ddc
--- /dev/null
+++ b/java/res/xml/rowkeys_qwertz1.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="q"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <Key
+ latin:keyLabel="w"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2"
+ latin:moreKeys="!text/more_keys_for_w" />
+ <Key
+ latin:keyLabel="e"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="!text/more_keys_for_e" />
+ <Key
+ latin:keyLabel="r"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4"
+ latin:moreKeys="!text/more_keys_for_r" />
+ <Key
+ latin:keyLabel="t"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5"
+ latin:moreKeys="!text/more_keys_for_t" />
+ <Key
+ latin:keyLabel="z"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6"
+ latin:moreKeys="!text/more_keys_for_z" />
+ <Key
+ latin:keyLabel="u"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7"
+ latin:moreKeys="!text/more_keys_for_u" />
+ <Key
+ latin:keyLabel="i"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="!text/more_keys_for_i" />
+ <Key
+ latin:keyLabel="o"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9"
+ latin:moreKeys="!text/more_keys_for_o" />
+ <Key
+ latin:keyLabel="p"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwertz3.xml b/java/res/xml/rowkeys_qwertz3.xml
new file mode 100644
index 000000000..9e39fe08e
--- /dev/null
+++ b/java/res/xml/rowkeys_qwertz3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="y"
+ latin:moreKeys="!text/more_keys_for_y" />
+ <Key
+ latin:keyLabel="x" />
+ <Key
+ latin:keyLabel="c"
+ latin:moreKeys="!text/more_keys_for_c" />
+ <Key
+ latin:keyLabel="v"
+ latin:moreKeys="!text/more_keys_for_v" />
+ <Key
+ latin:keyLabel="b" />
+ <Key
+ latin:keyLabel="n"
+ latin:moreKeys="!text/more_keys_for_n" />
+ <Key
+ latin:keyLabel="m" />
+</merge>
diff --git a/java/res/xml/rowkeys_south_slavic1.xml b/java/res/xml/rowkeys_south_slavic1.xml
new file mode 100644
index 000000000..6117d46f1
--- /dev/null
+++ b/java/res/xml/rowkeys_south_slavic1.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0459: "љ" CYRILLIC SMALL LETTER LJE -->
+ <Key
+ latin:keyLabel="&#x0459;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1" />
+ <!-- U+045A: "њ" CYRILLIC SMALL LETTER NJE -->
+ <Key
+ latin:keyLabel="&#x045A;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2" />
+ <!-- U+0435: "е" CYRILLIC SMALL LETTER IE -->
+ <Key
+ latin:keyLabel="&#x0435;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3"
+ latin:moreKeys="!text/more_keys_for_cyrillic_ie" />
+ <!-- U+0440: "р" CYRILLIC SMALL LETTER ER -->
+ <Key
+ latin:keyLabel="&#x0440;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4" />
+ <!-- U+0442: "т" CYRILLIC SMALL LETTER TE -->
+ <Key
+ latin:keyLabel="&#x0442;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_south_slavic_row1_6"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6" />
+ <!-- U+0443: "у" CYRILLIC SMALL LETTER U -->
+ <Key
+ latin:keyLabel="&#x0443;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7" />
+ <!-- U+0438: "и" CYRILLIC SMALL LETTER I -->
+ <Key
+ latin:keyLabel="&#x0438;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8"
+ latin:moreKeys="!text/more_keys_for_cyrillic_i" />
+ <!-- U+043E: "о" CYRILLIC SMALL LETTER O -->
+ <Key
+ latin:keyLabel="&#x043E;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9" />
+ <!-- U+043F: "п" CYRILLIC SMALL LETTER PE -->
+ <Key
+ latin:keyLabel="&#x043F;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0" />
+ <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA -->
+ <Key
+ latin:keyLabel="&#x0448;" />
+</merge>
diff --git a/java/res/xml/rowkeys_south_slavic2.xml b/java/res/xml/rowkeys_south_slavic2.xml
new file mode 100644
index 000000000..88e894053
--- /dev/null
+++ b/java/res/xml/rowkeys_south_slavic2.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0430: "а" CYRILLIC SMALL LETTER A -->
+ <Key
+ latin:keyLabel="&#x0430;" />
+ <!-- U+0441: "с" CYRILLIC SMALL LETTER ES -->
+ <Key
+ latin:keyLabel="&#x0441;" />
+ <!-- U+0434: "д" CYRILLIC SMALL LETTER DE -->
+ <Key
+ latin:keyLabel="&#x0434;" />
+ <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF -->
+ <Key
+ latin:keyLabel="&#x0444;" />
+ <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE -->
+ <Key
+ latin:keyLabel="&#x0433;" />
+ <!-- U+0445: "х" CYRILLIC SMALL LETTER HA -->
+ <Key
+ latin:keyLabel="&#x0445;" />
+ <!-- U+0458: "ј" CYRILLIC SMALL LETTER JE -->
+ <Key
+ latin:keyLabel="&#x0458;" />
+ <!-- U+043A: "к" CYRILLIC SMALL LETTER KA -->
+ <Key
+ latin:keyLabel="&#x043A;" />
+ <!-- U+043B: "л" CYRILLIC SMALL LETTER EL -->
+ <Key
+ latin:keyLabel="&#x043B;" />
+ <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE -->
+ <Key
+ latin:keyLabel="&#x0447;" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_south_slavic_row2_11" />
+</merge>
diff --git a/java/res/xml/rowkeys_south_slavic3.xml b/java/res/xml/rowkeys_south_slavic3.xml
new file mode 100644
index 000000000..b01550911
--- /dev/null
+++ b/java/res/xml/rowkeys_south_slavic3.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="!text/keylabel_for_south_slavic_row3_1" />
+ <!-- U+045F: "џ" CYRILLIC SMALL LETTER DZHE -->
+ <Key
+ latin:keyLabel="&#x045F;" />
+ <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE -->
+ <Key
+ latin:keyLabel="&#x0446;" />
+ <!-- U+0432: "в" CYRILLIC SMALL LETTER VE -->
+ <Key
+ latin:keyLabel="&#x0432;" />
+ <!-- U+0431: "б" CYRILLIC SMALL LETTER BE -->
+ <Key
+ latin:keyLabel="&#x0431;" />
+ <!-- U+043D: "н" CYRILLIC SMALL LETTER EN -->
+ <Key
+ latin:keyLabel="&#x043D;" />
+ <!-- U+043C: "м" CYRILLIC SMALL LETTER EM -->
+ <Key
+ latin:keyLabel="&#x043C;" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_south_slavic_row3_8" />
+ <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE -->
+ <Key
+ latin:keyLabel="&#x0436;" />
+</merge>
diff --git a/java/res/xml/rowkeys_spanish2.xml b/java/res/xml/rowkeys_spanish2.xml
new file mode 100644
index 000000000..4c7e57997
--- /dev/null
+++ b/java/res/xml/rowkeys_spanish2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+ <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
+ <Key
+ latin:keyLabel="&#x00F1;" />
+ </merge>
diff --git a/java/res/xml/rowkeys_symbols1.xml b/java/res/xml/rowkeys_symbols1.xml
new file mode 100644
index 000000000..6e2f92dd9
--- /dev/null
+++ b/java/res/xml/rowkeys_symbols1.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_1"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_1"
+ latin:moreKeys="!text/more_keys_for_symbols_1" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_2"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_2"
+ latin:moreKeys="!text/more_keys_for_symbols_2" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_3"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_3"
+ latin:moreKeys="!text/more_keys_for_symbols_3" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_4"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_4"
+ latin:moreKeys="!text/more_keys_for_symbols_4" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_5"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_5"
+ latin:moreKeys="!text/more_keys_for_symbols_5" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_6"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_6"
+ latin:moreKeys="!text/more_keys_for_symbols_6" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_7"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_7"
+ latin:moreKeys="!text/more_keys_for_symbols_7" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_8"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_8"
+ latin:moreKeys="!text/more_keys_for_symbols_8" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_9"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_9"
+ latin:moreKeys="!text/more_keys_for_symbols_9" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_0"
+ latin:additionalMoreKeys="!text/additional_more_keys_for_symbols_0"
+ latin:moreKeys="!text/more_keys_for_symbols_0" />
+</merge>
diff --git a/java/res/xml/rowkeys_symbols2.xml b/java/res/xml/rowkeys_symbols2.xml
new file mode 100644
index 000000000..425e20470
--- /dev/null
+++ b/java/res/xml/rowkeys_symbols2.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:languageCode="fa"
+ >
+ <!-- U+066C: "٬" ARABIC THOUSANDS SEPARATOR
+ U+066B: "٫" ARABIC DECIMAL SEPARATOR -->
+ <Key
+ latin:keyLabel="&#x066C;"
+ latin:keyHintLabel="\@"
+ latin:moreKeys="\@" />
+ <Key
+ latin:keyLabel="&#x066B;"
+ latin:keyHintLabel="#"
+ latin:moreKeys="#" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="\@" />
+ <Key
+ latin:keyLabel="#" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="currencyKeyStyle" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_percent"
+ latin:moreKeys="!text/more_keys_for_symbols_percent" />
+ <Key
+ latin:keyLabel="&amp;" />
+ <Key
+ latin:keyLabel="*"
+ latin:moreKeys="!text/more_keys_for_star" />
+ <!-- U+2013: "–" EN DASH
+ U+2014: "—" EM DASH -->
+ <Key
+ latin:keyLabel="-"
+ latin:moreKeys="_,&#x2013;,&#x2014;" />
+ <Key
+ latin:keyLabel="+"
+ latin:moreKeys="!text/more_keys_for_plus" />
+ <include
+ latin:keyboardLayout="@xml/keys_parentheses" />
+</merge>
diff --git a/java/res/xml/rowkeys_symbols3.xml b/java/res/xml/rowkeys_symbols3.xml
new file mode 100644
index 000000000..c89716bc7
--- /dev/null
+++ b/java/res/xml/rowkeys_symbols3.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_exclamation"
+ latin:moreKeys="!text/more_keys_for_symbols_exclamation" />
+ <switch>
+ <case
+ latin:languageCode="fa"
+ >
+ <!-- U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+ <Key
+ latin:keyLabel="&#x00AB;"
+ latin:code="0x00BB"
+ latin:moreKeys="!text/more_keys_for_double_quote" />
+ <Key
+ latin:keyLabel="&#x00BB;"
+ latin:code="0x00AB"
+ latin:moreKeys="!text/more_keys_for_single_quote" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="&quot;"
+ latin:moreKeys="!text/more_keys_for_double_quote" />
+ <Key
+ latin:keyLabel="\'"
+ latin:moreKeys="!text/more_keys_for_single_quote" />
+ </default>
+ </switch>
+ <Key
+ latin:keyLabel=":" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_semicolon"
+ latin:moreKeys="!text/more_keys_for_symbols_semicolon" />
+ <Key
+ latin:keyLabel="/" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_symbols_question"
+ latin:moreKeys="!text/more_keys_for_symbols_question" />
+</merge>
diff --git a/java/res/xml/rowkeys_symbols_shift1.xml b/java/res/xml/rowkeys_symbols_shift1.xml
new file mode 100644
index 000000000..fea8ae337
--- /dev/null
+++ b/java/res/xml/rowkeys_symbols_shift1.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyLabel="~" />
+ <Key
+ latin:keyLabel="`" />
+ <Key
+ latin:keyLabel="|" />
+ <!-- U+2022: "•" BULLET -->
+ <Key
+ latin:keyLabel="&#x2022;"
+ latin:moreKeys="!text/more_keys_for_bullet" />
+ <!-- U+221A: "√" SQUARE ROOT -->
+ <Key
+ latin:keyLabel="&#x221A;" />
+ <!-- U+03C0: "π" GREEK SMALL LETTER PI
+ U+03A0: "Π" GREEK CAPITAL LETTER PI -->
+ <Key
+ latin:keyLabel="&#x03C0;"
+ latin:moreKeys="&#x03A0;" />
+ <!-- U+00F7: "÷" DIVISION SIGN -->
+ <Key
+ latin:keyLabel="&#x00F7;" />
+ <!-- U+00D7: "×" MULTIPLICATION SIGN -->
+ <Key
+ latin:keyLabel="&#x00D7;" />
+ <include
+ latin:keyboardLayout="@xml/keys_curly_brackets" />
+</merge>
diff --git a/java/res/xml/rowkeys_symbols_shift2.xml b/java/res/xml/rowkeys_symbols_shift2.xml
new file mode 100644
index 000000000..3fd8aacb6
--- /dev/null
+++ b/java/res/xml/rowkeys_symbols_shift2.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Key
+ latin:keyStyle="nonSpecialBackgroundTabKeyStyle" />
+ <Key
+ latin:keyStyle="moreCurrency1KeyStyle" />
+ <Key
+ latin:keyStyle="moreCurrency2KeyStyle" />
+ <Key
+ latin:keyStyle="moreCurrency3KeyStyle" />
+ <!-- U+00B0: "°" DEGREE SIGN
+ U+2032: "′" PRIME
+ U+2033: "″" DOUBLE PRIME -->
+ <Key
+ latin:keyLabel="&#x00B0;"
+ latin:moreKeys="&#x2032;,&#x2033;" />
+ <!-- U+2191: "↑" UPWARDS ARROW
+ U+2193: "↓" DOWNWARDS ARROW
+ U+2190: "←" LEFTWARDS ARROW
+ U+2192: "→" RIGHTWARDS ARROW -->
+ <Key
+ latin:keyLabel="^"
+ latin:moreKeys="&#x2191;,&#x2193;,&#x2190;,&#x2192;" />
+ <Key
+ latin:keyLabel="_" />
+ <!-- U+2260: "≠" NOT EQUAL TO
+ U+2248: "≈" ALMOST EQUAL TO
+ U+221E: "∞" INFINITY -->
+ <Key
+ latin:keyLabel="="
+ latin:moreKeys="&#x2260;,&#x2248;,&#x221E;" />
+ <include
+ latin:keyboardLayout="@xml/keys_square_brackets" />
+</merge>
diff --git a/java/res/xml/rowkeys_symbols_shift3.xml b/java/res/xml/rowkeys_symbols_shift3.xml
new file mode 100644
index 000000000..a35af218f
--- /dev/null
+++ b/java/res/xml/rowkeys_symbols_shift3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+2122: "™" TRADE MARK SIGN -->
+ <Key
+ latin:keyLabel="&#x2122;" />
+ <!-- U+00AE: "®" REGISTERED SIGN -->
+ <Key
+ latin:keyLabel="&#x00AE;" />
+ <!-- U+00A9: "©" COPYRIGHT SIGN -->
+ <Key
+ latin:keyLabel="&#x00A9;" />
+ <!-- U+00B6: "¶" PILCROW SIGN
+ U+00A7: "§" SECTION SIGN -->
+ <Key
+ latin:keyLabel="&#x00B6;"
+ latin:moreKeys="&#x00A7;" />
+ <Key
+ latin:keyLabel="\\" />
+ <include
+ latin:keyboardLayout="@xml/keys_less_greater" />
+</merge>
diff --git a/java/res/xml/rowkeys_thai1.xml b/java/res/xml/rowkeys_thai1.xml
new file mode 100644
index 000000000..4b49da171
--- /dev/null
+++ b/java/res/xml/rowkeys_thai1.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0E0E: "ฎ" THAI CHARACTER DO CHADA -->
+ <Key
+ latin:keyLabel="&#x0E0E;" />
+ <!-- U+0E11: "ฑ" THAI CHARACTER THO NANGMONTHO -->
+ <Key
+ latin:keyLabel="&#x0E11;" />
+ <!-- U+0E18: "ธ" THAI CHARACTER THO THONG -->
+ <Key
+ latin:keyLabel="&#x0E18;" />
+ <!-- U+0E13: "ณ" THAI CHARACTER NO NEN -->
+ <Key
+ latin:keyLabel="&#x0E13;" />
+ <!-- U+0E0D: "ญ" THAI CHARACTER YO YING -->
+ <Key
+ latin:keyLabel="&#x0E0D;" />
+ <!-- U+0E10: "ฐ" THAI CHARACTER THO THAN -->
+ <Key
+ latin:keyLabel="&#x0E10;" />
+ <!-- U+0E03: "ฃ" THAI CHARACTER KHO KHUAT -->
+ <Key
+ latin:keyLabel="&#x0E03;" />
+ <!-- U+0E05: "ฅ" THAI CHARACTER KHO KHON -->
+ <Key
+ latin:keyLabel="&#x0E05;" />
+ <!-- U+0E51: "๑" THAI DIGIT ONE
+ U+0E52: "๒" THAI DIGIT TWO
+ U+0E53: "๓" THAI DIGIT THREE
+ U+0E54: "๔" THAI DIGIT FOUR
+ U+0E55: "๕" THAI DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x0E51;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x0E52;,&#x0E53;,&#x0E54;,&#x0E55;" />
+ <!-- U+0E56: "๖" THAI DIGIT SIX
+ U+0E57: "๗" THAI DIGIT SEVEN
+ U+0E58: "๘" THAI DIGIT EIGHT
+ U+0E59: "๙" THAI DIGIT NINE
+ U+0E50: "๐" THAI DIGIT ZERO -->
+ <Key
+ latin:keyLabel="&#x0E56;"
+ latin:moreKeys="!fixedColumnOrder!4,&#x0E57;,&#x0E58;,&#x0E59;,&#x0E50;" />
+ </case>
+ <default>
+ <!-- U+0E20: "ภ" THAI CHARACTER PHO SAMPHAO -->
+ <Key
+ latin:keyLabel="&#x0E20;"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="1,&#x0E51;" />
+ <!-- U+0E16: "ถ" THAI CHARACTER THO THUNG -->
+ <Key
+ latin:keyLabel="&#x0E16;"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="2,&#x0E52;" />
+ <!-- U+0E04: "ค" THAI CHARACTER KHO KHWAI -->
+ <Key
+ latin:keyLabel="&#x0E04;"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="3,&#x0E53;" />
+ <!-- U+0E15: "ต" THAI CHARACTER TO TAO -->
+ <Key
+ latin:keyLabel="&#x0E15;"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="4,&#x0E54;" />
+ <!-- U+0E08: "จ" THAI CHARACTER CHO CHAN -->
+ <Key
+ latin:keyLabel="&#x0E08;"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="5,&#x0E55;" />
+ <!-- U+0E02: "ข" THAI CHARACTER KHO KHAI -->
+ <Key
+ latin:keyLabel="&#x0E02;"
+ latin:keyHintLabel="6"
+ latin:additionalMoreKeys="6,&#x0E56;" />
+ <!-- U+0E0A: "ช" THAI CHARACTER CHO CHANG -->
+ <Key
+ latin:keyLabel="&#x0E0A;"
+ latin:keyHintLabel="7"
+ latin:additionalMoreKeys="7,&#x0E57;" />
+ <!-- U+0E23: "ร" THAI CHARACTER RO RUA
+ U+0E25: "ล" THAI CHARACTER LO LING -->
+ <Key
+ latin:keyLabel="&#x0E23;"
+ latin:moreKeys="&#x0E25;"
+ latin:keyHintLabel="8"
+ latin:additionalMoreKeys="8,&#x0E58;" />
+ <!-- U+0E19: "น" THAI CHARACTER NO NU -->
+ <Key
+ latin:keyLabel="&#x0E19;"
+ latin:keyHintLabel="9"
+ latin:additionalMoreKeys="9,&#x0E59;" />
+ <!-- U+0E22: "ย" THAI CHARACTER YO YAK -->
+ <Key
+ latin:keyLabel="&#x0E22;"
+ latin:keyHintLabel="0"
+ latin:additionalMoreKeys="0,&#x0E50;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_thai2.xml b/java/res/xml/rowkeys_thai2.xml
new file mode 100644
index 000000000..80e3563f8
--- /dev/null
+++ b/java/res/xml/rowkeys_thai2.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0E24: "ฤ" THAI CHARACTER RU -->
+ <Key
+ latin:keyLabel="&#x0E24;" />
+ <!-- U+0E06: "ฆ" THAI CHARACTER KHO RAKHANG -->
+ <Key
+ latin:keyLabel="&#x0E06;" />
+ <!-- U+0E0F: "ฏ" THAI CHARACTER TO PATAK -->
+ <Key
+ latin:keyLabel="&#x0E0F;" />
+ <!-- U+0E0C: "ฌ" THAI CHARACTER CHO CHOE -->
+ <Key
+ latin:keyLabel="&#x0E0C;" />
+ <!-- U+0E29: "ษ" THAI CHARACTER SO RUSI -->
+ <Key
+ latin:keyLabel="&#x0E29;" />
+ <!-- U+0E28: "ศ" THAI CHARACTER SO SALA -->
+ <Key
+ latin:keyLabel="&#x0E28;" />
+ <!-- U+0E0B: "ซ" THAI CHARACTER SO SO -->
+ <Key
+ latin:keyLabel="&#x0E0B;" />
+ <!-- U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT
+ U+0E45: "ๅ" THAI CHARACTER LAKKHANGYAO -->
+ <Key
+ latin:keyLabel="&#x0E3F;"
+ latin:moreKeys="&#x0E45;" />
+ <!-- U+0E46: "ๆ" THAI CHARACTER MAIYAMOK
+ U+0E2F: "ฯ" THAI CHARACTER PAIYANNOI -->
+ <Key
+ latin:keyLabel="&#x0E46;"
+ latin:moreKeys="&#x0E2F;" />
+ </case>
+ <default>
+ <!-- U+0E1F: "ฟ" THAI CHARACTER FO FAN
+ U+0E1E: "พ" THAI CHARACTER PHO PHAN -->
+ <Key
+ latin:keyLabel="&#x0E1F;"
+ latin:moreKeys="&#x0E1E;" />
+ <!-- U+0E2B: "ห" THAI CHARACTER HO HIP -->
+ <Key
+ latin:keyLabel="&#x0E2B;" />
+ <!-- U+0E01: "ก" THAI CHARACTER KO KAI -->
+ <Key
+ latin:keyLabel="&#x0E01;" />
+ <!-- U+0E14: "ด" THAI CHARACTER DO DEK -->
+ <Key
+ latin:keyLabel="&#x0E14;" />
+ <!-- U+0E2A: "ส" THAI CHARACTER SO SUA -->
+ <Key
+ latin:keyLabel="&#x0E2A;" />
+ <!-- U+0E27: "ว" THAI CHARACTER WO WAEN -->
+ <Key
+ latin:keyLabel="&#x0E27;" />
+ <!-- U+0E07: "ง" THAI CHARACTER NGO NGU -->
+ <Key
+ latin:keyLabel="&#x0E07;" />
+ <!-- U+0E30: "ะ" THAI CHARACTER SARA A
+ U+0E32: "า" THAI CHARACTER SARA AA
+ U+0E33: " ำ" THAI CHARACTER SARA AM
+ U+0E40: "เ" THAI CHARACTER SARA E
+ U+0E41: "แ" THAI CHARACTER SARA AE
+ U+0E43: "ใ" THAI CHARACTER SARA AI MAIMUAN
+ U+0E44: "ไ" THAI CHARACTER SARA AI MAIMALAI
+ U+0E42: "โ" THAI CHARACTER SARA O -->
+ <Key
+ latin:keyLabel="&#x0E30;"
+ latin:moreKeys="&#x0E32;,&#x0E33;,&#x0E40;,&#x0E41;,&#x0E43;,&#x0E44;,&#x0E42;" />
+ <!-- U+0E31: " ั" THAI CHARACTER MAI HAN-AKAT
+ U+0E34: " ิ" THAI CHARACTER SARA I
+ U+0E35: " ี" THAI CHARACTER SARA II
+ U+0E36: " ึ" THAI CHARACTER SARA UE
+ U+0E37: " ื" THAI CHARACTER SARA UEE
+ U+0E38: " ุ" THAI CHARACTER SARA U
+ U+0E39: " ู" THAI CHARACTER SARA UU -->
+ <Key
+ latin:keyLabel="&#x0E31;"
+ latin:moreKeys="&#x0E34;,&#x0E35;,&#x0E36;,&#x0E37;,&#x0E38;,&#x0E39;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_thai3.xml b/java/res/xml/rowkeys_thai3.xml
new file mode 100644
index 000000000..b8338073c
--- /dev/null
+++ b/java/res/xml/rowkeys_thai3.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <switch>
+ <case
+ latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted"
+ >
+ <!-- U+0E09: "ฉ" THAI CHARACTER CHO CHING -->
+ <Key
+ latin:keyLabel="&#x0E09;" />
+ <!-- U+0E2E: "ฮ" THAI CHARACTER HO NOKHUK -->
+ <Key
+ latin:keyLabel="&#x0E2E;" />
+ <!-- U+0E12: "ฒ" THAI CHARACTER THO PHUTHAO -->
+ <Key
+ latin:keyLabel="&#x0E12;" />
+ <!-- U+0E2C: "ฬ" THAI CHARACTER LO CHULA -->
+ <Key
+ latin:keyLabel="&#x0E2C;" />
+ <!-- U+0E26: "ฦ" THAI CHARACTER LU -->
+ <Key
+ latin:keyLabel="&#x0E26;" />
+ <!-- U+0E4C: " ์" THAI CHARACTER THANTHAKHAT
+ U+0E4D: " ํ" THAI CHARACTER NIKHAHIT
+ U+0E3A: " ฺ" THAI CHARACTER PHINTHU -->
+ <Key
+ latin:keyLabel="&#x0E4C;"
+ latin:moreKeys="&#x0E4D;,&#x0E3A;" />
+ <!-- U+0E47: " ็" THAI CHARACTER MAITAIKHU -->
+ <Key
+ latin:keyLabel="&#x0E47;" />
+ </case>
+ <default>
+ <!-- U+0E1C: "ผ" THAI CHARACTER PHO PHUNG -->
+ <Key
+ latin:keyLabel="&#x0E1C;" />
+ <!-- U+0E1B: "ป" THAI CHARACTER PO PLA
+ U+0E1A: "บ" THAI CHARACTER BO BAIMAI -->
+ <Key
+ latin:keyLabel="&#x0E1B;"
+ latin:moreKeys="&#x0E1A;" />
+ <!-- U+0E2D: "อ" THAI CHARACTER O ANG -->
+ <Key
+ latin:keyLabel="&#x0E2D;" />
+ <!-- U+0E17: "ท" THAI CHARACTER THO THAHAN -->
+ <Key
+ latin:keyLabel="&#x0E17;" />
+ <!-- U+0E21: "ม" THAI CHARACTER MO MA -->
+ <Key
+ latin:keyLabel="&#x0E21;" />
+ <!-- U+0E1D: "ฝ" THAI CHARACTER FO FA -->
+ <Key
+ latin:keyLabel="&#x0E1D;" />
+ <!-- U+0E48: " ่" THAI CHARACTER MAI EK
+ U+0E49: " ้" THAI CHARACTER MAI THO
+ U+0E4A: " ๊" THAI CHARACTER MAI TRI
+ U+0E4B: " ๋" THAI CHARACTER MAI CHATTAWA -->
+ <Key
+ latin:keyLabel="&#x0E48;"
+ latin:moreKeys="&#x0E49;,&#x0E4A;,&#x0E4B;" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rows_arabic.xml b/java/res/xml/rows_arabic.xml
new file mode 100644
index 000000000..6449af219
--- /dev/null
+++ b/java/res/xml/rows_arabic.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_arabic3"
+ latin:keyXPos="5.0%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/kbd_qwerty_row3.xml b/java/res/xml/rows_azerty.xml
index 98f0404c0..a52504c4f 100644
--- a/java/res/xml/kbd_qwerty_row3.xml
+++ b/java/res/xml/rows_azerty.xml
@@ -21,36 +21,34 @@
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty2" />
+ </Row>
<Row
latin:keyWidth="10%p"
>
<Key
latin:keyStyle="shiftKeyStyle"
latin:keyWidth="15%p"
- latin:visualInsetsRight="1%p"
- latin:keyEdgeFlags="left" />
- <Key
- latin:keyLabel="z"
- latin:popupCharacters="@string/alternates_for_z" />
- <Key
- latin:keyLabel="x" />
- <Key
- latin:keyLabel="c"
- latin:popupCharacters="@string/alternates_for_c" />
- <Key
- latin:keyLabel="v"
- latin:popupCharacters="@string/alternates_for_v" />
- <Key
- latin:keyLabel="b" />
- <Key
- latin:keyLabel="n"
- latin:popupCharacters="@string/alternates_for_n" />
- <Key
- latin:keyLabel="m" />
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_azerty3" />
<Key
latin:keyStyle="deleteKeyStyle"
- latin:keyWidth="fillBoth"
- latin:visualInsetsLeft="1%p"
- latin:keyEdgeFlags="right" />
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
</Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
</merge>
diff --git a/java/res/xml/rows_bulgarian.xml b/java/res/xml/rows_bulgarian.xml
new file mode 100644
index 000000000..883c2833d
--- /dev/null
+++ b/java/res/xml/rows_bulgarian.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian2" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="13.636%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_bulgarian_bds.xml b/java/res/xml/rows_bulgarian_bds.xml
new file mode 100644
index 000000000..b4f3f1207
--- /dev/null
+++ b/java/res/xml/rows_bulgarian_bds.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds2" />
+ </Row>
+ <Row
+ latin:keyWidth="8.711%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.8%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_bulgarian_bds3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_colemak.xml b/java/res/xml/rows_colemak.xml
new file mode 100644
index 000000000..d74c2c9ec
--- /dev/null
+++ b/java/res/xml/rows_colemak.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak1" />
+ <include
+ latin:keyboardLayout="@xml/key_colemak_colon" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_colemak3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_dvorak.xml b/java/res/xml/rows_dvorak.xml
new file mode 100644
index 000000000..8e3d071b0
--- /dev/null
+++ b/java/res/xml/rows_dvorak.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/keys_dvorak_123" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_dvorak3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_dvorak4" />
+</merge>
diff --git a/java/res/xml/rows_east_slavic.xml b/java/res/xml/rows_east_slavic.xml
new file mode 100644
index 000000000..5d3d768f3
--- /dev/null
+++ b/java/res/xml/rows_east_slavic.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<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_east_slavic1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic2" />
+ </Row>
+ <Row
+ latin:keyWidth="8.711%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.8%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_east_slavic3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_farsi.xml b/java/res/xml/rows_farsi.xml
new file mode 100644
index 000000000..cc0c526b3
--- /dev/null
+++ b/java/res/xml/rows_farsi.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_farsi3"
+ latin:keyXPos="5.0%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_georgian.xml b/java/res/xml/rows_georgian.xml
new file mode 100644
index 000000000..8c81dd007
--- /dev/null
+++ b/java/res/xml/rows_georgian.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian2"
+ latin:keyXPos="5%p" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_georgian3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_greek.xml b/java/res/xml/rows_greek.xml
new file mode 100644
index 000000000..ca6d24005
--- /dev/null
+++ b/java/res/xml/rows_greek.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/key_greek_semicolon" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek2"
+ latin:keyXPos="5%p" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_greek3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_hebrew.xml b/java/res/xml/rows_hebrew.xml
new file mode 100644
index 000000000..2d513df65
--- /dev/null
+++ b/java/res/xml/rows_hebrew.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew1"
+ latin:keyXPos="5%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hebrew3"
+ latin:keyXPos="5%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_hindi.xml b/java/res/xml/rows_hindi.xml
new file mode 100644
index 000000000..5c631ebff
--- /dev/null
+++ b/java/res/xml/rows_hindi.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi2" />
+ </Row>
+ <Row
+ latin:keyWidth="8.711%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.8%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_hindi3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_nordic.xml b/java/res/xml/rows_nordic.xml
new file mode 100644
index 000000000..3068917f5
--- /dev/null
+++ b/java/res/xml/rows_nordic.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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_nordic1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_nordic2" />
+ </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_qwerty3" />
+ <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/res/xml-fr-rCA/kbd_qwerty.xml b/java/res/xml/rows_number.xml
index 7bdfbadf1..96564e8ff 100644
--- a/java/res/xml-fr-rCA/kbd_qwerty.xml
+++ b/java/res/xml/rows_number.xml
@@ -18,10 +18,23 @@
*/
-->
-<Keyboard
+<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
- latin:keyboardLocale="fr_CA"
>
<include
- latin:keyboardLayout="@xml/kbd_rows_qwerty" />
-</Keyboard>
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_number" />
+ <switch>
+ <case
+ latin:passwordInput="true"
+ >
+ <include
+ latin:keyboardLayout="@xml/rows_number_password" />
+ </case>
+ <default>
+ <include
+ latin:keyboardLayout="@xml/rows_number_normal" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/rows_number_normal.xml b/java/res/xml/rows_number_normal.xml
new file mode 100644
index 000000000..c59e26247
--- /dev/null
+++ b/java/res/xml/rows_number_normal.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row>
+ <Key
+ latin:keyLabel="1"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="2"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="3"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyLabel="4"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="5"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="6"
+ latin:keyStyle="numKeyStyle" />
+ <switch>
+ <case
+ latin:mode="date"
+ >
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </case>
+ <case
+ latin:mode="time|datetime"
+ >
+ <Key
+ latin:keyLabel="."
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/more_keys_for_am_pm"
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </default>
+ </switch>
+ </Row>
+ <Row>
+ <Key
+ latin:keyLabel="7"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="8"
+ latin:keyStyle="numKeyStyle"/>
+ <Key
+ latin:keyLabel="9"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numSpaceKeyStyle" />
+ <Key
+ latin:keyLabel="0"
+ latin:keyStyle="numKeyStyle" />
+ <switch>
+ <case
+ latin:mode="date"
+ >
+ <Key
+ latin:keyLabel="/"
+ latin:keyStyle="numKeyStyle" />
+ </case>
+ <case
+ latin:mode="time"
+ >
+ <Key
+ latin:keyLabel=":"
+ latin:keyStyle="numKeyStyle" />
+ </case>
+ <case
+ latin:mode="datetime"
+ >
+ <!-- U+002F: "/" SOLIDUS -->
+ <Key
+ latin:code="0x002F"
+ latin:keyLabel="/ :"
+ latin:moreKeys="!embeddedMoreKey!,:"
+ latin:keyStyle="numKeyStyle" />
+ </case>
+ <default>
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numKeyStyle" />
+ </default>
+ </switch>
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/rows_number_password.xml b/java/res/xml/rows_number_password.xml
new file mode 100644
index 000000000..2e61a08ae
--- /dev/null
+++ b/java/res/xml/rows_number_password.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="10%p" />
+ <Key
+ latin:keyStyle="num1KeyStyle" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="10%p" />
+ <Key
+ latin:keyStyle="num4KeyStyle" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="10%p" />
+ <Key
+ latin:keyStyle="num7KeyStyle" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <!-- Note: This Spacer prevents the below key from being marked as a left edge key. -->
+ <Spacer
+ latin:keyWidth="10%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle" />
+ <Key
+ latin:keyStyle="num0KeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle" />
+ <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
+ <Spacer
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/rows_pcqwerty.xml b/java/res/xml/rows_pcqwerty.xml
new file mode 100644
index 000000000..a5ed74518
--- /dev/null
+++ b/java/res/xml/rows_pcqwerty.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
+ </Row>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty3"
+ latin:keyXPos="3.846%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="11.538%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty4" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_pcqwerty5" />
+</merge>
diff --git a/java/res/xml/rows_pcqwerty_symbols.xml b/java/res/xml/rows_pcqwerty_symbols.xml
new file mode 100644
index 000000000..107a4ad1f
--- /dev/null
+++ b/java/res/xml/rows_pcqwerty_symbols.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty1" />
+ </Row>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty2" />
+ </Row>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty3"
+ latin:keyXPos="3.846%p" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <Row
+ latin:keyWidth="7.692%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_pcqwerty4"
+ latin:keyXPos="11.538%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_pcqwerty5" />
+</merge>
diff --git a/java/res/xml/rows_phone.xml b/java/res/xml/rows_phone.xml
new file mode 100644
index 000000000..630b24ea4
--- /dev/null
+++ b/java/res/xml/rows_phone.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_number" />
+ <Row>
+ <Key
+ latin:keyStyle="num1KeyStyle" />
+ <Key
+ latin:keyStyle="num2KeyStyle" />
+ <Key
+ latin:keyStyle="num3KeyStyle" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="num4KeyStyle" />
+ <Key
+ latin:keyStyle="num5KeyStyle" />
+ <Key
+ latin:keyStyle="num6KeyStyle" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="num7KeyStyle" />
+ <Key
+ latin:keyStyle="num8KeyStyle" />
+ <Key
+ latin:keyStyle="num9KeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numPhoneToSymbolKeyStyle" />
+ <!-- U+0030: "0" DIGIT ZERO -->
+ <Key
+ latin:keyStyle="num0KeyStyle"
+ latin:code="0x0030"
+ latin:keyLabel="0 +"
+ latin:moreKeys="!embeddedMoreKey!,+" />
+ <Key
+ latin:keyStyle="numSpaceKeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/rows_phone_symbols.xml b/java/res/xml/rows_phone_symbols.xml
new file mode 100644
index 000000000..7841c56e5
--- /dev/null
+++ b/java/res/xml/rows_phone_symbols.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_number" />
+ <Row>
+ <Key
+ latin:keyLabel="("
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="/"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel=")"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="-"
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyLabel="N"
+ latin:keyStyle="numKeyBaseStyle" />
+ <!-- Pause is a comma. Check PhoneNumberUtils.java to see if this
+ has changed. -->
+ <Key
+ latin:keyStyle="numPauseKeyStyle" />
+ <Key
+ latin:keyLabel=","
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyLabel="."
+ latin:keyStyle="numFunctionalKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numStarKeyStyle" />
+ <!-- Wait is a semicolon. -->
+ <Key
+ latin:keyStyle="numWaitKeyStyle" />
+ <Key
+ latin:keyLabel="#"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row>
+ <Key
+ latin:keyStyle="numPhoneToNumericKeyStyle" />
+ <Key
+ latin:keyLabel="+"
+ latin:keyStyle="numKeyStyle" />
+ <Key
+ latin:keyStyle="numSpaceKeyStyle" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+</merge>
diff --git a/java/res/xml/rows_qwerty.xml b/java/res/xml/rows_qwerty.xml
new file mode 100644
index 000000000..cdd420361
--- /dev/null
+++ b/java/res/xml/rows_qwerty.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2"
+ latin:keyXPos="5%p" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_qwertz.xml b/java/res/xml/rows_qwertz.xml
new file mode 100644
index 000000000..31a147c12
--- /dev/null
+++ b/java/res/xml/rows_qwertz.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2"
+ latin:keyXPos="5%p" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_south_slavic.xml b/java/res/xml/rows_south_slavic.xml
new file mode 100644
index 000000000..05442848d
--- /dev/null
+++ b/java/res/xml/rows_south_slavic.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<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_south_slavic1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic2" />
+ </Row>
+ <Row
+ latin:keyWidth="8.711%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.8%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_south_slavic3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_spanish.xml b/java/res/xml/rows_spanish.xml
new file mode 100644
index 000000000..ecda4a4a6
--- /dev/null
+++ b/java/res/xml/rows_spanish.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_spanish2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_symbols.xml b/java/res/xml/rows_symbols.xml
new file mode 100644
index 000000000..bd1a57e75
--- /dev/null
+++ b/java/res/xml/rows_symbols.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="toMoreSymbolKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols4" />
+</merge>
diff --git a/java/res/xml/rows_symbols_shift.xml b/java/res/xml/rows_symbols_shift.xml
new file mode 100644
index 000000000..9c03d90b5
--- /dev/null
+++ b/java/res/xml/rows_symbols_shift.xml
@@ -0,0 +1,56 @@
+<?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.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <include
+ latin:keyboardLayout="@xml/key_styles_currency" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift2" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="backFromMoreSymbolKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_symbols_shift3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_symbols_shift4" />
+</merge>
diff --git a/java/res/xml/rows_thai.xml b/java/res/xml/rows_thai.xml
new file mode 100644
index 000000000..6b80df640
--- /dev/null
+++ b/java/res/xml/rows_thai.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai1" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai2"
+ latin:keyXPos="5%p" />
+ </Row>
+ <Row
+ latin:keyWidth="10%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_thai3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/spell_checker_settings.xml b/java/res/xml/spell_checker_settings.xml
new file mode 100644
index 000000000..222b98b6b
--- /dev/null
+++ b/java/res/xml/spell_checker_settings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/android_spell_checker_settings">
+ <CheckBoxPreference
+ android:key="pref_spellcheck_use_contacts"
+ android:title="@string/use_contacts_for_spellchecking_option_title"
+ android:summary="@string/use_contacts_for_spellchecking_option_summary"
+ android:persistent="true"
+ android:defaultValue="true" />
+</PreferenceScreen>
diff --git a/java/res/xml/spellchecker.xml b/java/res/xml/spellchecker.xml
new file mode 100644
index 000000000..66cd66280
--- /dev/null
+++ b/java/res/xml/spellchecker.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+
+<!-- The attributes in this XML file provide the configuration information
+ for the spell checker -->
+
+<spell-checker xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/aosp_spell_checker_service_name"
+ android:settingsActivity="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity">
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="en"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="en_US"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="en_GB"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="fr"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="de"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="it"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="es"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="ru"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="cs"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="nl"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="hr"
+ />
+ <subtype
+ android:label="@string/subtype_generic"
+ android:subtypeLocale="pt_BR"
+ />
+</spell-checker>
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
new file mode 100644
index 000000000..70e38fdb0
--- /dev/null
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.accessibility;
+
+import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
+import android.support.v4.view.accessibility.AccessibilityRecordCompat;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardView;
+
+/**
+ * Exposes a virtual view sub-tree for {@link KeyboardView} and generates
+ * {@link AccessibilityEvent}s for individual {@link Key}s.
+ * <p>
+ * A virtual sub-tree is composed of imaginary {@link View}s that are reported
+ * as a part of the view hierarchy for accessibility purposes. This enables
+ * custom views that draw complex content to report them selves as a tree of
+ * virtual views, thus conveying their logical structure.
+ * </p>
+ */
+public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat {
+ private static final String TAG = AccessibilityEntityProvider.class.getSimpleName();
+ private static final int UNDEFINED = Integer.MIN_VALUE;
+
+ private final InputMethodService mInputMethodService;
+ private final KeyCodeDescriptionMapper mKeyCodeDescriptionMapper;
+ private final AccessibilityUtils mAccessibilityUtils;
+
+ /** A map of integer IDs to {@link Key}s. */
+ private final SparseArray<Key> mVirtualViewIdToKey = new SparseArray<Key>();
+
+ /** Temporary rect used to calculate in-screen bounds. */
+ private final Rect mTempBoundsInScreen = new Rect();
+
+ /** The parent view's cached on-screen location. */
+ private final int[] mParentLocation = new int[2];
+
+ /** The virtual view identifier for the focused node. */
+ private int mAccessibilityFocusedView = UNDEFINED;
+
+ /** The current keyboard view. */
+ private KeyboardView mKeyboardView;
+
+ public AccessibilityEntityProvider(KeyboardView keyboardView, InputMethodService inputMethod) {
+ mInputMethodService = inputMethod;
+
+ mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance();
+ mAccessibilityUtils = AccessibilityUtils.getInstance();
+
+ setView(keyboardView);
+ }
+
+ /**
+ * Sets the keyboard view represented by this node provider.
+ *
+ * @param keyboardView The keyboard view to represent.
+ */
+ public void setView(KeyboardView keyboardView) {
+ mKeyboardView = keyboardView;
+ updateParentLocation();
+
+ // Since this class is constructed lazily, we might not get a subsequent
+ // call to setKeyboard() and therefore need to call it now.
+ setKeyboard(mKeyboardView.getKeyboard());
+ }
+
+ /**
+ * Sets the keyboard represented by this node provider.
+ *
+ * @param keyboard The keyboard to represent.
+ */
+ public void setKeyboard(Keyboard keyboard) {
+ assignVirtualViewIds();
+ }
+
+ /**
+ * Creates and populates an {@link AccessibilityEvent} for the specified key
+ * and event type.
+ *
+ * @param key A key on the host keyboard view.
+ * @param eventType The event type to create.
+ * @return A populated {@link AccessibilityEvent} for the key.
+ * @see AccessibilityEvent
+ */
+ public AccessibilityEvent createAccessibilityEvent(Key key, int eventType) {
+ final int virtualViewId = generateVirtualViewIdForKey(key);
+ final String keyDescription = getKeyDescription(key);
+
+ final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+ event.setPackageName(mKeyboardView.getContext().getPackageName());
+ event.setClassName(key.getClass().getName());
+ event.setContentDescription(keyDescription);
+ event.setEnabled(true);
+
+ final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event);
+ record.setSource(mKeyboardView, virtualViewId);
+
+ return event;
+ }
+
+ /**
+ * Returns an {@link AccessibilityNodeInfoCompat} representing a virtual
+ * view, i.e. a descendant of the host View, with the given <code>virtualViewId</code> or
+ * the host View itself if <code>virtualViewId</code> equals to {@link View#NO_ID}.
+ * <p>
+ * A virtual descendant is an imaginary View that is reported as a part of
+ * the view hierarchy for accessibility purposes. This enables custom views
+ * that draw complex content to report them selves as a tree of virtual
+ * views, thus conveying their logical structure.
+ * </p>
+ * <p>
+ * The implementer is responsible for obtaining an accessibility node info
+ * from the pool of reusable instances and setting the desired properties of
+ * the node info before returning it.
+ * </p>
+ *
+ * @param virtualViewId A client defined virtual view id.
+ * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual
+ * descendant or the host View.
+ * @see AccessibilityNodeInfoCompat
+ */
+ @Override
+ public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) {
+ AccessibilityNodeInfoCompat info = null;
+
+ if (virtualViewId == UNDEFINED) {
+ return null;
+ } else if (virtualViewId == View.NO_ID) {
+ // We are requested to create an AccessibilityNodeInfo describing
+ // this View, i.e. the root of the virtual sub-tree.
+ info = AccessibilityNodeInfoCompat.obtain(mKeyboardView);
+ ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info);
+
+ // Add the virtual children of the root View.
+ final Keyboard keyboard = mKeyboardView.getKeyboard();
+ final Key[] keys = keyboard.mKeys;
+ for (Key key : keys) {
+ final int childVirtualViewId = generateVirtualViewIdForKey(key);
+ info.addChild(mKeyboardView, childVirtualViewId);
+ }
+ } else {
+ // Find the view that corresponds to the given id.
+ final Key key = mVirtualViewIdToKey.get(virtualViewId);
+ if (key == null) {
+ Log.e(TAG, "Invalid virtual view ID: " + virtualViewId);
+ return null;
+ }
+
+ final String keyDescription = getKeyDescription(key);
+ final Rect boundsInParent = key.mHitBox;
+
+ // Calculate the key's in-screen bounds.
+ mTempBoundsInScreen.set(boundsInParent);
+ mTempBoundsInScreen.offset(mParentLocation[0], mParentLocation[1]);
+
+ final Rect boundsInScreen = mTempBoundsInScreen;
+
+ // Obtain and initialize an AccessibilityNodeInfo with
+ // information about the virtual view.
+ info = AccessibilityNodeInfoCompat.obtain();
+ info.setPackageName(mKeyboardView.getContext().getPackageName());
+ info.setClassName(key.getClass().getName());
+ info.setContentDescription(keyDescription);
+ info.setBoundsInParent(boundsInParent);
+ info.setBoundsInScreen(boundsInScreen);
+ info.setParent(mKeyboardView);
+ info.setSource(mKeyboardView, virtualViewId);
+ info.setBoundsInScreen(boundsInScreen);
+ info.setEnabled(true);
+ info.setClickable(true);
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+
+ if (mAccessibilityFocusedView == virtualViewId) {
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ } else {
+ info.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
+ }
+ }
+
+ return info;
+ }
+
+ /**
+ * Simulates a key press by injecting touch events into the keyboard view.
+ * This avoids the complexity of trackers and listeners within the keyboard.
+ *
+ * @param key The key to press.
+ */
+ void simulateKeyPress(Key key) {
+ final int x = key.mHitBox.centerX();
+ final int y = key.mHitBox.centerY();
+ final long downTime = SystemClock.uptimeMillis();
+ final MotionEvent downEvent = MotionEvent.obtain(
+ downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 0);
+ final MotionEvent upEvent = MotionEvent.obtain(
+ downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);
+
+ mKeyboardView.onTouchEvent(downEvent);
+ mKeyboardView.onTouchEvent(upEvent);
+ }
+
+ @Override
+ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
+ final Key key = mVirtualViewIdToKey.get(virtualViewId);
+
+ if (key == null) {
+ return false;
+ }
+
+ return performActionForKey(key, action, arguments);
+ }
+
+ /**
+ * Performs the specified accessibility action for the given key.
+ *
+ * @param key The on which to perform the action.
+ * @param action The action to perform.
+ * @param arguments The action's arguments.
+ * @return The result of performing the action, or false if the action is
+ * not supported.
+ */
+ boolean performActionForKey(Key key, int action, Bundle arguments) {
+ final int virtualViewId = generateVirtualViewIdForKey(key);
+
+ switch (action) {
+ case AccessibilityNodeInfoCompat.ACTION_CLICK:
+ simulateKeyPress(key);
+ return true;
+ case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS:
+ if (mAccessibilityFocusedView == virtualViewId) {
+ return false;
+ }
+ mAccessibilityFocusedView = virtualViewId;
+ sendAccessibilityEventForKey(
+ key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+ return true;
+ case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
+ if (mAccessibilityFocusedView != virtualViewId) {
+ return false;
+ }
+ mAccessibilityFocusedView = UNDEFINED;
+ sendAccessibilityEventForKey(
+ key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Sends an accessibility event for the given {@link Key}.
+ *
+ * @param key The key that's sending the event.
+ * @param eventType The type of event to send.
+ */
+ void sendAccessibilityEventForKey(Key key, int eventType) {
+ final AccessibilityEvent event = createAccessibilityEvent(key, eventType);
+ mAccessibilityUtils.requestSendAccessibilityEvent(event);
+ }
+
+ /**
+ * Returns the context-specific description for a {@link Key}.
+ *
+ * @param key The key to describe.
+ * @return The context-specific description of the key.
+ */
+ private String getKeyDescription(Key key) {
+ final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
+ final boolean shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo);
+ final String keyDescription = mKeyCodeDescriptionMapper.getDescriptionForKey(
+ mKeyboardView.getContext(), mKeyboardView.getKeyboard(), key, shouldObscure);
+
+ return keyDescription;
+ }
+
+ /**
+ * Assigns virtual view IDs to keyboard keys and populates the related maps.
+ */
+ private void assignVirtualViewIds() {
+ final Keyboard keyboard = mKeyboardView.getKeyboard();
+ if (keyboard == null) {
+ return;
+ }
+
+ mVirtualViewIdToKey.clear();
+
+ final Key[] keys = keyboard.mKeys;
+ for (Key key : keys) {
+ final int virtualViewId = generateVirtualViewIdForKey(key);
+ mVirtualViewIdToKey.put(virtualViewId, key);
+ }
+ }
+
+ /**
+ * Updates the parent's on-screen location.
+ */
+ private void updateParentLocation() {
+ mKeyboardView.getLocationOnScreen(mParentLocation);
+ }
+
+ /**
+ * Generates a virtual view identifier for the given key. Returned
+ * identifiers are valid until the next global layout state change.
+ *
+ * @param key The key to identify.
+ * @return A virtual view identifier.
+ */
+ private static int generateVirtualViewIdForKey(Key key) {
+ // The key x- and y-coordinates are stable between layout changes.
+ // Generate an identifier by bit-shifting the x-coordinate to the
+ // left-half of the integer and OR'ing with the y-coordinate.
+ return ((0xFFFF & key.mX) << (Integer.SIZE / 2)) | (0xFFFF & key.mY);
+ }
+}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index ae614b7e0..616b1c6d7 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -16,19 +16,21 @@
package com.android.inputmethod.accessibility;
-import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
-import android.content.SharedPreferences;
import android.inputmethodservice.InputMethodService;
+import android.media.AudioManager;
import android.os.SystemClock;
+import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.view.inputmethod.EditorInfo;
-import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
-import com.android.inputmethod.compat.AccessibilityManagerCompatWrapper;
-import com.android.inputmethod.compat.MotionEventCompatUtils;
+import com.android.inputmethod.compat.AudioManagerCompatWrapper;
+import com.android.inputmethod.compat.SettingsSecureCompatUtils;
+import com.android.inputmethod.latin.InputTypeUtils;
+import com.android.inputmethod.latin.R;
public class AccessibilityUtils {
private static final String TAG = AccessibilityUtils.class.getSimpleName();
@@ -38,8 +40,9 @@ public class AccessibilityUtils {
private static final AccessibilityUtils sInstance = new AccessibilityUtils();
+ private Context mContext;
private AccessibilityManager mAccessibilityManager;
- private AccessibilityManagerCompatWrapper mCompatManager;
+ private AudioManagerCompatWrapper mAudioManager;
/*
* Setting this constant to {@code false} will disable all keyboard
@@ -48,15 +51,14 @@ public class AccessibilityUtils {
*/
private static final boolean ENABLE_ACCESSIBILITY = true;
- public static void init(InputMethodService inputMethod, SharedPreferences prefs) {
+ public static void init(InputMethodService inputMethod) {
if (!ENABLE_ACCESSIBILITY)
return;
// These only need to be initialized if the kill switch is off.
- sInstance.initInternal(inputMethod, prefs);
- KeyCodeDescriptionMapper.init(inputMethod, prefs);
- AccessibleInputMethodServiceProxy.init(inputMethod, prefs);
- AccessibleKeyboardViewProxy.init(inputMethod, prefs);
+ sInstance.initInternal(inputMethod);
+ KeyCodeDescriptionMapper.init();
+ AccessibleKeyboardViewProxy.init(inputMethod);
}
public static AccessibilityUtils getInstance() {
@@ -67,10 +69,14 @@ public class AccessibilityUtils {
// This class is not publicly instantiable.
}
- private void initInternal(Context context, SharedPreferences prefs) {
+ private void initInternal(Context context) {
+ mContext = context;
mAccessibilityManager = (AccessibilityManager) context
.getSystemService(Context.ACCESSIBILITY_SERVICE);
- mCompatManager = new AccessibilityManagerCompatWrapper(mAccessibilityManager);
+
+ final AudioManager audioManager = (AudioManager) context
+ .getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager = new AudioManagerCompatWrapper(audioManager);
}
/**
@@ -82,10 +88,8 @@ public class AccessibilityUtils {
*/
public boolean isTouchExplorationEnabled() {
return ENABLE_ACCESSIBILITY
- && AccessibilityEventCompatUtils.supportsTouchExploration()
&& mAccessibilityManager.isEnabled()
- && !mCompatManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
+ && mAccessibilityManager.isTouchExplorationEnabled();
}
/**
@@ -99,9 +103,35 @@ public class AccessibilityUtils {
public boolean isTouchExplorationEvent(MotionEvent event) {
final int action = event.getAction();
- return action == MotionEventCompatUtils.ACTION_HOVER_ENTER
- || action == MotionEventCompatUtils.ACTION_HOVER_EXIT
- || action == MotionEventCompatUtils.ACTION_HOVER_MOVE;
+ return action == MotionEvent.ACTION_HOVER_ENTER
+ || action == MotionEvent.ACTION_HOVER_EXIT
+ || action == MotionEvent.ACTION_HOVER_MOVE;
+ }
+
+ /**
+ * Returns whether the device should obscure typed password characters.
+ * Typically this means speaking "dot" in place of non-control characters.
+ *
+ * @return {@code true} if the device should obscure password characters.
+ */
+ public boolean shouldObscureInput(EditorInfo editorInfo) {
+ if (editorInfo == null)
+ return false;
+
+ // The user can optionally force speaking passwords.
+ if (SettingsSecureCompatUtils.ACCESSIBILITY_SPEAK_PASSWORD != null) {
+ final boolean speakPassword = Settings.Secure.getInt(mContext.getContentResolver(),
+ SettingsSecureCompatUtils.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0;
+ if (speakPassword)
+ return false;
+ }
+
+ // Always speak if the user is listening through headphones.
+ if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn())
+ return false;
+
+ // Don't speak if the IME is connected to a password field.
+ return InputTypeUtils.isPasswordInputType(editorInfo.inputType);
}
/**
@@ -120,7 +150,7 @@ public class AccessibilityUtils {
// class. Instead, we're just forcing a fake AccessibilityEvent into
// the screen reader to make it speak.
final AccessibilityEvent event = AccessibilityEvent
- .obtain(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER);
+ .obtain(AccessibilityEvent.TYPE_VIEW_FOCUSED);
event.setPackageName(PACKAGE);
event.setClassName(CLASS);
@@ -130,4 +160,30 @@ public class AccessibilityUtils {
mAccessibilityManager.sendAccessibilityEvent(event);
}
+
+ /**
+ * Handles speaking the "connect a headset to hear passwords" notification
+ * when connecting to a password field.
+ *
+ * @param editorInfo The input connection's editor info attribute.
+ * @param restarting Whether the connection is being restarted.
+ */
+ public void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+ if (shouldObscureInput(editorInfo)) {
+ final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
+ speak(text);
+ }
+ }
+
+ /**
+ * Sends the specified {@link AccessibilityEvent} if accessibility is
+ * enabled. No operation if accessibility is disabled.
+ *
+ * @param event The event to send.
+ */
+ public void requestSendAccessibilityEvent(AccessibilityEvent event) {
+ if (mAccessibilityManager.isEnabled()) {
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
deleted file mode 100644
index 7199550a9..000000000
--- a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.accessibility;
-
-import android.content.SharedPreferences;
-import android.inputmethodservice.InputMethodService;
-import android.os.Looper;
-import android.os.Message;
-import android.text.TextUtils;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
-
-public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActionListener {
- private static final AccessibleInputMethodServiceProxy sInstance =
- new AccessibleInputMethodServiceProxy();
-
- /*
- * Delay for the handler event that's fired when Accessibility is on and the
- * user hovers outside of any valid keys. This is used to let the user know
- * that if they lift their finger, nothing will be typed.
- */
- private static final long DELAY_NO_HOVER_SELECTION = 250;
-
- private InputMethodService mInputMethod;
-
- private AccessibilityHandler mAccessibilityHandler;
-
- private static class AccessibilityHandler
- extends StaticInnerHandlerWrapper<AccessibleInputMethodServiceProxy> {
- private static final int MSG_NO_HOVER_SELECTION = 0;
-
- public AccessibilityHandler(AccessibleInputMethodServiceProxy outerInstance,
- Looper looper) {
- super(outerInstance, looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_NO_HOVER_SELECTION:
- getOuterInstance().notifyNoHoverSelection();
- break;
- }
- }
-
- public void postNoHoverSelection() {
- removeMessages(MSG_NO_HOVER_SELECTION);
- sendEmptyMessageDelayed(MSG_NO_HOVER_SELECTION, DELAY_NO_HOVER_SELECTION);
- }
-
- public void cancelNoHoverSelection() {
- removeMessages(MSG_NO_HOVER_SELECTION);
- }
- }
-
- public static void init(InputMethodService inputMethod, SharedPreferences prefs) {
- sInstance.initInternal(inputMethod, prefs);
- }
-
- public static AccessibleInputMethodServiceProxy getInstance() {
- return sInstance;
- }
-
- private AccessibleInputMethodServiceProxy() {
- // Not publicly instantiable.
- }
-
- private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) {
- mInputMethod = inputMethod;
- mAccessibilityHandler = new AccessibilityHandler(this, inputMethod.getMainLooper());
- }
-
- /**
- * If touch exploration is enabled, cancels the event sent by
- * {@link AccessibleInputMethodServiceProxy#onHoverExit(int)} because the
- * user is currently hovering above a key.
- */
- @Override
- public void onHoverEnter(int primaryCode) {
- mAccessibilityHandler.cancelNoHoverSelection();
- }
-
- /**
- * If touch exploration is enabled, sends a delayed event to notify the user
- * that they are not currently hovering above a key.
- */
- @Override
- public void onHoverExit(int primaryCode) {
- mAccessibilityHandler.postNoHoverSelection();
- }
-
- /**
- * When Accessibility is turned on, notifies the user that they are not
- * currently hovering above a key. By default this will speak the currently
- * entered text.
- */
- private void notifyNoHoverSelection() {
- final ExtractedText extracted = mInputMethod.getCurrentInputConnection().getExtractedText(
- new ExtractedTextRequest(), 0);
-
- if (extracted == null)
- return;
-
- final CharSequence text;
-
- if (TextUtils.isEmpty(extracted.text)) {
- text = mInputMethod.getString(R.string.spoken_no_text_entered);
- } else {
- text = mInputMethod.getString(R.string.spoken_current_text_is, extracted.text);
- }
-
- AccessibilityUtils.getInstance().speak(text);
- }
-}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java
deleted file mode 100644
index 12c59d0fc..000000000
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.accessibility;
-
-public interface AccessibleKeyboardActionListener {
- /**
- * Called when the user hovers inside a key. This is sent only when
- * Accessibility is turned on. For keys that repeat, this is only called
- * once.
- *
- * @param primaryCode the code of the key that was hovered over
- */
- public void onHoverEnter(int primaryCode);
-
- /**
- * Called when the user hovers outside a key. This is sent only when
- * Accessibility is turned on. For keys that repeat, this is only called
- * once.
- *
- * @param primaryCode the code of the key that was hovered over
- */
- public void onHoverExit(int primaryCode);
-}
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 96f7fc9f2..f6376d5f4 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -17,185 +17,279 @@
package com.android.inputmethod.accessibility;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.Log;
+import android.inputmethodservice.InputMethodService;
+import android.support.v4.view.AccessibilityDelegateCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.view.MotionEvent;
+import android.view.View;
import android.view.ViewConfiguration;
-import android.view.accessibility.AccessibilityEvent;
-import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
-import com.android.inputmethod.compat.MotionEventCompatUtils;
import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.KeyDetector;
-import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.LatinKeyboardView;
import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.latin.R;
-public class AccessibleKeyboardViewProxy {
- private static final String TAG = AccessibleKeyboardViewProxy.class.getSimpleName();
+public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat {
private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy();
- // Delay in milliseconds between key press DOWN and UP events
- private static final long DELAY_KEY_PRESS = 10;
+ private InputMethodService mInputMethod;
+ private LatinKeyboardView mView;
+ private AccessibilityEntityProvider mAccessibilityNodeProvider;
- private int mScaledEdgeSlop;
- private KeyboardView mView;
- private AccessibleKeyboardActionListener mListener;
+ private Key mLastHoverKey = null;
- private int mLastHoverKeyIndex = KeyDetector.NOT_A_KEY;
- private int mLastX = -1;
- private int mLastY = -1;
+ /**
+ * Inset in pixels to look for keys when the user's finger exits the
+ * keyboard area. See {@link ViewConfiguration#getScaledEdgeSlop()}.
+ */
+ private int mEdgeSlop;
- public static void init(Context context, SharedPreferences prefs) {
- sInstance.initInternal(context, prefs);
- sInstance.mListener = AccessibleInputMethodServiceProxy.getInstance();
+ public static void init(InputMethodService inputMethod) {
+ sInstance.initInternal(inputMethod);
}
public static AccessibleKeyboardViewProxy getInstance() {
return sInstance;
}
- public static void setView(KeyboardView view) {
- sInstance.mView = view;
- }
-
private AccessibleKeyboardViewProxy() {
// Not publicly instantiable.
}
- private void initInternal(Context context, SharedPreferences prefs) {
- final Paint paint = new Paint();
- paint.setTextAlign(Paint.Align.LEFT);
- paint.setTextSize(14.0f);
- paint.setAntiAlias(true);
- paint.setColor(Color.YELLOW);
-
- mScaledEdgeSlop = ViewConfiguration.get(context).getScaledEdgeSlop();
+ private void initInternal(InputMethodService inputMethod) {
+ mInputMethod = inputMethod;
+ mEdgeSlop = ViewConfiguration.get(inputMethod).getScaledEdgeSlop();
}
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event,
- PointerTracker tracker) {
- if (mView == null) {
- Log.e(TAG, "No keyboard view set!");
- return false;
+ /**
+ * Sets the view wrapped by this proxy.
+ *
+ * @param view The view to wrap.
+ */
+ public void setView(LatinKeyboardView view) {
+ if (view == null) {
+ // Ignore null views.
+ return;
}
- switch (event.getEventType()) {
- case AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER:
- final Key key = tracker.getKey(mLastHoverKeyIndex);
+ mView = view;
- if (key == null)
- break;
+ // Ensure that the view has an accessibility delegate.
+ ViewCompat.setAccessibilityDelegate(view, this);
- final CharSequence description = KeyCodeDescriptionMapper.getInstance()
- .getDescriptionForKey(mView.getContext(), mView.getKeyboard(), key);
-
- if (description == null)
- return false;
-
- event.getText().add(description);
-
- break;
+ if (mAccessibilityNodeProvider != null) {
+ mAccessibilityNodeProvider.setView(view);
}
+ }
- return true;
+ public void setKeyboard(Keyboard keyboard) {
+ if (mAccessibilityNodeProvider != null) {
+ mAccessibilityNodeProvider.setKeyboard(keyboard);
+ }
}
/**
- * Receives hover events when accessibility is turned on in API > 11. In
- * earlier API levels, events are manually routed from onTouchEvent.
+ * Proxy method for View.getAccessibilityNodeProvider(). This method is
+ * called in SDK version 15 and higher to obtain the virtual node hierarchy
+ * provider.
*
- * @param event The hover event.
- * @return {@code true} if the event is handled
+ * @return The accessibility node provider for the current keyboard.
*/
- public boolean onHoverEvent(MotionEvent event, PointerTracker tracker) {
- return onTouchExplorationEvent(event, tracker);
- }
-
- public boolean dispatchTouchEvent(MotionEvent event) {
- // Since touch exploration translates hover double-tap to a regular
- // single-tap, we're going to drop non-touch exploration events.
- if (!AccessibilityUtils.getInstance().isTouchExplorationEvent(event))
- return true;
-
- return false;
+ @Override
+ public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) {
+ return getAccessibilityNodeProvider();
}
/**
- * Handles touch exploration events when Accessibility is turned on.
+ * Receives hover events when accessibility is turned on in SDK versions ICS
+ * and higher.
*
- * @param event The touch exploration hover event.
- * @return {@code true} if the event was handled
+ * @param event The hover event.
+ * @return {@code true} if the event is handled
*/
- private boolean onTouchExplorationEvent(MotionEvent event, PointerTracker tracker) {
+ public boolean dispatchHoverEvent(MotionEvent event, PointerTracker tracker) {
final int x = (int) event.getX();
final int y = (int) event.getY();
+ final Key key = tracker.getKeyOn(x, y);
+ final Key previousKey = mLastHoverKey;
+
+ mLastHoverKey = key;
switch (event.getAction()) {
- case MotionEventCompatUtils.ACTION_HOVER_ENTER:
- case MotionEventCompatUtils.ACTION_HOVER_MOVE:
- final int keyIndex = tracker.getKeyIndexOn(x, y);
-
- if (keyIndex != mLastHoverKeyIndex) {
- fireKeyHoverEvent(tracker, mLastHoverKeyIndex, false);
- mLastHoverKeyIndex = keyIndex;
- mLastX = x;
- mLastY = y;
- fireKeyHoverEvent(tracker, mLastHoverKeyIndex, true);
+ case MotionEvent.ACTION_HOVER_EXIT:
+ // Make sure we're not getting an EXIT event because the user slid
+ // off the keyboard area, then force a key press.
+ if (pointInView(x, y) && (key != null)) {
+ getAccessibilityNodeProvider().simulateKeyPress(key);
}
-
- return true;
- case MotionEventCompatUtils.ACTION_HOVER_EXIT:
- final int width = mView.getWidth();
- final int height = mView.getHeight();
-
- if (x < mScaledEdgeSlop || y < mScaledEdgeSlop || x >= (width - mScaledEdgeSlop)
- || y >= (height - mScaledEdgeSlop)) {
- fireKeyHoverEvent(tracker, mLastHoverKeyIndex, false);
- mLastHoverKeyIndex = KeyDetector.NOT_A_KEY;
- mLastX = -1;
- mLastY = -1;
- } else if (mLastHoverKeyIndex != KeyDetector.NOT_A_KEY) {
- fireKeyPressEvent(tracker, mLastX, mLastY, event.getEventTime());
+ //$FALL-THROUGH$
+ case MotionEvent.ACTION_HOVER_ENTER:
+ return onHoverKey(key, event);
+ case MotionEvent.ACTION_HOVER_MOVE:
+ if (key != previousKey) {
+ return onTransitionKey(key, previousKey, event);
+ } else {
+ return onHoverKey(key, event);
}
-
- return true;
}
return false;
}
- private void fireKeyHoverEvent(PointerTracker tracker, int keyIndex, boolean entering) {
- if (mListener == null) {
- Log.e(TAG, "No accessible keyboard action listener set!");
- return;
+ /**
+ * @return A lazily-instantiated node provider for this view proxy.
+ */
+ private AccessibilityEntityProvider getAccessibilityNodeProvider() {
+ // Instantiate the provide only when requested. Since the system
+ // will call this method multiple times it is a good practice to
+ // cache the provider instance.
+ if (mAccessibilityNodeProvider == null) {
+ mAccessibilityNodeProvider = new AccessibilityEntityProvider(mView, mInputMethod);
}
+ return mAccessibilityNodeProvider;
+ }
- if (mView == null) {
- Log.e(TAG, "No keyboard view set!");
- return;
+ /**
+ * Utility method to determine whether the given point, in local
+ * coordinates, is inside the view, where the area of the view is contracted
+ * by the edge slop factor.
+ *
+ * @param localX The local x-coordinate.
+ * @param localY The local y-coordinate.
+ */
+ private boolean pointInView(int localX, int localY) {
+ return (localX >= mEdgeSlop) && (localY >= mEdgeSlop)
+ && (localX < (mView.getWidth() - mEdgeSlop))
+ && (localY < (mView.getHeight() - mEdgeSlop));
+ }
+
+ /**
+ * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT
+ * on the previous key, a HOVER_ENTER on the current key, and a HOVER_MOVE
+ * on the current key.
+ *
+ * @param currentKey The currently hovered key.
+ * @param previousKey The previously hovered key.
+ * @param event The event that triggered the transition.
+ * @return {@code true} if the event was handled.
+ */
+ private boolean onTransitionKey(Key currentKey, Key previousKey, MotionEvent event) {
+ final int savedAction = event.getAction();
+
+ event.setAction(MotionEvent.ACTION_HOVER_EXIT);
+ onHoverKey(previousKey, event);
+
+ event.setAction(MotionEvent.ACTION_HOVER_ENTER);
+ onHoverKey(currentKey, event);
+
+ event.setAction(MotionEvent.ACTION_HOVER_MOVE);
+ final boolean handled = onHoverKey(currentKey, event);
+
+ event.setAction(savedAction);
+
+ return handled;
+ }
+
+ /**
+ * Handles a hover event on a key. If {@link Key} extended View, this would
+ * be analogous to calling View.onHoverEvent(MotionEvent).
+ *
+ * @param key The currently hovered key.
+ * @param event The hover event.
+ * @return {@code true} if the event was handled.
+ */
+ private boolean onHoverKey(Key key, MotionEvent event) {
+ // Null keys can't receive events.
+ if (key == null) {
+ return false;
}
- if (keyIndex == KeyDetector.NOT_A_KEY)
- return;
+ final AccessibilityEntityProvider provider = getAccessibilityNodeProvider();
- final Key key = tracker.getKey(keyIndex);
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ provider.sendAccessibilityEventForKey(
+ key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
+ provider.performActionForKey(
+ key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ provider.sendAccessibilityEventForKey(
+ key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
+ break;
+ }
- if (key == null)
- return;
+ return true;
+ }
- if (entering) {
- mListener.onHoverEnter(key.mCode);
- mView.sendAccessibilityEvent(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER);
- } else {
- mListener.onHoverExit(key.mCode);
- mView.sendAccessibilityEvent(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_EXIT);
+ /**
+ * Notifies the user of changes in the keyboard shift state.
+ */
+ public void notifyShiftState() {
+ final Keyboard keyboard = mView.getKeyboard();
+ final KeyboardId keyboardId = keyboard.mId;
+ final int elementId = keyboardId.mElementId;
+ final Context context = mView.getContext();
+ final CharSequence text;
+
+ switch (elementId) {
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
+ text = context.getText(R.string.spoken_description_shiftmode_locked);
+ break;
+ case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+ case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
+ text = context.getText(R.string.spoken_description_shiftmode_on);
+ break;
+ default:
+ text = context.getText(R.string.spoken_description_shiftmode_off);
}
+
+ AccessibilityUtils.getInstance().speak(text);
}
- private void fireKeyPressEvent(PointerTracker tracker, int x, int y, long eventTime) {
- tracker.onDownEvent(x, y, eventTime, null);
- tracker.onUpEvent(x, y, eventTime + DELAY_KEY_PRESS, null);
+ /**
+ * Notifies the user of changes in the keyboard symbols state.
+ */
+ public void notifySymbolsState() {
+ final Keyboard keyboard = mView.getKeyboard();
+ final Context context = mView.getContext();
+ final KeyboardId keyboardId = keyboard.mId;
+ final int elementId = keyboardId.mElementId;
+ final int resId;
+
+ switch (elementId) {
+ case KeyboardId.ELEMENT_ALPHABET:
+ case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
+ resId = R.string.spoken_description_mode_alpha;
+ break;
+ case KeyboardId.ELEMENT_SYMBOLS:
+ case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
+ resId = R.string.spoken_description_mode_symbol;
+ break;
+ case KeyboardId.ELEMENT_PHONE:
+ resId = R.string.spoken_description_mode_phone;
+ break;
+ case KeyboardId.ELEMENT_PHONE_SYMBOLS:
+ resId = R.string.spoken_description_mode_phone_shift;
+ break;
+ default:
+ resId = -1;
+ }
+
+ if (resId < 0) {
+ return;
+ }
+
+ final String text = context.getString(resId);
+ AccessibilityUtils.getInstance().speak(text);
}
}
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index a31911d60..23acb8b74 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -17,8 +17,9 @@
package com.android.inputmethod.accessibility;
import android.content.Context;
-import android.content.SharedPreferences;
import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
@@ -28,6 +29,11 @@ import com.android.inputmethod.latin.R;
import java.util.HashMap;
public class KeyCodeDescriptionMapper {
+ private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName();
+
+ // The resource ID of the string spoken for obscured keys
+ private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot;
+
private static KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper();
// Map of key labels to spoken description resource IDs
@@ -36,14 +42,8 @@ public class KeyCodeDescriptionMapper {
// Map of key codes to spoken description resource IDs
private final HashMap<Integer, Integer> mKeyCodeMap;
- // Map of shifted key codes to spoken description resource IDs
- private final HashMap<Integer, Integer> mShiftedKeyCodeMap;
-
- // Map of shift-locked key codes to spoken description resource IDs
- private final HashMap<Integer, Integer> mShiftLockedKeyCodeMap;
-
- public static void init(Context context, SharedPreferences prefs) {
- sInstance.initInternal(context, prefs);
+ public static void init() {
+ sInstance.initInternal();
}
public static KeyCodeDescriptionMapper getInstance() {
@@ -53,39 +53,15 @@ public class KeyCodeDescriptionMapper {
private KeyCodeDescriptionMapper() {
mKeyLabelMap = new HashMap<CharSequence, Integer>();
mKeyCodeMap = new HashMap<Integer, Integer>();
- mShiftedKeyCodeMap = new HashMap<Integer, Integer>();
- mShiftLockedKeyCodeMap = new HashMap<Integer, Integer>();
}
- private void initInternal(Context context, SharedPreferences prefs) {
+ private void initInternal() {
// Manual label substitutions for key labels with no string resource
mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
// Symbols that most TTS engines can't speak
- mKeyCodeMap.put((int) '.', R.string.spoken_description_period);
- mKeyCodeMap.put((int) ',', R.string.spoken_description_comma);
- mKeyCodeMap.put((int) '(', R.string.spoken_description_left_parenthesis);
- mKeyCodeMap.put((int) ')', R.string.spoken_description_right_parenthesis);
- mKeyCodeMap.put((int) ':', R.string.spoken_description_colon);
- mKeyCodeMap.put((int) ';', R.string.spoken_description_semicolon);
- mKeyCodeMap.put((int) '!', R.string.spoken_description_exclamation_mark);
- mKeyCodeMap.put((int) '?', R.string.spoken_description_question_mark);
- mKeyCodeMap.put((int) '\"', R.string.spoken_description_double_quote);
- mKeyCodeMap.put((int) '\'', R.string.spoken_description_single_quote);
- mKeyCodeMap.put((int) '*', R.string.spoken_description_star);
- mKeyCodeMap.put((int) '#', R.string.spoken_description_pound);
mKeyCodeMap.put((int) ' ', R.string.spoken_description_space);
- // Non-ASCII symbols (must use escape codes!)
- mKeyCodeMap.put((int) '\u2022', R.string.spoken_description_dot);
- mKeyCodeMap.put((int) '\u221A', R.string.spoken_description_square_root);
- mKeyCodeMap.put((int) '\u03C0', R.string.spoken_description_pi);
- mKeyCodeMap.put((int) '\u0394', R.string.spoken_description_delta);
- mKeyCodeMap.put((int) '\u2122', R.string.spoken_description_trademark);
- mKeyCodeMap.put((int) '\u2105', R.string.spoken_description_care_of);
- mKeyCodeMap.put((int) '\u2026', R.string.spoken_description_ellipsis);
- mKeyCodeMap.put((int) '\u201E', R.string.spoken_description_low_double_quote);
-
// Special non-character codes defined in Keyboard
mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete);
mKeyCodeMap.put(Keyboard.CODE_ENTER, R.string.spoken_description_return);
@@ -94,12 +70,6 @@ public class KeyCodeDescriptionMapper {
mKeyCodeMap.put(Keyboard.CODE_SHORTCUT, R.string.spoken_description_mic);
mKeyCodeMap.put(Keyboard.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol);
mKeyCodeMap.put(Keyboard.CODE_TAB, R.string.spoken_description_tab);
-
- // Shifted versions of non-character codes defined in Keyboard
- mShiftedKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_shift_shifted);
-
- // Shift-locked versions of non-character codes defined in Keyboard
- mShiftLockedKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_caps_lock);
}
/**
@@ -117,30 +87,40 @@ public class KeyCodeDescriptionMapper {
* @param context The package's context.
* @param keyboard The keyboard on which the key resides.
* @param key The key from which to obtain a description.
+ * @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
* @return a character sequence describing the action performed by pressing
* the key
*/
- public CharSequence getDescriptionForKey(Context context, Keyboard keyboard, Key key) {
- if (key.mCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
- final CharSequence description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
+ public String getDescriptionForKey(Context context, Keyboard keyboard, Key key,
+ boolean shouldObscure) {
+ final int code = key.mCode;
+
+ if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
+ final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
if (description != null)
return description;
}
+ if (code == Keyboard.CODE_SHIFT) {
+ return getDescriptionForShiftKey(context, keyboard);
+ }
+
+ if (code == Keyboard.CODE_ACTION_ENTER) {
+ return getDescriptionForActionKey(context, keyboard, key);
+ }
+
if (!TextUtils.isEmpty(key.mLabel)) {
final String label = key.mLabel.toString().trim();
+ // First, attempt to map the label to a pre-defined description.
if (mKeyLabelMap.containsKey(label)) {
return context.getString(mKeyLabelMap.get(label));
- } else if (label.length() == 1
- || (keyboard.isManualTemporaryUpperCase() && !TextUtils
- .isEmpty(key.mHintLabel))) {
- return getDescriptionForKeyCode(context, keyboard, key);
- } else {
- return label;
}
- } else if (key.mCode != Keyboard.CODE_DUMMY) {
- return getDescriptionForKeyCode(context, keyboard, key);
+ }
+
+ // Just attempt to speak the description.
+ if (key.mCode != Keyboard.CODE_UNSPECIFIED) {
+ return getDescriptionForKeyCode(context, keyboard, key, shouldObscure);
}
return null;
@@ -156,36 +136,110 @@ public class KeyCodeDescriptionMapper {
* @return a character sequence describing the action performed by pressing
* the key
*/
- private CharSequence getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) {
- final KeyboardId id = keyboard.mId;
-
- if (id.isAlphabetKeyboard()) {
- return context.getString(R.string.spoken_description_to_symbol);
- } else if (id.isSymbolsKeyboard()) {
- return context.getString(R.string.spoken_description_to_alpha);
- } else if (id.isPhoneSymbolsKeyboard()) {
- return context.getString(R.string.spoken_description_to_numeric);
- } else if (id.isPhoneKeyboard()) {
- return context.getString(R.string.spoken_description_to_symbol);
- } else {
+ private String getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) {
+ final KeyboardId keyboardId = keyboard.mId;
+ final int elementId = keyboardId.mElementId;
+ final int resId;
+
+ switch (elementId) {
+ case KeyboardId.ELEMENT_ALPHABET:
+ case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
+ resId = R.string.spoken_description_to_symbol;
+ break;
+ case KeyboardId.ELEMENT_SYMBOLS:
+ case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
+ resId = R.string.spoken_description_to_alpha;
+ break;
+ case KeyboardId.ELEMENT_PHONE:
+ resId = R.string.spoken_description_to_symbol;
+ break;
+ case KeyboardId.ELEMENT_PHONE_SYMBOLS:
+ resId = R.string.spoken_description_to_numeric;
+ break;
+ default:
+ Log.e(TAG, "Missing description for keyboard element ID:" + elementId);
return null;
}
+
+ return context.getString(resId);
}
/**
- * Returns the keycode for the specified key given the current keyboard
- * state.
+ * Returns a context-sensitive description of the "Shift" key.
*
+ * @param context The package's context.
* @param keyboard The keyboard on which the key resides.
- * @param key The key from which to obtain a key code.
- * @return the key code for the specified key
+ * @return A context-sensitive description of the "Shift" key.
*/
- private int getCorrectKeyCode(Keyboard keyboard, Key key) {
- if (keyboard.isManualTemporaryUpperCase() && !TextUtils.isEmpty(key.mHintLabel)) {
- return key.mHintLabel.charAt(0);
- } else {
- return key.mCode;
+ private String getDescriptionForShiftKey(Context context, Keyboard keyboard) {
+ final KeyboardId keyboardId = keyboard.mId;
+ final int elementId = keyboardId.mElementId;
+ final int resId;
+
+ switch (elementId) {
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
+ resId = R.string.spoken_description_caps_lock;
+ break;
+ case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+ case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
+ resId = R.string.spoken_description_shift_shifted;
+ break;
+ default:
+ resId = R.string.spoken_description_shift;
+ }
+
+ return context.getString(resId);
+ }
+
+ /**
+ * Returns a context-sensitive description of the "Enter" action key.
+ *
+ * @param context The package's context.
+ * @param keyboard The keyboard on which the key resides.
+ * @param key The key to describe.
+ * @return Returns a context-sensitive description of the "Enter" action
+ * key.
+ */
+ private String getDescriptionForActionKey(Context context, Keyboard keyboard, Key key) {
+ final KeyboardId keyboardId = keyboard.mId;
+ final int actionId = keyboardId.imeActionId();
+ final int resId;
+
+ // Always use the label, if available.
+ if (!TextUtils.isEmpty(key.mLabel)) {
+ return key.mLabel.toString().trim();
+ }
+
+ // Otherwise, use the action ID.
+ switch (actionId) {
+ case EditorInfo.IME_ACTION_SEARCH:
+ resId = R.string.spoken_description_search;
+ break;
+ case EditorInfo.IME_ACTION_GO:
+ resId = R.string.label_go_key;
+ break;
+ case EditorInfo.IME_ACTION_SEND:
+ resId = R.string.label_send_key;
+ break;
+ case EditorInfo.IME_ACTION_NEXT:
+ resId = R.string.label_next_key;
+ break;
+ case EditorInfo.IME_ACTION_DONE:
+ resId = R.string.label_done_key;
+ break;
+ case EditorInfo.IME_ACTION_PREVIOUS:
+ resId = R.string.label_previous_key;
+ break;
+ default:
+ resId = R.string.spoken_description_return;
}
+
+ return context.getString(resId);
}
/**
@@ -205,20 +259,26 @@ public class KeyCodeDescriptionMapper {
* @param context The package's context.
* @param keyboard The keyboard on which the key resides.
* @param key The key from which to obtain a description.
+ * @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
* @return a character sequence describing the action performed by pressing
* the key
*/
- private CharSequence getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key) {
- final int code = getCorrectKeyCode(keyboard, key);
-
- if (keyboard.isShiftLocked() && mShiftLockedKeyCodeMap.containsKey(code)) {
- return context.getString(mShiftLockedKeyCodeMap.get(code));
- } else if (keyboard.isShiftedOrShiftLocked() && mShiftedKeyCodeMap.containsKey(code)) {
- return context.getString(mShiftedKeyCodeMap.get(code));
- } else if (mKeyCodeMap.containsKey(code)) {
+ private String getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key,
+ boolean shouldObscure) {
+ final int code = key.mCode;
+
+ // If the key description should be obscured, now is the time to do it.
+ final boolean isDefinedNonCtrl = Character.isDefined(code) && !Character.isISOControl(code);
+ if (shouldObscure && isDefinedNonCtrl) {
+ return context.getString(OBSCURED_KEY_RES_ID);
+ }
+
+ if (mKeyCodeMap.containsKey(code)) {
return context.getString(mKeyCodeMap.get(code));
- } else if (Character.isDefined(code) && !Character.isISOControl(code)) {
+ } else if (isDefinedNonCtrl) {
return Character.toString((char) code);
+ } else if (!TextUtils.isEmpty(key.mLabel)) {
+ return key.mLabel;
} else {
return context.getString(R.string.spoken_description_unknown, code);
}
diff --git a/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java b/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java
deleted file mode 100644
index 50057727a..000000000
--- a/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.view.accessibility.AccessibilityEvent;
-
-import java.lang.reflect.Field;
-
-public class AccessibilityEventCompatUtils {
- public static final int TYPE_VIEW_HOVER_ENTER = 0x80;
- public static final int TYPE_VIEW_HOVER_EXIT = 0x100;
-
- private static final Field FIELD_TYPE_VIEW_HOVER_ENTER = CompatUtils.getField(
- AccessibilityEvent.class, "TYPE_VIEW_HOVER_ENTER");
- private static final Field FIELD_TYPE_VIEW_HOVER_EXIT = CompatUtils.getField(
- AccessibilityEvent.class, "TYPE_VIEW_HOVER_EXIT");
- private static final Integer OBJ_TYPE_VIEW_HOVER_ENTER = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_TYPE_VIEW_HOVER_ENTER);
- private static final Integer OBJ_TYPE_VIEW_HOVER_EXIT = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_TYPE_VIEW_HOVER_EXIT);
-
- public static boolean supportsTouchExploration() {
- return OBJ_TYPE_VIEW_HOVER_ENTER != null && OBJ_TYPE_VIEW_HOVER_EXIT != null;
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java
deleted file mode 100644
index 4db1c7a24..000000000
--- a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.view.accessibility.AccessibilityManager;
-
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
-
-public class AccessibilityManagerCompatWrapper {
- private static final Method METHOD_getEnabledAccessibilityServiceList = CompatUtils.getMethod(
- AccessibilityManager.class, "getEnabledAccessibilityServiceList", int.class);
-
- private final AccessibilityManager mManager;
-
- public AccessibilityManagerCompatWrapper(AccessibilityManager manager) {
- mManager = manager;
- }
-
- @SuppressWarnings("unchecked")
- public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
- return (List<AccessibilityServiceInfo>) CompatUtils.invoke(mManager,
- Collections.<AccessibilityServiceInfo>emptyList(),
- METHOD_getEnabledAccessibilityServiceList, feedbackType);
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java b/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java
deleted file mode 100644
index f6afbcfe2..000000000
--- a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-public class ArraysCompatUtils {
- private static final Method METHOD_Arrays_binarySearch = CompatUtils
- .getMethod(Arrays.class, "binarySearch", int[].class, int.class, int.class, int.class);
-
- public static int binarySearch(int[] array, int startIndex, int endIndex, int value) {
- if (METHOD_Arrays_binarySearch != null) {
- final Object index = CompatUtils.invoke(null, 0, METHOD_Arrays_binarySearch,
- array, startIndex, endIndex, value);
- return (Integer)index;
- } else {
- return compatBinarySearch(array, startIndex, endIndex, value);
- }
- }
-
- /* package */ static int compatBinarySearch(int[] array, int startIndex, int endIndex,
- int value) {
- if (startIndex > endIndex) throw new IllegalArgumentException();
- if (startIndex < 0 || endIndex > array.length) throw new ArrayIndexOutOfBoundsException();
-
- final int work[] = new int[endIndex - startIndex];
- System.arraycopy(array, startIndex, work, 0, work.length);
- final int index = Arrays.binarySearch(work, value);
- if (index >= 0) {
- return index + startIndex;
- } else {
- return ~(~index + startIndex);
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java
new file mode 100644
index 000000000..b6c3e2a88
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.media.AudioManager;
+
+import java.lang.reflect.Method;
+
+public class AudioManagerCompatWrapper {
+ private static final Method METHOD_isWiredHeadsetOn = CompatUtils.getMethod(
+ AudioManager.class, "isWiredHeadsetOn");
+ private static final Method METHOD_isBluetoothA2dpOn = CompatUtils.getMethod(
+ AudioManager.class, "isBluetoothA2dpOn");
+
+ private final AudioManager mManager;
+
+ public AudioManagerCompatWrapper(AudioManager manager) {
+ mManager = manager;
+ }
+
+ /**
+ * Checks whether audio routing to the wired headset is on or off.
+ *
+ * @return true if audio is being routed to/from wired headset;
+ * false if otherwise
+ */
+ public boolean isWiredHeadsetOn() {
+ return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isWiredHeadsetOn);
+ }
+
+ /**
+ * Checks whether A2DP audio routing to the Bluetooth headset is on or off.
+ *
+ * @return true if A2DP audio is being routed to/from Bluetooth headset;
+ * false if otherwise
+ */
+ public boolean isBluetoothA2dpOn() {
+ return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isBluetoothA2dpOn);
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java
index b42633cd9..ce427e9c9 100644
--- a/java/src/com/android/inputmethod/compat/CompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/CompatUtils.java
@@ -23,8 +23,6 @@ import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
public class CompatUtils {
private static final String TAG = CompatUtils.class.getSimpleName();
@@ -32,28 +30,17 @@ public class CompatUtils {
// TODO: Can these be constants instead of literal String constants?
private static final String INPUT_METHOD_SUBTYPE_SETTINGS =
"android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
- private static final String INPUT_LANGUAGE_SELECTION =
- "com.android.inputmethod.latin.INPUT_LANGUAGE_SELECTION";
public static Intent getInputLanguageSelectionIntent(String inputMethodId,
int flagsForSubtypeSettings) {
- final String action;
- Intent intent;
- if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED
- /* android.os.Build.VERSION_CODES.HONEYCOMB */
- && android.os.Build.VERSION.SDK_INT >= 11) {
- // Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS
- action = INPUT_METHOD_SUBTYPE_SETTINGS;
- intent = new Intent(action);
- if (!TextUtils.isEmpty(inputMethodId)) {
- intent.putExtra(EXTRA_INPUT_METHOD_ID, inputMethodId);
- }
- if (flagsForSubtypeSettings > 0) {
- intent.setFlags(flagsForSubtypeSettings);
- }
- } else {
- action = INPUT_LANGUAGE_SELECTION;
- intent = new Intent(action);
+ // Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS
+ final String action = INPUT_METHOD_SUBTYPE_SETTINGS;
+ final Intent intent = new Intent(action);
+ if (!TextUtils.isEmpty(inputMethodId)) {
+ intent.putExtra(EXTRA_INPUT_METHOD_ID, inputMethodId);
+ }
+ if (flagsForSubtypeSettings > 0) {
+ intent.setFlags(flagsForSubtypeSettings);
}
return intent;
}
@@ -142,15 +129,4 @@ public class CompatUtils {
Log.e(TAG, "Exception in setFieldValue: " + e.getClass().getSimpleName());
}
}
-
- public static List<InputMethodSubtypeCompatWrapper> copyInputMethodSubtypeListToWrapper(
- Object listObject) {
- if (!(listObject instanceof List<?>)) return null;
- final List<InputMethodSubtypeCompatWrapper> subtypes =
- new ArrayList<InputMethodSubtypeCompatWrapper>();
- for (Object o: (List<?>)listObject) {
- subtypes.add(new InputMethodSubtypeCompatWrapper(o));
- }
- return subtypes;
- }
}
diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
index bcdcef7dc..08c246f8b 100644
--- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
@@ -17,86 +17,65 @@
package com.android.inputmethod.compat;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
import java.lang.reflect.Field;
public class EditorInfoCompatUtils {
- private static final Field FIELD_IME_FLAG_NAVIGATE_NEXT = CompatUtils.getField(
- EditorInfo.class, "IME_FLAG_NAVIGATE_NEXT");
- private static final Field FIELD_IME_FLAG_NAVIGATE_PREVIOUS = CompatUtils.getField(
- EditorInfo.class, "IME_FLAG_NAVIGATE_PREVIOUS");
- private static final Field FIELD_IME_ACTION_PREVIOUS = CompatUtils.getField(
- EditorInfo.class, "IME_ACTION_PREVIOUS");
- private static final Integer OBJ_IME_FLAG_NAVIGATE_NEXT = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_NEXT);
- private static final Integer OBJ_IME_FLAG_NAVIGATE_PREVIOUS = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_PREVIOUS);
- private static final Integer OBJ_IME_ACTION_PREVIOUS = (Integer) CompatUtils
- .getFieldValue(null, null, FIELD_IME_ACTION_PREVIOUS);
+ // EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean).
+ private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField(
+ EditorInfo.class, "IME_FLAG_FORCE_ASCII");
+ private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII);
- public static boolean hasFlagNavigateNext(int imeOptions) {
- if (OBJ_IME_FLAG_NAVIGATE_NEXT == null)
- return false;
- return (imeOptions & OBJ_IME_FLAG_NAVIGATE_NEXT) != 0;
+ private EditorInfoCompatUtils() {
+ // This utility class is not publicly instantiable.
}
- public static boolean hasFlagNavigatePrevious(int imeOptions) {
- if (OBJ_IME_FLAG_NAVIGATE_PREVIOUS == null)
+ public static boolean hasFlagForceAscii(int imeOptions) {
+ if (OBJ_IME_FLAG_FORCE_ASCII == null)
return false;
- return (imeOptions & OBJ_IME_FLAG_NAVIGATE_PREVIOUS) != 0;
- }
-
- public static void performEditorActionNext(InputConnection ic) {
- ic.performEditorAction(EditorInfo.IME_ACTION_NEXT);
+ return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0;
}
- public static void performEditorActionPrevious(InputConnection ic) {
- if (OBJ_IME_ACTION_PREVIOUS == null)
- return;
- ic.performEditorAction(OBJ_IME_ACTION_PREVIOUS);
- }
-
- public static String imeOptionsName(int imeOptions) {
- if (imeOptions == -1)
- return null;
+ public static String imeActionName(int imeOptions) {
final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION;
- final String action;
switch (actionId) {
- case EditorInfo.IME_ACTION_UNSPECIFIED:
- action = "actionUnspecified";
- break;
- case EditorInfo.IME_ACTION_NONE:
- action = "actionNone";
- break;
- case EditorInfo.IME_ACTION_GO:
- action = "actionGo";
- break;
- case EditorInfo.IME_ACTION_SEARCH:
- action = "actionSearch";
- break;
- case EditorInfo.IME_ACTION_SEND:
- action = "actionSend";
- break;
- case EditorInfo.IME_ACTION_NEXT:
- action = "actionNext";
- break;
- case EditorInfo.IME_ACTION_DONE:
- action = "actionDone";
- break;
- default: {
- if (OBJ_IME_ACTION_PREVIOUS != null && actionId == OBJ_IME_ACTION_PREVIOUS) {
- action = "actionPrevious";
- } else {
- action = "actionUnknown(" + actionId + ")";
- }
- break;
- }
+ case EditorInfo.IME_ACTION_UNSPECIFIED:
+ return "actionUnspecified";
+ case EditorInfo.IME_ACTION_NONE:
+ return "actionNone";
+ case EditorInfo.IME_ACTION_GO:
+ return "actionGo";
+ case EditorInfo.IME_ACTION_SEARCH:
+ return "actionSearch";
+ case EditorInfo.IME_ACTION_SEND:
+ return "actionSend";
+ case EditorInfo.IME_ACTION_NEXT:
+ return "actionNext";
+ case EditorInfo.IME_ACTION_DONE:
+ return "actionDone";
+ case EditorInfo.IME_ACTION_PREVIOUS:
+ return "actionPrevious";
+ default:
+ return "actionUnknown(" + actionId + ")";
}
+ }
+
+ public static String imeOptionsName(int imeOptions) {
+ final String action = imeActionName(imeOptions);
+ final StringBuilder flags = new StringBuilder();
if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
- return "flagNoEnterAction|" + action;
- } else {
- return action;
+ flags.append("flagNoEnterAction|");
+ }
+ if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0) {
+ flags.append("flagNavigateNext|");
+ }
+ if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0) {
+ flags.append("flagNavigatePrevious|");
+ }
+ if (hasFlagForceAscii(imeOptions)) {
+ flags.append("flagForceAscii|");
}
+ return (action != null) ? flags + action : flags.toString();
}
}
diff --git a/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java b/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java
deleted file mode 100644
index 7d00b6007..000000000
--- a/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import com.android.inputmethod.latin.EditingUtils.SelectedWord;
-
-import android.view.inputmethod.InputConnection;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-
-public class InputConnectionCompatUtils {
- private static final Class<?> CLASS_CorrectionInfo = CompatUtils
- .getClass("android.view.inputmethod.CorrectionInfo");
- private static final Class<?>[] INPUT_TYPE_CorrectionInfo = new Class<?>[] { int.class,
- CharSequence.class, CharSequence.class };
- private static final Constructor<?> CONSTRUCTOR_CorrectionInfo = CompatUtils
- .getConstructor(CLASS_CorrectionInfo, INPUT_TYPE_CorrectionInfo);
- private static final Method METHOD_InputConnection_commitCorrection = CompatUtils
- .getMethod(InputConnection.class, "commitCorrection", CLASS_CorrectionInfo);
- private static final Method METHOD_getSelectedText = CompatUtils
- .getMethod(InputConnection.class, "getSelectedText", int.class);
- private static final Method METHOD_setComposingRegion = CompatUtils
- .getMethod(InputConnection.class, "setComposingRegion", int.class, int.class);
- public static final boolean RECORRECTION_SUPPORTED;
-
- static {
- RECORRECTION_SUPPORTED = METHOD_getSelectedText != null
- && METHOD_setComposingRegion != null;
- }
-
- public static void commitCorrection(InputConnection ic, int offset, CharSequence oldText,
- CharSequence newText) {
- if (ic == null || CONSTRUCTOR_CorrectionInfo == null
- || METHOD_InputConnection_commitCorrection == null) {
- return;
- }
- Object[] args = { offset, oldText, newText };
- Object correctionInfo = CompatUtils.newInstance(CONSTRUCTOR_CorrectionInfo, args);
- if (correctionInfo != null) {
- CompatUtils.invoke(ic, null, METHOD_InputConnection_commitCorrection,
- correctionInfo);
- }
- }
-
-
- /**
- * Returns the selected text between the selStart and selEnd positions.
- */
- public static CharSequence getSelectedText(InputConnection ic, int selStart, int selEnd) {
- // Use reflection, for backward compatibility
- return (CharSequence) CompatUtils.invoke(
- ic, null, METHOD_getSelectedText, 0);
- }
-
- /**
- * Tries to set the text into composition mode if there is support for it in the framework.
- */
- public static void underlineWord(InputConnection ic, SelectedWord word) {
- // Use reflection, for backward compatibility
- // If method not found, there's nothing we can do. It still works but just wont underline
- // the word.
- CompatUtils.invoke(
- ic, null, METHOD_setComposingRegion, word.mStart, word.mEnd);
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java
deleted file mode 100644
index 8e22bbc79..000000000
--- a/java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.content.pm.ServiceInfo;
-import android.view.inputmethod.InputMethodInfo;
-
-import java.lang.reflect.Method;
-
-public class InputMethodInfoCompatWrapper {
- private final InputMethodInfo mImi;
- private static final Method METHOD_getSubtypeAt = CompatUtils.getMethod(
- InputMethodInfo.class, "getSubtypeAt", int.class);
- private static final Method METHOD_getSubtypeCount = CompatUtils.getMethod(
- InputMethodInfo.class, "getSubtypeCount");
-
- public InputMethodInfoCompatWrapper(InputMethodInfo imi) {
- mImi = imi;
- }
-
- public InputMethodInfo getInputMethodInfo() {
- return mImi;
- }
-
- public String getId() {
- return mImi.getId();
- }
-
- public String getPackageName() {
- return mImi.getPackageName();
- }
-
- public ServiceInfo getServiceInfo() {
- return mImi.getServiceInfo();
- }
-
- public int getSubtypeCount() {
- return (Integer) CompatUtils.invoke(mImi, 0, METHOD_getSubtypeCount);
- }
-
- public InputMethodSubtypeCompatWrapper getSubtypeAt(int index) {
- return new InputMethodSubtypeCompatWrapper(CompatUtils.invoke(mImi, null,
- METHOD_getSubtypeAt, index));
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
index 1cc13f249..cc10a4ed2 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
@@ -16,212 +16,56 @@
package com.android.inputmethod.compat;
-import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.Utils;
-
import android.content.Context;
import android.os.IBinder;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.ImfUtils;
import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
// TODO: Override this class with the concrete implementation if we need to take care of the
// performance.
public class InputMethodManagerCompatWrapper {
private static final String TAG = InputMethodManagerCompatWrapper.class.getSimpleName();
- private static final Method METHOD_getCurrentInputMethodSubtype =
- CompatUtils.getMethod(InputMethodManager.class, "getCurrentInputMethodSubtype");
- private static final Method METHOD_getEnabledInputMethodSubtypeList =
- CompatUtils.getMethod(InputMethodManager.class, "getEnabledInputMethodSubtypeList",
- InputMethodInfo.class, boolean.class);
- private static final Method METHOD_getShortcutInputMethodsAndSubtypes =
- CompatUtils.getMethod(InputMethodManager.class, "getShortcutInputMethodsAndSubtypes");
- private static final Method METHOD_setInputMethodAndSubtype =
- CompatUtils.getMethod(
- InputMethodManager.class, "setInputMethodAndSubtype", IBinder.class,
- String.class, InputMethodSubtypeCompatWrapper.CLASS_InputMethodSubtype);
- private static final Method METHOD_switchToLastInputMethod = CompatUtils.getMethod(
- InputMethodManager.class, "switchToLastInputMethod", IBinder.class);
+ private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod(
+ InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE);
private static final InputMethodManagerCompatWrapper sInstance =
new InputMethodManagerCompatWrapper();
- public static final boolean SUBTYPE_SUPPORTED;
-
- static {
- // This static initializer guarantees that METHOD_getShortcutInputMethodsAndSubtypes is
- // already instantiated.
- SUBTYPE_SUPPORTED = METHOD_getShortcutInputMethodsAndSubtypes != null;
- }
-
- // For the compatibility, IMM will create dummy subtypes if subtypes are not found.
- // This is required to be false if the current behavior is broken. For now, it's ok to be true.
- public static final boolean FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES =
- !InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED;
- private static final String VOICE_MODE = "voice";
- private static final String KEYBOARD_MODE = "keyboard";
-
private InputMethodManager mImm;
- private LanguageSwitcherProxy mLanguageSwitcherProxy;
- private String mLatinImePackageName;
private InputMethodManagerCompatWrapper() {
+ // This wrapper class is not publicly instantiable.
}
- public static InputMethodManagerCompatWrapper getInstance(Context context) {
+ public static InputMethodManagerCompatWrapper getInstance() {
if (sInstance.mImm == null) {
- sInstance.init(context);
+ throw new RuntimeException(TAG + ".getInstance() is called before initialization");
}
return sInstance;
}
- private synchronized void init(Context context) {
- mImm = (InputMethodManager) context.getSystemService(
- Context.INPUT_METHOD_SERVICE);
- if (context instanceof LatinIME) {
- mLatinImePackageName = context.getPackageName();
- }
- mLanguageSwitcherProxy = LanguageSwitcherProxy.getInstance();
+ public static void init(Context context) {
+ sInstance.mImm = ImfUtils.getInputMethodManager(context);
}
- public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() {
- if (!SUBTYPE_SUPPORTED) {
- return new InputMethodSubtypeCompatWrapper(
- 0, 0, mLanguageSwitcherProxy.getInputLocale().toString(), KEYBOARD_MODE, "");
- }
- Object o = CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype);
- return new InputMethodSubtypeCompatWrapper(o);
- }
-
- public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList(
- InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) {
- if (!SUBTYPE_SUPPORTED) {
- String[] languages = mLanguageSwitcherProxy.getEnabledLanguages(
- allowsImplicitlySelectedSubtypes);
- List<InputMethodSubtypeCompatWrapper> subtypeList =
- new ArrayList<InputMethodSubtypeCompatWrapper>();
- for (String lang: languages) {
- subtypeList.add(new InputMethodSubtypeCompatWrapper(0, 0, lang, KEYBOARD_MODE, ""));
- }
- return subtypeList;
- }
- Object retval = CompatUtils.invoke(mImm, null, METHOD_getEnabledInputMethodSubtypeList,
- (imi != null ? imi.getInputMethodInfo() : null), allowsImplicitlySelectedSubtypes);
- if (retval == null || !(retval instanceof List<?>) || ((List<?>)retval).isEmpty()) {
- if (!FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) {
- // Returns an empty list
- return Collections.emptyList();
- }
- // Creates dummy subtypes
- @SuppressWarnings("unused")
- List<InputMethodSubtypeCompatWrapper> subtypeList =
- new ArrayList<InputMethodSubtypeCompatWrapper>();
- InputMethodSubtypeCompatWrapper keyboardSubtype = getLastResortSubtype(KEYBOARD_MODE);
- InputMethodSubtypeCompatWrapper voiceSubtype = getLastResortSubtype(VOICE_MODE);
- if (keyboardSubtype != null) {
- subtypeList.add(keyboardSubtype);
- }
- if (voiceSubtype != null) {
- subtypeList.add(voiceSubtype);
- }
- return subtypeList;
- }
- return CompatUtils.copyInputMethodSubtypeListToWrapper(retval);
- }
-
- private InputMethodInfoCompatWrapper getLatinImeInputMethodInfo() {
- if (TextUtils.isEmpty(mLatinImePackageName))
- return null;
- return Utils.getInputMethodInfo(this, mLatinImePackageName);
- }
-
- @SuppressWarnings("unused")
- private InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) {
- if (VOICE_MODE.equals(mode) && !FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES)
- return null;
- Locale inputLocale = SubtypeSwitcher.getInstance().getInputLocale();
- if (inputLocale == null)
- return null;
- return new InputMethodSubtypeCompatWrapper(0, 0, inputLocale.toString(), mode, "");
- }
-
- public Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>
- getShortcutInputMethodsAndSubtypes() {
- Object retval = CompatUtils.invoke(mImm, null, METHOD_getShortcutInputMethodsAndSubtypes);
- if (retval == null || !(retval instanceof Map<?, ?>) || ((Map<?, ?>)retval).isEmpty()) {
- if (!FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) {
- // Returns an empty map
- return Collections.emptyMap();
- }
- // Creates dummy subtypes
- @SuppressWarnings("unused")
- InputMethodInfoCompatWrapper imi = getLatinImeInputMethodInfo();
- InputMethodSubtypeCompatWrapper voiceSubtype = getLastResortSubtype(VOICE_MODE);
- if (imi != null && voiceSubtype != null) {
- Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>
- shortcutMap =
- new HashMap<InputMethodInfoCompatWrapper,
- List<InputMethodSubtypeCompatWrapper>>();
- List<InputMethodSubtypeCompatWrapper> subtypeList =
- new ArrayList<InputMethodSubtypeCompatWrapper>();
- subtypeList.add(voiceSubtype);
- shortcutMap.put(imi, subtypeList);
- return shortcutMap;
- } else {
- return Collections.emptyMap();
- }
- }
- Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> shortcutMap =
- new HashMap<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>();
- final Map<?, ?> retvalMap = (Map<?, ?>)retval;
- for (Object key : retvalMap.keySet()) {
- if (!(key instanceof InputMethodInfo)) {
- Log.e(TAG, "Class type error.");
- return null;
- }
- shortcutMap.put(new InputMethodInfoCompatWrapper((InputMethodInfo)key),
- CompatUtils.copyInputMethodSubtypeListToWrapper(retvalMap.get(key)));
- }
- return shortcutMap;
- }
-
- public void setInputMethodAndSubtype(
- IBinder token, String id, InputMethodSubtypeCompatWrapper subtype) {
- if (subtype != null && subtype.hasOriginalObject()) {
- CompatUtils.invoke(mImm, null, METHOD_setInputMethodAndSubtype,
- token, id, subtype.getOriginalObject());
- }
+ public InputMethodSubtype getLastInputMethodSubtype() {
+ return mImm.getLastInputMethodSubtype();
}
public boolean switchToLastInputMethod(IBinder token) {
- if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) {
- return true;
- }
- return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token);
+ return mImm.switchToLastInputMethod(token);
}
- public List<InputMethodInfoCompatWrapper> getEnabledInputMethodList() {
- if (mImm == null) return null;
- List<InputMethodInfoCompatWrapper> imis = new ArrayList<InputMethodInfoCompatWrapper>();
- for (InputMethodInfo imi : mImm.getEnabledInputMethodList()) {
- imis.add(new InputMethodInfoCompatWrapper(imi));
- }
- return imis;
+ public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
+ return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token,
+ onlyCurrentIme);
}
public void showInputMethodPicker() {
- if (mImm == null) return;
mImm.showInputMethodPicker();
}
}
diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
deleted file mode 100644
index ec7250c2a..000000000
--- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.inputmethodservice.InputMethodService;
-// import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-
-public class InputMethodServiceCompatWrapper extends InputMethodService {
- // CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10
- // or previous. Note that InputMethodSubtype was added in the API level 11.
- // For the API level 11 or later, LatinIME should override onCurrentInputMethodSubtypeChanged().
- // For the API level 10 or previous, we handle the "subtype changed" events by ourselves
- // without having support from framework -- onCurrentInputMethodSubtypeChanged().
- public static final boolean CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED = false;
-
- private InputMethodManagerCompatWrapper mImm;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mImm = InputMethodManagerCompatWrapper.getInstance(this);
- }
-
- // When the API level is 10 or previous, notifyOnCurrentInputMethodSubtypeChanged should
- // handle the event the current subtype was changed. LatinIME calls
- // notifyOnCurrentInputMethodSubtypeChanged every time LatinIME
- // changes the current subtype.
- // This call is required to let LatinIME itself know a subtype changed
- // event when the API level is 10 or previous.
- @SuppressWarnings("unused")
- public void notifyOnCurrentInputMethodSubtypeChanged(InputMethodSubtypeCompatWrapper subtype) {
- // Do nothing when the API level is 11 or later
- // and FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES is not true
- if (CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED && !InputMethodManagerCompatWrapper.
- FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) {
- return;
- }
- if (subtype == null) {
- subtype = mImm.getCurrentInputMethodSubtype();
- }
- if (subtype != null) {
- if (!InputMethodManagerCompatWrapper.FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES
- && !subtype.isDummy()) return;
- if (!InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) {
- LanguageSwitcherProxy.getInstance().setLocale(subtype.getLocale());
- }
- SubtypeSwitcher.getInstance().updateSubtype(subtype);
- }
- }
-
- //////////////////////////////////////
- // Functions using API v11 or later //
- //////////////////////////////////////
- /*@Override
- public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
- // Do nothing when the API level is 10 or previous
- if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) return;
- SubtypeSwitcher.getInstance().updateSubtype(
- new InputMethodSubtypeCompatWrapper(subtype));
- }*/
-
- protected static void setTouchableRegionCompat(InputMethodService.Insets outInsets,
- int x, int y, int width, int height) {
- //outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION;
- //outInsets.touchableRegion.set(x, y, width, height);
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java
deleted file mode 100644
index 667d86c42..000000000
--- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import com.android.inputmethod.latin.LatinImeLogger;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-// TODO: Override this class with the concrete implementation if we need to take care of the
-// performance.
-public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper {
- private static final boolean DBG = LatinImeLogger.sDBG;
- private static final String TAG = InputMethodSubtypeCompatWrapper.class.getSimpleName();
- private static final String DEFAULT_LOCALE = "en_US";
- private static final String DEFAULT_MODE = "keyboard";
-
- public static final Class<?> CLASS_InputMethodSubtype =
- CompatUtils.getClass("android.view.inputmethod.InputMethodSubtype");
- private static final Method METHOD_getNameResId =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "getNameResId");
- private static final Method METHOD_getIconResId =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "getIconResId");
- private static final Method METHOD_getLocale =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "getLocale");
- private static final Method METHOD_getMode =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "getMode");
- private static final Method METHOD_getExtraValue =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValue");
- private static final Method METHOD_containsExtraValueKey =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "containsExtraValueKey", String.class);
- private static final Method METHOD_getExtraValueOf =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValueOf", String.class);
- private static final Method METHOD_isAuxiliary =
- CompatUtils.getMethod(CLASS_InputMethodSubtype, "isAuxiliary");
-
- private final int mDummyNameResId;
- private final int mDummyIconResId;
- private final String mDummyLocale;
- private final String mDummyMode;
- private final String mDummyExtraValues;
-
- public InputMethodSubtypeCompatWrapper(Object subtype) {
- super((CLASS_InputMethodSubtype != null && CLASS_InputMethodSubtype.isInstance(subtype))
- ? subtype : null);
- mDummyNameResId = 0;
- mDummyIconResId = 0;
- mDummyLocale = DEFAULT_LOCALE;
- mDummyMode = DEFAULT_MODE;
- mDummyExtraValues = "";
- }
-
- // Constructor for creating a dummy subtype.
- public InputMethodSubtypeCompatWrapper(int nameResId, int iconResId, String locale,
- String mode, String extraValues) {
- super(null);
- if (DBG) {
- Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper");
- }
- mDummyNameResId = nameResId;
- mDummyIconResId = iconResId;
- mDummyLocale = locale != null ? locale : "";
- mDummyMode = mode != null ? mode : "";
- mDummyExtraValues = extraValues != null ? extraValues : "";
- }
-
- public int getNameResId() {
- if (mObj == null) return mDummyNameResId;
- return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getNameResId);
- }
-
- public int getIconResId() {
- if (mObj == null) return mDummyIconResId;
- return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getIconResId);
- }
-
- public String getLocale() {
- if (mObj == null) return mDummyLocale;
- final String s = (String)CompatUtils.invoke(mObj, null, METHOD_getLocale);
- if (TextUtils.isEmpty(s)) return DEFAULT_LOCALE;
- return s;
- }
-
- public String getMode() {
- if (mObj == null) return mDummyMode;
- String s = (String)CompatUtils.invoke(mObj, null, METHOD_getMode);
- if (TextUtils.isEmpty(s)) return DEFAULT_MODE;
- return s;
- }
-
- public String getExtraValue() {
- if (mObj == null) return mDummyExtraValues;
- return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValue);
- }
-
- public boolean containsExtraValueKey(String key) {
- return (Boolean)CompatUtils.invoke(mObj, false, METHOD_containsExtraValueKey, key);
- }
-
- public String getExtraValueOf(String key) {
- return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValueOf, key);
- }
-
- public boolean isAuxiliary() {
- return (Boolean)CompatUtils.invoke(mObj, false, METHOD_isAuxiliary);
- }
-
- public boolean isDummy() {
- return !hasOriginalObject();
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof InputMethodSubtypeCompatWrapper) {
- InputMethodSubtypeCompatWrapper subtype = (InputMethodSubtypeCompatWrapper)o;
- if (mObj == null) {
- // easy check of dummy subtypes
- return (mDummyNameResId == subtype.mDummyNameResId
- && mDummyIconResId == subtype.mDummyIconResId
- && mDummyLocale.equals(subtype.mDummyLocale)
- && mDummyMode.equals(subtype.mDummyMode)
- && mDummyExtraValues.equals(subtype.mDummyExtraValues));
- }
- return mObj.equals(subtype.getOriginalObject());
- } else {
- return mObj.equals(o);
- }
- }
-
- @Override
- public int hashCode() {
- if (mObj == null) {
- return hashCodeInternal(mDummyNameResId, mDummyIconResId, mDummyLocale,
- mDummyMode, mDummyExtraValues);
- }
- return mObj.hashCode();
- }
-
- private static int hashCodeInternal(int nameResId, int iconResId, String locale,
- String mode, String extraValue) {
- return Arrays
- .hashCode(new Object[] { nameResId, iconResId, locale, mode, extraValue });
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java
deleted file mode 100644
index 6c2f0f799..000000000
--- a/java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.text.InputType;
-
-import java.lang.reflect.Field;
-
-public class InputTypeCompatUtils {
- private static final Field FIELD_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS =
- CompatUtils.getField(InputType.class, "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS");
- private static final Field FIELD_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD = CompatUtils
- .getField(InputType.class, "TYPE_TEXT_VARIATION_WEB_PASSWORD");
- private static final Field FIELD_InputType_TYPE_NUMBER_VARIATION_PASSWORD = CompatUtils
- .getField(InputType.class, "TYPE_NUMBER_VARIATION_PASSWORD");
- private static final Integer OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS =
- (Integer) CompatUtils.getFieldValue(null, null,
- FIELD_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS);
- private static final Integer OBJ_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD =
- (Integer) CompatUtils.getFieldValue(null, null,
- FIELD_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD);
- private static final Integer OBJ_InputType_TYPE_NUMBER_VARIATION_PASSWORD =
- (Integer) CompatUtils.getFieldValue(null, null,
- FIELD_InputType_TYPE_NUMBER_VARIATION_PASSWORD);
- private static final int WEB_TEXT_PASSWORD_INPUT_TYPE;
- private static final int WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE;
- private static final int NUMBER_PASSWORD_INPUT_TYPE;
- private static final int TEXT_PASSWORD_INPUT_TYPE =
- InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
- private static final int TEXT_VISIBLE_PASSWORD_INPUT_TYPE =
- InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
-
- static {
- WEB_TEXT_PASSWORD_INPUT_TYPE =
- OBJ_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD != null
- ? InputType.TYPE_CLASS_TEXT | OBJ_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD
- : 0;
- WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE =
- OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != null
- ? InputType.TYPE_CLASS_TEXT
- | OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS
- : 0;
- NUMBER_PASSWORD_INPUT_TYPE =
- OBJ_InputType_TYPE_NUMBER_VARIATION_PASSWORD != null
- ? InputType.TYPE_CLASS_NUMBER | OBJ_InputType_TYPE_NUMBER_VARIATION_PASSWORD
- : 0;
- }
-
- private static boolean isWebEditTextInputType(int inputType) {
- return inputType == (InputType.TYPE_CLASS_TEXT
- | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
- }
-
- private static boolean isWebPasswordInputType(int inputType) {
- return WEB_TEXT_PASSWORD_INPUT_TYPE != 0
- && inputType == WEB_TEXT_PASSWORD_INPUT_TYPE;
- }
-
- private static boolean isWebEmailAddressInputType(int inputType) {
- return WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE != 0
- && inputType == WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE;
- }
-
- private static boolean isNumberPasswordInputType(int inputType) {
- return NUMBER_PASSWORD_INPUT_TYPE != 0
- && inputType == NUMBER_PASSWORD_INPUT_TYPE;
- }
-
- private static boolean isTextPasswordInputType(int inputType) {
- return inputType == TEXT_PASSWORD_INPUT_TYPE;
- }
-
- private static boolean isWebEmailAddressVariation(int variation) {
- return OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != null
- && variation == OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
- }
-
- public static boolean isEmailVariation(int variation) {
- return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
- || isWebEmailAddressVariation(variation);
- }
-
- public static boolean isWebInputType(int inputType) {
- final int maskedInputType =
- inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
- return isWebEditTextInputType(maskedInputType) || isWebPasswordInputType(maskedInputType)
- || isWebEmailAddressInputType(maskedInputType);
- }
-
- // Please refer to TextView.isPasswordInputType
- public static boolean isPasswordInputType(int inputType) {
- final int maskedInputType =
- inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
- return isTextPasswordInputType(maskedInputType) || isWebPasswordInputType(maskedInputType)
- || isNumberPasswordInputType(maskedInputType);
- }
-
- // Please refer to TextView.isVisiblePasswordInputType
- public static boolean isVisiblePasswordInputType(int inputType) {
- final int maskedInputType =
- inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION);
- return maskedInputType == TEXT_VISIBLE_PASSWORD_INPUT_TYPE;
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/LinearLayoutCompatUtils.java b/java/src/com/android/inputmethod/compat/LinearLayoutCompatUtils.java
deleted file mode 100644
index 674cbe74b..000000000
--- a/java/src/com/android/inputmethod/compat/LinearLayoutCompatUtils.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.compat;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-
-import java.lang.reflect.Field;
-
-public class LinearLayoutCompatUtils {
- private static final String TAG = LinearLayoutCompatUtils.class.getSimpleName();
-
- private static final Class<?> CLASS_R_STYLEABLE = CompatUtils.getClass(
- "com.android.internal.R$styleable");
- private static final Field STYLEABLE_VIEW = CompatUtils.getField(
- CLASS_R_STYLEABLE, "View");
- private static final Field STYLEABLE_VIEW_BACKGROUND = CompatUtils.getField(
- CLASS_R_STYLEABLE, "View_background");
- private static final Object VALUE_STYLEABLE_VIEW = CompatUtils.getFieldValue(
- null, null, STYLEABLE_VIEW);
- private static final Integer VALUE_STYLEABLE_VIEW_BACKGROUND =
- (Integer)CompatUtils.getFieldValue(null, null, STYLEABLE_VIEW_BACKGROUND);
-
- public static Drawable getBackgroundDrawable(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- if (!(VALUE_STYLEABLE_VIEW instanceof int[]) || VALUE_STYLEABLE_VIEW_BACKGROUND == null) {
- Log.w(TAG, "Can't get View background attribute using reflection");
- return null;
- }
-
- final int[] styleableView = (int[])VALUE_STYLEABLE_VIEW;
- final TypedArray a = context.obtainStyledAttributes(
- attrs, styleableView, defStyleAttr, defStyleRes);
- final Drawable background = a.getDrawable(VALUE_STYLEABLE_VIEW_BACKGROUND);
- a.recycle();
- return background;
- }
-}
diff --git a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java b/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java
index 65949357f..1b79992f0 100644
--- a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java
@@ -16,24 +16,19 @@
package com.android.inputmethod.compat;
-import android.util.Log;
+import java.lang.reflect.Field;
-public abstract class AbstractCompatWrapper {
- private static final String TAG = AbstractCompatWrapper.class.getSimpleName();
- protected final Object mObj;
+public class SettingsSecureCompatUtils {
+ private static final Field FIELD_ACCESSIBILITY_SPEAK_PASSWORD = CompatUtils.getField(
+ android.provider.Settings.Secure.class, "ACCESSIBILITY_SPEAK_PASSWORD");
- public AbstractCompatWrapper(Object obj) {
- if (obj == null) {
- Log.e(TAG, "Invalid input to AbstructCompatWrapper");
- }
- mObj = obj;
+ private SettingsSecureCompatUtils() {
+ // This class is non-instantiable.
}
- public Object getOriginalObject() {
- return mObj;
- }
-
- public boolean hasOriginalObject() {
- return mObj != null;
- }
+ /**
+ * Whether to speak passwords while in accessibility mode.
+ */
+ public static final String ACCESSIBILITY_SPEAK_PASSWORD = (String) CompatUtils.getFieldValue(
+ null, null, FIELD_ACCESSIBILITY_SPEAK_PASSWORD);
}
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index 4929dd948..a0f48d24c 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.compat;
+import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestionSpanPickedNotificationReceiver;
@@ -24,19 +25,21 @@ import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
+import android.util.Log;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Locale;
public class SuggestionSpanUtils {
+ private static final String TAG = SuggestionSpanUtils.class.getSimpleName();
// TODO: Use reflection to get field values
public static final String ACTION_SUGGESTION_PICKED =
"android.text.style.SUGGESTION_PICKED";
public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
- public static final int SUGGESTION_MAX_SIZE = 5;
public static final boolean SUGGESTION_SPAN_IS_SUPPORTED;
private static final Class<?> CLASS_SuggestionSpan = CompatUtils
@@ -45,15 +48,68 @@ public class SuggestionSpanUtils {
Context.class, Locale.class, String[].class, int.class, Class.class };
private static final Constructor<?> CONSTRUCTOR_SuggestionSpan = CompatUtils
.getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan);
+ public static final Field FIELD_FLAG_EASY_CORRECT =
+ CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_EASY_CORRECT");
+ public static final Field FIELD_FLAG_MISSPELLED =
+ CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_MISSPELLED");
+ public static final Field FIELD_FLAG_AUTO_CORRECTION =
+ CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION");
+ public static final Field FIELD_SUGGESTIONS_MAX_SIZE
+ = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE");
+ public static final Integer OBJ_FLAG_EASY_CORRECT = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_FLAG_EASY_CORRECT);
+ public static final Integer OBJ_FLAG_MISSPELLED = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_FLAG_MISSPELLED);
+ public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);
+ public static final Integer OBJ_SUGGESTIONS_MAX_SIZE = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE);
+
static {
SUGGESTION_SPAN_IS_SUPPORTED =
CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null;
+ if (LatinImeLogger.sDBG) {
+ if (SUGGESTION_SPAN_IS_SUPPORTED
+ && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null
+ || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null)) {
+ throw new RuntimeException("Field is accidentially null.");
+ }
+ }
+ }
+
+ private SuggestionSpanUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
+ Context context, CharSequence text) {
+ if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null
+ || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null
+ || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null) {
+ return text;
+ }
+ final Spannable spannable = text instanceof Spannable
+ ? (Spannable) text : new SpannableString(text);
+ final Object[] args =
+ { context, null, new String[] {}, (int)OBJ_FLAG_AUTO_CORRECTION,
+ (Class<?>) SuggestionSpanPickedNotificationReceiver.class };
+ final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args);
+ if (ss == null) {
+ Log.w(TAG, "Suggestion span was not created.");
+ return text;
+ }
+ spannable.setSpan(ss, 0, text.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
+ return spannable;
}
public static CharSequence getTextWithSuggestionSpan(Context context,
- CharSequence pickedWord, SuggestedWords suggestedWords) {
- if (TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null
- || suggestedWords == null || suggestedWords.size() == 0) {
+ CharSequence pickedWord, SuggestedWords suggestedWords, boolean dictionaryAvailable) {
+ if (!dictionaryAvailable || TextUtils.isEmpty(pickedWord)
+ || CONSTRUCTOR_SuggestionSpan == null
+ || suggestedWords == null || suggestedWords.size() == 0
+ || suggestedWords.mIsPrediction || suggestedWords.mIsPunctuationSuggestions
+ || OBJ_SUGGESTIONS_MAX_SIZE == null) {
return pickedWord;
}
@@ -64,16 +120,21 @@ public class SuggestionSpanUtils {
spannable = new SpannableString(pickedWord);
}
final ArrayList<String> suggestionsList = new ArrayList<String>();
+ boolean sameAsTyped = false;
for (int i = 0; i < suggestedWords.size(); ++i) {
- if (suggestionsList.size() >= SUGGESTION_MAX_SIZE) {
+ if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) {
break;
}
final CharSequence word = suggestedWords.getWord(i);
if (!TextUtils.equals(pickedWord, word)) {
suggestionsList.add(word.toString());
+ } else if (i == 0) {
+ sameAsTyped = true;
}
}
+ // TODO: We should avoid adding suggestion span candidates that came from the bigram
+ // prediction.
final Object[] args =
{ context, null, suggestionsList.toArray(new String[suggestionsList.size()]), 0,
(Class<?>) SuggestionSpanPickedNotificationReceiver.class };
diff --git a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
new file mode 100644
index 000000000..e5f9db27c
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.view.textservice.SuggestionsInfo;
+
+import java.lang.reflect.Field;
+
+public class SuggestionsInfoCompatUtils {
+ private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = CompatUtils.getField(
+ SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS");
+ private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = (Integer) CompatUtils
+ .getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);
+ private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS =
+ OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null
+ ? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0;
+
+ private SuggestionsInfoCompatUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ /**
+ * Returns the flag value of the attributes of the suggestions that can be obtained by
+ * {@link SuggestionsInfo#getSuggestionsAttributes()}: this tells that the text service thinks
+ * the result suggestions include highly recommended ones.
+ */
+ public static int getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() {
+ return RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS;
+ }
+}
diff --git a/java/src/com/android/inputmethod/deprecated/LanguageSwitcherProxy.java b/java/src/com/android/inputmethod/deprecated/LanguageSwitcherProxy.java
deleted file mode 100644
index 290e6b554..000000000
--- a/java/src/com/android/inputmethod/deprecated/LanguageSwitcherProxy.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.deprecated;
-
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.deprecated.languageswitcher.LanguageSwitcher;
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.Settings;
-
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-
-import java.util.Locale;
-
-// This class is used only when the IME doesn't use method.xml for language switching.
-public class LanguageSwitcherProxy implements SharedPreferences.OnSharedPreferenceChangeListener {
- private static final LanguageSwitcherProxy sInstance = new LanguageSwitcherProxy();
- private LatinIME mService;
- private LanguageSwitcher mLanguageSwitcher;
- private SharedPreferences mPrefs;
-
- public static LanguageSwitcherProxy getInstance() {
- if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return null;
- return sInstance;
- }
-
- public static void init(LatinIME service, SharedPreferences prefs) {
- if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return;
- final Configuration conf = service.getResources().getConfiguration();
- sInstance.mLanguageSwitcher = new LanguageSwitcher(service);
- sInstance.mLanguageSwitcher.loadLocales(prefs, conf.locale);
- sInstance.mPrefs = prefs;
- sInstance.mService = service;
- prefs.registerOnSharedPreferenceChangeListener(sInstance);
- }
-
- public static void onConfigurationChanged(Configuration conf) {
- if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return;
- sInstance.mLanguageSwitcher.onConfigurationChanged(conf, sInstance.mPrefs);
- }
-
- public static void loadSettings() {
- if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return;
- sInstance.mLanguageSwitcher.loadLocales(sInstance.mPrefs, null);
- }
-
- public int getLocaleCount() {
- return mLanguageSwitcher.getLocaleCount();
- }
-
- public String[] getEnabledLanguages(boolean allowImplicitlySelectedLanguages) {
- return mLanguageSwitcher.getEnabledLanguages(allowImplicitlySelectedLanguages);
- }
-
- public Locale getInputLocale() {
- return mLanguageSwitcher.getInputLocale();
- }
-
- public void setLocale(String localeStr) {
- mLanguageSwitcher.setLocale(localeStr);
- mLanguageSwitcher.persist(mPrefs);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- // PREF_SELECTED_LANGUAGES: enabled input subtypes
- // PREF_INPUT_LANGUAGE: current input subtype
- if (key.equals(Settings.PREF_SELECTED_LANGUAGES)
- || key.equals(Settings.PREF_INPUT_LANGUAGE)) {
- mLanguageSwitcher.loadLocales(prefs, null);
- if (mService != null) {
- mService.onRefreshKeyboard();
- }
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
deleted file mode 100644
index 85993ea4d..000000000
--- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * Copyright (C) 2010 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.deprecated;
-
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.deprecated.voice.FieldContext;
-import com.android.inputmethod.deprecated.voice.Hints;
-import com.android.inputmethod.deprecated.voice.SettingsUtil;
-import com.android.inputmethod.deprecated.voice.VoiceInput;
-import com.android.inputmethod.deprecated.voice.VoiceInputLogger;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.latin.EditingUtils;
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.LatinIME.UIHandler;
-import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.Utils;
-
-import android.app.AlertDialog;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.IBinder;
-import android.preference.PreferenceManager;
-import android.provider.Browser;
-import android.speech.SpeechRecognizer;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextUtils;
-import android.text.method.LinkMovementMethod;
-import android.text.style.URLSpan;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class VoiceProxy implements VoiceInput.UiListener {
- private static final VoiceProxy sInstance = new VoiceProxy();
-
- public static final boolean VOICE_INSTALLED = true;
- private static final boolean ENABLE_VOICE_BUTTON = true;
- private static final String PREF_VOICE_MODE = "voice_mode";
- // Whether or not the user has used voice input before (and thus, whether to show the
- // first-run warning dialog or not).
- private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input";
- // Whether or not the user has used voice input from an unsupported locale UI before.
- // For example, the user has a Chinese UI but activates voice input.
- private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE =
- "has_used_voice_input_unsupported_locale";
- private static final int RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO = 6;
- // TODO: Adjusted on phones for now
- private static final int RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP = 244;
-
- private static final String TAG = VoiceProxy.class.getSimpleName();
- private static final boolean DEBUG = LatinImeLogger.sDBG;
-
- private boolean mAfterVoiceInput;
- private boolean mHasUsedVoiceInput;
- private boolean mHasUsedVoiceInputUnsupportedLocale;
- private boolean mImmediatelyAfterVoiceInput;
- private boolean mIsShowingHint;
- private boolean mLocaleSupportedForVoiceInput;
- private boolean mPasswordText;
- private boolean mRecognizing;
- private boolean mShowingVoiceSuggestions;
- private boolean mVoiceButtonEnabled;
- private boolean mVoiceButtonOnPrimary;
- private boolean mVoiceInputHighlighted;
-
- private int mMinimumVoiceRecognitionViewHeightPixel;
- private InputMethodManagerCompatWrapper mImm;
- private LatinIME mService;
- private AlertDialog mVoiceWarningDialog;
- private VoiceInput mVoiceInput;
- private final VoiceResults mVoiceResults = new VoiceResults();
- private Hints mHints;
- private UIHandler mHandler;
- private SubtypeSwitcher mSubtypeSwitcher;
-
- // For each word, a list of potential replacements, usually from voice.
- private final Map<String, List<CharSequence>> mWordToSuggestions =
- new HashMap<String, List<CharSequence>>();
-
- public static VoiceProxy init(LatinIME context, SharedPreferences prefs, UIHandler h) {
- sInstance.initInternal(context, prefs, h);
- return sInstance;
- }
-
- public static VoiceProxy getInstance() {
- return sInstance;
- }
-
- private void initInternal(LatinIME service, SharedPreferences prefs, UIHandler h) {
- mService = service;
- mHandler = h;
- mMinimumVoiceRecognitionViewHeightPixel = Utils.dipToPixel(
- Utils.getDipScale(service), RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP);
- mImm = InputMethodManagerCompatWrapper.getInstance(service);
- mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- if (VOICE_INSTALLED) {
- mVoiceInput = new VoiceInput(service, this);
- mHints = new Hints(service, prefs, new Hints.Display() {
- @Override
- public void showHint(int viewResource) {
- View view = LayoutInflater.from(mService).inflate(viewResource, null);
-// mService.setCandidatesView(view);
-// mService.setCandidatesViewShown(true);
- mIsShowingHint = true;
- }
- });
- }
- }
-
- private VoiceProxy() {
- // Intentional empty constructor for singleton.
- }
-
- public void resetVoiceStates(boolean isPasswordText) {
- mAfterVoiceInput = false;
- mImmediatelyAfterVoiceInput = false;
- mShowingVoiceSuggestions = false;
- mVoiceInputHighlighted = false;
- mPasswordText = isPasswordText;
- }
-
- public void flushVoiceInputLogs(boolean configurationChanged) {
- if (VOICE_INSTALLED && !configurationChanged) {
- if (mAfterVoiceInput) {
- mVoiceInput.flushAllTextModificationCounters();
- mVoiceInput.logInputEnded();
- }
- mVoiceInput.flushLogs();
- mVoiceInput.cancel();
- }
- }
-
- public void flushAndLogAllTextModificationCounters(int index, CharSequence suggestion,
- String wordSeparators) {
- if (mAfterVoiceInput && mShowingVoiceSuggestions) {
- mVoiceInput.flushAllTextModificationCounters();
- // send this intent AFTER logging any prior aggregated edits.
- mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.toString(), index,
- wordSeparators, mService.getCurrentInputConnection());
- }
- }
-
- private void showVoiceWarningDialog(final boolean swipe, IBinder token) {
- if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
- return;
- }
- AlertDialog.Builder builder = new UrlLinkAlertDialogBuilder(mService);
- builder.setCancelable(true);
- builder.setIcon(R.drawable.ic_mic_dialog);
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- mVoiceInput.logKeyboardWarningDialogOk();
- reallyStartListening(swipe);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- mVoiceInput.logKeyboardWarningDialogCancel();
- switchToLastInputMethod();
- }
- });
- // When the dialog is dismissed by user's cancellation, switch back to the last input method
- builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface arg0) {
- mVoiceInput.logKeyboardWarningDialogCancel();
- switchToLastInputMethod();
- }
- });
-
- final CharSequence message;
- if (mLocaleSupportedForVoiceInput) {
- message = TextUtils.concat(
- mService.getText(R.string.voice_warning_may_not_understand), "\n\n",
- mService.getText(R.string.voice_warning_how_to_turn_off));
- } else {
- message = TextUtils.concat(
- mService.getText(R.string.voice_warning_locale_not_supported), "\n\n",
- mService.getText(R.string.voice_warning_may_not_understand), "\n\n",
- mService.getText(R.string.voice_warning_how_to_turn_off));
- }
- builder.setMessage(message);
- builder.setTitle(R.string.voice_warning_title);
- mVoiceWarningDialog = builder.create();
- final Window window = mVoiceWarningDialog.getWindow();
- final WindowManager.LayoutParams lp = window.getAttributes();
- lp.token = token;
- lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
- window.setAttributes(lp);
- window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- mVoiceInput.logKeyboardWarningDialogShown();
- mVoiceWarningDialog.show();
- }
-
- private static class UrlLinkAlertDialogBuilder extends AlertDialog.Builder {
- private AlertDialog mAlertDialog;
-
- public UrlLinkAlertDialogBuilder(Context context) {
- super(context);
- }
-
- @Override
- public AlertDialog.Builder setMessage(CharSequence message) {
- return super.setMessage(replaceURLSpan(message));
- }
-
- private Spanned replaceURLSpan(CharSequence message) {
- // Replace all spans with the custom span
- final SpannableStringBuilder ssb = new SpannableStringBuilder(message);
- for (URLSpan span : ssb.getSpans(0, ssb.length(), URLSpan.class)) {
- int spanStart = ssb.getSpanStart(span);
- int spanEnd = ssb.getSpanEnd(span);
- int spanFlags = ssb.getSpanFlags(span);
- ssb.removeSpan(span);
- ssb.setSpan(new ClickableSpan(span.getURL()), spanStart, spanEnd, spanFlags);
- }
- return ssb;
- }
-
- @Override
- public AlertDialog create() {
- final AlertDialog dialog = super.create();
-
- dialog.setOnShowListener(new DialogInterface.OnShowListener() {
- @Override
- public void onShow(DialogInterface dialogInterface) {
- // Make URL in the dialog message click-able.
- TextView textView = (TextView) mAlertDialog.findViewById(android.R.id.message);
- if (textView != null) {
- textView.setMovementMethod(LinkMovementMethod.getInstance());
- }
- }
- });
- mAlertDialog = dialog;
- return dialog;
- }
-
- class ClickableSpan extends URLSpan {
- public ClickableSpan(String url) {
- super(url);
- }
-
- @Override
- public void onClick(View widget) {
- Uri uri = Uri.parse(getURL());
- Context context = widget.getContext();
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- // Add this flag to start an activity from service
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
- // Dismiss the warning dialog and go back to the previous IME.
- // TODO: If we can find a way to bring the new activity to front while keeping
- // the warning dialog, we don't need to dismiss it here.
- mAlertDialog.cancel();
- context.startActivity(intent);
- }
- }
- }
-
- public void showPunctuationHintIfNecessary() {
- InputConnection ic = mService.getCurrentInputConnection();
- if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) {
- if (mHints.showPunctuationHintIfNecessary(ic)) {
- mVoiceInput.logPunctuationHintDisplayed();
- }
- }
- mImmediatelyAfterVoiceInput = false;
- }
-
- public void hideVoiceWindow(boolean configurationChanging) {
- if (!configurationChanging) {
- if (mAfterVoiceInput)
- mVoiceInput.logInputEnded();
- if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
- mVoiceInput.logKeyboardWarningDialogDismissed();
- mVoiceWarningDialog.dismiss();
- mVoiceWarningDialog = null;
- }
- if (VOICE_INSTALLED & mRecognizing) {
- mVoiceInput.cancel();
- }
- }
- mWordToSuggestions.clear();
- }
-
- public void setCursorAndSelection(int newSelEnd, int newSelStart) {
- if (mAfterVoiceInput) {
- mVoiceInput.setCursorPos(newSelEnd);
- mVoiceInput.setSelectionSpan(newSelEnd - newSelStart);
- }
- }
-
- public void setVoiceInputHighlighted(boolean b) {
- mVoiceInputHighlighted = b;
- }
-
- public void setShowingVoiceSuggestions(boolean b) {
- mShowingVoiceSuggestions = b;
- }
-
- public boolean isVoiceButtonEnabled() {
- return mVoiceButtonEnabled;
- }
-
- public boolean isVoiceButtonOnPrimary() {
- return mVoiceButtonOnPrimary;
- }
-
- public boolean isVoiceInputHighlighted() {
- return mVoiceInputHighlighted;
- }
-
- public boolean isRecognizing() {
- return mRecognizing;
- }
-
- public boolean needsToShowWarningDialog() {
- return !mHasUsedVoiceInput
- || (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale);
- }
-
- public boolean getAndResetIsShowingHint() {
- boolean ret = mIsShowingHint;
- mIsShowingHint = false;
- return ret;
- }
-
- private void revertVoiceInput() {
- InputConnection ic = mService.getCurrentInputConnection();
- if (ic != null) ic.commitText("", 1);
- mService.updateSuggestions();
- mVoiceInputHighlighted = false;
- }
-
- public void commitVoiceInput() {
- if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- InputConnection ic = mService.getCurrentInputConnection();
- if (ic != null) ic.finishComposingText();
- mService.updateSuggestions();
- mVoiceInputHighlighted = false;
- }
- }
-
- public boolean logAndRevertVoiceInput() {
- if (VOICE_INSTALLED && mVoiceInputHighlighted) {
- mVoiceInput.incrementTextModificationDeleteCount(
- mVoiceResults.candidates.get(0).toString().length());
- revertVoiceInput();
- return true;
- } else {
- return false;
- }
- }
-
- public void rememberReplacedWord(CharSequence suggestion,String wordSeparators) {
- if (mShowingVoiceSuggestions) {
- // Retain the replaced word in the alternatives array.
- String wordToBeReplaced = EditingUtils.getWordAtCursor(
- mService.getCurrentInputConnection(), wordSeparators);
- if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
- wordToBeReplaced = wordToBeReplaced.toLowerCase();
- }
- if (mWordToSuggestions.containsKey(wordToBeReplaced)) {
- List<CharSequence> suggestions = mWordToSuggestions.get(wordToBeReplaced);
- if (suggestions.contains(suggestion)) {
- suggestions.remove(suggestion);
- }
- suggestions.add(wordToBeReplaced);
- mWordToSuggestions.remove(wordToBeReplaced);
- mWordToSuggestions.put(suggestion.toString(), suggestions);
- }
- }
- }
-
- /**
- * Tries to apply any voice alternatives for the word if this was a spoken word and
- * there are voice alternatives.
- * @param touching The word that the cursor is touching, with position information
- * @return true if an alternative was found, false otherwise.
- */
- public boolean applyVoiceAlternatives(EditingUtils.SelectedWord touching) {
- // Search for result in spoken word alternatives
- String selectedWord = touching.mWord.toString().trim();
- if (!mWordToSuggestions.containsKey(selectedWord)) {
- selectedWord = selectedWord.toLowerCase();
- }
- if (mWordToSuggestions.containsKey(selectedWord)) {
- mShowingVoiceSuggestions = true;
- List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
- SuggestedWords.Builder builder = new SuggestedWords.Builder();
- // If the first letter of touching is capitalized, make all the suggestions
- // start with a capital letter.
- if (Character.isUpperCase(touching.mWord.charAt(0))) {
- for (CharSequence word : suggestions) {
- String str = word.toString();
- word = Character.toUpperCase(str.charAt(0)) + str.substring(1);
- builder.addWord(word);
- }
- } else {
- builder.addWords(suggestions, null);
- }
- builder.setTypedWordValid(true).setHasMinimalSuggestion(true);
- mService.setSuggestions(builder.build());
-// mService.setCandidatesViewShown(true);
- return true;
- }
- return false;
- }
-
- public void handleBackspace() {
- if (mAfterVoiceInput) {
- // Don't log delete if the user is pressing delete at
- // the beginning of the text box (hence not deleting anything)
- if (mVoiceInput.getCursorPos() > 0) {
- // If anything was selected before the delete was pressed, increment the
- // delete count by the length of the selection
- int deleteLen = mVoiceInput.getSelectionSpan() > 0 ?
- mVoiceInput.getSelectionSpan() : 1;
- mVoiceInput.incrementTextModificationDeleteCount(deleteLen);
- }
- }
- }
-
- public void handleCharacter() {
- commitVoiceInput();
- if (mAfterVoiceInput) {
- // Assume input length is 1. This assumption fails for smiley face insertions.
- mVoiceInput.incrementTextModificationInsertCount(1);
- }
- }
-
- public void handleSeparator() {
- commitVoiceInput();
- if (mAfterVoiceInput){
- // Assume input length is 1. This assumption fails for smiley face insertions.
- mVoiceInput.incrementTextModificationInsertPunctuationCount(1);
- }
- }
-
- public void handleClose() {
- if (VOICE_INSTALLED & mRecognizing) {
- mVoiceInput.cancel();
- }
- }
-
-
- public void handleVoiceResults(boolean capitalizeFirstWord) {
- mAfterVoiceInput = true;
- mImmediatelyAfterVoiceInput = true;
-
- InputConnection ic = mService.getCurrentInputConnection();
- if (!mService.isFullscreenMode()) {
- // Start listening for updates to the text from typing, etc.
- if (ic != null) {
- ExtractedTextRequest req = new ExtractedTextRequest();
- ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
- }
- }
- mService.vibrate();
-
- final List<CharSequence> nBest = new ArrayList<CharSequence>();
- for (String c : mVoiceResults.candidates) {
- if (capitalizeFirstWord) {
- c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length());
- }
- nBest.add(c);
- }
- if (nBest.size() == 0) {
- return;
- }
- String bestResult = nBest.get(0).toString();
- mVoiceInput.logVoiceInputDelivered(bestResult.length());
- mHints.registerVoiceResult(bestResult);
-
- if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
- mService.commitTyped(ic);
- EditingUtils.appendText(ic, bestResult);
- if (ic != null) ic.endBatchEdit();
-
- mVoiceInputHighlighted = true;
- mWordToSuggestions.putAll(mVoiceResults.alternatives);
- onCancelVoice();
- }
-
- public void switchToRecognitionStatusView(final Configuration configuration) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
-// mService.setCandidatesViewShown(false);
- mRecognizing = true;
- mVoiceInput.newView();
- View v = mVoiceInput.getView();
-
- ViewParent p = v.getParent();
- if (p != null && p instanceof ViewGroup) {
- ((ViewGroup) p).removeView(v);
- }
-
- View keyboardView = KeyboardSwitcher.getInstance().getKeyboardView();
-
- // The full height of the keyboard is difficult to calculate
- // as the dimension is expressed in "mm" and not in "pixel"
- // As we add mm, we don't know how the rounding is going to work
- // thus we may end up with few pixels extra (or less).
- if (keyboardView != null) {
- View popupLayout = v.findViewById(R.id.popup_layout);
- final int displayHeight =
- mService.getResources().getDisplayMetrics().heightPixels;
- final int currentHeight = popupLayout.getLayoutParams().height;
- final int keyboardHeight = keyboardView.getHeight();
- if (mMinimumVoiceRecognitionViewHeightPixel > keyboardHeight
- || mMinimumVoiceRecognitionViewHeightPixel > currentHeight) {
- popupLayout.getLayoutParams().height =
- mMinimumVoiceRecognitionViewHeightPixel;
- } else if (keyboardHeight > currentHeight || keyboardHeight
- > (displayHeight / RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO)) {
- popupLayout.getLayoutParams().height = keyboardHeight;
- }
- }
- mService.setInputView(v);
- mService.updateInputViewShown();
-
- if (configuration != null) {
- mVoiceInput.onConfigurationChanged(configuration);
- }
- }});
- }
-
- private void switchToLastInputMethod() {
- final IBinder token = mService.getWindow().getWindow().getAttributes().token;
- new AsyncTask<Void, Void, Boolean>() {
- @Override
- protected Boolean doInBackground(Void... params) {
- return mImm.switchToLastInputMethod(token);
- }
-
- @Override
- protected void onPostExecute(Boolean result) {
- // Calls in this method need to be done in the same thread as the thread which
- // called switchToLastInputMethod()
- if (!result) {
- if (DEBUG) {
- Log.d(TAG, "Couldn't switch back to last IME.");
- }
- // Because the current IME and subtype failed to switch to any other IME and
- // subtype by switchToLastInputMethod, the current IME and subtype should keep
- // being LatinIME and voice subtype in the next time. And for re-showing voice
- // mode, the state of voice input should be reset and the voice view should be
- // hidden.
- mVoiceInput.reset();
- mService.requestHideSelf(0);
- } else {
- // Notify an event that the current subtype was changed. This event will be
- // handled if "onCurrentInputMethodSubtypeChanged" can't be implemented
- // when the API level is 10 or previous.
- mService.notifyOnCurrentInputMethodSubtypeChanged(null);
- }
- }
- }.execute();
- }
-
- private void reallyStartListening(boolean swipe) {
- if (!VOICE_INSTALLED) {
- return;
- }
- if (!mHasUsedVoiceInput) {
- // The user has started a voice input, so remember that in the
- // future (so we don't show the warning dialog after the first run).
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(mService).edit();
- editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true);
- SharedPreferencesCompat.apply(editor);
- mHasUsedVoiceInput = true;
- }
-
- if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) {
- // The user has started a voice input from an unsupported locale, so remember that
- // in the future (so we don't show the warning dialog the next time they do this).
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(mService).edit();
- editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true);
- SharedPreferencesCompat.apply(editor);
- mHasUsedVoiceInputUnsupportedLocale = true;
- }
-
- // Clear N-best suggestions
- mService.clearSuggestions();
-
- FieldContext context = makeFieldContext();
- mVoiceInput.startListening(context, swipe);
- switchToRecognitionStatusView(null);
- }
-
- public void startListening(final boolean swipe, IBinder token) {
- // TODO: remove swipe which is no longer used.
- if (VOICE_INSTALLED) {
- if (needsToShowWarningDialog()) {
- // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
- showVoiceWarningDialog(swipe, token);
- } else {
- reallyStartListening(swipe);
- }
- }
- }
-
- private boolean fieldCanDoVoice(FieldContext fieldContext) {
- return !mPasswordText
- && mVoiceInput != null
- && !mVoiceInput.isBlacklistedField(fieldContext);
- }
-
- private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) {
- @SuppressWarnings("deprecation")
- final boolean noMic = Utils.inPrivateImeOptions(null,
- LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, attribute)
- || Utils.inPrivateImeOptions(mService.getPackageName(),
- LatinIME.IME_OPTION_NO_MICROPHONE, attribute);
- return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic
- && SpeechRecognizer.isRecognitionAvailable(mService);
- }
-
- public void loadSettings(EditorInfo attribute, SharedPreferences sp) {
- mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false);
- mHasUsedVoiceInputUnsupportedLocale =
- sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false);
-
- mLocaleSupportedForVoiceInput = SubtypeSwitcher.getInstance().isVoiceSupported(
- SubtypeSwitcher.getInstance().getInputLocaleStr());
-
- if (VOICE_INSTALLED) {
- final String voiceMode = sp.getString(PREF_VOICE_MODE,
- mService.getString(R.string.voice_mode_main));
- mVoiceButtonEnabled = !voiceMode.equals(mService.getString(R.string.voice_mode_off))
- && shouldShowVoiceButton(makeFieldContext(), attribute);
- mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main));
- }
- }
-
- public void destroy() {
- if (VOICE_INSTALLED && mVoiceInput != null) {
- mVoiceInput.destroy();
- }
- }
-
- public void onStartInputView(IBinder keyboardViewToken) {
- // If keyboardViewToken is null, keyboardView is not attached but voiceView is attached.
- IBinder windowToken = keyboardViewToken != null ? keyboardViewToken
- : mVoiceInput.getView().getWindowToken();
- // If IME is in voice mode, but still needs to show the voice warning dialog,
- // keep showing the warning.
- if (mSubtypeSwitcher.isVoiceMode() && windowToken != null) {
- // Close keyboard view if it is been shown.
- if (KeyboardSwitcher.getInstance().isInputViewShown())
- KeyboardSwitcher.getInstance().getKeyboardView().purgeKeyboardAndClosing();
- startListening(false, windowToken);
- }
- // If we have no token, onAttachedToWindow will take care of showing dialog and start
- // listening.
- }
-
- public void onAttachedToWindow() {
- // After onAttachedToWindow, we can show the voice warning dialog. See startListening()
- // above.
- VoiceInputWrapper.getInstance().setVoiceInput(mVoiceInput, mSubtypeSwitcher);
- }
-
- public void onConfigurationChanged(Configuration configuration) {
- if (mRecognizing) {
- switchToRecognitionStatusView(configuration);
- }
- }
-
- @Override
- public void onCancelVoice() {
- if (mRecognizing) {
- if (mSubtypeSwitcher.isVoiceMode()) {
- // If voice mode is being canceled within LatinIME (i.e. time-out or user
- // cancellation etc.), onCancelVoice() will be called first. LatinIME thinks it's
- // still in voice mode. LatinIME needs to call switchToLastInputMethod().
- // Note that onCancelVoice() will be called again from SubtypeSwitcher.
- switchToLastInputMethod();
- } else if (mSubtypeSwitcher.isKeyboardMode()) {
- // If voice mode is being canceled out of LatinIME (i.e. by user's IME switching or
- // as a result of switchToLastInputMethod() etc.),
- // onCurrentInputMethodSubtypeChanged() will be called first. LatinIME will know
- // that it's in keyboard mode and SubtypeSwitcher will call onCancelVoice().
- mRecognizing = false;
- mService.switchToKeyboardView();
- }
- }
- }
-
- @Override
- public void onVoiceResults(List<String> candidates,
- Map<String, List<CharSequence>> alternatives) {
- if (!mRecognizing) {
- return;
- }
- mVoiceResults.candidates = candidates;
- mVoiceResults.alternatives = alternatives;
- mHandler.updateVoiceResults();
- }
-
- private FieldContext makeFieldContext() {
- SubtypeSwitcher switcher = SubtypeSwitcher.getInstance();
- return new FieldContext(mService.getCurrentInputConnection(),
- mService.getCurrentInputEditorInfo(), switcher.getInputLocaleStr(),
- switcher.getEnabledLanguages());
- }
-
- private class VoiceResults {
- List<String> candidates;
- Map<String, List<CharSequence>> alternatives;
- }
-
- public static class VoiceLoggerWrapper {
- private static final VoiceLoggerWrapper sLoggerWrapperInstance = new VoiceLoggerWrapper();
- private VoiceInputLogger mLogger;
-
- public static VoiceLoggerWrapper getInstance(Context context) {
- if (sLoggerWrapperInstance.mLogger == null) {
- // Not thread safe, but it's ok.
- sLoggerWrapperInstance.mLogger = VoiceInputLogger.getLogger(context);
- }
- return sLoggerWrapperInstance;
- }
-
- // private for the singleton
- private VoiceLoggerWrapper() {
- }
-
- public void settingsWarningDialogCancel() {
- mLogger.settingsWarningDialogCancel();
- }
-
- public void settingsWarningDialogOk() {
- mLogger.settingsWarningDialogOk();
- }
-
- public void settingsWarningDialogShown() {
- mLogger.settingsWarningDialogShown();
- }
-
- public void settingsWarningDialogDismissed() {
- mLogger.settingsWarningDialogDismissed();
- }
-
- public void voiceInputSettingEnabled(boolean enabled) {
- if (enabled) {
- mLogger.voiceInputSettingEnabled();
- } else {
- mLogger.voiceInputSettingDisabled();
- }
- }
- }
-
- public static class VoiceInputWrapper {
- private static final VoiceInputWrapper sInputWrapperInstance = new VoiceInputWrapper();
- private VoiceInput mVoiceInput;
- public static VoiceInputWrapper getInstance() {
- return sInputWrapperInstance;
- }
- public void setVoiceInput(VoiceInput voiceInput, SubtypeSwitcher switcher) {
- if (mVoiceInput == null && voiceInput != null) {
- mVoiceInput = voiceInput;
- }
- switcher.setVoiceInputWrapper(this);
- }
-
- private VoiceInputWrapper() {
- }
-
- public void cancel() {
- if (mVoiceInput != null) mVoiceInput.cancel();
- }
-
- public void reset() {
- if (mVoiceInput != null) mVoiceInput.reset();
- }
- }
-
- // A list of locales which are supported by default for voice input, unless we get a
- // different list from Gservices.
- private static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
- "en " +
- "en_US " +
- "en_GB " +
- "en_AU " +
- "en_CA " +
- "en_IE " +
- "en_IN " +
- "en_NZ " +
- "en_SG " +
- "en_ZA ";
-
- public static String getSupportedLocalesString (ContentResolver resolver) {
- return SettingsUtil.getSettingsString(
- resolver,
- SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
- DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java b/java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java
deleted file mode 100644
index 488390fbc..000000000
--- a/java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.deprecated.compat;
-
-import com.android.common.userhappiness.UserHappinessSignals;
-import com.android.inputmethod.compat.CompatUtils;
-
-import java.lang.reflect.Method;
-
-public class VoiceInputLoggerCompatUtils {
- public static final String EXTRA_TEXT_REPLACED_LENGTH = "length";
- public static final String EXTRA_BEFORE_N_BEST_CHOOSE = "before";
- public static final String EXTRA_AFTER_N_BEST_CHOOSE = "after";
- private static final Method METHOD_UserHappinessSignals_setHasVoiceLoggingInfo =
- CompatUtils.getMethod(UserHappinessSignals.class, "setHasVoiceLoggingInfo",
- boolean.class);
-
- public static void setHasVoiceLoggingInfoCompat(boolean hasLoggingInfo) {
- CompatUtils.invoke(null, null, METHOD_UserHappinessSignals_setHasVoiceLoggingInfo,
- hasLoggingInfo);
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
deleted file mode 100644
index cf6cd0f5e..000000000
--- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2008-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.deprecated.languageswitcher;
-
-import com.android.inputmethod.keyboard.internal.KeyboardParser;
-import com.android.inputmethod.latin.DictionaryFactory;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.Settings;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.Utils;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceManager;
-import android.text.TextUtils;
-import android.util.Pair;
-
-import java.io.IOException;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-public class InputLanguageSelection extends PreferenceActivity {
-
- private SharedPreferences mPrefs;
- private String mSelectedLanguages;
- private HashMap<CheckBoxPreference, Locale> mLocaleMap =
- new HashMap<CheckBoxPreference, Locale>();
-
- private static class LocaleEntry implements Comparable<Object> {
- private static Collator sCollator = Collator.getInstance();
-
- private String mLabel;
- public final Locale mLocale;
-
- public LocaleEntry(String label, Locale locale) {
- this.mLabel = label;
- this.mLocale = locale;
- }
-
- @Override
- public String toString() {
- return this.mLabel;
- }
-
- @Override
- public int compareTo(Object o) {
- return sCollator.compare(this.mLabel, ((LocaleEntry) o).mLabel);
- }
- }
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- addPreferencesFromResource(R.xml.language_prefs);
- // Get the settings preferences
- mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- mSelectedLanguages = mPrefs.getString(Settings.PREF_SELECTED_LANGUAGES, "");
- String[] languageList = mSelectedLanguages.split(",");
- ArrayList<LocaleEntry> availableLanguages = getUniqueLocales();
- PreferenceGroup parent = getPreferenceScreen();
- final HashMap<Long, LocaleEntry> dictionaryIdLocaleMap = new HashMap<Long, LocaleEntry>();
- final TreeMap<LocaleEntry, Boolean> localeHasDictionaryMap =
- new TreeMap<LocaleEntry, Boolean>();
- for (int i = 0; i < availableLanguages.size(); i++) {
- LocaleEntry loc = availableLanguages.get(i);
- Locale locale = loc.mLocale;
- final Pair<Long, Boolean> hasDictionaryOrLayout = hasDictionaryOrLayout(locale);
- final Long dictionaryId = hasDictionaryOrLayout.first;
- final boolean hasLayout = hasDictionaryOrLayout.second;
- final boolean hasDictionary = dictionaryId != null;
- // Add this locale to the supported list if:
- // 1) this locale has a layout/ 2) this locale has a dictionary
- // If some locales have no layout but have a same dictionary, the shortest locale
- // will be added to the supported list.
- if (!hasLayout && !hasDictionary) {
- continue;
- }
- if (hasLayout) {
- localeHasDictionaryMap.put(loc, hasDictionary);
- }
- if (!hasDictionary) {
- continue;
- }
- if (dictionaryIdLocaleMap.containsKey(dictionaryId)) {
- final String newLocale = locale.toString();
- final String oldLocale =
- dictionaryIdLocaleMap.get(dictionaryId).mLocale.toString();
- // Check if this locale is more appropriate to be the candidate of the input locale.
- if (oldLocale.length() <= newLocale.length() && !hasLayout) {
- // Don't add this new locale to the map<dictionary id, locale> if:
- // 1) the new locale's name is longer than the existing one, and
- // 2) the new locale doesn't have its layout
- continue;
- }
- }
- dictionaryIdLocaleMap.put(dictionaryId, loc);
- }
-
- for (LocaleEntry localeEntry : dictionaryIdLocaleMap.values()) {
- if (!localeHasDictionaryMap.containsKey(localeEntry)) {
- localeHasDictionaryMap.put(localeEntry, true);
- }
- }
-
- for (Entry<LocaleEntry, Boolean> entry : localeHasDictionaryMap.entrySet()) {
- final LocaleEntry localeEntry = entry.getKey();
- final Locale locale = localeEntry.mLocale;
- final Boolean hasDictionary = entry.getValue();
- CheckBoxPreference pref = new CheckBoxPreference(this);
- pref.setTitle(localeEntry.mLabel);
- boolean checked = isLocaleIn(locale, languageList);
- pref.setChecked(checked);
- if (hasDictionary) {
- pref.setSummary(R.string.has_dictionary);
- }
- mLocaleMap.put(pref, locale);
- parent.addPreference(pref);
- }
- }
-
- private boolean isLocaleIn(Locale locale, String[] list) {
- String lang = get5Code(locale);
- for (int i = 0; i < list.length; i++) {
- if (lang.equalsIgnoreCase(list[i])) return true;
- }
- return false;
- }
-
- private Pair<Long, Boolean> hasDictionaryOrLayout(Locale locale) {
- if (locale == null) return new Pair<Long, Boolean>(null, false);
- final Resources res = getResources();
- final Locale saveLocale = Utils.setSystemLocale(res, locale);
- final Long dictionaryId = DictionaryFactory.getDictionaryId(this, locale);
- boolean hasLayout = false;
-
- try {
- final String localeStr = locale.toString();
- final String[] layoutCountryCodes = KeyboardParser.parseKeyboardLocale(
- this, R.xml.kbd_qwerty).split(",", -1);
- if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) {
- for (String s : layoutCountryCodes) {
- if (s.equals(localeStr)) {
- hasLayout = true;
- break;
- }
- }
- }
- } catch (XmlPullParserException e) {
- } catch (IOException e) {
- }
- Utils.setSystemLocale(res, saveLocale);
- return new Pair<Long, Boolean>(dictionaryId, hasLayout);
- }
-
- private String get5Code(Locale locale) {
- String country = locale.getCountry();
- return locale.getLanguage()
- + (TextUtils.isEmpty(country) ? "" : "_" + country);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- // Save the selected languages
- String checkedLanguages = "";
- PreferenceGroup parent = getPreferenceScreen();
- int count = parent.getPreferenceCount();
- for (int i = 0; i < count; i++) {
- CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i);
- if (pref.isChecked()) {
- checkedLanguages += get5Code(mLocaleMap.get(pref)) + ",";
- }
- }
- if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null
- Editor editor = mPrefs.edit();
- editor.putString(Settings.PREF_SELECTED_LANGUAGES, checkedLanguages);
- SharedPreferencesCompat.apply(editor);
- }
-
- public ArrayList<LocaleEntry> getUniqueLocales() {
- String[] locales = getAssets().getLocales();
- Arrays.sort(locales);
- ArrayList<LocaleEntry> uniqueLocales = new ArrayList<LocaleEntry>();
-
- final int origSize = locales.length;
- LocaleEntry[] preprocess = new LocaleEntry[origSize];
- int finalSize = 0;
- for (int i = 0 ; i < origSize; i++ ) {
- String s = locales[i];
- int len = s.length();
- String language = "";
- String country = "";
- if (len == 5) {
- language = s.substring(0, 2);
- country = s.substring(3, 5);
- } else if (len < 5) {
- language = s;
- }
- Locale l = new Locale(language, country);
-
- // Exclude languages that are not relevant to LatinIME
- if (TextUtils.isEmpty(language)) {
- continue;
- }
-
- if (finalSize == 0) {
- preprocess[finalSize++] =
- new LocaleEntry(SubtypeSwitcher.getFullDisplayName(l, false), l);
- } else {
- if (s.equals("zz_ZZ")) {
- // ignore this locale
- } else {
- final String displayName = SubtypeSwitcher.getFullDisplayName(l, false);
- preprocess[finalSize++] = new LocaleEntry(displayName, l);
- }
- }
- }
- for (int i = 0; i < finalSize ; i++) {
- uniqueLocales.add(preprocess[i]);
- }
- return uniqueLocales;
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java
deleted file mode 100644
index 1eedb5ee1..000000000
--- a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2010 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.deprecated.languageswitcher;
-
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.Settings;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
-import com.android.inputmethod.latin.Utils;
-
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.content.res.Configuration;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-/**
- * Keeps track of list of selected input languages and the current
- * input language that the user has selected.
- */
-public class LanguageSwitcher {
- private static final String TAG = LanguageSwitcher.class.getSimpleName();
-
- @SuppressWarnings("unused")
- private static final String KEYBOARD_MODE = "keyboard";
- private static final String[] EMPTY_STIRNG_ARRAY = new String[0];
-
- private final ArrayList<Locale> mLocales = new ArrayList<Locale>();
- private final LatinIME mIme;
- private String[] mSelectedLanguageArray = EMPTY_STIRNG_ARRAY;
- private String mSelectedLanguages;
- private int mCurrentIndex = 0;
- private String mDefaultInputLanguage;
- private Locale mDefaultInputLocale;
- private Locale mSystemLocale;
-
- public LanguageSwitcher(LatinIME ime) {
- mIme = ime;
- }
-
- public int getLocaleCount() {
- return mLocales.size();
- }
-
- public void onConfigurationChanged(Configuration conf, SharedPreferences prefs) {
- final Locale newLocale = conf.locale;
- if (!getSystemLocale().toString().equals(newLocale.toString())) {
- loadLocales(prefs, newLocale);
- }
- }
-
- /**
- * Loads the currently selected input languages from shared preferences.
- * @param sp shared preference for getting the current input language and enabled languages
- * @param systemLocale the current system locale, stored for changing the current input language
- * based on the system current system locale.
- * @return whether there was any change
- */
- public boolean loadLocales(SharedPreferences sp, Locale systemLocale) {
- if (LatinImeLogger.sDBG) {
- Log.d(TAG, "load locales");
- }
- if (systemLocale != null) {
- setSystemLocale(systemLocale);
- }
- String selectedLanguages = sp.getString(Settings.PREF_SELECTED_LANGUAGES, null);
- String currentLanguage = sp.getString(Settings.PREF_INPUT_LANGUAGE, null);
- if (TextUtils.isEmpty(selectedLanguages)) {
- mSelectedLanguageArray = EMPTY_STIRNG_ARRAY;
- mSelectedLanguages = null;
- loadDefaults();
- if (mLocales.size() == 0) {
- return false;
- }
- mLocales.clear();
- return true;
- }
- if (selectedLanguages.equals(mSelectedLanguages)) {
- return false;
- }
- mSelectedLanguageArray = selectedLanguages.split(",");
- mSelectedLanguages = selectedLanguages; // Cache it for comparison later
- constructLocales();
- mCurrentIndex = 0;
- if (currentLanguage != null) {
- // Find the index
- mCurrentIndex = 0;
- for (int i = 0; i < mLocales.size(); i++) {
- if (mSelectedLanguageArray[i].equals(currentLanguage)) {
- mCurrentIndex = i;
- break;
- }
- }
- // If we didn't find the index, use the first one
- }
- return true;
- }
-
- private void loadDefaults() {
- if (LatinImeLogger.sDBG) {
- Log.d(TAG, "load default locales:");
- }
- mDefaultInputLocale = mIme.getResources().getConfiguration().locale;
- String country = mDefaultInputLocale.getCountry();
- mDefaultInputLanguage = mDefaultInputLocale.getLanguage() +
- (TextUtils.isEmpty(country) ? "" : "_" + country);
- }
-
- private void constructLocales() {
- mLocales.clear();
- for (final String lang : mSelectedLanguageArray) {
- final Locale locale = Utils.constructLocaleFromString(lang);
- mLocales.add(locale);
- }
- }
-
- /**
- * Returns the currently selected input language code, or the display language code if
- * no specific locale was selected for input.
- */
- public String getInputLanguage() {
- if (getLocaleCount() == 0) return mDefaultInputLanguage;
-
- return mSelectedLanguageArray[mCurrentIndex];
- }
-
- /**
- * Returns the list of enabled language codes.
- */
- public String[] getEnabledLanguages(boolean allowImplicitlySelectedLanguages) {
- if (mSelectedLanguageArray.length == 0 && allowImplicitlySelectedLanguages) {
- return new String[] { mDefaultInputLanguage };
- }
- return mSelectedLanguageArray;
- }
-
- /**
- * Returns the currently selected input locale, or the display locale if no specific
- * locale was selected for input.
- */
- public Locale getInputLocale() {
- if (getLocaleCount() == 0) return mDefaultInputLocale;
-
- return mLocales.get(mCurrentIndex);
- }
-
- private int nextLocaleIndex() {
- final int size = mLocales.size();
- return (mCurrentIndex + 1) % size;
- }
-
- private int prevLocaleIndex() {
- final int size = mLocales.size();
- return (mCurrentIndex - 1 + size) % size;
- }
-
- /**
- * Returns the next input locale in the list. Wraps around to the beginning of the
- * list if we're at the end of the list.
- */
- public Locale getNextInputLocale() {
- if (getLocaleCount() == 0) return mDefaultInputLocale;
- return mLocales.get(nextLocaleIndex());
- }
-
- /**
- * Sets the system locale (display UI) used for comparing with the input language.
- * @param locale the locale of the system
- */
- private void setSystemLocale(Locale locale) {
- mSystemLocale = locale;
- }
-
- /**
- * Returns the system locale.
- * @return the system locale
- */
- private Locale getSystemLocale() {
- return mSystemLocale;
- }
-
- /**
- * Returns the previous input locale in the list. Wraps around to the end of the
- * list if we're at the beginning of the list.
- */
- public Locale getPrevInputLocale() {
- if (getLocaleCount() == 0) return mDefaultInputLocale;
- return mLocales.get(prevLocaleIndex());
- }
-
- public void reset() {
- mCurrentIndex = 0;
- }
-
- public void next() {
- mCurrentIndex = nextLocaleIndex();
- }
-
- public void prev() {
- mCurrentIndex = prevLocaleIndex();
- }
-
- public void setLocale(String localeStr) {
- final int N = mLocales.size();
- for (int i = 0; i < N; ++i) {
- if (mLocales.get(i).toString().equals(localeStr)) {
- mCurrentIndex = i;
- }
- }
- }
-
- public void persist(SharedPreferences prefs) {
- Editor editor = prefs.edit();
- editor.putString(Settings.PREF_INPUT_LANGUAGE, getInputLanguage());
- SharedPreferencesCompat.apply(editor);
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java b/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java
deleted file mode 100644
index d40728d25..000000000
--- a/java/src/com/android/inputmethod/deprecated/recorrection/Recorrection.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.deprecated.recorrection;
-
-import com.android.inputmethod.compat.InputConnectionCompatUtils;
-import com.android.inputmethod.compat.SuggestionSpanUtils;
-import com.android.inputmethod.deprecated.VoiceProxy;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.latin.AutoCorrection;
-import com.android.inputmethod.latin.CandidateView;
-import com.android.inputmethod.latin.EditingUtils;
-import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.Settings;
-import com.android.inputmethod.latin.Suggest;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.TextEntryState;
-import com.android.inputmethod.latin.WordComposer;
-
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.text.TextUtils;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-import java.util.ArrayList;
-
-/**
- * Manager of re-correction functionalities
- */
-public class Recorrection implements SharedPreferences.OnSharedPreferenceChangeListener {
- private static final Recorrection sInstance = new Recorrection();
-
- private LatinIME mService;
- private boolean mRecorrectionEnabled = false;
- private final ArrayList<RecorrectionSuggestionEntries> mRecorrectionSuggestionsList =
- new ArrayList<RecorrectionSuggestionEntries>();
-
- public static Recorrection getInstance() {
- return sInstance;
- }
-
- public static void init(LatinIME context, SharedPreferences prefs) {
- if (context == null || prefs == null) {
- return;
- }
- sInstance.initInternal(context, prefs);
- }
-
- private Recorrection() {
- }
-
- public boolean isRecorrectionEnabled() {
- return mRecorrectionEnabled;
- }
-
- private void initInternal(LatinIME context, SharedPreferences prefs) {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED) {
- mRecorrectionEnabled = false;
- return;
- }
- updateRecorrectionEnabled(context.getResources(), prefs);
- mService = context;
- prefs.registerOnSharedPreferenceChangeListener(this);
- }
-
- public void checkRecorrectionOnStart() {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return;
-
- final InputConnection ic = mService.getCurrentInputConnection();
- if (ic == null) return;
- // There could be a pending composing span. Clean it up first.
- ic.finishComposingText();
-
- if (mService.isShowingSuggestionsStrip() && mService.isSuggestionsRequested()) {
- // First get the cursor position. This is required by setOldSuggestions(), so that
- // it can pass the correct range to setComposingRegion(). At this point, we don't
- // have valid values for mLastSelectionStart/End because onUpdateSelection() has
- // not been called yet.
- ExtractedTextRequest etr = new ExtractedTextRequest();
- etr.token = 0; // anything is fine here
- ExtractedText et = ic.getExtractedText(etr, 0);
- if (et == null) return;
- mService.setLastSelection(
- et.startOffset + et.selectionStart, et.startOffset + et.selectionEnd);
-
- // Then look for possible corrections in a delayed fashion
- if (!TextUtils.isEmpty(et.text) && mService.isCursorTouchingWord()) {
- mService.mHandler.postUpdateOldSuggestions();
- }
- }
- }
-
- public void updateRecorrectionSelection(KeyboardSwitcher keyboardSwitcher,
- CandidateView candidateView, int candidatesStart, int candidatesEnd,
- int newSelStart, int newSelEnd, int oldSelStart, int lastSelectionStart,
- int lastSelectionEnd, boolean hasUncommittedTypedChars) {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return;
- if (!mService.isShowingSuggestionsStrip()) return;
- if (!keyboardSwitcher.isInputViewShown()) return;
- if (!mService.isSuggestionsRequested()) return;
- // Don't look for corrections if the keyboard is not visible
- // Check if we should go in or out of correction mode.
- if ((candidatesStart == candidatesEnd || newSelStart != oldSelStart || TextEntryState
- .isRecorrecting())
- && (newSelStart < newSelEnd - 1 || !hasUncommittedTypedChars)) {
- if (mService.isCursorTouchingWord() || lastSelectionStart < lastSelectionEnd) {
- mService.mHandler.cancelUpdateBigramPredictions();
- mService.mHandler.postUpdateOldSuggestions();
- } else {
- abortRecorrection(false);
- // If showing the "touch again to save" hint, do not replace it. Else,
- // show the bigrams if we are at the end of the text, punctuation
- // otherwise.
- if (candidateView != null && !candidateView.isShowingAddToDictionaryHint()) {
- InputConnection ic = mService.getCurrentInputConnection();
- if (null == ic || !TextUtils.isEmpty(ic.getTextAfterCursor(1, 0))) {
- if (!mService.isShowingPunctuationList()) {
- mService.setPunctuationSuggestions();
- }
- } else {
- mService.mHandler.postUpdateBigramPredictions();
- }
- }
- }
- }
- }
-
- public void saveRecorrectionSuggestion(WordComposer word, CharSequence result) {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return;
- if (word.size() <= 1) {
- return;
- }
- // Skip if result is null. It happens in some edge case.
- if (TextUtils.isEmpty(result)) {
- return;
- }
-
- // Make a copy of the CharSequence, since it is/could be a mutable CharSequence
- final String resultCopy = result.toString();
- RecorrectionSuggestionEntries entry = new RecorrectionSuggestionEntries(
- resultCopy, new WordComposer(word));
- mRecorrectionSuggestionsList.add(entry);
- }
-
- public void clearWordsInHistory() {
- mRecorrectionSuggestionsList.clear();
- }
-
- /**
- * Tries to apply any typed alternatives for the word if we have any cached alternatives,
- * otherwise tries to find new corrections and completions for the word.
- * @param touching The word that the cursor is touching, with position information
- * @return true if an alternative was found, false otherwise.
- */
- public boolean applyTypedAlternatives(WordComposer word, Suggest suggest,
- KeyboardSwitcher keyboardSwitcher, EditingUtils.SelectedWord touching) {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return false;
- // If we didn't find a match, search for result in typed word history
- WordComposer foundWord = null;
- RecorrectionSuggestionEntries alternatives = null;
- // Search old suggestions to suggest re-corrected suggestions.
- for (RecorrectionSuggestionEntries entry : mRecorrectionSuggestionsList) {
- if (TextUtils.equals(entry.getChosenWord(), touching.mWord)) {
- foundWord = entry.mWordComposer;
- alternatives = entry;
- break;
- }
- }
- // If we didn't find a match, at least suggest corrections as re-corrected suggestions.
- if (foundWord == null
- && (AutoCorrection.isValidWord(suggest.getUnigramDictionaries(),
- touching.mWord, true))) {
- foundWord = new WordComposer();
- for (int i = 0; i < touching.mWord.length(); i++) {
- foundWord.add(touching.mWord.charAt(i),
- new int[] { touching.mWord.charAt(i) }, WordComposer.NOT_A_COORDINATE,
- WordComposer.NOT_A_COORDINATE);
- }
- foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.mWord.charAt(0)));
- }
- // Found a match, show suggestions
- if (foundWord != null || alternatives != null) {
- if (alternatives == null) {
- alternatives = new RecorrectionSuggestionEntries(touching.mWord, foundWord);
- }
- showRecorrections(suggest, keyboardSwitcher, alternatives);
- if (foundWord != null) {
- word.init(foundWord);
- } else {
- word.reset();
- }
- return true;
- }
- return false;
- }
-
-
- private void showRecorrections(Suggest suggest, KeyboardSwitcher keyboardSwitcher,
- RecorrectionSuggestionEntries entries) {
- SuggestedWords.Builder builder = entries.getAlternatives(suggest, keyboardSwitcher);
- builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
- mService.showSuggestions(builder.build(), entries.getOriginalWord());
- }
-
- public void fetchAndDisplayRecorrectionSuggestions(VoiceProxy voiceProxy,
- CandidateView candidateView, Suggest suggest, KeyboardSwitcher keyboardSwitcher,
- WordComposer word, boolean hasUncommittedTypedChars, int lastSelectionStart,
- int lastSelectionEnd, String wordSeparators) {
- if (!InputConnectionCompatUtils.RECORRECTION_SUPPORTED) return;
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED || !mRecorrectionEnabled) return;
- voiceProxy.setShowingVoiceSuggestions(false);
- if (candidateView != null && candidateView.isShowingAddToDictionaryHint()) {
- return;
- }
- InputConnection ic = mService.getCurrentInputConnection();
- if (ic == null) return;
- if (!hasUncommittedTypedChars) {
- // Extract the selected or touching text
- EditingUtils.SelectedWord touching = EditingUtils.getWordAtCursorOrSelection(ic,
- lastSelectionStart, lastSelectionEnd, wordSeparators);
-
- if (touching != null && touching.mWord.length() > 1) {
- ic.beginBatchEdit();
-
- if (applyTypedAlternatives(word, suggest, keyboardSwitcher, touching)
- || voiceProxy.applyVoiceAlternatives(touching)) {
- TextEntryState.selectedForRecorrection();
- InputConnectionCompatUtils.underlineWord(ic, touching);
- } else {
- abortRecorrection(true);
- }
-
- ic.endBatchEdit();
- } else {
- abortRecorrection(true);
- mService.updateBigramPredictions();
- }
- } else {
- abortRecorrection(true);
- }
- }
-
- public void abortRecorrection(boolean force) {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED) return;
- if (force || TextEntryState.isRecorrecting()) {
- TextEntryState.onAbortRecorrection();
- mService.setCandidatesViewShown(mService.isCandidateStripVisible());
- mService.getCurrentInputConnection().finishComposingText();
- mService.clearSuggestions();
- }
- }
-
- public void updateRecorrectionEnabled(Resources res, SharedPreferences prefs) {
- // If the option should not be shown, do not read the re-correction preference
- // but always use the default setting defined in the resources.
- if (res.getBoolean(R.bool.config_enable_show_recorrection_option)) {
- mRecorrectionEnabled = prefs.getBoolean(Settings.PREF_RECORRECTION_ENABLED,
- res.getBoolean(R.bool.config_default_recorrection_enabled));
- } else {
- mRecorrectionEnabled = res.getBoolean(R.bool.config_default_recorrection_enabled);
- }
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- if (SuggestionSpanUtils.SUGGESTION_SPAN_IS_SUPPORTED) return;
- if (key.equals(Settings.PREF_RECORRECTION_ENABLED)) {
- updateRecorrectionEnabled(mService.getResources(), prefs);
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/recorrection/RecorrectionSuggestionEntries.java b/java/src/com/android/inputmethod/deprecated/recorrection/RecorrectionSuggestionEntries.java
deleted file mode 100644
index 5e6c87044..000000000
--- a/java/src/com/android/inputmethod/deprecated/recorrection/RecorrectionSuggestionEntries.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.deprecated.recorrection;
-
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.latin.Suggest;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.WordComposer;
-
-import android.text.TextUtils;
-
-public class RecorrectionSuggestionEntries {
- public final CharSequence mChosenWord;
- public final WordComposer mWordComposer;
-
- public RecorrectionSuggestionEntries(CharSequence chosenWord, WordComposer wordComposer) {
- mChosenWord = chosenWord;
- mWordComposer = wordComposer;
- }
-
- public CharSequence getChosenWord() {
- return mChosenWord;
- }
-
- public CharSequence getOriginalWord() {
- return mWordComposer.getTypedWord();
- }
-
- public SuggestedWords.Builder getAlternatives(
- Suggest suggest, KeyboardSwitcher keyboardSwitcher) {
- return getTypedSuggestions(suggest, keyboardSwitcher, mWordComposer);
- }
-
- @Override
- public int hashCode() {
- return mChosenWord.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof CharSequence && TextUtils.equals(mChosenWord, (CharSequence)o);
- }
-
- private static SuggestedWords.Builder getTypedSuggestions(
- Suggest suggest, KeyboardSwitcher keyboardSwitcher, WordComposer word) {
- return suggest.getSuggestedWordBuilder(keyboardSwitcher.getKeyboardView(), word, null);
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
deleted file mode 100644
index 3c79cc218..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
+++ /dev/null
@@ -1,104 +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.deprecated.voice;
-
-import android.os.Bundle;
-import android.util.Log;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-/**
- * Represents information about a given text field, which can be passed
- * to the speech recognizer as context information.
- */
-public class FieldContext {
- private static final boolean DBG = false;
-
- static final String LABEL = "label";
- static final String HINT = "hint";
- static final String PACKAGE_NAME = "packageName";
- static final String FIELD_ID = "fieldId";
- static final String FIELD_NAME = "fieldName";
- static final String SINGLE_LINE = "singleLine";
- static final String INPUT_TYPE = "inputType";
- static final String IME_OPTIONS = "imeOptions";
- static final String SELECTED_LANGUAGE = "selectedLanguage";
- static final String ENABLED_LANGUAGES = "enabledLanguages";
-
- Bundle mFieldInfo;
-
- public FieldContext(InputConnection conn, EditorInfo info,
- String selectedLanguage, String[] enabledLanguages) {
- mFieldInfo = new Bundle();
- addEditorInfoToBundle(info, mFieldInfo);
- addInputConnectionToBundle(conn, mFieldInfo);
- addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo);
- if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString());
- }
-
- private static String safeToString(Object o) {
- if (o == null) {
- return "";
- }
- return o.toString();
- }
-
- private static void addEditorInfoToBundle(EditorInfo info, Bundle bundle) {
- if (info == null) {
- return;
- }
-
- bundle.putString(LABEL, safeToString(info.label));
- bundle.putString(HINT, safeToString(info.hintText));
- bundle.putString(PACKAGE_NAME, safeToString(info.packageName));
- bundle.putInt(FIELD_ID, info.fieldId);
- bundle.putString(FIELD_NAME, safeToString(info.fieldName));
- bundle.putInt(INPUT_TYPE, info.inputType);
- bundle.putInt(IME_OPTIONS, info.imeOptions);
- }
-
- @SuppressWarnings("static-access")
- private static void addInputConnectionToBundle(
- InputConnection conn, Bundle bundle) {
- if (conn == null) {
- return;
- }
-
- ExtractedText et = conn.getExtractedText(new ExtractedTextRequest(), 0);
- if (et == null) {
- return;
- }
- bundle.putBoolean(SINGLE_LINE, (et.flags & et.FLAG_SINGLE_LINE) > 0);
- }
-
- private static void addLanguageInfoToBundle(
- String selectedLanguage, String[] enabledLanguages, Bundle bundle) {
- bundle.putString(SELECTED_LANGUAGE, selectedLanguage);
- bundle.putStringArray(ENABLED_LANGUAGES, enabledLanguages);
- }
-
- public Bundle getBundle() {
- return mFieldInfo;
- }
-
- @Override
- public String toString() {
- return mFieldInfo.toString();
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/Hints.java b/java/src/com/android/inputmethod/deprecated/voice/Hints.java
deleted file mode 100644
index 06b234381..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/Hints.java
+++ /dev/null
@@ -1,188 +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.deprecated.voice;
-
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SharedPreferencesCompat;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.view.inputmethod.InputConnection;
-
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Logic to determine when to display hints on usage to the user.
- */
-public class Hints {
- public interface Display {
- public void showHint(int viewResource);
- }
-
- private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN =
- "voice_hint_num_unique_days_shown";
- private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN =
- "voice_hint_last_time_shown";
- private static final String PREF_VOICE_INPUT_LAST_TIME_USED =
- "voice_input_last_time_used";
- private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT =
- "voice_punctuation_hint_view_count";
- private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7;
- private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7;
-
- private final Context mContext;
- private final SharedPreferences mPrefs;
- private final Display mDisplay;
- private boolean mVoiceResultContainedPunctuation;
- private int mSwipeHintMaxDaysToShow;
- private int mPunctuationHintMaxDisplays;
-
- // Only show punctuation hint if voice result did not contain punctuation.
- static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION
- = new HashMap<CharSequence, String>();
- static {
- SPEAKABLE_PUNCTUATION.put(",", "comma");
- SPEAKABLE_PUNCTUATION.put(".", "period");
- SPEAKABLE_PUNCTUATION.put("?", "question mark");
- }
-
- public Hints(Context context, SharedPreferences prefs, Display display) {
- mContext = context;
- mPrefs = prefs;
- mDisplay = display;
-
- ContentResolver cr = mContext.getContentResolver();
- mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt(
- cr,
- SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS,
- DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW);
- mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt(
- cr,
- SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS,
- DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS);
- }
-
- public boolean showSwipeHintIfNecessary(boolean fieldRecommended) {
- if (fieldRecommended && shouldShowSwipeHint()) {
- showHint(R.layout.voice_swipe_hint);
- return true;
- }
-
- return false;
- }
-
- public boolean showPunctuationHintIfNecessary(InputConnection ic) {
- if (!mVoiceResultContainedPunctuation
- && ic != null
- && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT)
- < mPunctuationHintMaxDisplays) {
- CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0);
- if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) {
- showHint(R.layout.voice_punctuation_hint);
- return true;
- }
- }
-
- return false;
- }
-
- public void registerVoiceResult(String text) {
- // Update the current time as the last time voice input was used.
- SharedPreferences.Editor editor = mPrefs.edit();
- editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis());
- SharedPreferencesCompat.apply(editor);
-
- mVoiceResultContainedPunctuation = false;
- for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) {
- if (text.indexOf(s.toString()) >= 0) {
- mVoiceResultContainedPunctuation = true;
- break;
- }
- }
- }
-
- private boolean shouldShowSwipeHint() {
- final SharedPreferences prefs = mPrefs;
-
- int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
-
- // If we've already shown the hint for enough days, we'll return false.
- if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) {
-
- long lastTimeVoiceWasUsed = prefs.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0);
-
- // If the user has used voice today, we'll return false. (We don't show the hint on
- // any day that the user has already used voice.)
- if (!isFromToday(lastTimeVoiceWasUsed)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Determines whether the provided time is from some time today (i.e., this day, month,
- * and year).
- */
- private boolean isFromToday(long timeInMillis) {
- if (timeInMillis == 0) return false;
-
- Calendar today = Calendar.getInstance();
- today.setTimeInMillis(System.currentTimeMillis());
-
- Calendar timestamp = Calendar.getInstance();
- timestamp.setTimeInMillis(timeInMillis);
-
- return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) &&
- today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) &&
- today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH));
- }
-
- private void showHint(int hintViewResource) {
- final SharedPreferences prefs = mPrefs;
-
- int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
- long lastTimeHintWasShown = prefs.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0);
-
- // If this is the first time the hint is being shown today, increase the saved values
- // to represent that. We don't need to increase the last time the hint was shown unless
- // it is a different day from the current value.
- if (!isFromToday(lastTimeHintWasShown)) {
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1);
- editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis());
- SharedPreferencesCompat.apply(editor);
- }
-
- if (mDisplay != null) {
- mDisplay.showHint(hintViewResource);
- }
- }
-
- private int getAndIncrementPref(String pref) {
- final SharedPreferences prefs = mPrefs;
- int value = prefs.getInt(pref, 0);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(pref, value + 1);
- SharedPreferencesCompat.apply(editor);
- return value;
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java
deleted file mode 100644
index dcb826e8f..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java
+++ /dev/null
@@ -1,354 +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.deprecated.voice;
-
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.CornerPathEffect;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PathEffect;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.util.Locale;
-
-/**
- * The user interface for the "Speak now" and "working" states.
- * Displays a recognition dialog (with waveform, voice meter, etc.),
- * plays beeps, shows errors, etc.
- */
-public class RecognitionView {
- private static final String TAG = "RecognitionView";
-
- private Handler mUiHandler; // Reference to UI thread
- private View mView;
- private Context mContext;
-
- private TextView mText;
- private ImageView mImage;
- private View mProgress;
- private SoundIndicator mSoundIndicator;
- private TextView mLanguage;
- private Button mButton;
-
- private Drawable mInitializing;
- private Drawable mError;
-
- private static final int INIT = 0;
- private static final int LISTENING = 1;
- private static final int WORKING = 2;
- private static final int READY = 3;
-
- private int mState = INIT;
-
- private final View mPopupLayout;
-
- private final Drawable mListeningBorder;
- private final Drawable mWorkingBorder;
- private final Drawable mErrorBorder;
-
- public RecognitionView(Context context, OnClickListener clickListener) {
- mUiHandler = new Handler();
-
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
-
- mView = inflater.inflate(R.layout.recognition_status, null);
-
- mPopupLayout= mView.findViewById(R.id.popup_layout);
-
- // Pre-load volume level images
- Resources r = context.getResources();
-
- mListeningBorder = r.getDrawable(R.drawable.vs_dialog_red);
- mWorkingBorder = r.getDrawable(R.drawable.vs_dialog_blue);
- mErrorBorder = r.getDrawable(R.drawable.vs_dialog_yellow);
-
- mInitializing = r.getDrawable(R.drawable.mic_slash);
- mError = r.getDrawable(R.drawable.caution);
-
- mImage = (ImageView) mView.findViewById(R.id.image);
- mProgress = mView.findViewById(R.id.progress);
- mSoundIndicator = (SoundIndicator) mView.findViewById(R.id.sound_indicator);
-
- mButton = (Button) mView.findViewById(R.id.button);
- mButton.setOnClickListener(clickListener);
- mText = (TextView) mView.findViewById(R.id.text);
- mLanguage = (TextView) mView.findViewById(R.id.language);
-
- mContext = context;
- }
-
- public View getView() {
- return mView;
- }
-
- public void restoreState() {
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- // Restart the spinner
- if (mState == WORKING) {
- ((ProgressBar) mProgress).setIndeterminate(false);
- ((ProgressBar) mProgress).setIndeterminate(true);
- }
- }
- });
- }
-
- public void showInitializing() {
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- mState = INIT;
- prepareDialog(mContext.getText(R.string.voice_initializing), mInitializing,
- mContext.getText(R.string.cancel));
- }
- });
- }
-
- public void showListening() {
- Log.d(TAG, "#showListening");
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- mState = LISTENING;
- prepareDialog(mContext.getText(R.string.voice_listening), null,
- mContext.getText(R.string.cancel));
- }
- });
- }
-
- public void updateVoiceMeter(float rmsdB) {
- mSoundIndicator.setRmsdB(rmsdB);
- }
-
- public void showError(final String message) {
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- mState = READY;
- prepareDialog(message, mError, mContext.getText(R.string.ok));
- }
- });
- }
-
- public void showWorking(
- final ByteArrayOutputStream waveBuffer,
- final int speechStartPosition,
- final int speechEndPosition) {
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- mState = WORKING;
- prepareDialog(mContext.getText(R.string.voice_working), null, mContext
- .getText(R.string.cancel));
- final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order(
- ByteOrder.nativeOrder()).asShortBuffer();
- buf.position(0);
- waveBuffer.reset();
- showWave(buf, speechStartPosition / 2, speechEndPosition / 2);
- }
- });
- }
-
- private void prepareDialog(CharSequence text, Drawable image,
- CharSequence btnTxt) {
-
- /*
- * The mic of INIT and of LISTENING has to be displayed in the same position. To accomplish
- * that, some text visibility are not set as GONE but as INVISIBLE.
- */
- switch (mState) {
- case INIT:
- mText.setVisibility(View.INVISIBLE);
-
- mProgress.setVisibility(View.GONE);
-
- mImage.setVisibility(View.VISIBLE);
- mImage.setImageResource(R.drawable.mic_slash);
-
- mSoundIndicator.setVisibility(View.GONE);
- mSoundIndicator.stop();
-
- mLanguage.setVisibility(View.INVISIBLE);
-
- mPopupLayout.setBackgroundDrawable(mListeningBorder);
- break;
- case LISTENING:
- mText.setVisibility(View.VISIBLE);
- mText.setText(text);
-
- mProgress.setVisibility(View.GONE);
-
- mImage.setVisibility(View.GONE);
-
- mSoundIndicator.setVisibility(View.VISIBLE);
- mSoundIndicator.start();
-
- Locale locale = SubtypeSwitcher.getInstance().getInputLocale();
-
- mLanguage.setVisibility(View.VISIBLE);
- mLanguage.setText(SubtypeSwitcher.getFullDisplayName(locale, true));
-
- mPopupLayout.setBackgroundDrawable(mListeningBorder);
- break;
- case WORKING:
-
- mText.setVisibility(View.VISIBLE);
- mText.setText(text);
-
- mProgress.setVisibility(View.VISIBLE);
-
- mImage.setVisibility(View.VISIBLE);
-
- mSoundIndicator.setVisibility(View.GONE);
- mSoundIndicator.stop();
-
- mLanguage.setVisibility(View.GONE);
-
- mPopupLayout.setBackgroundDrawable(mWorkingBorder);
- break;
- case READY:
- mText.setVisibility(View.VISIBLE);
- mText.setText(text);
-
- mProgress.setVisibility(View.GONE);
-
- mImage.setVisibility(View.VISIBLE);
- mImage.setImageResource(R.drawable.caution);
-
- mSoundIndicator.setVisibility(View.GONE);
- mSoundIndicator.stop();
-
- mLanguage.setVisibility(View.GONE);
-
- mPopupLayout.setBackgroundDrawable(mErrorBorder);
- break;
- default:
- Log.w(TAG, "Unknown state " + mState);
- }
- mPopupLayout.requestLayout();
- mButton.setText(btnTxt);
- }
-
- /**
- * @return an average abs of the specified buffer.
- */
- private static int getAverageAbs(ShortBuffer buffer, int start, int i, int npw) {
- int from = start + i * npw;
- int end = from + npw;
- int total = 0;
- for (int x = from; x < end; x++) {
- total += Math.abs(buffer.get(x));
- }
- return total / npw;
- }
-
-
- /**
- * Shows waveform of input audio.
- *
- * Copied from version in VoiceSearch's RecognitionActivity.
- *
- * TODO: adjust stroke width based on the size of data.
- * TODO: use dip rather than pixels.
- */
- private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) {
- final int w = ((View) mImage.getParent()).getWidth();
- final int h = ((View) mImage.getParent()).getHeight();
- if (w <= 0 || h <= 0) {
- // view is not visible this time. Skip drawing.
- return;
- }
- final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- final Canvas c = new Canvas(b);
- final Paint paint = new Paint();
- paint.setColor(0xFFFFFFFF); // 0xAARRGGBB
- paint.setAntiAlias(true);
- paint.setStyle(Paint.Style.STROKE);
- paint.setAlpha(80);
-
- final PathEffect effect = new CornerPathEffect(3);
- paint.setPathEffect(effect);
-
- final int numSamples = waveBuffer.remaining();
- int endIndex;
- if (endPosition == 0) {
- endIndex = numSamples;
- } else {
- endIndex = Math.min(endPosition, numSamples);
- }
-
- int startIndex = startPosition - 2000; // include 250ms before speech
- if (startIndex < 0) {
- startIndex = 0;
- }
- final int numSamplePerWave = 200; // 8KHz 25ms = 200 samples
- final float scale = 10.0f / 65536.0f;
-
- final int count = (endIndex - startIndex) / numSamplePerWave;
- final float deltaX = 1.0f * w / count;
- int yMax = h / 2;
- Path path = new Path();
- c.translate(0, yMax);
- float x = 0;
- path.moveTo(x, 0);
- for (int i = 0; i < count; i++) {
- final int avabs = getAverageAbs(waveBuffer, startIndex, i , numSamplePerWave);
- int sign = ( (i & 01) == 0) ? -1 : 1;
- final float y = Math.min(yMax, avabs * h * scale) * sign;
- path.lineTo(x, y);
- x += deltaX;
- path.lineTo(x, y);
- }
- if (deltaX > 4) {
- paint.setStrokeWidth(2);
- } else {
- paint.setStrokeWidth(Math.max(0, (int) (deltaX -.05)));
- }
- c.drawPath(path, paint);
- mImage.setImageBitmap(b);
- }
-
- public void finish() {
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- mSoundIndicator.stop();
- }
- });
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java b/java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java
deleted file mode 100644
index 855a09a1d..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java
+++ /dev/null
@@ -1,110 +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.deprecated.voice;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-
-/**
- * Utility for retrieving settings from Settings.Secure.
- */
-public class SettingsUtil {
- /**
- * A whitespace-separated list of supported locales for voice input from the keyboard.
- */
- public static final String LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES =
- "latin_ime_voice_input_supported_locales";
-
- /**
- * A whitespace-separated list of recommended app packages for voice input from the
- * keyboard.
- */
- public static final String LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES =
- "latin_ime_voice_input_recommended_packages";
-
- /**
- * The maximum number of unique days to show the swipe hint for voice input.
- */
- public static final String LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS =
- "latin_ime_voice_input_swipe_hint_max_days";
-
- /**
- * The maximum number of times to show the punctuation hint for voice input.
- */
- public static final String LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS =
- "latin_ime_voice_input_punctuation_hint_max_displays";
-
- /**
- * Endpointer parameters for voice input from the keyboard.
- */
- public static final String LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS =
- "latin_ime_speech_minimum_length_millis";
- public static final String LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
- "latin_ime_speech_input_complete_silence_length_millis";
- public static final String LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
- "latin_ime_speech_input_possibly_complete_silence_length_millis";
-
- /**
- * Min and max volume levels that can be displayed on the "speak now" screen.
- */
- public static final String LATIN_IME_MIN_MICROPHONE_LEVEL =
- "latin_ime_min_microphone_level";
- public static final String LATIN_IME_MAX_MICROPHONE_LEVEL =
- "latin_ime_max_microphone_level";
-
- /**
- * The number of sentence-level alternates to request of the server.
- */
- public static final String LATIN_IME_MAX_VOICE_RESULTS = "latin_ime_max_voice_results";
-
- /**
- * Get a string-valued setting.
- *
- * @param cr The content resolver to use
- * @param key The setting to look up
- * @param defaultValue The default value to use if none can be found
- * @return The value of the setting, or defaultValue if it couldn't be found
- */
- public static String getSettingsString(ContentResolver cr, String key, String defaultValue) {
- String result = Settings.Secure.getString(cr, key);
- return (result == null) ? defaultValue : result;
- }
-
- /**
- * Get an int-valued setting.
- *
- * @param cr The content resolver to use
- * @param key The setting to look up
- * @param defaultValue The default value to use if the setting couldn't be found or parsed
- * @return The value of the setting, or defaultValue if it couldn't be found or parsed
- */
- public static int getSettingsInt(ContentResolver cr, String key, int defaultValue) {
- return Settings.Secure.getInt(cr, key, defaultValue);
- }
-
- /**
- * Get a float-valued setting.
- *
- * @param cr The content resolver to use
- * @param key The setting to look up
- * @param defaultValue The default value to use if the setting couldn't be found or parsed
- * @return The value of the setting, or defaultValue if it couldn't be found or parsed
- */
- public static float getSettingsFloat(ContentResolver cr, String key, float defaultValue) {
- return Settings.Secure.getFloat(cr, key, defaultValue);
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java b/java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java
deleted file mode 100644
index 25b314085..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.deprecated.voice;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.android.inputmethod.latin.R;
-
-/**
- * A widget which shows the volume of audio using a microphone icon
- */
-public class SoundIndicator extends ImageView {
- @SuppressWarnings("unused")
- private static final String TAG = "SoundIndicator";
-
- private static final float UP_SMOOTHING_FACTOR = 0.9f;
- private static final float DOWN_SMOOTHING_FACTOR = 0.4f;
-
- private static final float AUDIO_METER_MIN_DB = 7.0f;
- private static final float AUDIO_METER_DB_RANGE = 20.0f;
-
- private static final long FRAME_DELAY = 50;
-
- private Bitmap mDrawingBuffer;
- private Canvas mBufferCanvas;
- private Bitmap mEdgeBitmap;
- private float mLevel = 0.0f;
- private Drawable mFrontDrawable;
- private Paint mClearPaint;
- private Paint mMultPaint;
- private int mEdgeBitmapOffset;
-
- private Handler mHandler;
-
- private Runnable mDrawFrame = new Runnable() {
- public void run() {
- invalidate();
- mHandler.postDelayed(mDrawFrame, FRAME_DELAY);
- }
- };
-
- public SoundIndicator(Context context) {
- this(context, null);
- }
-
- public SoundIndicator(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- mFrontDrawable = getDrawable();
- BitmapDrawable edgeDrawable =
- (BitmapDrawable) context.getResources().getDrawable(R.drawable.vs_popup_mic_edge);
- mEdgeBitmap = edgeDrawable.getBitmap();
- mEdgeBitmapOffset = mEdgeBitmap.getHeight() / 2;
-
- mDrawingBuffer =
- Bitmap.createBitmap(mFrontDrawable.getIntrinsicWidth(),
- mFrontDrawable.getIntrinsicHeight(), Config.ARGB_8888);
-
- mBufferCanvas = new Canvas(mDrawingBuffer);
-
- // Initialize Paints.
- mClearPaint = new Paint();
- mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
-
- mMultPaint = new Paint();
- mMultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
-
- mHandler = new Handler();
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- //super.onDraw(canvas);
-
- float w = getWidth();
- float h = getHeight();
-
- // Clear the buffer canvas
- mBufferCanvas.drawRect(0, 0, w, h, mClearPaint);
-
- // Set its clip so we don't draw the front image all the way to the top
- Rect clip = new Rect(0,
- (int) ((1.0 - mLevel) * (h + mEdgeBitmapOffset)) - mEdgeBitmapOffset,
- (int) w,
- (int) h);
-
- mBufferCanvas.save();
- mBufferCanvas.clipRect(clip);
-
- // Draw the front image
- mFrontDrawable.setBounds(new Rect(0, 0, (int) w, (int) h));
- mFrontDrawable.draw(mBufferCanvas);
-
- mBufferCanvas.restore();
-
- // Draw the edge image on top of the buffer image with a multiply mode
- mBufferCanvas.drawBitmap(mEdgeBitmap, 0, clip.top, mMultPaint);
-
- // Draw the buffer image (on top of the background image)
- canvas.drawBitmap(mDrawingBuffer, 0, 0, null);
- }
-
- /**
- * Sets the sound level
- *
- * @param rmsdB The level of the sound, in dB.
- */
- public void setRmsdB(float rmsdB) {
- float level = ((rmsdB - AUDIO_METER_MIN_DB) / AUDIO_METER_DB_RANGE);
-
- level = Math.min(Math.max(0.0f, level), 1.0f);
-
- // We smooth towards the new level
- if (level > mLevel) {
- mLevel = (level - mLevel) * UP_SMOOTHING_FACTOR + mLevel;
- } else {
- mLevel = (level - mLevel) * DOWN_SMOOTHING_FACTOR + mLevel;
- }
- invalidate();
- }
-
- public void start() {
- mHandler.post(mDrawFrame);
- }
-
- public void stop() {
- mHandler.removeCallbacks(mDrawFrame);
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java b/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java
deleted file mode 100644
index 8969a2168..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java
+++ /dev/null
@@ -1,692 +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.deprecated.voice;
-
-import com.android.inputmethod.latin.EditingUtils;
-import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Message;
-import android.os.Parcelable;
-import android.speech.RecognitionListener;
-import android.speech.RecognizerIntent;
-import android.speech.SpeechRecognizer;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.inputmethod.InputConnection;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Speech recognition input, including both user interface and a background
- * process to stream audio to the network recognizer. This class supplies a
- * View (getView()), which it updates as recognition occurs. The user of this
- * class is responsible for making the view visible to the user, as well as
- * handling various events returned through UiListener.
- */
-public class VoiceInput implements OnClickListener {
- private static final String TAG = "VoiceInput";
- private static final String EXTRA_RECOGNITION_CONTEXT =
- "android.speech.extras.RECOGNITION_CONTEXT";
- private static final String EXTRA_CALLING_PACKAGE = "calling_package";
- private static final String EXTRA_ALTERNATES = "android.speech.extra.ALTERNATES";
- private static final int MAX_ALT_LIST_LENGTH = 6;
- private static boolean DBG = LatinImeLogger.sDBG;
-
- private static final String DEFAULT_RECOMMENDED_PACKAGES =
- "com.android.mms " +
- "com.google.android.gm " +
- "com.google.android.talk " +
- "com.google.android.apps.googlevoice " +
- "com.android.email " +
- "com.android.browser ";
-
- // WARNING! Before enabling this, fix the problem with calling getExtractedText() in
- // landscape view. It causes Extracted text updates to be rejected due to a token mismatch
- public static boolean ENABLE_WORD_CORRECTIONS = true;
-
- // Dummy word suggestion which means "delete current word"
- public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
-
- private Whitelist mRecommendedList;
- private Whitelist mBlacklist;
-
- private VoiceInputLogger mLogger;
-
- // Names of a few extras defined in VoiceSearch's RecognitionController
- // Note, the version of voicesearch that shipped in Froyo returns the raw
- // RecognitionClientAlternates protocol buffer under the key "alternates",
- // so a VS market update must be installed on Froyo devices in order to see
- // alternatives.
- private static final String ALTERNATES_BUNDLE = "alternates_bundle";
-
- // This is copied from the VoiceSearch app.
- @SuppressWarnings("unused")
- private static final class AlternatesBundleKeys {
- public static final String ALTERNATES = "alternates";
- public static final String CONFIDENCE = "confidence";
- public static final String LENGTH = "length";
- public static final String MAX_SPAN_LENGTH = "max_span_length";
- public static final String SPANS = "spans";
- public static final String SPAN_KEY_DELIMITER = ":";
- public static final String START = "start";
- public static final String TEXT = "text";
- }
-
- // Names of a few intent extras defined in VoiceSearch's RecognitionService.
- // These let us tweak the endpointer parameters.
- private static final String EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS =
- "android.speech.extras.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS";
- private static final String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS =
- "android.speech.extras.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS";
- private static final String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS =
- "android.speech.extras.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS";
-
- // The usual endpointer default value for input complete silence length is 0.5 seconds,
- // but that's used for things like voice search. For dictation-like voice input like this,
- // we go with a more liberal value of 1 second. This value will only be used if a value
- // is not provided from Gservices.
- private static final String INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS = "1000";
-
- // Used to record part of that state for logging purposes.
- public static final int DEFAULT = 0;
- public static final int LISTENING = 1;
- public static final int WORKING = 2;
- public static final int ERROR = 3;
-
- private int mAfterVoiceInputDeleteCount = 0;
- private int mAfterVoiceInputInsertCount = 0;
- private int mAfterVoiceInputInsertPunctuationCount = 0;
- private int mAfterVoiceInputCursorPos = 0;
- private int mAfterVoiceInputSelectionSpan = 0;
-
- private int mState = DEFAULT;
-
- private final static int MSG_RESET = 1;
-
- private final UIHandler mHandler = new UIHandler(this);
-
- private static class UIHandler extends StaticInnerHandlerWrapper<VoiceInput> {
- public UIHandler(VoiceInput outerInstance) {
- super(outerInstance);
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_RESET) {
- final VoiceInput voiceInput = getOuterInstance();
- voiceInput.mState = DEFAULT;
- voiceInput.mRecognitionView.finish();
- voiceInput.mUiListener.onCancelVoice();
- }
- }
- };
-
- /**
- * Events relating to the recognition UI. You must implement these.
- */
- public interface UiListener {
-
- /**
- * @param recognitionResults a set of transcripts for what the user
- * spoke, sorted by likelihood.
- */
- public void onVoiceResults(
- List<String> recognitionResults,
- Map<String, List<CharSequence>> alternatives);
-
- /**
- * Called when the user cancels speech recognition.
- */
- public void onCancelVoice();
- }
-
- private SpeechRecognizer mSpeechRecognizer;
- private RecognitionListener mRecognitionListener;
- private RecognitionView mRecognitionView;
- private UiListener mUiListener;
- private Context mContext;
-
- /**
- * @param context the service or activity in which we're running.
- * @param uiHandler object to receive events from VoiceInput.
- */
- public VoiceInput(Context context, UiListener uiHandler) {
- mLogger = VoiceInputLogger.getLogger(context);
- mRecognitionListener = new ImeRecognitionListener();
- mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(context);
- mSpeechRecognizer.setRecognitionListener(mRecognitionListener);
- mUiListener = uiHandler;
- mContext = context;
- newView();
-
- String recommendedPackages = SettingsUtil.getSettingsString(
- context.getContentResolver(),
- SettingsUtil.LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES,
- DEFAULT_RECOMMENDED_PACKAGES);
-
- mRecommendedList = new Whitelist();
- for (String recommendedPackage : recommendedPackages.split("\\s+")) {
- mRecommendedList.addApp(recommendedPackage);
- }
-
- mBlacklist = new Whitelist();
- mBlacklist.addApp("com.google.android.setupwizard");
- }
-
- public void setCursorPos(int pos) {
- mAfterVoiceInputCursorPos = pos;
- }
-
- public int getCursorPos() {
- return mAfterVoiceInputCursorPos;
- }
-
- public void setSelectionSpan(int span) {
- mAfterVoiceInputSelectionSpan = span;
- }
-
- public int getSelectionSpan() {
- return mAfterVoiceInputSelectionSpan;
- }
-
- public void incrementTextModificationDeleteCount(int count){
- mAfterVoiceInputDeleteCount += count;
- // Send up intents for other text modification types
- if (mAfterVoiceInputInsertCount > 0) {
- logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount);
- mAfterVoiceInputInsertCount = 0;
- }
- if (mAfterVoiceInputInsertPunctuationCount > 0) {
- logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount);
- mAfterVoiceInputInsertPunctuationCount = 0;
- }
-
- }
-
- public void incrementTextModificationInsertCount(int count){
- mAfterVoiceInputInsertCount += count;
- if (mAfterVoiceInputSelectionSpan > 0) {
- // If text was highlighted before inserting the char, count this as
- // a delete.
- mAfterVoiceInputDeleteCount += mAfterVoiceInputSelectionSpan;
- }
- // Send up intents for other text modification types
- if (mAfterVoiceInputDeleteCount > 0) {
- logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount);
- mAfterVoiceInputDeleteCount = 0;
- }
- if (mAfterVoiceInputInsertPunctuationCount > 0) {
- logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount);
- mAfterVoiceInputInsertPunctuationCount = 0;
- }
- }
-
- public void incrementTextModificationInsertPunctuationCount(int count){
- mAfterVoiceInputInsertPunctuationCount += count;
- if (mAfterVoiceInputSelectionSpan > 0) {
- // If text was highlighted before inserting the char, count this as
- // a delete.
- mAfterVoiceInputDeleteCount += mAfterVoiceInputSelectionSpan;
- }
- // Send up intents for aggregated non-punctuation insertions
- if (mAfterVoiceInputDeleteCount > 0) {
- logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount);
- mAfterVoiceInputDeleteCount = 0;
- }
- if (mAfterVoiceInputInsertCount > 0) {
- logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount);
- mAfterVoiceInputInsertCount = 0;
- }
- }
-
- public void flushAllTextModificationCounters() {
- if (mAfterVoiceInputInsertCount > 0) {
- logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount);
- mAfterVoiceInputInsertCount = 0;
- }
- if (mAfterVoiceInputDeleteCount > 0) {
- logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount);
- mAfterVoiceInputDeleteCount = 0;
- }
- if (mAfterVoiceInputInsertPunctuationCount > 0) {
- logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount);
- mAfterVoiceInputInsertPunctuationCount = 0;
- }
- }
-
- /**
- * The configuration of the IME changed and may have caused the views to be layed out
- * again. Restore the state of the recognition view.
- */
- public void onConfigurationChanged(Configuration configuration) {
- mRecognitionView.restoreState();
- mRecognitionView.getView().dispatchConfigurationChanged(configuration);
- }
-
- /**
- * @return true if field is blacklisted for voice
- */
- public boolean isBlacklistedField(FieldContext context) {
- return mBlacklist.matches(context);
- }
-
- /**
- * Used to decide whether to show voice input hints for this field, etc.
- *
- * @return true if field is recommended for voice
- */
- public boolean isRecommendedField(FieldContext context) {
- return mRecommendedList.matches(context);
- }
-
- /**
- * Start listening for speech from the user. This will grab the microphone
- * and start updating the view provided by getView(). It is the caller's
- * responsibility to ensure that the view is visible to the user at this stage.
- *
- * @param context the same FieldContext supplied to voiceIsEnabled()
- * @param swipe whether this voice input was started by swipe, for logging purposes
- */
- public void startListening(FieldContext context, boolean swipe) {
- if (DBG) {
- Log.d(TAG, "startListening: " + context);
- }
-
- if (mState != DEFAULT) {
- Log.w(TAG, "startListening in the wrong status " + mState);
- }
-
- // If everything works ok, the voice input should be already in the correct state. As this
- // class can be called by third-party, we call reset just to be on the safe side.
- reset();
-
- Locale locale = Locale.getDefault();
- String localeString = locale.getLanguage() + "-" + locale.getCountry();
-
- mLogger.start(localeString, swipe);
-
- mState = LISTENING;
-
- mRecognitionView.showInitializing();
- startListeningAfterInitialization(context);
- }
-
- /**
- * Called only when the recognition manager's initialization completed
- *
- * @param context context with which {@link #startListening(FieldContext, boolean)} was executed
- */
- private void startListeningAfterInitialization(FieldContext context) {
- Intent intent = makeIntent();
- intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "");
- intent.putExtra(EXTRA_RECOGNITION_CONTEXT, context.getBundle());
- intent.putExtra(EXTRA_CALLING_PACKAGE, "VoiceIME");
- intent.putExtra(EXTRA_ALTERNATES, true);
- intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS,
- SettingsUtil.getSettingsInt(
- mContext.getContentResolver(),
- SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
- 1));
- // Get endpointer params from Gservices.
- // TODO: Consider caching these values for improved performance on slower devices.
- final ContentResolver cr = mContext.getContentResolver();
- putEndpointerExtra(
- cr,
- intent,
- SettingsUtil.LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS,
- EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS,
- null /* rely on endpointer default */);
- putEndpointerExtra(
- cr,
- intent,
- SettingsUtil.LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
- EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
- INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS
- /* our default value is different from the endpointer's */);
- putEndpointerExtra(
- cr,
- intent,
- SettingsUtil.
- LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
- EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
- null /* rely on endpointer default */);
-
- mSpeechRecognizer.startListening(intent);
- }
-
- /**
- * Gets the value of the provided Gservices key, attempts to parse it into a long,
- * and if successful, puts the long value as an extra in the provided intent.
- */
- private void putEndpointerExtra(ContentResolver cr, Intent i,
- String gservicesKey, String intentExtraKey, String defaultValue) {
- long l = -1;
- String s = SettingsUtil.getSettingsString(cr, gservicesKey, defaultValue);
- if (s != null) {
- try {
- l = Long.valueOf(s);
- } catch (NumberFormatException e) {
- Log.e(TAG, "could not parse value for " + gservicesKey + ": " + s);
- }
- }
-
- if (l != -1) i.putExtra(intentExtraKey, l);
- }
-
- public void destroy() {
- mSpeechRecognizer.destroy();
- }
-
- /**
- * Creates a new instance of the view that is returned by {@link #getView()}
- * Clients should use this when a previously returned view is stuck in a
- * layout that is being thrown away and a new one is need to show to the
- * user.
- */
- public void newView() {
- mRecognitionView = new RecognitionView(mContext, this);
- }
-
- /**
- * @return a view that shows the recognition flow--e.g., "Speak now" and
- * "working" dialogs.
- */
- public View getView() {
- return mRecognitionView.getView();
- }
-
- /**
- * Handle the cancel button.
- */
- @Override
- public void onClick(View view) {
- switch(view.getId()) {
- case R.id.button:
- cancel();
- break;
- }
- }
-
- public void logTextModifiedByTypingInsertion(int length) {
- mLogger.textModifiedByTypingInsertion(length);
- }
-
- public void logTextModifiedByTypingInsertionPunctuation(int length) {
- mLogger.textModifiedByTypingInsertionPunctuation(length);
- }
-
- public void logTextModifiedByTypingDeletion(int length) {
- mLogger.textModifiedByTypingDeletion(length);
- }
-
- public void logTextModifiedByChooseSuggestion(String suggestion, int index,
- String wordSeparators, InputConnection ic) {
- String wordToBeReplaced = EditingUtils.getWordAtCursor(ic, wordSeparators);
- // If we enable phrase-based alternatives, only send up the first word
- // in suggestion and wordToBeReplaced.
- mLogger.textModifiedByChooseSuggestion(suggestion.length(), wordToBeReplaced.length(),
- index, wordToBeReplaced, suggestion);
- }
-
- public void logKeyboardWarningDialogShown() {
- mLogger.keyboardWarningDialogShown();
- }
-
- public void logKeyboardWarningDialogDismissed() {
- mLogger.keyboardWarningDialogDismissed();
- }
-
- public void logKeyboardWarningDialogOk() {
- mLogger.keyboardWarningDialogOk();
- }
-
- public void logKeyboardWarningDialogCancel() {
- mLogger.keyboardWarningDialogCancel();
- }
-
- public void logSwipeHintDisplayed() {
- mLogger.swipeHintDisplayed();
- }
-
- public void logPunctuationHintDisplayed() {
- mLogger.punctuationHintDisplayed();
- }
-
- public void logVoiceInputDelivered(int length) {
- mLogger.voiceInputDelivered(length);
- }
-
- public void logInputEnded() {
- mLogger.inputEnded();
- }
-
- public void flushLogs() {
- mLogger.flush();
- }
-
- private static Intent makeIntent() {
- Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
-
- // On Cupcake, use VoiceIMEHelper since VoiceSearch doesn't support.
- // On Donut, always use VoiceSearch, since VoiceIMEHelper and
- // VoiceSearch may conflict.
- if (Build.VERSION.RELEASE.equals("1.5")) {
- intent = intent.setClassName(
- "com.google.android.voiceservice",
- "com.google.android.voiceservice.IMERecognitionService");
- } else {
- intent = intent.setClassName(
- "com.google.android.voicesearch",
- "com.google.android.voicesearch.RecognitionService");
- }
-
- return intent;
- }
-
- /**
- * Reset the current voice recognition.
- */
- public void reset() {
- if (mState != DEFAULT) {
- mState = DEFAULT;
-
- // Remove all pending tasks (e.g., timers to cancel voice input)
- mHandler.removeMessages(MSG_RESET);
-
- mSpeechRecognizer.cancel();
- mRecognitionView.finish();
- }
- }
-
- /**
- * Cancel in-progress speech recognition.
- */
- public void cancel() {
- switch (mState) {
- case LISTENING:
- mLogger.cancelDuringListening();
- break;
- case WORKING:
- mLogger.cancelDuringWorking();
- break;
- case ERROR:
- mLogger.cancelDuringError();
- break;
- }
-
- reset();
- mUiListener.onCancelVoice();
- }
-
- private int getErrorStringId(int errorType, boolean endpointed) {
- switch (errorType) {
- // We use CLIENT_ERROR to signify that voice search is not available on the device.
- case SpeechRecognizer.ERROR_CLIENT:
- return R.string.voice_not_installed;
- case SpeechRecognizer.ERROR_NETWORK:
- return R.string.voice_network_error;
- case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
- return endpointed ?
- R.string.voice_network_error : R.string.voice_too_much_speech;
- case SpeechRecognizer.ERROR_AUDIO:
- return R.string.voice_audio_error;
- case SpeechRecognizer.ERROR_SERVER:
- return R.string.voice_server_error;
- case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
- return R.string.voice_speech_timeout;
- case SpeechRecognizer.ERROR_NO_MATCH:
- return R.string.voice_no_match;
- default: return R.string.voice_error;
- }
- }
-
- private void onError(int errorType, boolean endpointed) {
- Log.i(TAG, "error " + errorType);
- mLogger.error(errorType);
- onError(mContext.getString(getErrorStringId(errorType, endpointed)));
- }
-
- private void onError(String error) {
- mState = ERROR;
- mRecognitionView.showError(error);
- // Wait a couple seconds and then automatically dismiss message.
- mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_RESET), 2000);
- }
-
- private class ImeRecognitionListener implements RecognitionListener {
- // Waveform data
- final ByteArrayOutputStream mWaveBuffer = new ByteArrayOutputStream();
- int mSpeechStart;
- private boolean mEndpointed = false;
-
- @Override
- public void onReadyForSpeech(Bundle noiseParams) {
- mRecognitionView.showListening();
- }
-
- @Override
- public void onBeginningOfSpeech() {
- mEndpointed = false;
- mSpeechStart = mWaveBuffer.size();
- }
-
- @Override
- public void onRmsChanged(float rmsdB) {
- mRecognitionView.updateVoiceMeter(rmsdB);
- }
-
- @Override
- public void onBufferReceived(byte[] buf) {
- try {
- mWaveBuffer.write(buf);
- } catch (IOException e) {
- // ignore.
- }
- }
-
- @Override
- public void onEndOfSpeech() {
- mEndpointed = true;
- mState = WORKING;
- mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
- }
-
- @Override
- public void onError(int errorType) {
- mState = ERROR;
- VoiceInput.this.onError(errorType, mEndpointed);
- }
-
- @Override
- public void onResults(Bundle resultsBundle) {
- List<String> results = resultsBundle
- .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
- // VS Market update is needed for IME froyo clients to access the alternatesBundle
- // TODO: verify this.
- Bundle alternatesBundle = resultsBundle.getBundle(ALTERNATES_BUNDLE);
- mState = DEFAULT;
-
- final Map<String, List<CharSequence>> alternatives =
- new HashMap<String, List<CharSequence>>();
-
- if (ENABLE_WORD_CORRECTIONS && alternatesBundle != null && results.size() > 0) {
- // Use the top recognition result to map each alternative's start:length to a word.
- String[] words = results.get(0).split(" ");
- Bundle spansBundle = alternatesBundle.getBundle(AlternatesBundleKeys.SPANS);
- for (String key : spansBundle.keySet()) {
- // Get the word for which these alternates correspond to.
- Bundle spanBundle = spansBundle.getBundle(key);
- int start = spanBundle.getInt(AlternatesBundleKeys.START);
- int length = spanBundle.getInt(AlternatesBundleKeys.LENGTH);
- // Only keep single-word based alternatives.
- if (length == 1 && start < words.length) {
- // Get the alternatives associated with the span.
- // If a word appears twice in a recognition result,
- // concatenate the alternatives for the word.
- List<CharSequence> altList = alternatives.get(words[start]);
- if (altList == null) {
- altList = new ArrayList<CharSequence>();
- alternatives.put(words[start], altList);
- }
- Parcelable[] alternatesArr = spanBundle
- .getParcelableArray(AlternatesBundleKeys.ALTERNATES);
- for (int j = 0; j < alternatesArr.length &&
- altList.size() < MAX_ALT_LIST_LENGTH; j++) {
- Bundle alternateBundle = (Bundle) alternatesArr[j];
- String alternate = alternateBundle.getString(AlternatesBundleKeys.TEXT);
- // Don't allow duplicates in the alternates list.
- if (!altList.contains(alternate)) {
- altList.add(alternate);
- }
- }
- }
- }
- }
-
- if (results.size() > 5) {
- results = results.subList(0, 5);
- }
- mUiListener.onVoiceResults(results, alternatives);
- mRecognitionView.finish();
- }
-
- @Override
- public void onPartialResults(final Bundle partialResults) {
- // currently - do nothing
- }
-
- @Override
- public void onEvent(int eventType, Bundle params) {
- // do nothing - reserved for events that might be added in the future
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java b/java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java
deleted file mode 100644
index 22e8207bf..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.deprecated.voice;
-
-import com.android.common.speech.LoggingEvents;
-import com.android.inputmethod.deprecated.compat.VoiceInputLoggerCompatUtils;
-
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Provides the logging facility for voice input events. This fires broadcasts back to
- * the voice search app which then logs on our behalf.
- *
- * Note that debug console logging does not occur in this class. If you want to
- * see console output of these logging events, there is a boolean switch to turn
- * on on the VoiceSearch side.
- */
-public class VoiceInputLogger {
- @SuppressWarnings("unused")
- private static final String TAG = VoiceInputLogger.class.getSimpleName();
-
- private static VoiceInputLogger sVoiceInputLogger;
-
- private final Context mContext;
-
- // The base intent used to form all broadcast intents to the logger
- // in VoiceSearch.
- private final Intent mBaseIntent;
-
- // This flag is used to indicate when there are voice events that
- // need to be flushed.
- private boolean mHasLoggingInfo = false;
-
- /**
- * Returns the singleton of the logger.
- *
- * @param contextHint a hint context used when creating the logger instance.
- * Ignored if the singleton instance already exists.
- */
- public static synchronized VoiceInputLogger getLogger(Context contextHint) {
- if (sVoiceInputLogger == null) {
- sVoiceInputLogger = new VoiceInputLogger(contextHint);
- }
- return sVoiceInputLogger;
- }
-
- public VoiceInputLogger(Context context) {
- mContext = context;
-
- mBaseIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
- mBaseIntent.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME);
- }
-
- private Intent newLoggingBroadcast(int event) {
- Intent i = new Intent(mBaseIntent);
- i.putExtra(LoggingEvents.EXTRA_EVENT, event);
- return i;
- }
-
- public void flush() {
- if (hasLoggingInfo()) {
- Intent i = new Intent(mBaseIntent);
- i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
- mContext.sendBroadcast(i);
- setHasLoggingInfo(false);
- }
- }
-
- public void keyboardWarningDialogShown() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_SHOWN));
- }
-
- public void keyboardWarningDialogDismissed() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_DISMISSED));
- }
-
- public void keyboardWarningDialogOk() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_OK));
- }
-
- public void keyboardWarningDialogCancel() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_CANCEL));
- }
-
- public void settingsWarningDialogShown() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_SHOWN));
- }
-
- public void settingsWarningDialogDismissed() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_DISMISSED));
- }
-
- public void settingsWarningDialogOk() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_OK));
- }
-
- public void settingsWarningDialogCancel() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_CANCEL));
- }
-
- public void swipeHintDisplayed() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.SWIPE_HINT_DISPLAYED));
- }
-
- public void cancelDuringListening() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_LISTENING));
- }
-
- public void cancelDuringWorking() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_WORKING));
- }
-
- public void cancelDuringError() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_ERROR));
- }
-
- public void punctuationHintDisplayed() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.PUNCTUATION_HINT_DISPLAYED));
- }
-
- public void error(int code) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.ERROR);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_ERROR_CODE, code);
- mContext.sendBroadcast(i);
- }
-
- public void start(String locale, boolean swipe) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.START);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_LOCALE, locale);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_SWIPE, swipe);
- i.putExtra(LoggingEvents.EXTRA_TIMESTAMP, System.currentTimeMillis());
- mContext.sendBroadcast(i);
- }
-
- public void voiceInputDelivered(int length) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.VOICE_INPUT_DELIVERED);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length);
- mContext.sendBroadcast(i);
- }
-
- public void textModifiedByTypingInsertion(int length) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE,
- LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_INSERTION);
- mContext.sendBroadcast(i);
- }
-
- public void textModifiedByTypingInsertionPunctuation(int length) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE,
- LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_INSERTION_PUNCTUATION);
- mContext.sendBroadcast(i);
- }
-
- public void textModifiedByTypingDeletion(int length) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE,
- LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_DELETION);
-
- mContext.sendBroadcast(i);
- }
-
-
- public void textModifiedByChooseSuggestion(int suggestionLength, int replacedPhraseLength,
- int index, String before, String after) {
- setHasLoggingInfo(true);
- Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, suggestionLength);
- i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_TEXT_REPLACED_LENGTH, replacedPhraseLength);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE,
- LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_CHOOSE_SUGGESTION);
- i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index);
- i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_BEFORE_N_BEST_CHOOSE, before);
- i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_AFTER_N_BEST_CHOOSE, after);
- mContext.sendBroadcast(i);
- }
-
- public void inputEnded() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.INPUT_ENDED));
- }
-
- public void voiceInputSettingEnabled() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_ENABLED));
- }
-
- public void voiceInputSettingDisabled() {
- setHasLoggingInfo(true);
- mContext.sendBroadcast(newLoggingBroadcast(
- LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_DISABLED));
- }
-
- private void setHasLoggingInfo(boolean hasLoggingInfo) {
- mHasLoggingInfo = hasLoggingInfo;
- // If applications that call UserHappinessSignals.userAcceptedImeText
- // make that call after VoiceInputLogger.flush() calls this method with false, we
- // will lose those happiness signals. For example, consider the gmail sequence:
- // 1. compose message
- // 2. speak message into message field
- // 3. type subject into subject field
- // 4. press send
- // We will NOT get the signal that the user accepted the voice inputted message text
- // because when the user tapped on the subject field, the ime's flush will be triggered
- // and the hasLoggingInfo will be then set to false. So by the time the user hits send
- // we have essentially forgotten about any voice input.
- // However the following (more common) use case is properly logged
- // 1. compose message
- // 2. type subject in subject field
- // 3. speak message in message field
- // 4. press send
- VoiceInputLoggerCompatUtils.setHasVoiceLoggingInfoCompat(hasLoggingInfo);
- }
-
- private boolean hasLoggingInfo(){
- return mHasLoggingInfo;
- }
-
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java b/java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java
deleted file mode 100644
index 8ed279f42..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2008-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.deprecated.voice;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-
-/**
- * Utility class to draw a waveform into a bitmap, given a byte array
- * that represents the waveform as a sequence of 16-bit integers.
- * Adapted from RecognitionActivity.java.
- */
-public class WaveformImage {
- private static final int SAMPLING_RATE = 8000;
-
- private WaveformImage() {
- // Intentional empty constructor.
- }
-
- public static Bitmap drawWaveform(
- ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) {
- final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- final Canvas c = new Canvas(b);
- final Paint paint = new Paint();
- paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA
- paint.setAntiAlias(true);
- paint.setStrokeWidth(0);
-
- final ShortBuffer buf = ByteBuffer
- .wrap(waveBuffer.toByteArray())
- .order(ByteOrder.nativeOrder())
- .asShortBuffer();
- buf.position(0);
-
- final int numSamples = waveBuffer.size() / 2;
- final int delay = (SAMPLING_RATE * 100 / 1000);
- int endIndex = end / 2 + delay;
- if (end == 0 || endIndex >= numSamples) {
- endIndex = numSamples;
- }
- int index = start / 2 - delay;
- if (index < 0) {
- index = 0;
- }
- final int size = endIndex - index;
- int numSamplePerPixel = 32;
- int delta = size / (numSamplePerPixel * w);
- if (delta == 0) {
- numSamplePerPixel = size / w;
- delta = 1;
- }
-
- final float scale = 3.5f / 65536.0f;
- // do one less column to make sure we won't read past
- // the buffer.
- try {
- for (int i = 0; i < w - 1 ; i++) {
- final float x = i;
- for (int j = 0; j < numSamplePerPixel; j++) {
- final short s = buf.get(index);
- final float y = (h / 2) - (s * h * scale);
- c.drawPoint(x, y, paint);
- index += delta;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- // this can happen, but we don't care
- }
-
- return b;
- }
-}
diff --git a/java/src/com/android/inputmethod/deprecated/voice/Whitelist.java b/java/src/com/android/inputmethod/deprecated/voice/Whitelist.java
deleted file mode 100644
index 6c5f52ae2..000000000
--- a/java/src/com/android/inputmethod/deprecated/voice/Whitelist.java
+++ /dev/null
@@ -1,68 +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.deprecated.voice;
-
-import android.os.Bundle;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A set of text fields where speech has been explicitly enabled.
- */
-public class Whitelist {
- private List<Bundle> mConditions;
-
- public Whitelist() {
- mConditions = new ArrayList<Bundle>();
- }
-
- public Whitelist(List<Bundle> conditions) {
- this.mConditions = conditions;
- }
-
- public void addApp(String app) {
- Bundle bundle = new Bundle();
- bundle.putString("packageName", app);
- mConditions.add(bundle);
- }
-
- /**
- * @return true if the field is a member of the whitelist.
- */
- public boolean matches(FieldContext context) {
- for (Bundle condition : mConditions) {
- if (matches(condition, context.getBundle())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * @return true of all values in condition are matched by a value
- * in target.
- */
- private boolean matches(Bundle condition, Bundle target) {
- for (String key : condition.keySet()) {
- if (!condition.getString(key).equals(target.getString(key))) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 872fbf823..e1e1ca9cf 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -16,385 +16,574 @@
package com.android.inputmethod.keyboard;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_OUTPUT_TEXT;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_SHIFT;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
+import static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED;
+import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
+
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Xml;
-import com.android.inputmethod.keyboard.internal.KeyStyles;
+import com.android.inputmethod.keyboard.internal.KeySpecParser;
+import com.android.inputmethod.keyboard.internal.KeySpecParser.MoreKeySpec;
import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardParser;
-import com.android.inputmethod.keyboard.internal.KeyboardParser.ParseException;
-import com.android.inputmethod.keyboard.internal.PopupCharactersParser;
-import com.android.inputmethod.keyboard.internal.Row;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StringUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Locale;
/**
* Class for describing the position and characteristics of a single key in the keyboard.
*/
public class Key {
+ private static final String TAG = Key.class.getSimpleName();
+
/**
* The key code (unicode or custom code) that this key generates.
*/
public final int mCode;
+ public final int mAltCode;
/** Label to display */
- public final CharSequence mLabel;
+ public final String mLabel;
/** Hint label to display on the key in conjunction with the label */
- public final CharSequence mHintLabel;
- /** Option of the label */
- public final int mLabelOption;
- public static final int LABEL_OPTION_ALIGN_LEFT = 0x01;
- public static final int LABEL_OPTION_ALIGN_RIGHT = 0x02;
- public static final int LABEL_OPTION_ALIGN_BOTTOM = 0x04;
- public static final int LABEL_OPTION_ALIGN_LEFT_OF_CENTER = 0x08;
- private static final int LABEL_OPTION_LARGE_LETTER = 0x10;
- private static final int LABEL_OPTION_FONT_NORMAL = 0x20;
- private static final int LABEL_OPTION_FONT_MONO_SPACE = 0x40;
- private static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x80;
- private static final int LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
- private static final int LABEL_OPTION_HAS_POPUP_HINT = 0x200;
- private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x400;
- private static final int LABEL_OPTION_HAS_HINT_LABEL = 0x800;
+ public final String mHintLabel;
+ /** Flags of the label */
+ private final int mLabelFlags;
+ private static final int LABEL_FLAGS_ALIGN_LEFT = 0x01;
+ private static final int LABEL_FLAGS_ALIGN_RIGHT = 0x02;
+ private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08;
+ private static final int LABEL_FLAGS_FONT_NORMAL = 0x10;
+ private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x20;
+ // Start of key text ratio enum values
+ private static final int LABEL_FLAGS_FOLLOW_KEY_TEXT_RATIO_MASK = 0x1C0;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO = 0x40;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO = 0xC0;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_LARGE_LABEL_RATIO = 0x100;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x140;
+ // End of key text ratio mask enum values
+ private static final int LABEL_FLAGS_HAS_POPUP_HINT = 0x200;
+ private static final int LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT = 0x400;
+ 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;
+ 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_DISABLE_HINT_LABEL = 0x40000000;
+ private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000;
/** Icon to display instead of a label. Icon takes precedence over a label */
- private Drawable mIcon;
+ private final int mIconId;
+ /** Icon for disabled state */
+ private final int mDisabledIconId;
/** Preview version of the icon, for the preview popup */
- private Drawable mPreviewIcon;
+ private final int mPreviewIconId;
/** Width of the key, not including the gap */
public final int mWidth;
/** Height of the key, not including the gap */
public final int mHeight;
/** The horizontal gap around this key */
- public final int mGap;
+ public final int mHorizontalGap;
+ /** The vertical gap below this key */
+ public final int mVerticalGap;
/** The visual insets */
public final int mVisualInsetsLeft;
public final int mVisualInsetsRight;
- /** Whether this key is sticky, i.e., a toggle key */
- public final boolean mSticky;
/** X coordinate of the key in the keyboard layout */
public final int mX;
/** Y coordinate of the key in the keyboard layout */
public final int mY;
+ /** Hit bounding box of the key */
+ public final Rect mHitBox = new Rect();
+
/** Text to output when pressed. This can be multiple characters, like ".com" */
public final CharSequence mOutputText;
- /** Popup characters */
- public final CharSequence[] mPopupCharacters;
- /** Popup keyboard maximum column number */
- public final int mMaxPopupColumn;
-
- /**
- * Flags that specify the anchoring to edges of the keyboard for detecting touch events
- * that are just out of the boundary of the key. This is a bit mask of
- * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT},
- * {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}.
- */
- public final int mEdgeFlags;
- /** Whether this is a functional key which has different key top than normal key */
- public final boolean mFunctional;
- /** Whether this key repeats itself when held down */
- public final boolean mRepeatable;
-
- /** The Keyboard that this key belongs to */
- private final Keyboard mKeyboard;
+ /** More keys */
+ public final MoreKeySpec[] mMoreKeys;
+ /** More keys column number and flags */
+ private final int mMoreKeysColumnAndFlags;
+ private static final int MORE_KEYS_COLUMN_MASK = 0x000000ff;
+ private static final int MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER = 0x80000000;
+ private static final int MORE_KEYS_FLAGS_HAS_LABELS = 0x40000000;
+ private static final int MORE_KEYS_FLAGS_NEEDS_DIVIDERS = 0x20000000;
+ private static final int MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY = 0x10000000;
+ private static final String MORE_KEYS_AUTO_COLUMN_ORDER = "!autoColumnOrder!";
+ private static final String MORE_KEYS_FIXED_COLUMN_ORDER = "!fixedColumnOrder!";
+ private static final String MORE_KEYS_HAS_LABELS = "!hasLabels!";
+ private static final String MORE_KEYS_NEEDS_DIVIDERS = "!needsDividers!";
+ private static final String MORE_KEYS_EMBEDDED_MORE_KEY = "!embeddedMoreKey!";
+
+ /** Background type that represents different key background visual than normal one. */
+ public final int mBackgroundType;
+ public static final int BACKGROUND_TYPE_NORMAL = 0;
+ public static final int BACKGROUND_TYPE_FUNCTIONAL = 1;
+ public static final int BACKGROUND_TYPE_ACTION = 2;
+ public static final int BACKGROUND_TYPE_STICKY_OFF = 3;
+ public static final int BACKGROUND_TYPE_STICKY_ON = 4;
+
+ private final int mActionFlags;
+ private static final int ACTION_FLAGS_IS_REPEATABLE = 0x01;
+ private static final int ACTION_FLAGS_NO_KEY_PREVIEW = 0x02;
+ private static final int ACTION_FLAGS_ALT_CODE_WHILE_TYPING = 0x04;
+ private static final int ACTION_FLAGS_ENABLE_LONG_PRESS = 0x08;
+
+ private final int mHashCode;
/** The current pressed state of this key */
private boolean mPressed;
- /** If this is a sticky key, is its highlight on? */
- private boolean mHighlightOn;
/** Key is enabled and responds on press */
private boolean mEnabled = true;
- // keyWidth constants
- private static final int KEYWIDTH_FILL_RIGHT = 0;
- private static final int KEYWIDTH_FILL_BOTH = -1;
-
- private final static int[] KEY_STATE_NORMAL_ON = {
- android.R.attr.state_checkable,
- android.R.attr.state_checked
- };
-
- private final static int[] KEY_STATE_PRESSED_ON = {
- android.R.attr.state_pressed,
- android.R.attr.state_checkable,
- android.R.attr.state_checked
- };
-
- private final static int[] KEY_STATE_NORMAL_OFF = {
- android.R.attr.state_checkable
- };
-
- private final static int[] KEY_STATE_PRESSED_OFF = {
- android.R.attr.state_pressed,
- android.R.attr.state_checkable
- };
-
- private final static int[] KEY_STATE_NORMAL = {
- };
-
- private final static int[] KEY_STATE_PRESSED = {
- android.R.attr.state_pressed
- };
-
- // functional normal state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
- android.R.attr.state_single
- };
-
- // functional pressed state (with properties)
- private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
- android.R.attr.state_single,
- android.R.attr.state_pressed
- };
+ /**
+ * This constructor is being used only for keys in more keys keyboard.
+ */
+ public Key(Keyboard.Params params, MoreKeySpec moreKeySpec, int x, int y, int width, int height,
+ int labelFlags) {
+ this(params, moreKeySpec.mLabel, null, moreKeySpec.mIconId, moreKeySpec.mCode,
+ moreKeySpec.mOutputText, x, y, width, height, labelFlags);
+ }
/**
- * This constructor is being used only for key in popup mini keyboard.
+ * This constructor is being used only for key in popup suggestions pane.
*/
- public Key(Resources res, Keyboard keyboard, CharSequence popupCharacter, int x, int y,
- int width, int height, int edgeFlags) {
- mKeyboard = keyboard;
- mHeight = height - keyboard.getVerticalGap();
- mGap = keyboard.getHorizontalGap();
+ public Key(Keyboard.Params params, String label, String hintLabel, int iconId,
+ int code, String outputText, int x, int y, int width, int height, int labelFlags) {
+ mHeight = height - params.mVerticalGap;
+ mHorizontalGap = params.mHorizontalGap;
+ mVerticalGap = params.mVerticalGap;
mVisualInsetsLeft = mVisualInsetsRight = 0;
- mWidth = width - mGap;
- mEdgeFlags = edgeFlags;
- mHintLabel = null;
- mLabelOption = 0;
- mFunctional = false;
- mSticky = false;
- mRepeatable = false;
- mPopupCharacters = null;
- mMaxPopupColumn = 0;
- final String popupSpecification = popupCharacter.toString();
- mLabel = PopupCharactersParser.getLabel(popupSpecification);
- mOutputText = PopupCharactersParser.getOutputText(popupSpecification);
- mCode = PopupCharactersParser.getCode(res, popupSpecification);
- mIcon = keyboard.mIconsSet.getIcon(PopupCharactersParser.getIconId(popupSpecification));
+ mWidth = width - mHorizontalGap;
+ mHintLabel = hintLabel;
+ mLabelFlags = labelFlags;
+ mBackgroundType = BACKGROUND_TYPE_NORMAL;
+ mActionFlags = 0;
+ mMoreKeys = null;
+ mMoreKeysColumnAndFlags = 0;
+ mLabel = label;
+ mOutputText = outputText;
+ mCode = code;
+ mEnabled = (code != CODE_UNSPECIFIED);
+ mAltCode = CODE_UNSPECIFIED;
+ mIconId = iconId;
+ mDisabledIconId = ICON_UNDEFINED;
+ mPreviewIconId = ICON_UNDEFINED;
// Horizontal gap is divided equally to both sides of the key.
- mX = x + mGap / 2;
+ mX = x + mHorizontalGap / 2;
mY = y;
+ mHitBox.set(x, y, x + width + 1, y + height);
+
+ mHashCode = computeHashCode(this);
}
/**
* Create a key with the given top-left coordinate and extract its attributes from the XML
* parser.
* @param res resources associated with the caller's context
- * @param row the row that this key belongs to. The row must already be attached to
- * a {@link Keyboard}.
- * @param x the x coordinate of the top-left
- * @param y the y coordinate of the top-left
+ * @param params the keyboard building parameters.
+ * @param row the row that this key belongs to. row's x-coordinate will be the right edge of
+ * this key.
* @param parser the XML parser containing the attributes for this key
- * @param keyStyles active key styles set
+ * @throws XmlPullParserException
*/
- public Key(Resources res, Row row, int x, int y, XmlResourceParser parser,
- KeyStyles keyStyles) {
- mKeyboard = row.getKeyboard();
-
- final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- int keyWidth;
- try {
- mHeight = KeyboardParser.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight,
- mKeyboard.getKeyboardHeight(), row.mDefaultHeight) - row.mVerticalGap;
- mGap = KeyboardParser.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_horizontalGap,
- mKeyboard.getDisplayWidth(), row.mDefaultHorizontalGap);
- keyWidth = KeyboardParser.getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyWidth,
- mKeyboard.getDisplayWidth(), row.mDefaultWidth);
- } finally {
- keyboardAttr.recycle();
- }
+ public Key(Resources res, Keyboard.Params params, Keyboard.Builder.Row row,
+ XmlPullParser parser) throws XmlPullParserException {
+ final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
+ final int keyHeight = row.mRowHeight;
+ mVerticalGap = params.mVerticalGap;
+ mHeight = keyHeight - mVerticalGap;
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Key);
- try {
- final KeyStyle style;
- if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
- String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
- style = keyStyles.getKeyStyle(styleName);
- if (style == null)
- throw new ParseException("Unknown key style: " + styleName, parser);
- } else {
- style = keyStyles.getEmptyKeyStyle();
- }
- final int keyboardWidth = mKeyboard.getDisplayWidth();
- int keyXPos = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyXPos, keyboardWidth, x);
- if (keyXPos < 0) {
- // If keyXPos is negative, the actual x-coordinate will be k + keyXPos.
- keyXPos += keyboardWidth;
- if (keyXPos < x) {
- // keyXPos shouldn't be less than x because drawable area for this key starts
- // at x. Or, this key will overlaps the adjacent key on its left hand side.
- keyXPos = x;
- }
- }
- if (keyWidth == KEYWIDTH_FILL_RIGHT) {
- // If keyWidth is zero, the actual key width will be determined to fill out the
- // area up to the right edge of the keyboard.
- keyWidth = keyboardWidth - keyXPos;
- } else if (keyWidth <= KEYWIDTH_FILL_BOTH) {
- // If keyWidth is negative, the actual key width will be determined to fill out the
- // area between the nearest key on the left hand side and the right edge of the
- // keyboard.
- keyXPos = x;
- keyWidth = keyboardWidth - keyXPos;
- }
+ final KeyStyle style = params.mKeyStyles.getKeyStyle(keyAttr, parser);
+ final float keyXPos = row.getKeyX(keyAttr);
+ final float keyWidth = row.getKeyWidth(keyAttr, keyXPos);
+ final int keyYPos = row.getKeyY();
+
+ // Horizontal gap is divided equally to both sides of the key.
+ mX = Math.round(keyXPos + horizontalGap / 2);
+ mY = keyYPos;
+ mWidth = Math.round(keyWidth - horizontalGap);
+ mHorizontalGap = Math.round(horizontalGap);
+ mHitBox.set(Math.round(keyXPos), keyYPos, Math.round(keyXPos + keyWidth) + 1,
+ keyYPos + keyHeight);
+ // Update row to have current x coordinate.
+ row.setXPos(keyXPos + keyWidth);
+
+ mBackgroundType = style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_backgroundType, row.getDefaultBackgroundType());
+
+ mVisualInsetsLeft = Math.round(Keyboard.Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0));
+ mVisualInsetsRight = Math.round(Keyboard.Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0));
+ mIconId = KeySpecParser.getIconId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyIcon));
+ mDisabledIconId = KeySpecParser.getIconId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyIconDisabled));
+ mPreviewIconId = KeySpecParser.getIconId(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyIconPreview));
+
+ mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
+ | row.getDefaultKeyLabelFlags();
+ final boolean needsToUpperCase = needsToUpperCase(mLabelFlags, params.mId.mElementId);
+ final Locale locale = params.mId.mLocale;
+ int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
+ String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
+
+ int moreKeysColumn = style.getInt(keyAttr,
+ R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn);
+ int value;
+ if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
+ moreKeysColumn = value & MORE_KEYS_COLUMN_MASK;
+ }
+ if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
+ moreKeysColumn = MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER | (value & MORE_KEYS_COLUMN_MASK);
+ }
+ if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) {
+ moreKeysColumn |= MORE_KEYS_FLAGS_HAS_LABELS;
+ }
+ if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_NEEDS_DIVIDERS)) {
+ moreKeysColumn |= MORE_KEYS_FLAGS_NEEDS_DIVIDERS;
+ }
+ if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_EMBEDDED_MORE_KEY)) {
+ moreKeysColumn |= MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY;
+ }
+ mMoreKeysColumnAndFlags = moreKeysColumn;
- // Horizontal gap is divided equally to both sides of the key.
- mX = keyXPos + mGap / 2;
- mY = y;
- mWidth = keyWidth - mGap;
+ final String[] additionalMoreKeys;
+ if ((mLabelFlags & LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS) != 0) {
+ additionalMoreKeys = null;
+ } else {
+ additionalMoreKeys = style.getStringArray(keyAttr,
+ R.styleable.Keyboard_Key_additionalMoreKeys);
+ }
+ moreKeys = KeySpecParser.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys);
+ if (moreKeys != null) {
+ actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
+ mMoreKeys = new MoreKeySpec[moreKeys.length];
+ for (int i = 0; i < moreKeys.length; i++) {
+ mMoreKeys[i] = new MoreKeySpec(
+ moreKeys[i], needsToUpperCase, locale, params.mCodesSet);
+ }
+ } else {
+ mMoreKeys = null;
+ }
+ mActionFlags = actionFlags;
- final CharSequence[] popupCharacters = style.getTextArray(keyAttr,
- R.styleable.Keyboard_Key_popupCharacters);
- if (res.getBoolean(R.bool.config_digit_popup_characters_enabled)) {
- mPopupCharacters = popupCharacters;
+ if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) {
+ mLabel = params.mId.mCustomActionLabel;
+ } else {
+ mLabel = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyLabel), needsToUpperCase, locale);
+ }
+ if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
+ mHintLabel = null;
+ } else {
+ mHintLabel = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyHintLabel), needsToUpperCase, locale);
+ }
+ String outputText = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_keyOutputText), needsToUpperCase, locale);
+ final int code = KeySpecParser.parseCode(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_code), params.mCodesSet, CODE_UNSPECIFIED);
+ // Choose the first letter of the label as primary code if not specified.
+ if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
+ && !TextUtils.isEmpty(mLabel)) {
+ if (StringUtils.codePointCount(mLabel) == 1) {
+ // Use the first letter of the hint label if shiftedLetterActivated flag is
+ // specified.
+ if (hasShiftedLetterHint() && isShiftedLetterActivated()
+ && !TextUtils.isEmpty(mHintLabel)) {
+ mCode = mHintLabel.codePointAt(0);
+ } else {
+ mCode = mLabel.codePointAt(0);
+ }
} else {
- mPopupCharacters = filterOutDigitPopupCharacters(popupCharacters);
+ // In some locale and case, the character might be represented by multiple code
+ // points, such as upper case Eszett of German alphabet.
+ outputText = mLabel;
+ mCode = CODE_OUTPUT_TEXT;
}
- mMaxPopupColumn = style.getInt(keyboardAttr,
- R.styleable.Keyboard_Key_maxPopupKeyboardColumn,
- mKeyboard.getMaxPopupKeyboardColumn());
-
- mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
- mFunctional = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isFunctional, false);
- mSticky = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isSticky, false);
- mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
- mEdgeFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyEdgeFlags, 0)
- | row.mRowEdgeFlags;
-
- final KeyboardIconsSet iconsSet = mKeyboard.mIconsSet;
- mVisualInsetsLeft = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_visualInsetsLeft, mKeyboard.getDisplayHeight(), 0);
- mVisualInsetsRight = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_visualInsetsRight, mKeyboard.getDisplayHeight(), 0);
- mPreviewIcon = iconsSet.getIcon(style.getInt(
- keyAttr, R.styleable.Keyboard_Key_keyIconPreview,
- KeyboardIconsSet.ICON_UNDEFINED));
- Keyboard.setDefaultBounds(mPreviewIcon);
- mIcon = iconsSet.getIcon(style.getInt(
- keyAttr, R.styleable.Keyboard_Key_keyIcon,
- KeyboardIconsSet.ICON_UNDEFINED));
- Keyboard.setDefaultBounds(mIcon);
- mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
-
- mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
- mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0);
- mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
- // Choose the first letter of the label as primary code if not
- // specified.
- final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code,
- Keyboard.CODE_UNSPECIFIED);
- if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) {
- mCode = mLabel.charAt(0);
- } else if (code != Keyboard.CODE_UNSPECIFIED) {
- mCode = code;
+ } else if (code == CODE_UNSPECIFIED && outputText != null) {
+ if (StringUtils.codePointCount(outputText) == 1) {
+ mCode = outputText.codePointAt(0);
+ outputText = null;
} else {
- mCode = Keyboard.CODE_DUMMY;
+ mCode = CODE_OUTPUT_TEXT;
}
+ } else {
+ mCode = KeySpecParser.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale);
+ }
+ mOutputText = outputText;
+ mAltCode = KeySpecParser.toUpperCaseOfCodeForLocale(
+ KeySpecParser.parseCode(style.getString(keyAttr,
+ R.styleable.Keyboard_Key_altCode), params.mCodesSet, CODE_UNSPECIFIED),
+ needsToUpperCase, locale);
+ mHashCode = computeHashCode(this);
- final Drawable shiftedIcon = iconsSet.getIcon(style.getInt(
- keyAttr, R.styleable.Keyboard_Key_keyIconShifted,
- KeyboardIconsSet.ICON_UNDEFINED));
- if (shiftedIcon != null)
- mKeyboard.getShiftedIcons().put(this, shiftedIcon);
- } finally {
- keyAttr.recycle();
+ keyAttr.recycle();
+
+ if (hasShiftedLetterHint() && TextUtils.isEmpty(mHintLabel)) {
+ Log.w(TAG, "hasShiftedLetterHint specified without keyHintLabel: " + this);
+ }
+ }
+
+ private static boolean needsToUpperCase(int labelFlags, int keyboardElementId) {
+ if ((labelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0) return false;
+ switch (keyboardElementId) {
+ case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
+ case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static int computeHashCode(Key key) {
+ return Arrays.hashCode(new Object[] {
+ key.mX,
+ key.mY,
+ key.mWidth,
+ key.mHeight,
+ key.mCode,
+ key.mLabel,
+ key.mHintLabel,
+ key.mIconId,
+ key.mBackgroundType,
+ Arrays.hashCode(key.mMoreKeys),
+ key.mOutputText,
+ key.mActionFlags,
+ key.mLabelFlags,
+ // Key can be distinguishable without the following members.
+ // key.mAltCode,
+ // key.mDisabledIconId,
+ // key.mPreviewIconId,
+ // key.mHorizontalGap,
+ // key.mVerticalGap,
+ // key.mVisualInsetLeft,
+ // key.mVisualInsetRight,
+ // key.mMaxMoreKeysColumn,
+ });
+ }
+
+ private boolean equals(Key o) {
+ if (this == o) return true;
+ return o.mX == mX
+ && o.mY == mY
+ && o.mWidth == mWidth
+ && o.mHeight == mHeight
+ && o.mCode == mCode
+ && TextUtils.equals(o.mLabel, mLabel)
+ && TextUtils.equals(o.mHintLabel, mHintLabel)
+ && o.mIconId == mIconId
+ && o.mBackgroundType == mBackgroundType
+ && Arrays.equals(o.mMoreKeys, mMoreKeys)
+ && TextUtils.equals(o.mOutputText, mOutputText)
+ && o.mActionFlags == mActionFlags
+ && o.mLabelFlags == mLabelFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ return mHashCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof Key && equals((Key)o);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s/%s %d,%d %dx%d %s/%s/%s",
+ Keyboard.printableCode(mCode), mLabel, mX, mY, mWidth, mHeight, mHintLabel,
+ KeyboardIconsSet.getIconName(mIconId), backgroundName(mBackgroundType));
+ }
+
+ private static String backgroundName(int backgroundType) {
+ switch (backgroundType) {
+ case BACKGROUND_TYPE_NORMAL: return "normal";
+ case BACKGROUND_TYPE_FUNCTIONAL: return "functional";
+ case BACKGROUND_TYPE_ACTION: return "action";
+ case BACKGROUND_TYPE_STICKY_OFF: return "stickyOff";
+ case BACKGROUND_TYPE_STICKY_ON: return "stickyOn";
+ default: return null;
}
}
+ public void markAsLeftEdge(Keyboard.Params params) {
+ mHitBox.left = params.mHorizontalEdgesPadding;
+ }
+
+ public void markAsRightEdge(Keyboard.Params params) {
+ mHitBox.right = params.mOccupiedWidth - params.mHorizontalEdgesPadding;
+ }
+
+ public void markAsTopEdge(Keyboard.Params params) {
+ mHitBox.top = params.mTopPadding;
+ }
+
+ public void markAsBottomEdge(Keyboard.Params params) {
+ mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
+ }
+
+ public final boolean isSpacer() {
+ return this instanceof Spacer;
+ }
+
+ public boolean isShift() {
+ return mCode == CODE_SHIFT;
+ }
+
+ public boolean isModifier() {
+ return mCode == CODE_SHIFT || mCode == CODE_SWITCH_ALPHA_SYMBOL;
+ }
+
+ public boolean isRepeatable() {
+ return (mActionFlags & ACTION_FLAGS_IS_REPEATABLE) != 0;
+ }
+
+ public boolean noKeyPreview() {
+ return (mActionFlags & ACTION_FLAGS_NO_KEY_PREVIEW) != 0;
+ }
+
+ public boolean altCodeWhileTyping() {
+ return (mActionFlags & ACTION_FLAGS_ALT_CODE_WHILE_TYPING) != 0;
+ }
+
+ public boolean isLongPressEnabled() {
+ // We need not start long press timer on the key which has activated shifted letter.
+ return (mActionFlags & ACTION_FLAGS_ENABLE_LONG_PRESS) != 0
+ && (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) == 0;
+ }
+
public Typeface selectTypeface(Typeface defaultTypeface) {
// TODO: Handle "bold" here too?
- if ((mLabelOption & LABEL_OPTION_FONT_NORMAL) != 0) {
+ if ((mLabelFlags & LABEL_FLAGS_FONT_NORMAL) != 0) {
return Typeface.DEFAULT;
- } else if ((mLabelOption & LABEL_OPTION_FONT_MONO_SPACE) != 0) {
+ } else if ((mLabelFlags & LABEL_FLAGS_FONT_MONO_SPACE) != 0) {
return Typeface.MONOSPACE;
} else {
return defaultTypeface;
}
}
- public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) {
- if (mLabel.length() > 1
- && (mLabelOption & (LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO
- | LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) {
- return label;
- } else if ((mLabelOption & LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) {
- return hintLabel;
- } else if ((mLabelOption & LABEL_OPTION_LARGE_LETTER) != 0) {
- return largeLetter;
- } else {
- return letter;
+ public int selectTextSize(int letterSize, int largeLetterSize, int labelSize,
+ int largeLabelSize, int hintLabelSize) {
+ switch (mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_TEXT_RATIO_MASK) {
+ case LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO:
+ return letterSize;
+ case LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO:
+ return largeLetterSize;
+ case LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO:
+ return labelSize;
+ case LABEL_FLAGS_FOLLOW_KEY_LARGE_LABEL_RATIO:
+ return largeLabelSize;
+ case LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO:
+ return hintLabelSize;
+ default: // No follow key ratio flag specified.
+ return StringUtils.codePointCount(mLabel) == 1 ? letterSize : labelSize;
}
}
+ public boolean isAlignLeft() {
+ return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT) != 0;
+ }
+
+ public boolean isAlignRight() {
+ return (mLabelFlags & LABEL_FLAGS_ALIGN_RIGHT) != 0;
+ }
+
+ public boolean isAlignLeftOfCenter() {
+ return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT_OF_CENTER) != 0;
+ }
+
public boolean hasPopupHint() {
- return (mLabelOption & LABEL_OPTION_HAS_POPUP_HINT) != 0;
+ return (mLabelFlags & LABEL_FLAGS_HAS_POPUP_HINT) != 0;
}
- public boolean hasUppercaseLetter() {
- return (mLabelOption & LABEL_OPTION_HAS_UPPERCASE_LETTER) != 0;
+ public boolean hasShiftedLetterHint() {
+ return (mLabelFlags & LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT) != 0;
}
public boolean hasHintLabel() {
- return (mLabelOption & LABEL_OPTION_HAS_HINT_LABEL) != 0;
- }
-
- private static boolean isDigitPopupCharacter(CharSequence label) {
- return label != null && label.length() == 1 && Character.isDigit(label.charAt(0));
- }
-
- private static CharSequence[] filterOutDigitPopupCharacters(CharSequence[] popupCharacters) {
- if (popupCharacters == null || popupCharacters.length < 1)
- return null;
- if (popupCharacters.length == 1 && isDigitPopupCharacter(
- PopupCharactersParser.getLabel(popupCharacters[0].toString())))
- return null;
- ArrayList<CharSequence> filtered = null;
- for (int i = 0; i < popupCharacters.length; i++) {
- final CharSequence popupSpec = popupCharacters[i];
- if (isDigitPopupCharacter(PopupCharactersParser.getLabel(popupSpec.toString()))) {
- if (filtered == null) {
- filtered = new ArrayList<CharSequence>();
- for (int j = 0; j < i; j++)
- filtered.add(popupCharacters[j]);
- }
- } else if (filtered != null) {
- filtered.add(popupSpec);
- }
- }
- if (filtered == null)
- return popupCharacters;
- if (filtered.size() == 0)
- return null;
- return filtered.toArray(new CharSequence[filtered.size()]);
+ return (mLabelFlags & LABEL_FLAGS_HAS_HINT_LABEL) != 0;
+ }
+
+ public boolean hasLabelWithIconLeft() {
+ return (mLabelFlags & LABEL_FLAGS_WITH_ICON_LEFT) != 0;
+ }
+
+ public boolean hasLabelWithIconRight() {
+ return (mLabelFlags & LABEL_FLAGS_WITH_ICON_RIGHT) != 0;
+ }
+
+ public boolean needsXScale() {
+ return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0;
+ }
+
+ public boolean isShiftedLetterActivated() {
+ return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0;
+ }
+
+ public int getMoreKeysColumn() {
+ return mMoreKeysColumnAndFlags & MORE_KEYS_COLUMN_MASK;
+ }
+
+ public boolean isFixedColumnOrderMoreKeys() {
+ return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER) != 0;
+ }
+
+ public boolean hasLabelsInMoreKeys() {
+ return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_HAS_LABELS) != 0;
}
- public Drawable getIcon() {
- return mIcon;
+ public int getMoreKeyLabelFlags() {
+ return hasLabelsInMoreKeys()
+ ? LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO
+ : LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO;
}
- public Drawable getPreviewIcon() {
- return mPreviewIcon;
+ public boolean needsDividersInMoreKeys() {
+ return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_NEEDS_DIVIDERS) != 0;
}
- public void setIcon(Drawable icon) {
- mIcon = icon;
+ public boolean hasEmbeddedMoreKey() {
+ return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY) != 0;
+ }
+
+ public Drawable getIcon(KeyboardIconsSet iconSet, int alpha) {
+ final int iconId = mEnabled ? mIconId : mDisabledIconId;
+ final Drawable icon = iconSet.getIconDrawable(iconId);
+ if (icon != null) {
+ icon.setAlpha(alpha);
+ }
+ return icon;
}
- public void setPreviewIcon(Drawable icon) {
- mPreviewIcon = icon;
+ public Drawable getPreviewIcon(KeyboardIconsSet iconSet) {
+ return mPreviewIconId != ICON_UNDEFINED
+ ? iconSet.getIconDrawable(mPreviewIconId)
+ : iconSet.getIconDrawable(mIconId);
}
/**
@@ -415,10 +604,6 @@ public class Key {
mPressed = false;
}
- public void setHighlightOn(boolean highlightOn) {
- mHighlightOn = highlightOn;
- }
-
public boolean isEnabled() {
return mEnabled;
}
@@ -431,22 +616,12 @@ public class Key {
* Detects if a point falls on this key.
* @param x the x-coordinate of the point
* @param y the y-coordinate of the point
- * @return whether or not the point falls on the key. If the key is attached to an edge, it will
- * assume that all points between the key and the edge are considered to be on the key.
+ * @return whether or not the point falls on the key. If the key is attached to an edge, it
+ * will assume that all points between the key and the edge are considered to be on the key.
+ * @see #markAsLeftEdge(Keyboard.Params) etc.
*/
public boolean isOnKey(int x, int y) {
- final int flags = mEdgeFlags;
- final boolean leftEdge = (flags & Keyboard.EDGE_LEFT) != 0;
- final boolean rightEdge = (flags & Keyboard.EDGE_RIGHT) != 0;
- final boolean topEdge = (flags & Keyboard.EDGE_TOP) != 0;
- final boolean bottomEdge = (flags & Keyboard.EDGE_BOTTOM) != 0;
- final int left = mX - mGap / 2;
- final int right = left + mWidth + mGap;
- final int top = mY;
- final int bottom = top + mHeight + mKeyboard.getVerticalGap();
- // In order to mitigate rounding errors, we use (left <= x <= right) here.
- return (x >= left || leftEdge) && (x <= right || rightEdge)
- && (y >= top || topEdge) && (y <= bottom || bottomEdge);
+ return mHitBox.contains(x, y);
}
/**
@@ -467,42 +642,87 @@ public class Key {
return dx * dx + dy * dy;
}
+ private final static int[] KEY_STATE_NORMAL_HIGHLIGHT_ON = {
+ android.R.attr.state_checkable,
+ android.R.attr.state_checked
+ };
+
+ private final static int[] KEY_STATE_PRESSED_HIGHLIGHT_ON = {
+ android.R.attr.state_pressed,
+ android.R.attr.state_checkable,
+ android.R.attr.state_checked
+ };
+
+ private final static int[] KEY_STATE_NORMAL_HIGHLIGHT_OFF = {
+ android.R.attr.state_checkable
+ };
+
+ private final static int[] KEY_STATE_PRESSED_HIGHLIGHT_OFF = {
+ android.R.attr.state_pressed,
+ android.R.attr.state_checkable
+ };
+
+ private final static int[] KEY_STATE_NORMAL = {
+ };
+
+ private final static int[] KEY_STATE_PRESSED = {
+ android.R.attr.state_pressed
+ };
+
+ // functional normal state (with properties)
+ private static final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
+ android.R.attr.state_single
+ };
+
+ // functional pressed state (with properties)
+ private static final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
+ android.R.attr.state_single,
+ android.R.attr.state_pressed
+ };
+
+ // action normal state (with properties)
+ private static final int[] KEY_STATE_ACTIVE_NORMAL = {
+ android.R.attr.state_active
+ };
+
+ // action pressed state (with properties)
+ private static final int[] KEY_STATE_ACTIVE_PRESSED = {
+ android.R.attr.state_active,
+ android.R.attr.state_pressed
+ };
+
/**
* Returns the drawable state for the key, based on the current state and type of the key.
* @return the drawable state of the key.
* @see android.graphics.drawable.StateListDrawable#setState(int[])
*/
public int[] getCurrentDrawableState() {
- final boolean pressed = mPressed;
- if (!mSticky && mFunctional) {
- if (pressed) {
- return KEY_STATE_FUNCTIONAL_PRESSED;
- } else {
- return KEY_STATE_FUNCTIONAL_NORMAL;
- }
+ switch (mBackgroundType) {
+ case BACKGROUND_TYPE_FUNCTIONAL:
+ return mPressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL;
+ case BACKGROUND_TYPE_ACTION:
+ return mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL;
+ case BACKGROUND_TYPE_STICKY_OFF:
+ return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF;
+ case BACKGROUND_TYPE_STICKY_ON:
+ return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON;
+ default: /* BACKGROUND_TYPE_NORMAL */
+ return mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL;
}
+ }
- int[] states = KEY_STATE_NORMAL;
+ public static class Spacer extends Key {
+ public Spacer(Resources res, Keyboard.Params params, Keyboard.Builder.Row row,
+ XmlPullParser parser) throws XmlPullParserException {
+ super(res, params, row, parser);
+ }
- if (mHighlightOn) {
- if (pressed) {
- states = KEY_STATE_PRESSED_ON;
- } else {
- states = KEY_STATE_NORMAL_ON;
- }
- } else {
- if (mSticky) {
- if (pressed) {
- states = KEY_STATE_PRESSED_OFF;
- } else {
- states = KEY_STATE_NORMAL_OFF;
- }
- } else {
- if (pressed) {
- states = KEY_STATE_PRESSED;
- }
- }
+ /**
+ * This constructor is being used only for divider in more keys keyboard.
+ */
+ protected Spacer(Keyboard.Params params, int x, int y, int width, int height) {
+ super(params, null, null, ICON_UNDEFINED, CODE_UNSPECIFIED,
+ null, x, y, width, height, 0);
}
- return states;
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 7add43a6d..13e909c7e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -16,28 +16,26 @@
package com.android.inputmethod.keyboard;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.List;
public class KeyDetector {
- private static final String TAG = KeyDetector.class.getSimpleName();
- private static final boolean DEBUG = false;
-
public static final int NOT_A_CODE = -1;
- public static final int NOT_A_KEY = -1;
+
+ private final int mKeyHysteresisDistanceSquared;
private Keyboard mKeyboard;
private int mCorrectionX;
private int mCorrectionY;
private boolean mProximityCorrectOn;
- private int mProximityThresholdSquare;
- // working area
- private static final int MAX_NEARBY_KEYS = 12;
- private final int[] mDistances = new int[MAX_NEARBY_KEYS];
- private final int[] mIndices = new int[MAX_NEARBY_KEYS];
+ /**
+ * This class handles key detection.
+ *
+ * @param keyHysteresisDistance if the pointer movement distance is smaller than this, the
+ * movement will not been handled as meaningful movement. The unit is pixel.
+ */
+ public KeyDetector(float keyHysteresisDistance) {
+ mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
+ }
public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
if (keyboard == null)
@@ -47,19 +45,22 @@ public class KeyDetector {
mKeyboard = keyboard;
}
- protected int getTouchX(int x) {
+ public int getKeyHysteresisDistanceSquared() {
+ return mKeyHysteresisDistanceSquared;
+ }
+
+ public int getTouchX(int x) {
return x + mCorrectionX;
}
- protected int getTouchY(int y) {
+ public int getTouchY(int y) {
return y + mCorrectionY;
}
- protected List<Key> getKeys() {
+ public Keyboard getKeyboard() {
if (mKeyboard == null)
throw new IllegalStateException("keyboard isn't set");
- // mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null
- return mKeyboard.getKeys();
+ return mKeyboard;
}
public void setProximityCorrectionEnabled(boolean enabled) {
@@ -70,133 +71,49 @@ public class KeyDetector {
return mProximityCorrectOn;
}
- public void setProximityThreshold(int threshold) {
- mProximityThresholdSquare = threshold * threshold;
- }
-
- /**
- * Computes maximum size of the array that can contain all nearby key indices returned by
- * {@link #getKeyIndexAndNearbyCodes}.
- *
- * @return Returns maximum size of the array that can contain all nearby key indices returned
- * by {@link #getKeyIndexAndNearbyCodes}.
- */
- protected int getMaxNearbyKeys() {
- return MAX_NEARBY_KEYS;
+ public boolean alwaysAllowsSlidingInput() {
+ return false;
}
/**
- * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes}
- * method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}.
- *
- * @return Allocates and returns an array that can hold all key indices returned by
- * {@link #getKeyIndexAndNearbyCodes} method. All elements in the returned array are
- * initialized by {@link #NOT_A_CODE} value.
- */
- public int[] newCodeArray() {
- int[] codes = new int[getMaxNearbyKeys()];
- Arrays.fill(codes, NOT_A_CODE);
- return codes;
- }
-
- private void initializeNearbyKeys() {
- Arrays.fill(mDistances, Integer.MAX_VALUE);
- Arrays.fill(mIndices, NOT_A_KEY);
- }
-
- /**
- * Insert the key into nearby keys buffer and sort nearby keys by ascending order of distance.
- * If the distance of two keys are the same, the key which the point is on should be considered
- * as a closer one.
- *
- * @param keyIndex index of the key.
- * @param distance distance between the key's edge and user touched point.
- * @param isOnKey true if the point is on the key.
- * @return order of the key in the nearby buffer, 0 if it is the nearest key.
- */
- private int sortNearbyKeys(int keyIndex, int distance, boolean isOnKey) {
- final int[] distances = mDistances;
- final int[] indices = mIndices;
- for (int insertPos = 0; insertPos < distances.length; insertPos++) {
- final int comparingDistance = distances[insertPos];
- if (distance < comparingDistance || (distance == comparingDistance && isOnKey)) {
- final int nextPos = insertPos + 1;
- if (nextPos < distances.length) {
- System.arraycopy(distances, insertPos, distances, nextPos,
- distances.length - nextPos);
- System.arraycopy(indices, insertPos, indices, nextPos,
- indices.length - nextPos);
- }
- distances[insertPos] = distance;
- indices[insertPos] = keyIndex;
- return insertPos;
- }
- }
- return distances.length;
- }
-
- private void getNearbyKeyCodes(final int[] allCodes) {
- final List<Key> keys = getKeys();
- final int[] indices = mIndices;
-
- // allCodes[0] should always have the key code even if it is a non-letter key.
- if (indices[0] == NOT_A_KEY) {
- allCodes[0] = NOT_A_CODE;
- return;
- }
-
- int numCodes = 0;
- for (int j = 0; j < indices.length && numCodes < allCodes.length; j++) {
- final int index = indices[j];
- if (index == NOT_A_KEY)
- break;
- final int code = keys.get(index).mCode;
- // filter out a non-letter key from nearby keys
- if (code < Keyboard.CODE_SPACE)
- continue;
- allCodes[numCodes++] = code;
- }
- }
-
- /**
- * Finds all possible nearby key indices around a touch event point and returns the nearest key
- * index. The algorithm to determine the nearby keys depends on the threshold set by
- * {@link #setProximityThreshold(int)} and the mode set by
- * {@link #setProximityCorrectionEnabled(boolean)}.
+ * Detect the key whose hitbox the touch point is in.
*
* @param x The x-coordinate of a touch point
* @param y The y-coordinate of a touch point
- * @param allCodes All nearby key code except functional key are returned in this array
- * @return The nearest key index
+ * @return the key that the touch point hits.
*/
- public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
- final List<Key> keys = getKeys();
+ public Key detectHitKey(int x, int y) {
final int touchX = getTouchX(x);
final int touchY = getTouchY(y);
- initializeNearbyKeys();
- int primaryIndex = NOT_A_KEY;
- for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
- final Key key = keys.get(index);
+ int minDistance = Integer.MAX_VALUE;
+ Key primaryKey = null;
+ for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) {
final boolean isOnKey = key.isOnKey(touchX, touchY);
final int distance = key.squaredDistanceToEdge(touchX, touchY);
- if (isOnKey || (mProximityCorrectOn && distance < mProximityThresholdSquare)) {
- final int insertedPosition = sortNearbyKeys(index, distance, isOnKey);
- if (insertedPosition == 0 && isOnKey)
- primaryIndex = index;
+ // To take care of hitbox overlaps, we compare mCode here too.
+ if (primaryKey == null || distance < minDistance
+ || (distance == minDistance && isOnKey && key.mCode > primaryKey.mCode)) {
+ minDistance = distance;
+ primaryKey = key;
}
}
+ return primaryKey;
+ }
- if (allCodes != null && allCodes.length > 0) {
- getNearbyKeyCodes(allCodes);
- if (DEBUG) {
- Log.d(TAG, "x=" + x + " y=" + y
- + " primary="
- + (primaryIndex == NOT_A_KEY ? "none" : keys.get(primaryIndex).mCode)
- + " codes=" + Arrays.toString(allCodes));
- }
- }
+ public static String printableCode(Key key) {
+ return key != null ? Keyboard.printableCode(key.mCode) : "none";
+ }
- return primaryIndex;
+ public static String printableCodes(int[] codes) {
+ final StringBuilder sb = new StringBuilder();
+ boolean addDelimiter = false;
+ for (final int code : codes) {
+ if (code == NOT_A_CODE) break;
+ if (addDelimiter) sb.append(", ");
+ sb.append(Keyboard.printableCode(code));
+ addDelimiter = true;
+ }
+ return "[" + sb + "]";
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 20327c5b2..6fc630d05 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -18,22 +18,35 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.view.InflateException;
+import com.android.inputmethod.keyboard.internal.KeyStyles;
+import com.android.inputmethod.keyboard.internal.KeyboardCodesSet;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.keyboard.internal.KeyboardParser;
-import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
+import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SubtypeLocale;
+import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.XmlParseUtils;
+import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.Locale;
/**
* Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
@@ -56,12 +69,9 @@ import java.util.Map;
public class Keyboard {
private static final String TAG = Keyboard.class.getSimpleName();
- public static final int EDGE_LEFT = 0x01;
- public static final int EDGE_RIGHT = 0x02;
- public static final int EDGE_TOP = 0x04;
- public static final int EDGE_BOTTOM = 0x08;
-
- /** Some common keys code. These should be aligned with values/keycodes.xml */
+ /** Some common keys code. Must be positive.
+ * These should be aligned with values/keycodes.xml
+ */
public static final int CODE_ENTER = '\n';
public static final int CODE_TAB = '\t';
public static final int CODE_SPACE = ' ';
@@ -69,393 +79,1275 @@ public class Keyboard {
public static final int CODE_DASH = '-';
public static final int CODE_SINGLE_QUOTE = '\'';
public static final int CODE_DOUBLE_QUOTE = '"';
-
- /** Special keys code. These should be aligned with values/keycodes.xml */
- public static final int CODE_DUMMY = 0;
+ // TODO: Check how this should work for right-to-left languages. It seems to stand
+ // that for rtl languages, a closing parenthesis is a left parenthesis. Is this
+ // managed by the font? Or is it a different char?
+ public static final int CODE_CLOSING_PARENTHESIS = ')';
+ public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
+ public static final int CODE_CLOSING_CURLY_BRACKET = '}';
+ public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
+ private static final int MINIMUM_LETTER_CODE = CODE_TAB;
+
+ /** Special keys code. Must be negative.
+ * These should be aligned with KeyboardCodesSet.ID_TO_NAME[],
+ * KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[]
+ */
public static final int CODE_SHIFT = -1;
public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
- public static final int CODE_CAPSLOCK = -3;
- public static final int CODE_CANCEL = -4;
- public static final int CODE_DELETE = -5;
- public static final int CODE_SETTINGS = -6;
- public static final int CODE_SETTINGS_LONGPRESS = -7;
- public static final int CODE_SHORTCUT = -8;
+ public static final int CODE_OUTPUT_TEXT = -3;
+ public static final int CODE_DELETE = -4;
+ public static final int CODE_SETTINGS = -5;
+ public static final int CODE_SHORTCUT = -6;
+ public static final int CODE_ACTION_ENTER = -7;
+ public static final int CODE_ACTION_NEXT = -8;
+ public static final int CODE_ACTION_PREVIOUS = -9;
+ public static final int CODE_LANGUAGE_SWITCH = -10;
+ public static final int CODE_RESEARCH = -11;
// Code value representing the code is not specified.
- public static final int CODE_UNSPECIFIED = -99;
+ public static final int CODE_UNSPECIFIED = -12;
- /** Horizontal gap default for all rows */
- private int mDefaultHorizontalGap;
-
- /** Default key width */
- private int mDefaultWidth;
+ public final KeyboardId mId;
+ public final int mThemeId;
- /** Default key height */
- private int mDefaultHeight;
+ /** Total height of the keyboard, including the padding and keys */
+ public final int mOccupiedHeight;
+ /** Total width of the keyboard, including the padding and keys */
+ public final int mOccupiedWidth;
+ /** The padding above the keyboard */
+ public final int mTopPadding;
/** Default gap between rows */
- private int mDefaultVerticalGap;
+ public final int mVerticalGap;
- /** Popup keyboard template */
- private int mPopupKeyboardResId;
+ public final int mMostCommonKeyHeight;
+ public final int mMostCommonKeyWidth;
- /** Maximum column for popup keyboard */
- private int mMaxPopupColumn;
+ /** More keys keyboard template */
+ public final int mMoreKeysTemplate;
- /** List of shift keys in this keyboard and its icons and state */
- private final List<Key> mShiftKeys = new ArrayList<Key>();
- private final HashMap<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>();
- private final HashMap<Key, Drawable> mNormalShiftIcons = new HashMap<Key, Drawable>();
- private final HashSet<Key> mShiftLockEnabled = new HashSet<Key>();
- private final KeyboardShiftState mShiftState = new KeyboardShiftState();
+ /** Maximum column for more keys keyboard */
+ public final int mMaxMoreKeysKeyboardColumn;
- /** Total height of the keyboard, including the padding and keys */
- private int mTotalHeight;
+ /** Array of keys and icons in this keyboard */
+ public final Key[] mKeys;
+ public final Key[] mShiftKeys;
+ public final Key[] mAltCodeKeysWhileTyping;
+ public final KeyboardIconsSet mIconsSet;
- /**
- * Total width (minimum width) of the keyboard, including left side gaps and keys, but not any
- * gaps on the right side.
- */
- private int mMinWidth;
+ private final HashMap<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
- /** List of keys in this keyboard */
- private final List<Key> mKeys = new ArrayList<Key>();
+ private final ProximityInfo mProximityInfo;
+ private final boolean mProximityCharsCorrectionEnabled;
+
+ public Keyboard(Params params) {
+ mId = params.mId;
+ mThemeId = params.mThemeId;
+ mOccupiedHeight = params.mOccupiedHeight;
+ mOccupiedWidth = params.mOccupiedWidth;
+ mMostCommonKeyHeight = params.mMostCommonKeyHeight;
+ mMostCommonKeyWidth = params.mMostCommonKeyWidth;
+ mMoreKeysTemplate = params.mMoreKeysTemplate;
+ mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
+
+ mTopPadding = params.mTopPadding;
+ mVerticalGap = params.mVerticalGap;
+
+ mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]);
+ mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]);
+ mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray(
+ new Key[params.mAltCodeKeysWhileTyping.size()]);
+ mIconsSet = params.mIconsSet;
+
+ mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(),
+ params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
+ mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
+ mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled;
+ }
- /** Width of the screen available to fit the keyboard */
- private final int mDisplayWidth;
+ public boolean hasProximityCharsCorrection(int code) {
+ if (!mProximityCharsCorrectionEnabled) {
+ return false;
+ }
+ // Note: The native code has the main keyboard layout only at this moment.
+ // TODO: Figure out how to handle proximity characters information of all layouts.
+ final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = (
+ mId.mElementId == KeyboardId.ELEMENT_ALPHABET
+ || mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED);
+ return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code);
+ }
- /** Height of the screen */
- private final int mDisplayHeight;
+ public ProximityInfo getProximityInfo() {
+ return mProximityInfo;
+ }
- /** Height of keyboard */
- private int mKeyboardHeight;
+ public Key getKey(int code) {
+ if (code == CODE_UNSPECIFIED) {
+ return null;
+ }
+ final Integer keyCode = code;
+ if (mKeyCache.containsKey(keyCode)) {
+ return mKeyCache.get(keyCode);
+ }
- private int mMostCommonKeyWidth = 0;
+ for (final Key key : mKeys) {
+ if (key.mCode == code) {
+ mKeyCache.put(keyCode, key);
+ return key;
+ }
+ }
+ mKeyCache.put(keyCode, null);
+ return null;
+ }
- public final KeyboardId mId;
+ public boolean hasKey(Key aKey) {
+ if (mKeyCache.containsKey(aKey)) {
+ return true;
+ }
- public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
+ for (final Key key : mKeys) {
+ if (key == aKey) {
+ mKeyCache.put(key.mCode, key);
+ return true;
+ }
+ }
+ return false;
+ }
- // Variables for pre-computing nearest keys.
+ public static boolean isLetterCode(int code) {
+ return code >= MINIMUM_LETTER_CODE;
+ }
- // TODO: Change GRID_WIDTH and GRID_HEIGHT to private.
- public final int GRID_WIDTH;
- public final int GRID_HEIGHT;
- private final int GRID_SIZE;
- private int mCellWidth;
- private int mCellHeight;
- private int[][] mGridNeighbors;
- private int mProximityThreshold;
- private static int[] EMPTY_INT_ARRAY = new int[0];
- /** Number of key widths from current touch point to search for nearest keys. */
- private static float SEARCH_DISTANCE = 1.2f;
+ public static class Params {
+ public KeyboardId mId;
+ public int mThemeId;
+
+ /** Total height and width of the keyboard, including the paddings and keys */
+ public int mOccupiedHeight;
+ public int mOccupiedWidth;
+
+ /** Base height and width of the keyboard used to calculate rows' or keys' heights and
+ * widths
+ */
+ public int mBaseHeight;
+ public int mBaseWidth;
+
+ public int mTopPadding;
+ public int mBottomPadding;
+ public int mHorizontalEdgesPadding;
+ public int mHorizontalCenterPadding;
+
+ public int mDefaultRowHeight;
+ public int mDefaultKeyWidth;
+ public int mHorizontalGap;
+ public int mVerticalGap;
+
+ public int mMoreKeysTemplate;
+ public int mMaxMoreKeysKeyboardColumn;
+
+ public int GRID_WIDTH;
+ public int GRID_HEIGHT;
+
+ public final HashSet<Key> mKeys = new HashSet<Key>();
+ public final ArrayList<Key> mShiftKeys = new ArrayList<Key>();
+ public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>();
+ public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
+ public final KeyboardCodesSet mCodesSet = new KeyboardCodesSet();
+ public final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
+ public final KeyStyles mKeyStyles = new KeyStyles(mTextsSet);
+
+ public KeyboardLayoutSet.KeysCache mKeysCache;
+
+ public int mMostCommonKeyHeight = 0;
+ public int mMostCommonKeyWidth = 0;
+
+ public boolean mProximityCharsCorrectionEnabled;
+
+ public final TouchPositionCorrection mTouchPositionCorrection =
+ new TouchPositionCorrection();
+
+ public static class TouchPositionCorrection {
+ private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3;
+
+ public boolean mEnabled;
+ public float[] mXs;
+ public float[] mYs;
+ public float[] mRadii;
+
+ public void load(String[] data) {
+ final int dataLength = data.length;
+ if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) {
+ if (LatinImeLogger.sDBG)
+ throw new RuntimeException(
+ "the size of touch position correction data is invalid");
+ return;
+ }
- private final ProximityInfo mProximityInfo;
+ final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ mXs = new float[length];
+ mYs = new float[length];
+ mRadii = new float[length];
+ try {
+ for (int i = 0; i < dataLength; ++i) {
+ final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ final float value = Float.parseFloat(data[i]);
+ if (type == 0) {
+ mXs[index] = value;
+ } else if (type == 1) {
+ mYs[index] = value;
+ } else {
+ mRadii[index] = value;
+ }
+ }
+ } catch (NumberFormatException e) {
+ if (LatinImeLogger.sDBG) {
+ throw new RuntimeException(
+ "the number format for touch position correction data is invalid");
+ }
+ mXs = null;
+ mYs = null;
+ mRadii = null;
+ }
+ }
- /**
- * Creates a keyboard from the given xml key layout file.
- * @param context the application or service context
- * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
- * @param id keyboard identifier
- * @param width keyboard width
- */
+ // TODO: Remove this method.
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
- public Keyboard(Context context, int xmlLayoutResId, KeyboardId id, int width) {
- final Resources res = context.getResources();
- GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
- GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
- GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
-
- final int horizontalEdgesPadding = (int)res.getDimension(
- R.dimen.keyboard_horizontal_edges_padding);
- mDisplayWidth = width - horizontalEdgesPadding * 2;
- // TODO: Adjust the height by referring to the height of area available for drawing as well.
- mDisplayHeight = res.getDisplayMetrics().heightPixels;
-
- mDefaultHorizontalGap = 0;
- setKeyWidth(mDisplayWidth / 10);
- mDefaultVerticalGap = 0;
- mDefaultHeight = mDefaultWidth;
- mId = id;
- mProximityInfo = new ProximityInfo(GRID_WIDTH, GRID_HEIGHT);
- loadKeyboard(context, xmlLayoutResId);
- }
+ public boolean isValid() {
+ return mEnabled && mXs != null && mYs != null && mRadii != null
+ && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0;
+ }
+ }
- public int getProximityInfo() {
- return mProximityInfo.getNativeProximityInfo(this);
- }
+ protected void clearKeys() {
+ mKeys.clear();
+ mShiftKeys.clear();
+ clearHistogram();
+ }
- public List<Key> getKeys() {
- return mKeys;
- }
+ public void onAddKey(Key newKey) {
+ final Key key = (mKeysCache != null) ? mKeysCache.get(newKey) : newKey;
+ final boolean zeroWidthSpacer = key.isSpacer() && key.mWidth == 0;
+ if (!zeroWidthSpacer) {
+ mKeys.add(key);
+ updateHistogram(key);
+ }
+ if (key.mCode == Keyboard.CODE_SHIFT) {
+ mShiftKeys.add(key);
+ }
+ if (key.altCodeWhileTyping()) {
+ mAltCodeKeysWhileTyping.add(key);
+ }
+ }
- public int getHorizontalGap() {
- return mDefaultHorizontalGap;
- }
+ private int mMaxHeightCount = 0;
+ private int mMaxWidthCount = 0;
+ private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
+ private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
- public void setHorizontalGap(int gap) {
- mDefaultHorizontalGap = gap;
- }
+ private void clearHistogram() {
+ mMostCommonKeyHeight = 0;
+ mMaxHeightCount = 0;
+ mHeightHistogram.clear();
- public int getVerticalGap() {
- return mDefaultVerticalGap;
- }
+ mMaxWidthCount = 0;
+ mMostCommonKeyWidth = 0;
+ mWidthHistogram.clear();
+ }
- public void setVerticalGap(int gap) {
- mDefaultVerticalGap = gap;
- }
+ private static int updateHistogramCounter(HashMap<Integer, Integer> histogram,
+ Integer key) {
+ final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
+ histogram.put(key, count);
+ return count;
+ }
- public int getRowHeight() {
- return mDefaultHeight;
- }
+ private void updateHistogram(Key key) {
+ final Integer height = key.mHeight + key.mVerticalGap;
+ final int heightCount = updateHistogramCounter(mHeightHistogram, height);
+ if (heightCount > mMaxHeightCount) {
+ mMaxHeightCount = heightCount;
+ mMostCommonKeyHeight = height;
+ }
- public void setRowHeight(int height) {
- mDefaultHeight = height;
+ final Integer width = key.mWidth + key.mHorizontalGap;
+ final int widthCount = updateHistogramCounter(mWidthHistogram, width);
+ if (widthCount > mMaxWidthCount) {
+ mMaxWidthCount = widthCount;
+ mMostCommonKeyWidth = width;
+ }
+ }
}
- public int getKeyWidth() {
- return mDefaultWidth;
+ /**
+ * Returns the array of the keys that are closest to the given point.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return the array of the nearest keys to the given point. If the given
+ * point is out of range, then an array of size zero is returned.
+ */
+ public Key[] getNearestKeys(int x, int y) {
+ // Avoid dead pixels at edges of the keyboard
+ final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));
+ final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1));
+ return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
}
- public void setKeyWidth(int width) {
- mDefaultWidth = width;
- final int threshold = (int) (width * SEARCH_DISTANCE);
- mProximityThreshold = threshold * threshold;
+ public static String printableCode(int code) {
+ switch (code) {
+ case CODE_SHIFT: return "shift";
+ case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
+ case CODE_OUTPUT_TEXT: return "text";
+ case CODE_DELETE: return "delete";
+ case CODE_SETTINGS: return "settings";
+ case CODE_SHORTCUT: return "shortcut";
+ case CODE_ACTION_ENTER: return "actionEnter";
+ case CODE_ACTION_NEXT: return "actionNext";
+ case CODE_ACTION_PREVIOUS: return "actionPrevious";
+ case CODE_LANGUAGE_SWITCH: return "languageSwitch";
+ case CODE_UNSPECIFIED: return "unspec";
+ case CODE_TAB: return "tab";
+ case CODE_ENTER: return "enter";
+ default:
+ if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code);
+ if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
+ if (code < 0x100) return String.format("'%c'", code);
+ return String.format("'\\u%04x'", code);
+ }
}
- /**
- * Returns the total height of the keyboard
- * @return the total height of the keyboard
+ /**
+ * Keyboard Building helper.
+ *
+ * This class parses Keyboard XML file and eventually build a Keyboard.
+ * The Keyboard XML file looks like:
+ * <pre>
+ * &lt;!-- xml/keyboard.xml --&gt;
+ * &lt;Keyboard keyboard_attributes*&gt;
+ * &lt;!-- Keyboard Content --&gt;
+ * &lt;Row row_attributes*&gt;
+ * &lt;!-- Row Content --&gt;
+ * &lt;Key key_attributes* /&gt;
+ * &lt;Spacer horizontalGap="32.0dp" /&gt;
+ * &lt;include keyboardLayout="@xml/other_keys"&gt;
+ * ...
+ * &lt;/Row&gt;
+ * &lt;include keyboardLayout="@xml/other_rows"&gt;
+ * ...
+ * &lt;/Keyboard&gt;
+ * </pre>
+ * The XML file which is included in other file must have &lt;merge&gt; as root element,
+ * such as:
+ * <pre>
+ * &lt;!-- xml/other_keys.xml --&gt;
+ * &lt;merge&gt;
+ * &lt;Key key_attributes* /&gt;
+ * ...
+ * &lt;/merge&gt;
+ * </pre>
+ * and
+ * <pre>
+ * &lt;!-- xml/other_rows.xml --&gt;
+ * &lt;merge&gt;
+ * &lt;Row row_attributes*&gt;
+ * &lt;Key key_attributes* /&gt;
+ * &lt;/Row&gt;
+ * ...
+ * &lt;/merge&gt;
+ * </pre>
+ * You can also use switch-case-default tags to select Rows and Keys.
+ * <pre>
+ * &lt;switch&gt;
+ * &lt;case case_attribute*&gt;
+ * &lt;!-- Any valid tags at switch position --&gt;
+ * &lt;/case&gt;
+ * ...
+ * &lt;default&gt;
+ * &lt;!-- Any valid tags at switch position --&gt;
+ * &lt;/default&gt;
+ * &lt;/switch&gt;
+ * </pre>
+ * You can declare Key style and specify styles within Key tags.
+ * <pre>
+ * &lt;switch&gt;
+ * &lt;case mode="email"&gt;
+ * &lt;key-style styleName="f1-key" parentStyle="modifier-key"
+ * keyLabel=".com"
+ * /&gt;
+ * &lt;/case&gt;
+ * &lt;case mode="url"&gt;
+ * &lt;key-style styleName="f1-key" parentStyle="modifier-key"
+ * keyLabel="http://"
+ * /&gt;
+ * &lt;/case&gt;
+ * &lt;/switch&gt;
+ * ...
+ * &lt;Key keyStyle="shift-key" ... /&gt;
+ * </pre>
*/
- public int getHeight() {
- return mTotalHeight;
- }
- public void setHeight(int height) {
- mTotalHeight = height;
- }
+ public static class Builder<KP extends Params> {
+ private static final String BUILDER_TAG = "Keyboard.Builder";
+ private static final boolean DEBUG = false;
+
+ // Keyboard XML Tags
+ private static final String TAG_KEYBOARD = "Keyboard";
+ private static final String TAG_ROW = "Row";
+ private static final String TAG_KEY = "Key";
+ private static final String TAG_SPACER = "Spacer";
+ private static final String TAG_INCLUDE = "include";
+ private static final String TAG_MERGE = "merge";
+ private static final String TAG_SWITCH = "switch";
+ private static final String TAG_CASE = "case";
+ private static final String TAG_DEFAULT = "default";
+ public static final String TAG_KEY_STYLE = "key-style";
+
+ private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
+ private static final int DEFAULT_KEYBOARD_ROWS = 4;
+
+ protected final KP mParams;
+ protected final Context mContext;
+ protected final Resources mResources;
+ private final DisplayMetrics mDisplayMetrics;
+
+ private int mCurrentY = 0;
+ private Row mCurrentRow = null;
+ private boolean mLeftEdge;
+ private boolean mTopEdge;
+ private Key mRightEdgeKey = null;
+
+ /**
+ * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
+ * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
+ * defines.
+ */
+ public static class Row {
+ // keyWidth enum constants
+ private static final int KEYWIDTH_NOT_ENUM = 0;
+ private static final int KEYWIDTH_FILL_RIGHT = -1;
+
+ private final Params mParams;
+ /** Default width of a key in this row. */
+ private float mDefaultKeyWidth;
+ /** Default height of a key in this row. */
+ public final int mRowHeight;
+ /** Default keyLabelFlags in this row. */
+ private int mDefaultKeyLabelFlags;
+ /** Default backgroundType for this row */
+ private int mDefaultBackgroundType;
+
+ private final int mCurrentY;
+ // Will be updated by {@link Key}'s constructor.
+ private float mCurrentX;
+
+ public Row(Resources res, Params params, XmlPullParser parser, int y) {
+ mParams = params;
+ TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard);
+ mRowHeight = (int)Builder.getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight,
+ params.mBaseHeight, params.mDefaultRowHeight);
+ keyboardAttr.recycle();
+ TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ mDefaultKeyWidth = Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth,
+ params.mBaseWidth, params.mDefaultKeyWidth);
+ mDefaultBackgroundType = keyAttr.getInt(R.styleable.Keyboard_Key_backgroundType,
+ Key.BACKGROUND_TYPE_NORMAL);
+ keyAttr.recycle();
+
+ // TODO: Initialize this with <Row> attribute as backgroundType is done.
+ mDefaultKeyLabelFlags = 0;
+ mCurrentY = y;
+ mCurrentX = 0.0f;
+ }
- public int getMinWidth() {
- return mMinWidth;
- }
+ public float getDefaultKeyWidth() {
+ return mDefaultKeyWidth;
+ }
- public void setMinWidth(int minWidth) {
- mMinWidth = minWidth;
- }
+ public void setDefaultKeyWidth(float defaultKeyWidth) {
+ mDefaultKeyWidth = defaultKeyWidth;
+ }
- public int getDisplayHeight() {
- return mDisplayHeight;
- }
+ public int getDefaultKeyLabelFlags() {
+ return mDefaultKeyLabelFlags;
+ }
- public int getDisplayWidth() {
- return mDisplayWidth;
- }
+ public void setDefaultKeyLabelFlags(int keyLabelFlags) {
+ mDefaultKeyLabelFlags = keyLabelFlags;
+ }
- public int getKeyboardHeight() {
- return mKeyboardHeight;
- }
+ public int getDefaultBackgroundType() {
+ return mDefaultBackgroundType;
+ }
- public void setKeyboardHeight(int height) {
- mKeyboardHeight = height;
- }
+ public void setDefaultBackgroundType(int backgroundType) {
+ mDefaultBackgroundType = backgroundType;
+ }
- public int getPopupKeyboardResId() {
- return mPopupKeyboardResId;
- }
+ public void setXPos(float keyXPos) {
+ mCurrentX = keyXPos;
+ }
- public void setPopupKeyboardResId(int resId) {
- mPopupKeyboardResId = resId;
- }
+ public void advanceXPos(float width) {
+ mCurrentX += width;
+ }
- public int getMaxPopupKeyboardColumn() {
- return mMaxPopupColumn;
- }
+ public int getKeyY() {
+ return mCurrentY;
+ }
- public void setMaxPopupKeyboardColumn(int column) {
- mMaxPopupColumn = column;
- }
+ public float getKeyX(TypedArray keyAttr) {
+ final int widthType = Builder.getEnumValue(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
+
+ final int keyboardRightEdge = mParams.mOccupiedWidth
+ - mParams.mHorizontalEdgesPadding;
+ if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) {
+ final float keyXPos = Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyXPos, mParams.mBaseWidth, 0);
+ if (keyXPos < 0) {
+ // If keyXPos is negative, the actual x-coordinate will be
+ // keyboardWidth + keyXPos.
+ // keyXPos shouldn't be less than mCurrentX because drawable area for this
+ // key starts at mCurrentX. Or, this key will overlaps the adjacent key on
+ // its left hand side.
+ return Math.max(keyXPos + keyboardRightEdge, mCurrentX);
+ } else {
+ return keyXPos + mParams.mHorizontalEdgesPadding;
+ }
+ }
+ return mCurrentX;
+ }
- public List<Key> getShiftKeys() {
- return mShiftKeys;
- }
+ public float getKeyWidth(TypedArray keyAttr) {
+ return getKeyWidth(keyAttr, mCurrentX);
+ }
- public Map<Key, Drawable> getShiftedIcons() {
- return mShiftedIcons;
- }
+ public float getKeyWidth(TypedArray keyAttr, float keyXPos) {
+ final int widthType = Builder.getEnumValue(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
+ switch (widthType) {
+ case KEYWIDTH_FILL_RIGHT:
+ final int keyboardRightEdge =
+ mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding;
+ // If keyWidth is fillRight, the actual key width will be determined to fill
+ // out the area up to the right edge of the keyboard.
+ return keyboardRightEdge - keyXPos;
+ default: // KEYWIDTH_NOT_ENUM
+ return Builder.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth,
+ mParams.mBaseWidth, mDefaultKeyWidth);
+ }
+ }
+ }
+
+ public Builder(Context context, KP params) {
+ mContext = context;
+ final Resources res = context.getResources();
+ mResources = res;
+ mDisplayMetrics = res.getDisplayMetrics();
- public void enableShiftLock() {
- for (final Key key : getShiftKeys()) {
- mShiftLockEnabled.add(key);
- mNormalShiftIcons.put(key, key.getIcon());
+ mParams = params;
+
+ params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
+ params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
}
- }
- public boolean isShiftLockEnabled(Key key) {
- return mShiftLockEnabled.contains(key);
- }
+ public void setAutoGenerate(KeyboardLayoutSet.KeysCache keysCache) {
+ mParams.mKeysCache = keysCache;
+ }
+
+ public Builder<KP> load(int xmlId, KeyboardId id) {
+ mParams.mId = id;
+ final XmlResourceParser parser = mResources.getXml(xmlId);
+ try {
+ parseKeyboard(parser);
+ } catch (XmlPullParserException e) {
+ Log.w(BUILDER_TAG, "keyboard XML parse error: " + e);
+ throw new IllegalArgumentException(e);
+ } catch (IOException e) {
+ Log.w(BUILDER_TAG, "keyboard XML parse error: " + e);
+ throw new RuntimeException(e);
+ } finally {
+ parser.close();
+ }
+ return this;
+ }
- public boolean setShiftLocked(boolean newShiftLockState) {
- final Map<Key, Drawable> shiftedIcons = getShiftedIcons();
- for (final Key key : getShiftKeys()) {
- key.setHighlightOn(newShiftLockState);
- key.setIcon(newShiftLockState ? shiftedIcons.get(key) : mNormalShiftIcons.get(key));
+ // TODO: Remove this method.
+ public void setTouchPositionCorrectionEnabled(boolean enabled) {
+ mParams.mTouchPositionCorrection.setEnabled(enabled);
}
- mShiftState.setShiftLocked(newShiftLockState);
- return true;
- }
- public boolean isShiftLocked() {
- return mShiftState.isShiftLocked();
- }
+ public void setProximityCharsCorrectionEnabled(boolean enabled) {
+ mParams.mProximityCharsCorrectionEnabled = enabled;
+ }
+
+ public Keyboard build() {
+ return new Keyboard(mParams);
+ }
+
+ private int mIndent;
+ private static final String SPACES = " ";
+
+ private static String spaces(int count) {
+ return (count < SPACES.length()) ? SPACES.substring(0, count) : SPACES;
+ }
+
+ private void startTag(String format, Object ... args) {
+ Log.d(BUILDER_TAG, String.format(spaces(++mIndent * 2) + format, args));
+ }
+
+ private void endTag(String format, Object ... args) {
+ Log.d(BUILDER_TAG, String.format(spaces(mIndent-- * 2) + format, args));
+ }
- public boolean setShifted(boolean newShiftState) {
- final Map<Key, Drawable> shiftedIcons = getShiftedIcons();
- for (final Key key : getShiftKeys()) {
- if (!newShiftState && !mShiftState.isShiftLocked()) {
- key.setIcon(mNormalShiftIcons.get(key));
- } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) {
- key.setIcon(shiftedIcons.get(key));
+ private void startEndTag(String format, Object ... args) {
+ Log.d(BUILDER_TAG, String.format(spaces(++mIndent * 2) + format, args));
+ mIndent--;
+ }
+
+ private void parseKeyboard(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) startTag("<%s> %s", TAG_KEYBOARD, mParams.mId);
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD.equals(tag)) {
+ parseKeyboardAttributes(parser);
+ startKeyboard();
+ parseKeyboardContent(parser, false);
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD);
+ }
+ }
}
}
- return mShiftState.setShifted(newShiftState);
- }
- public boolean isShiftedOrShiftLocked() {
- return mShiftState.isShiftedOrShiftLocked();
- }
+ private void parseKeyboardAttributes(XmlPullParser parser) {
+ final int displayWidth = mDisplayMetrics.widthPixels;
+ final TypedArray keyboardAttr = mContext.obtainStyledAttributes(
+ Xml.asAttributeSet(parser), R.styleable.Keyboard, R.attr.keyboardStyle,
+ R.style.Keyboard);
+ final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ try {
+ final int displayHeight = mDisplayMetrics.heightPixels;
+ final String keyboardHeightString = Utils.getDeviceOverrideValue(
+ mResources, R.array.keyboard_heights, null);
+ final float keyboardHeight;
+ if (keyboardHeightString != null) {
+ keyboardHeight = Float.parseFloat(keyboardHeightString)
+ * mDisplayMetrics.density;
+ } else {
+ keyboardHeight = keyboardAttr.getDimension(
+ R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
+ }
+ final float maxKeyboardHeight = getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2);
+ float minKeyboardHeight = getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2);
+ if (minKeyboardHeight < 0) {
+ // Specified fraction was negative, so it should be calculated against display
+ // width.
+ minKeyboardHeight = -getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
+ }
+ final Params params = mParams;
+ // Keyboard height will not exceed maxKeyboardHeight and will not be less than
+ // minKeyboardHeight.
+ params.mOccupiedHeight = (int)Math.max(
+ Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
+ params.mOccupiedWidth = params.mId.mWidth;
+ params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0);
+ params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0);
+ params.mHorizontalEdgesPadding = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_keyboardHorizontalEdgesPadding,
+ mParams.mOccupiedWidth, 0);
+
+ params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2
+ - params.mHorizontalCenterPadding;
+ params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth,
+ params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS);
+ params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0);
+ params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0);
+ params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding
+ - params.mBottomPadding + params.mVerticalGap;
+ params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr,
+ R.styleable.Keyboard_rowHeight, params.mBaseHeight,
+ params.mBaseHeight / DEFAULT_KEYBOARD_ROWS);
+
+ params.mMoreKeysTemplate = keyboardAttr.getResourceId(
+ R.styleable.Keyboard_moreKeysTemplate, 0);
+ params.mMaxMoreKeysKeyboardColumn = keyAttr.getInt(
+ R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
+
+ params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
+ params.mIconsSet.loadIcons(keyboardAttr);
+ final String language = params.mId.mLocale.getLanguage();
+ params.mCodesSet.setLanguage(language);
+ params.mTextsSet.setLanguage(language);
+ final RunInLocale<Void> job = new RunInLocale<Void>() {
+ @Override
+ protected Void job(Resources res) {
+ params.mTextsSet.loadStringResources(mContext);
+ return null;
+ }
+ };
+ // Null means the current system locale.
+ final Locale locale = SubtypeLocale.isNoLanguage(params.mId.mSubtype)
+ ? null : params.mId.mLocale;
+ job.runInLocale(mResources, locale);
+
+ final int resourceId = keyboardAttr.getResourceId(
+ R.styleable.Keyboard_touchPositionCorrectionData, 0);
+ params.mTouchPositionCorrection.setEnabled(resourceId != 0);
+ if (resourceId != 0) {
+ final String[] data = mResources.getStringArray(resourceId);
+ params.mTouchPositionCorrection.load(data);
+ }
+ } finally {
+ keyAttr.recycle();
+ keyboardAttr.recycle();
+ }
+ }
- public void setAutomaticTemporaryUpperCase() {
- setShifted(true);
- mShiftState.setAutomaticTemporaryUpperCase();
- }
+ private void parseKeyboardContent(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_ROW.equals(tag)) {
+ Row row = parseRowAttributes(parser);
+ if (DEBUG) startTag("<%s>%s", TAG_ROW, skip ? " skipped" : "");
+ if (!skip) {
+ startRow(row);
+ }
+ parseRowContent(parser, row, skip);
+ } else if (TAG_INCLUDE.equals(tag)) {
+ parseIncludeKeyboardContent(parser, skip);
+ } else if (TAG_SWITCH.equals(tag)) {
+ parseSwitchKeyboardContent(parser, skip);
+ } else if (TAG_KEY_STYLE.equals(tag)) {
+ parseKeyStyle(parser, skip);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_ROW);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (DEBUG) endTag("</%s>", tag);
+ if (TAG_KEYBOARD.equals(tag)) {
+ endKeyboard();
+ break;
+ } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
+ || TAG_MERGE.equals(tag)) {
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW);
+ }
+ }
+ }
+ }
- public boolean isAutomaticTemporaryUpperCase() {
- return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase();
- }
+ private Row parseRowAttributes(XmlPullParser parser) throws XmlPullParserException {
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard);
+ try {
+ if (a.hasValue(R.styleable.Keyboard_horizontalGap))
+ throw new XmlParseUtils.IllegalAttribute(parser, "horizontalGap");
+ if (a.hasValue(R.styleable.Keyboard_verticalGap))
+ throw new XmlParseUtils.IllegalAttribute(parser, "verticalGap");
+ return new Row(mResources, mParams, parser, mCurrentY);
+ } finally {
+ a.recycle();
+ }
+ }
- public boolean isManualTemporaryUpperCase() {
- return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
- }
+ private void parseRowContent(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEY.equals(tag)) {
+ parseKey(parser, row, skip);
+ } else if (TAG_SPACER.equals(tag)) {
+ parseSpacer(parser, row, skip);
+ } else if (TAG_INCLUDE.equals(tag)) {
+ parseIncludeRowContent(parser, row, skip);
+ } else if (TAG_SWITCH.equals(tag)) {
+ parseSwitchRowContent(parser, row, skip);
+ } else if (TAG_KEY_STYLE.equals(tag)) {
+ parseKeyStyle(parser, skip);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (DEBUG) endTag("</%s>", tag);
+ if (TAG_ROW.equals(tag)) {
+ if (!skip) {
+ endRow(row);
+ }
+ break;
+ } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
+ || TAG_MERGE.equals(tag)) {
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
+ }
+ }
+ }
+ }
- public boolean isManualTemporaryUpperCaseFromAuto() {
- return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCaseFromAuto();
- }
+ private void parseKey(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_KEY, parser);
+ if (DEBUG) startEndTag("<%s /> skipped", TAG_KEY);
+ } else {
+ final Key key = new Key(mResources, mParams, row, parser);
+ if (DEBUG) {
+ startEndTag("<%s%s %s moreKeys=%s />", TAG_KEY,
+ (key.isEnabled() ? "" : " disabled"), key,
+ Arrays.toString(key.mMoreKeys));
+ }
+ XmlParseUtils.checkEndTag(TAG_KEY, parser);
+ endKey(key);
+ }
+ }
- public KeyboardShiftState getKeyboardShiftState() {
- return mShiftState;
- }
+ private void parseSpacer(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_SPACER, parser);
+ if (DEBUG) startEndTag("<%s /> skipped", TAG_SPACER);
+ } else {
+ final Key.Spacer spacer = new Key.Spacer(mResources, mParams, row, parser);
+ if (DEBUG) startEndTag("<%s />", TAG_SPACER);
+ XmlParseUtils.checkEndTag(TAG_SPACER, parser);
+ endKey(spacer);
+ }
+ }
- public boolean isAlphaKeyboard() {
- return mId != null && mId.isAlphabetKeyboard();
- }
+ private void parseIncludeKeyboardContent(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseIncludeInternal(parser, null, skip);
+ }
- public boolean isPhoneKeyboard() {
- return mId != null && mId.isPhoneKeyboard();
- }
+ private void parseIncludeRowContent(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseIncludeInternal(parser, row, skip);
+ }
- public boolean isNumberKeyboard() {
- return mId != null && mId.isNumberKeyboard();
- }
+ private void parseIncludeInternal(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
+ if (DEBUG) startEndTag("</%s> skipped", TAG_INCLUDE);
+ } else {
+ final AttributeSet attr = Xml.asAttributeSet(parser);
+ final TypedArray keyboardAttr = mResources.obtainAttributes(attr,
+ R.styleable.Keyboard_Include);
+ final TypedArray keyAttr = mResources.obtainAttributes(attr,
+ R.styleable.Keyboard_Key);
+ int keyboardLayout = 0;
+ float savedDefaultKeyWidth = 0;
+ int savedDefaultKeyLabelFlags = 0;
+ int savedDefaultBackgroundType = Key.BACKGROUND_TYPE_NORMAL;
+ try {
+ XmlParseUtils.checkAttributeExists(keyboardAttr,
+ R.styleable.Keyboard_Include_keyboardLayout, "keyboardLayout",
+ TAG_INCLUDE, parser);
+ keyboardLayout = keyboardAttr.getResourceId(
+ R.styleable.Keyboard_Include_keyboardLayout, 0);
+ if (row != null) {
+ if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) {
+ // Override current x coordinate.
+ row.setXPos(row.getKeyX(keyAttr));
+ }
+ // TODO: Remove this if-clause and do the same as backgroundType below.
+ savedDefaultKeyWidth = row.getDefaultKeyWidth();
+ if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyWidth)) {
+ // Override default key width.
+ row.setDefaultKeyWidth(row.getKeyWidth(keyAttr));
+ }
+ savedDefaultKeyLabelFlags = row.getDefaultKeyLabelFlags();
+ // Bitwise-or default keyLabelFlag if exists.
+ row.setDefaultKeyLabelFlags(keyAttr.getInt(
+ R.styleable.Keyboard_Key_keyLabelFlags, 0)
+ | savedDefaultKeyLabelFlags);
+ savedDefaultBackgroundType = row.getDefaultBackgroundType();
+ // Override default backgroundType if exists.
+ row.setDefaultBackgroundType(keyAttr.getInt(
+ R.styleable.Keyboard_Key_backgroundType,
+ savedDefaultBackgroundType));
+ }
+ } finally {
+ keyboardAttr.recycle();
+ keyAttr.recycle();
+ }
- // TODO: Move this function to ProximityInfo and make this private.
- public void computeNearestNeighbors() {
- // Round-up so we don't have any pixels outside the grid
- mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
- mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
- mGridNeighbors = new int[GRID_SIZE][];
- final int[] indices = new int[mKeys.size()];
- final int gridWidth = GRID_WIDTH * mCellWidth;
- final int gridHeight = GRID_HEIGHT * mCellHeight;
- final int threshold = mProximityThreshold;
- for (int x = 0; x < gridWidth; x += mCellWidth) {
- for (int y = 0; y < gridHeight; y += mCellHeight) {
- final int centerX = x + mCellWidth / 2;
- final int centerY = y + mCellHeight / 2;
- int count = 0;
- for (int i = 0; i < mKeys.size(); i++) {
- final Key key = mKeys.get(i);
- if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
- indices[count++] = i;
+ XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
+ if (DEBUG) {
+ startEndTag("<%s keyboardLayout=%s />",TAG_INCLUDE,
+ mResources.getResourceEntryName(keyboardLayout));
+ }
+ final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout);
+ try {
+ parseMerge(parserForInclude, row, skip);
+ } finally {
+ if (row != null) {
+ // Restore default keyWidth, keyLabelFlags, and backgroundType.
+ row.setDefaultKeyWidth(savedDefaultKeyWidth);
+ row.setDefaultKeyLabelFlags(savedDefaultKeyLabelFlags);
+ row.setDefaultBackgroundType(savedDefaultBackgroundType);
+ }
+ parserForInclude.close();
}
- final int[] cell = new int[count];
- System.arraycopy(indices, 0, cell, 0, count);
- mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
}
}
- mProximityInfo.setProximityInfo(mGridNeighbors, getMinWidth(), getHeight(), mKeys);
- }
- /**
- * Returns the indices of the keys that are closest to the given point.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return the array of integer indices for the nearest keys to the given point. If the given
- * point is out of range, then an array of size zero is returned.
- */
- public int[] getNearestKeys(int x, int y) {
- if (mGridNeighbors == null) computeNearestNeighbors();
- if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
- int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
- if (index < GRID_SIZE) {
- return mGridNeighbors[index];
+ private void parseMerge(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) startTag("<%s>", TAG_MERGE);
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_MERGE.equals(tag)) {
+ if (row == null) {
+ parseKeyboardContent(parser, skip);
+ } else {
+ parseRowContent(parser, row, skip);
+ }
+ break;
+ } else {
+ throw new XmlParseUtils.ParseException(
+ "Included keyboard layout must have <merge> root element", parser);
+ }
+ }
}
}
- return EMPTY_INT_ARRAY;
- }
- /**
- * Compute the most common key width in order to use it as proximity key detection threshold.
- *
- * @return The most common key width in the keyboard
- */
- public int getMostCommonKeyWidth() {
- if (mMostCommonKeyWidth == 0) {
- final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
- int maxCount = 0;
- int mostCommonWidth = 0;
- for (final Key key : mKeys) {
- final Integer width = key.mWidth + key.mGap;
- Integer count = histogram.get(width);
- if (count == null)
- count = 0;
- histogram.put(width, ++count);
- if (count > maxCount) {
- maxCount = count;
- mostCommonWidth = width;
+ private void parseSwitchKeyboardContent(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseSwitchInternal(parser, null, skip);
+ }
+
+ private void parseSwitchRowContent(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ parseSwitchInternal(parser, row, skip);
+ }
+
+ private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) startTag("<%s> %s", TAG_SWITCH, mParams.mId);
+ boolean selected = false;
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_CASE.equals(tag)) {
+ selected |= parseCase(parser, row, selected ? true : skip);
+ } else if (TAG_DEFAULT.equals(tag)) {
+ selected |= parseDefault(parser, row, selected ? true : skip);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_SWITCH.equals(tag)) {
+ if (DEBUG) endTag("</%s>", TAG_SWITCH);
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
+ }
}
}
- mMostCommonKeyWidth = mostCommonWidth;
}
- return mMostCommonKeyWidth;
- }
- /**
- * Return true if spacebar needs showing preview even when "popup on keypress" is off.
- * @param keyIndex index of the pressing key
- * @return true if spacebar needs showing preview
- */
- public boolean needSpacebarPreview(int keyIndex) {
- return false;
- }
+ private boolean parseCase(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ final boolean selected = parseCaseCondition(parser);
+ if (row == null) {
+ // Processing Rows.
+ parseKeyboardContent(parser, selected ? skip : true);
+ } else {
+ // Processing Keys.
+ parseRowContent(parser, row, selected ? skip : true);
+ }
+ return selected;
+ }
+
+ private boolean parseCaseCondition(XmlPullParser parser) {
+ final KeyboardId id = mParams.mId;
+ if (id == null)
+ return true;
+
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Case);
+ try {
+ final boolean keyboardLayoutSetElementMatched = matchTypedValue(a,
+ R.styleable.Keyboard_Case_keyboardLayoutSetElement, id.mElementId,
+ KeyboardId.elementIdToName(id.mElementId));
+ final boolean modeMatched = matchTypedValue(a,
+ R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
+ final boolean navigateNextMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_navigateNext, id.navigateNext());
+ final boolean navigatePreviousMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_navigatePrevious, id.navigatePrevious());
+ final boolean passwordInputMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
+ final boolean clobberSettingsKeyMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
+ final boolean shortcutKeyEnabledMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled);
+ final boolean hasShortcutKeyMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
+ final boolean languageSwitchKeyEnabledMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
+ id.mLanguageSwitchKeyEnabled);
+ final boolean isMultiLineMatched = matchBoolean(a,
+ R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
+ final boolean imeActionMatched = matchInteger(a,
+ R.styleable.Keyboard_Case_imeAction, id.imeAction());
+ final boolean localeCodeMatched = matchString(a,
+ R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
+ final boolean languageCodeMatched = matchString(a,
+ R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage());
+ final boolean countryCodeMatched = matchString(a,
+ R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
+ final boolean selected = keyboardLayoutSetElementMatched && modeMatched
+ && navigateNextMatched && navigatePreviousMatched && passwordInputMatched
+ && clobberSettingsKeyMatched && shortcutKeyEnabledMatched
+ && hasShortcutKeyMatched && languageSwitchKeyEnabledMatched
+ && isMultiLineMatched && imeActionMatched && localeCodeMatched
+ && languageCodeMatched && countryCodeMatched;
+
+ if (DEBUG) {
+ startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
+ textAttr(a.getString(
+ R.styleable.Keyboard_Case_keyboardLayoutSetElement),
+ "keyboardLayoutSetElement"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_imeAction),
+ "imeAction"),
+ booleanAttr(a, R.styleable.Keyboard_Case_navigateNext,
+ "navigateNext"),
+ booleanAttr(a, R.styleable.Keyboard_Case_navigatePrevious,
+ "navigatePrevious"),
+ booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey,
+ "clobberSettingsKey"),
+ booleanAttr(a, R.styleable.Keyboard_Case_passwordInput,
+ "passwordInput"),
+ booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled,
+ "shortcutKeyEnabled"),
+ booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey,
+ "hasShortcutKey"),
+ booleanAttr(a, R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
+ "languageSwitchKeyEnabled"),
+ booleanAttr(a, R.styleable.Keyboard_Case_isMultiLine,
+ "isMultiLine"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_localeCode),
+ "localeCode"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_languageCode),
+ "languageCode"),
+ textAttr(a.getString(R.styleable.Keyboard_Case_countryCode),
+ "countryCode"),
+ selected ? "" : " skipped");
+ }
- private void loadKeyboard(Context context, int xmlLayoutResId) {
- try {
- KeyboardParser parser = new KeyboardParser(this, context);
- parser.parseKeyboard(xmlLayoutResId);
- // mMinWidth is the width of this keyboard which is maximum width of row.
- mMinWidth = parser.getMaxRowWidth();
- mTotalHeight = parser.getTotalHeight();
- } catch (XmlPullParserException e) {
- Log.w(TAG, "keyboard XML parse error: " + e);
- throw new IllegalArgumentException(e);
- } catch (IOException e) {
- Log.w(TAG, "keyboard XML parse error: " + e);
- throw new RuntimeException(e);
+ return selected;
+ } finally {
+ a.recycle();
+ }
+ }
+
+ private static boolean matchInteger(TypedArray a, int index, int value) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ return !a.hasValue(index) || a.getInt(index, 0) == value;
+ }
+
+ private static boolean matchBoolean(TypedArray a, int index, boolean value) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ return !a.hasValue(index) || a.getBoolean(index, false) == value;
+ }
+
+ private static boolean matchString(TypedArray a, int index, String value) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ return !a.hasValue(index)
+ || stringArrayContains(a.getString(index).split("\\|"), value);
+ }
+
+ private static boolean matchTypedValue(TypedArray a, int index, int intValue,
+ String strValue) {
+ // If <case> does not have "index" attribute, that means this <case> is wild-card for
+ // the attribute.
+ final TypedValue v = a.peekValue(index);
+ if (v == null)
+ return true;
+
+ if (isIntegerValue(v)) {
+ return intValue == a.getInt(index, 0);
+ } else if (isStringValue(v)) {
+ return stringArrayContains(a.getString(index).split("\\|"), strValue);
+ }
+ return false;
+ }
+
+ private static boolean stringArrayContains(String[] array, String value) {
+ for (final String elem : array) {
+ if (elem.equals(value))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean parseDefault(XmlPullParser parser, Row row, boolean skip)
+ throws XmlPullParserException, IOException {
+ if (DEBUG) startTag("<%s>", TAG_DEFAULT);
+ if (row == null) {
+ parseKeyboardContent(parser, skip);
+ } else {
+ parseRowContent(parser, row, skip);
+ }
+ return true;
+ }
+
+ private void parseKeyStyle(XmlPullParser parser, boolean skip)
+ throws XmlPullParserException, IOException {
+ TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_KeyStyle);
+ TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ try {
+ if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
+ throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE
+ + "/> needs styleName attribute", parser);
+ if (DEBUG) {
+ startEndTag("<%s styleName=%s />%s", TAG_KEY_STYLE,
+ keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName),
+ skip ? " skipped" : "");
+ }
+ if (!skip)
+ mParams.mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
+ } finally {
+ keyStyleAttr.recycle();
+ keyAttrs.recycle();
+ }
+ XmlParseUtils.checkEndTag(TAG_KEY_STYLE, parser);
+ }
+
+ private void startKeyboard() {
+ mCurrentY += mParams.mTopPadding;
+ mTopEdge = true;
+ }
+
+ private void startRow(Row row) {
+ addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
+ mCurrentRow = row;
+ mLeftEdge = true;
+ mRightEdgeKey = null;
}
- }
- public static void setDefaultBounds(Drawable drawable) {
- if (drawable != null)
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight());
+ private void endRow(Row row) {
+ if (mCurrentRow == null)
+ throw new InflateException("orphan end row tag");
+ if (mRightEdgeKey != null) {
+ mRightEdgeKey.markAsRightEdge(mParams);
+ mRightEdgeKey = null;
+ }
+ addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
+ mCurrentY += row.mRowHeight;
+ mCurrentRow = null;
+ mTopEdge = false;
+ }
+
+ private void endKey(Key key) {
+ mParams.onAddKey(key);
+ if (mLeftEdge) {
+ key.markAsLeftEdge(mParams);
+ mLeftEdge = false;
+ }
+ if (mTopEdge) {
+ key.markAsTopEdge(mParams);
+ }
+ mRightEdgeKey = key;
+ }
+
+ private void endKeyboard() {
+ // nothing to do here.
+ }
+
+ private void addEdgeSpace(float width, Row row) {
+ row.advanceXPos(width);
+ mLeftEdge = false;
+ mRightEdgeKey = null;
+ }
+
+ public static float getDimensionOrFraction(TypedArray a, int index, int base,
+ float defValue) {
+ final TypedValue value = a.peekValue(index);
+ if (value == null)
+ return defValue;
+ if (isFractionValue(value)) {
+ return a.getFraction(index, base, base, defValue);
+ } else if (isDimensionValue(value)) {
+ return a.getDimension(index, defValue);
+ }
+ return defValue;
+ }
+
+ public static int getEnumValue(TypedArray a, int index, int defValue) {
+ final TypedValue value = a.peekValue(index);
+ if (value == null)
+ return defValue;
+ if (isIntegerValue(value)) {
+ return a.getInt(index, defValue);
+ }
+ return defValue;
+ }
+
+ private static boolean isFractionValue(TypedValue v) {
+ return v.type == TypedValue.TYPE_FRACTION;
+ }
+
+ private static boolean isDimensionValue(TypedValue v) {
+ return v.type == TypedValue.TYPE_DIMENSION;
+ }
+
+ private static boolean isIntegerValue(TypedValue v) {
+ return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT;
+ }
+
+ private static boolean isStringValue(TypedValue v) {
+ return v.type == TypedValue.TYPE_STRING;
+ }
+
+ private static String textAttr(String value, String name) {
+ return value != null ? String.format(" %s=%s", name, value) : "";
+ }
+
+ private static String booleanAttr(TypedArray a, int index, String name) {
+ return a.hasValue(index)
+ ? String.format(" %s=%s", name, a.getBoolean(index, false)) : "";
+ }
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index 7e67d6f6b..275aacf36 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -24,10 +24,8 @@ public interface KeyboardActionListener {
*
* @param primaryCode the unicode of the key being pressed. If the touch is not on a valid key,
* the value will be zero.
- * @param withSliding true if pressing has occurred because the user slid finger from other key
- * to this key without releasing the finger.
*/
- public void onPress(int primaryCode, boolean withSliding);
+ public void onPressKey(int primaryCode);
/**
* Called when the user releases a key. This is sent after the {@link #onCodeInput} is called.
@@ -37,27 +35,26 @@ public interface KeyboardActionListener {
* @param withSliding true if releasing has occurred because the user slid finger from the key
* to other key without releasing the finger.
*/
- public void onRelease(int primaryCode, boolean withSliding);
+ public void onReleaseKey(int primaryCode, boolean withSliding);
/**
* Send a key code to the listener.
*
* @param primaryCode this is the code of the key that was pressed
- * @param keyCodes the codes for all the possible alternative keys with the primary code being
- * the first. If the primary key code is a single character such as an alphabet or
- * number or symbol, the alternatives will include other characters that may be on
- * the same key or adjacent keys. These codes are useful to correct for accidental
- * presses of a key adjacent to the intended key.
* @param x x-coordinate pixel of touched event. If {@link #onCodeInput} is not called by
- * {@link PointerTracker#onTouchEvent} or so, the value should be
- * {@link #NOT_A_TOUCH_COORDINATE}.
+ * {@link PointerTracker} or so, the value should be {@link #NOT_A_TOUCH_COORDINATE}.
+ * If it's called on insertion from the suggestion strip, it should be
+ * {@link #SUGGESTION_STRIP_COORDINATE}.
* @param y y-coordinate pixel of touched event. If {@link #onCodeInput} is not called by
- * {@link PointerTracker#onTouchEvent} or so, the value should be
- * {@link #NOT_A_TOUCH_COORDINATE}.
+ * {@link PointerTracker} or so, the value should be {@link #NOT_A_TOUCH_COORDINATE}.
+ * If it's called on insertion from the suggestion strip, it should be
+ * {@link #SUGGESTION_STRIP_COORDINATE}.
*/
- public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y);
+ public void onCodeInput(int primaryCode, int x, int y);
public static final int NOT_A_TOUCH_COORDINATE = -1;
+ public static final int SUGGESTION_STRIP_COORDINATE = -2;
+ public static final int SPELL_CHECKER_COORDINATE = -3;
/**
* Sends a sequence of characters to the listener.
@@ -72,7 +69,25 @@ public interface KeyboardActionListener {
public void onCancelInput();
/**
- * Called when the user quickly moves the finger from up to down.
+ * Send a non-"code input" custom request to the listener.
+ * @return true if the request has been consumed, false otherwise.
*/
- public void onSwipeDown();
+ public boolean onCustomRequest(int requestCode);
+
+ public static class Adapter implements KeyboardActionListener {
+ @Override
+ public void onPressKey(int primaryCode) {}
+ @Override
+ public void onReleaseKey(int primaryCode, boolean withSliding) {}
+ @Override
+ public void onCodeInput(int primaryCode, int x, int y) {}
+ @Override
+ public void onTextInput(CharSequence text) {}
+ @Override
+ public void onCancelInput() {}
+ @Override
+ public boolean onCustomRequest(int requestCode) {
+ return false;
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 9c63c198c..233716acf 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -16,18 +16,22 @@
package com.android.inputmethod.keyboard;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
+import android.text.InputType;
+import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
-import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.InputTypeUtils;
+import com.android.inputmethod.latin.SubtypeLocale;
import java.util.Arrays;
import java.util.Locale;
/**
- * Represents the parameters necessary to construct a new LatinKeyboard,
- * which also serve as a unique identifier for each keyboard type.
+ * Unique identifier for each keyboard type.
*/
public class KeyboardId {
public static final int MODE_TEXT = 0;
@@ -36,118 +40,134 @@ public class KeyboardId {
public static final int MODE_IM = 3;
public static final int MODE_PHONE = 4;
public static final int MODE_NUMBER = 5;
-
- public static final int F2KEY_MODE_NONE = 0;
- public static final int F2KEY_MODE_SETTINGS = 1;
- public static final int F2KEY_MODE_SHORTCUT_IME = 2;
- public static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
-
+ public static final int MODE_DATE = 6;
+ public static final int MODE_TIME = 7;
+ public static final int MODE_DATETIME = 8;
+
+ public static final int ELEMENT_ALPHABET = 0;
+ public static final int ELEMENT_ALPHABET_MANUAL_SHIFTED = 1;
+ public static final int ELEMENT_ALPHABET_AUTOMATIC_SHIFTED = 2;
+ public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3;
+ public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4;
+ public static final int ELEMENT_SYMBOLS = 5;
+ public static final int ELEMENT_SYMBOLS_SHIFTED = 6;
+ public static final int ELEMENT_PHONE = 7;
+ public static final int ELEMENT_PHONE_SYMBOLS = 8;
+ public static final int ELEMENT_NUMBER = 9;
+
+ private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1;
+
+ public final InputMethodSubtype mSubtype;
public final Locale mLocale;
public final int mOrientation;
public final int mWidth;
public final int mMode;
- public final int mXmlId;
- public final boolean mNavigateAction;
- public final boolean mPasswordInput;
- // TODO: Clean up these booleans and modes.
- public final boolean mHasSettingsKey;
- public final int mF2KeyMode;
+ public final int mElementId;
+ private final EditorInfo mEditorInfo;
public final boolean mClobberSettingsKey;
- public final boolean mVoiceKeyEnabled;
- public final boolean mHasVoiceKey;
- public final int mImeAction;
- public final boolean mEnableShiftLock;
-
- public final String mXmlName;
- public final EditorInfo mAttribute;
+ public final boolean mShortcutKeyEnabled;
+ public final boolean mHasShortcutKey;
+ public final boolean mLanguageSwitchKeyEnabled;
+ public final String mCustomActionLabel;
private final int mHashCode;
- public KeyboardId(String xmlName, int xmlId, Locale locale, int orientation, int width,
- int mode, EditorInfo attribute, boolean hasSettingsKey, int f2KeyMode,
- boolean clobberSettingsKey, boolean voiceKeyEnabled, boolean hasVoiceKey,
- boolean enableShiftLock) {
- final int inputType = (attribute != null) ? attribute.inputType : 0;
- final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
- this.mLocale = locale;
- this.mOrientation = orientation;
- this.mWidth = width;
- this.mMode = mode;
- this.mXmlId = xmlId;
- // Note: Turn off checking navigation flag to show TAB key for now.
- this.mNavigateAction = InputTypeCompatUtils.isWebInputType(inputType);
-// || EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
-// || EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions);
- this.mPasswordInput = InputTypeCompatUtils.isPasswordInputType(inputType)
- || InputTypeCompatUtils.isVisiblePasswordInputType(inputType);
- this.mHasSettingsKey = hasSettingsKey;
- this.mF2KeyMode = f2KeyMode;
- this.mClobberSettingsKey = clobberSettingsKey;
- this.mVoiceKeyEnabled = voiceKeyEnabled;
- this.mHasVoiceKey = hasVoiceKey;
- // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and
- // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}.
- this.mImeAction = imeOptions & (
- EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
- this.mEnableShiftLock = enableShiftLock;
-
- this.mXmlName = xmlName;
- this.mAttribute = attribute;
-
- this.mHashCode = Arrays.hashCode(new Object[] {
- locale,
- orientation,
- width,
- mode,
- xmlId,
- mNavigateAction,
- mPasswordInput,
- hasSettingsKey,
- f2KeyMode,
- clobberSettingsKey,
- voiceKeyEnabled,
- hasVoiceKey,
- mImeAction,
- enableShiftLock,
+ public KeyboardId(int elementId, InputMethodSubtype subtype, int orientation, int width,
+ int mode, EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled,
+ boolean hasShortcutKey, boolean languageSwitchKeyEnabled) {
+ mSubtype = subtype;
+ mLocale = SubtypeLocale.getSubtypeLocale(subtype);
+ mOrientation = orientation;
+ mWidth = width;
+ mMode = mode;
+ mElementId = elementId;
+ mEditorInfo = editorInfo;
+ mClobberSettingsKey = clobberSettingsKey;
+ mShortcutKeyEnabled = shortcutKeyEnabled;
+ mHasShortcutKey = hasShortcutKey;
+ mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled;
+ mCustomActionLabel = (editorInfo.actionLabel != null)
+ ? editorInfo.actionLabel.toString() : null;
+
+ mHashCode = computeHashCode(this);
+ }
+
+ private static int computeHashCode(KeyboardId id) {
+ return Arrays.hashCode(new Object[] {
+ id.mOrientation,
+ id.mElementId,
+ id.mMode,
+ id.mWidth,
+ id.passwordInput(),
+ id.mClobberSettingsKey,
+ id.mShortcutKeyEnabled,
+ id.mHasShortcutKey,
+ id.mLanguageSwitchKeyEnabled,
+ id.isMultiLine(),
+ id.imeAction(),
+ id.mCustomActionLabel,
+ id.navigateNext(),
+ id.navigatePrevious(),
+ id.mSubtype
});
}
- public KeyboardId cloneWithNewLayout(String xmlName, int xmlId) {
- return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mAttribute,
- mHasSettingsKey, mF2KeyMode, mClobberSettingsKey, mVoiceKeyEnabled, mHasVoiceKey,
- mEnableShiftLock);
+ private boolean equals(KeyboardId other) {
+ if (other == this)
+ return true;
+ return other.mOrientation == mOrientation
+ && other.mElementId == mElementId
+ && other.mMode == mMode
+ && other.mWidth == mWidth
+ && other.passwordInput() == passwordInput()
+ && other.mClobberSettingsKey == mClobberSettingsKey
+ && other.mShortcutKeyEnabled == mShortcutKeyEnabled
+ && other.mHasShortcutKey == mHasShortcutKey
+ && other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled
+ && other.isMultiLine() == isMultiLine()
+ && other.imeAction() == imeAction()
+ && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)
+ && other.navigateNext() == navigateNext()
+ && other.navigatePrevious() == navigatePrevious()
+ && other.mSubtype.equals(mSubtype);
}
- public KeyboardId cloneWithNewGeometry(int width) {
- if (mWidth == width)
- return this;
- return new KeyboardId(mXmlName, mXmlId, mLocale, mOrientation, width, mMode, mAttribute,
- mHasSettingsKey, mF2KeyMode, mClobberSettingsKey, mVoiceKeyEnabled, mHasVoiceKey,
- mEnableShiftLock);
+ public boolean isAlphabetKeyboard() {
+ return mElementId < ELEMENT_SYMBOLS;
}
- public int getXmlId() {
- return mXmlId;
+ public boolean navigateNext() {
+ return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0;
}
- public boolean isAlphabetKeyboard() {
- return mXmlId == R.xml.kbd_qwerty;
+ public boolean navigatePrevious() {
+ return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0;
}
- public boolean isSymbolsKeyboard() {
- return mXmlId == R.xml.kbd_symbols || mXmlId == R.xml.kbd_symbols_shift;
+ public boolean passwordInput() {
+ final int inputType = mEditorInfo.inputType;
+ return InputTypeUtils.isPasswordInputType(inputType)
+ || InputTypeUtils.isVisiblePasswordInputType(inputType);
}
- public boolean isPhoneKeyboard() {
- return mMode == MODE_PHONE;
+ public boolean isMultiLine() {
+ return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0;
}
- public boolean isPhoneSymbolsKeyboard() {
- return mXmlId == R.xml.kbd_phone_symbols;
+ public int imeAction() {
+ final int actionId = mEditorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
+ if ((mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
+ return EditorInfo.IME_ACTION_NONE;
+ } else if (mEditorInfo.actionLabel != null) {
+ return IME_ACTION_CUSTOM_LABEL;
+ } else {
+ return actionId;
+ }
}
- public boolean isNumberKeyboard() {
- return mMode == MODE_NUMBER;
+ public int imeActionId() {
+ final int actionId = imeAction();
+ return actionId == IME_ACTION_CUSTOM_LABEL ? mEditorInfo.actionId : actionId;
}
@Override
@@ -155,23 +175,6 @@ public class KeyboardId {
return other instanceof KeyboardId && equals((KeyboardId) other);
}
- boolean equals(KeyboardId other) {
- return other.mLocale.equals(this.mLocale)
- && other.mOrientation == this.mOrientation
- && other.mWidth == this.mWidth
- && other.mMode == this.mMode
- && other.mXmlId == this.mXmlId
- && other.mNavigateAction == this.mNavigateAction
- && other.mPasswordInput == this.mPasswordInput
- && other.mHasSettingsKey == this.mHasSettingsKey
- && other.mF2KeyMode == this.mF2KeyMode
- && other.mClobberSettingsKey == this.mClobberSettingsKey
- && other.mVoiceKeyEnabled == this.mVoiceKeyEnabled
- && other.mHasVoiceKey == this.mHasVoiceKey
- && other.mImeAction == this.mImeAction
- && other.mEnableShiftLock == this.mEnableShiftLock;
- }
-
@Override
public int hashCode() {
return mHashCode;
@@ -179,23 +182,48 @@ public class KeyboardId {
@Override
public String toString() {
- return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s%s%s]",
- mXmlName,
+ return String.format("[%s %s:%s %s%d %s %s %s%s%s%s%s%s%s%s]",
+ elementIdToName(mElementId),
mLocale,
+ mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
(mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode),
- EditorInfoCompatUtils.imeOptionsName(mImeAction),
- f2KeyModeName(mF2KeyMode),
+ imeAction(),
+ (navigateNext() ? "navigateNext" : ""),
+ (navigatePrevious() ? "navigatePrevious" : ""),
(mClobberSettingsKey ? " clobberSettingsKey" : ""),
- (mNavigateAction ? " navigateAction" : ""),
- (mPasswordInput ? " passwordInput" : ""),
- (mHasSettingsKey ? " hasSettingsKey" : ""),
- (mVoiceKeyEnabled ? " voiceKeyEnabled" : ""),
- (mHasVoiceKey ? " hasVoiceKey" : ""),
- (mEnableShiftLock ? " enableShiftLock" : "")
+ (passwordInput() ? " passwordInput" : ""),
+ (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
+ (mHasShortcutKey ? " hasShortcutKey" : ""),
+ (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
+ (isMultiLine() ? "isMultiLine" : "")
);
}
+ public static boolean equivalentEditorInfoForKeyboard(EditorInfo a, EditorInfo b) {
+ if (a == null && b == null) return true;
+ if (a == null || b == null) return false;
+ return a.inputType == b.inputType
+ && a.imeOptions == b.imeOptions
+ && TextUtils.equals(a.privateImeOptions, b.privateImeOptions);
+ }
+
+ public static String elementIdToName(int elementId) {
+ switch (elementId) {
+ case ELEMENT_ALPHABET: return "alphabet";
+ case ELEMENT_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted";
+ case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted";
+ case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked";
+ case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted";
+ case ELEMENT_SYMBOLS: return "symbols";
+ case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted";
+ case ELEMENT_PHONE: return "phone";
+ case ELEMENT_PHONE_SYMBOLS: return "phoneSymbols";
+ case ELEMENT_NUMBER: return "number";
+ default: return null;
+ }
+ }
+
public static String modeName(int mode) {
switch (mode) {
case MODE_TEXT: return "text";
@@ -204,17 +232,15 @@ public class KeyboardId {
case MODE_IM: return "im";
case MODE_PHONE: return "phone";
case MODE_NUMBER: return "number";
+ case MODE_DATE: return "date";
+ case MODE_TIME: return "time";
+ case MODE_DATETIME: return "datetime";
default: return null;
}
}
- public static String f2KeyModeName(int f2KeyMode) {
- switch (f2KeyMode) {
- case F2KEY_MODE_NONE: return "none";
- case F2KEY_MODE_SETTINGS: return "settings";
- case F2KEY_MODE_SHORTCUT_IME: return "shortcutIme";
- case F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS: return "shortcutImeOrSettings";
- default: return null;
- }
+ public static String actionName(int actionId) {
+ return (actionId == IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel"
+ : EditorInfoCompatUtils.imeActionName(actionId);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
new file mode 100644
index 000000000..8c7246855
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_SETTINGS_KEY;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.text.InputType;
+import android.util.Log;
+import android.util.Xml;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.compat.EditorInfoCompatUtils;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet.Params.ElementParams;
+import com.android.inputmethod.latin.InputAttributes;
+import com.android.inputmethod.latin.InputTypeUtils;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SubtypeLocale;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.XmlParseUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+
+/**
+ * This class represents a set of keyboard layouts. Each of them represents a different keyboard
+ * specific to a keyboard state, such as alphabet, symbols, and so on. Layouts in the same
+ * {@link KeyboardLayoutSet} are related to each other.
+ * A {@link KeyboardLayoutSet} needs to be created for each
+ * {@link android.view.inputmethod.EditorInfo}.
+ */
+public class KeyboardLayoutSet {
+ private static final String TAG = KeyboardLayoutSet.class.getSimpleName();
+ private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
+
+ private static final String TAG_KEYBOARD_SET = "KeyboardLayoutSet";
+ private static final String TAG_ELEMENT = "Element";
+
+ private static final String KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX = "keyboard_layout_set_";
+
+ private final Context mContext;
+ private final Params mParams;
+
+ private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
+ new HashMap<KeyboardId, SoftReference<Keyboard>>();
+ private static final KeysCache sKeysCache = new KeysCache();
+
+ public static class KeyboardLayoutSetException extends RuntimeException {
+ public final KeyboardId mKeyboardId;
+
+ public KeyboardLayoutSetException(Throwable cause, KeyboardId keyboardId) {
+ super(cause);
+ mKeyboardId = keyboardId;
+ }
+ }
+
+ public static class KeysCache {
+ private final HashMap<Key, Key> mMap;
+
+ public KeysCache() {
+ mMap = new HashMap<Key, Key>();
+ }
+
+ public void clear() {
+ mMap.clear();
+ }
+
+ public Key get(Key key) {
+ final Key existingKey = mMap.get(key);
+ if (existingKey != null) {
+ // Reuse the existing element that equals to "key" without adding "key" to the map.
+ return existingKey;
+ }
+ mMap.put(key, key);
+ return key;
+ }
+ }
+
+ static class Params {
+ String mKeyboardLayoutSetName;
+ int mMode;
+ EditorInfo mEditorInfo;
+ boolean mTouchPositionCorrectionEnabled;
+ boolean mVoiceKeyEnabled;
+ boolean mVoiceKeyOnMain;
+ boolean mNoSettingsKey;
+ boolean mLanguageSwitchKeyEnabled;
+ InputMethodSubtype mSubtype;
+ int mOrientation;
+ int mWidth;
+ // KeyboardLayoutSet element id to element's parameters map.
+ final HashMap<Integer, ElementParams> mKeyboardLayoutSetElementIdToParamsMap =
+ new HashMap<Integer, ElementParams>();
+
+ static class ElementParams {
+ int mKeyboardXmlId;
+ boolean mProximityCharsCorrectionEnabled;
+ }
+ }
+
+ public static void clearKeyboardCache() {
+ sKeyboardCache.clear();
+ sKeysCache.clear();
+ }
+
+ private KeyboardLayoutSet(Context context, Params params) {
+ mContext = context;
+ mParams = params;
+ }
+
+ public Keyboard getKeyboard(int baseKeyboardLayoutSetElementId) {
+ final int keyboardLayoutSetElementId;
+ switch (mParams.mMode) {
+ case KeyboardId.MODE_PHONE:
+ if (baseKeyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS) {
+ keyboardLayoutSetElementId = KeyboardId.ELEMENT_PHONE_SYMBOLS;
+ } else {
+ keyboardLayoutSetElementId = KeyboardId.ELEMENT_PHONE;
+ }
+ break;
+ case KeyboardId.MODE_NUMBER:
+ case KeyboardId.MODE_DATE:
+ case KeyboardId.MODE_TIME:
+ case KeyboardId.MODE_DATETIME:
+ keyboardLayoutSetElementId = KeyboardId.ELEMENT_NUMBER;
+ break;
+ default:
+ keyboardLayoutSetElementId = baseKeyboardLayoutSetElementId;
+ break;
+ }
+
+ ElementParams elementParams = mParams.mKeyboardLayoutSetElementIdToParamsMap.get(
+ keyboardLayoutSetElementId);
+ if (elementParams == null) {
+ elementParams = mParams.mKeyboardLayoutSetElementIdToParamsMap.get(
+ KeyboardId.ELEMENT_ALPHABET);
+ }
+ final KeyboardId id = getKeyboardId(keyboardLayoutSetElementId);
+ try {
+ return getKeyboard(elementParams, id);
+ } catch (RuntimeException e) {
+ throw new KeyboardLayoutSetException(e, id);
+ }
+ }
+
+ private Keyboard getKeyboard(ElementParams elementParams, final KeyboardId id) {
+ final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
+ Keyboard keyboard = (ref == null) ? null : ref.get();
+ if (keyboard == null) {
+ final Keyboard.Builder<Keyboard.Params> builder =
+ new Keyboard.Builder<Keyboard.Params>(mContext, new Keyboard.Params());
+ if (id.isAlphabetKeyboard()) {
+ builder.setAutoGenerate(sKeysCache);
+ }
+ final int keyboardXmlId = elementParams.mKeyboardXmlId;
+ builder.load(keyboardXmlId, id);
+ builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled);
+ builder.setProximityCharsCorrectionEnabled(
+ elementParams.mProximityCharsCorrectionEnabled);
+ keyboard = builder.build();
+ sKeyboardCache.put(id, new SoftReference<Keyboard>(keyboard));
+
+ if (DEBUG_CACHE) {
+ Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": "
+ + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
+ }
+ } else if (DEBUG_CACHE) {
+ Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT id=" + id);
+ }
+
+ return keyboard;
+ }
+
+ // Note: The keyboard for each locale, shift state, and mode are represented as
+ // KeyboardLayoutSet element id that is a key in keyboard_set.xml. Also that file specifies
+ // which XML layout should be used for each keyboard. The KeyboardId is an internal key for
+ // Keyboard object.
+ private KeyboardId getKeyboardId(int keyboardLayoutSetElementId) {
+ final Params params = mParams;
+ final boolean isSymbols = (keyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS
+ || keyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED);
+ final boolean noLanguage = SubtypeLocale.isNoLanguage(params.mSubtype);
+ final boolean voiceKeyEnabled = params.mVoiceKeyEnabled && !noLanguage;
+ final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != params.mVoiceKeyOnMain);
+ return new KeyboardId(keyboardLayoutSetElementId, params.mSubtype, params.mOrientation,
+ params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey,
+ voiceKeyEnabled, hasShortcutKey, params.mLanguageSwitchKeyEnabled);
+ }
+
+ public static class Builder {
+ private final Context mContext;
+ private final String mPackageName;
+ private final Resources mResources;
+ private final EditorInfo mEditorInfo;
+
+ private final Params mParams = new Params();
+
+ private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo();
+
+ public Builder(Context context, EditorInfo editorInfo) {
+ mContext = context;
+ mPackageName = context.getPackageName();
+ mResources = context.getResources();
+ mEditorInfo = editorInfo;
+ final Params params = mParams;
+
+ params.mMode = getKeyboardMode(editorInfo);
+ params.mEditorInfo = (editorInfo != null) ? editorInfo : EMPTY_EDITOR_INFO;
+ params.mNoSettingsKey = InputAttributes.inPrivateImeOptions(
+ mPackageName, NO_SETTINGS_KEY, mEditorInfo);
+ }
+
+ public Builder setScreenGeometry(int orientation, int widthPixels) {
+ mParams.mOrientation = orientation;
+ mParams.mWidth = widthPixels;
+ return this;
+ }
+
+ public Builder setSubtype(InputMethodSubtype subtype) {
+ final boolean asciiCapable = subtype.containsExtraValueKey(ASCII_CAPABLE);
+ @SuppressWarnings("deprecation")
+ final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
+ mPackageName, FORCE_ASCII, mEditorInfo);
+ final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
+ mParams.mEditorInfo.imeOptions)
+ || deprecatedForceAscii;
+ final InputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
+ ? SubtypeSwitcher.getInstance().getNoLanguageSubtype()
+ : subtype;
+ mParams.mSubtype = keyboardSubtype;
+ mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX
+ + SubtypeLocale.getKeyboardLayoutSetName(keyboardSubtype);
+ return this;
+ }
+
+ public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain,
+ boolean languageSwitchKeyEnabled) {
+ @SuppressWarnings("deprecation")
+ final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions(
+ null, NO_MICROPHONE_COMPAT, mEditorInfo);
+ final boolean noMicrophone = InputAttributes.inPrivateImeOptions(
+ mPackageName, NO_MICROPHONE, mEditorInfo)
+ || deprecatedNoMicrophone;
+ mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone;
+ mParams.mVoiceKeyOnMain = voiceKeyOnMain;
+ mParams.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled;
+ return this;
+ }
+
+ public void setTouchPositionCorrectionEnabled(boolean enabled) {
+ mParams.mTouchPositionCorrectionEnabled = enabled;
+ }
+
+ public KeyboardLayoutSet build() {
+ if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED)
+ throw new RuntimeException("Screen geometry is not specified");
+ if (mParams.mSubtype == null)
+ throw new RuntimeException("KeyboardLayoutSet subtype is not specified");
+ final String packageName = mResources.getResourcePackageName(
+ R.xml.keyboard_layout_set_qwerty);
+ final String keyboardLayoutSetName = mParams.mKeyboardLayoutSetName;
+ final int xmlId = mResources.getIdentifier(keyboardLayoutSetName, "xml", packageName);
+ try {
+ parseKeyboardLayoutSet(mResources, xmlId);
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName);
+ }
+ return new KeyboardLayoutSet(mContext, mParams);
+ }
+
+ private void parseKeyboardLayoutSet(Resources res, int resId)
+ throws XmlPullParserException, IOException {
+ final XmlResourceParser parser = res.getXml(resId);
+ try {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ parseKeyboardLayoutSetContent(parser);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
+ }
+ } finally {
+ parser.close();
+ }
+ }
+
+ private void parseKeyboardLayoutSetContent(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event == XmlPullParser.START_TAG) {
+ final String tag = parser.getName();
+ if (TAG_ELEMENT.equals(tag)) {
+ parseKeyboardLayoutSetElement(parser);
+ } else {
+ throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
+ }
+ } else if (event == XmlPullParser.END_TAG) {
+ final String tag = parser.getName();
+ if (TAG_KEYBOARD_SET.equals(tag)) {
+ break;
+ } else {
+ throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEYBOARD_SET);
+ }
+ }
+ }
+ }
+
+ private void parseKeyboardLayoutSetElement(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.KeyboardLayoutSet_Element);
+ try {
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.KeyboardLayoutSet_Element_elementName, "elementName",
+ TAG_ELEMENT, parser);
+ XmlParseUtils.checkAttributeExists(a,
+ R.styleable.KeyboardLayoutSet_Element_elementKeyboard, "elementKeyboard",
+ TAG_ELEMENT, parser);
+ XmlParseUtils.checkEndTag(TAG_ELEMENT, parser);
+
+ final ElementParams elementParams = new ElementParams();
+ final int elementName = a.getInt(
+ R.styleable.KeyboardLayoutSet_Element_elementName, 0);
+ elementParams.mKeyboardXmlId = a.getResourceId(
+ R.styleable.KeyboardLayoutSet_Element_elementKeyboard, 0);
+ elementParams.mProximityCharsCorrectionEnabled = a.getBoolean(
+ R.styleable.KeyboardLayoutSet_Element_enableProximityCharsCorrection,
+ false);
+ mParams.mKeyboardLayoutSetElementIdToParamsMap.put(elementName, elementParams);
+ } finally {
+ a.recycle();
+ }
+ }
+
+ private static int getKeyboardMode(EditorInfo editorInfo) {
+ if (editorInfo == null)
+ return KeyboardId.MODE_TEXT;
+
+ final int inputType = editorInfo.inputType;
+ final int variation = inputType & InputType.TYPE_MASK_VARIATION;
+
+ switch (inputType & InputType.TYPE_MASK_CLASS) {
+ case InputType.TYPE_CLASS_NUMBER:
+ return KeyboardId.MODE_NUMBER;
+ case InputType.TYPE_CLASS_DATETIME:
+ switch (variation) {
+ case InputType.TYPE_DATETIME_VARIATION_DATE:
+ return KeyboardId.MODE_DATE;
+ case InputType.TYPE_DATETIME_VARIATION_TIME:
+ return KeyboardId.MODE_TIME;
+ default: // InputType.TYPE_DATETIME_VARIATION_NORMAL
+ return KeyboardId.MODE_DATETIME;
+ }
+ case InputType.TYPE_CLASS_PHONE:
+ return KeyboardId.MODE_PHONE;
+ case InputType.TYPE_CLASS_TEXT:
+ if (InputTypeUtils.isEmailVariation(variation)) {
+ return KeyboardId.MODE_EMAIL;
+ } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
+ return KeyboardId.MODE_URL;
+ } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
+ return KeyboardId.MODE_IM;
+ } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
+ return KeyboardId.MODE_TEXT;
+ } else {
+ return KeyboardId.MODE_TEXT;
+ }
+ default:
+ return KeyboardId.MODE_TEXT;
+ }
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 275e9d1fe..2e4ce199e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -27,86 +27,64 @@ import android.view.View;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.keyboard.internal.ModifierKeyState;
-import com.android.inputmethod.keyboard.internal.ShiftKeyState;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
+import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.keyboard.internal.KeyboardState;
+import com.android.inputmethod.latin.DebugSettings;
+import com.android.inputmethod.latin.ImfUtils;
+import com.android.inputmethod.latin.InputView;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.Settings;
+import com.android.inputmethod.latin.SettingsValues;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
-import java.lang.ref.SoftReference;
-import java.util.HashMap;
-import java.util.Locale;
-
-public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener {
+public class KeyboardSwitcher implements KeyboardState.SwitchActions {
private static final String TAG = KeyboardSwitcher.class.getSimpleName();
- private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
- public static final boolean DEBUG_STATE = false;
-
- public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
- private static final int[] KEYBOARD_THEMES = {
- R.style.KeyboardTheme,
- R.style.KeyboardTheme_HighContrast,
- R.style.KeyboardTheme_Stone,
- R.style.KeyboardTheme_Stone_Bold,
- R.style.KeyboardTheme_Gingerbread,
- R.style.KeyboardTheme_IceCreamSandwich,
+
+ public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916";
+
+ static class KeyboardTheme {
+ public final String mName;
+ public final int mThemeId;
+ public final int mStyleId;
+
+ public KeyboardTheme(String name, int themeId, int styleId) {
+ mName = name;
+ mThemeId = themeId;
+ mStyleId = styleId;
+ }
+ }
+
+ private static final KeyboardTheme[] KEYBOARD_THEMES = {
+ new KeyboardTheme("Basic", 0, R.style.KeyboardTheme),
+ new KeyboardTheme("HighContrast", 1, R.style.KeyboardTheme_HighContrast),
+ new KeyboardTheme("Stone", 6, R.style.KeyboardTheme_Stone),
+ new KeyboardTheme("Stne.Bold", 7, R.style.KeyboardTheme_Stone_Bold),
+ new KeyboardTheme("GingerBread", 8, R.style.KeyboardTheme_Gingerbread),
+ new KeyboardTheme("IceCreamSandwich", 5, R.style.KeyboardTheme_IceCreamSandwich),
};
private SubtypeSwitcher mSubtypeSwitcher;
private SharedPreferences mPrefs;
+ private boolean mForceNonDistinctMultitouch;
- private View mCurrentInputView;
+ private InputView mCurrentInputView;
private LatinKeyboardView mKeyboardView;
- private LatinIME mInputMethodService;
-
- // TODO: Combine these key state objects with auto mode switch state.
- private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
- private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
+ private LatinIME mLatinIME;
+ private Resources mResources;
- private KeyboardId mSymbolsId;
- private KeyboardId mSymbolsShiftedId;
+ private KeyboardState mState;
- private KeyboardId mCurrentId;
- private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
- new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
+ private KeyboardLayoutSet mKeyboardLayoutSet;
- private EditorInfo mAttribute;
- private boolean mIsSymbols;
/** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of
* what user actually typed. */
private boolean mIsAutoCorrectionActive;
- private boolean mVoiceKeyEnabled;
- private boolean mVoiceButtonOnPrimary;
-
- // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState
- // and ModifierKeyState.
- private static final int SWITCH_STATE_ALPHA = 0;
- private static final int SWITCH_STATE_SYMBOL_BEGIN = 1;
- private static final int SWITCH_STATE_SYMBOL = 2;
- // The following states are used only on the distinct multi-touch panel devices.
- private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3;
- private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4;
- private static final int SWITCH_STATE_CHORDING_ALPHA = 5;
- private static final int SWITCH_STATE_CHORDING_SYMBOL = 6;
- private int mSwitchState = SWITCH_STATE_ALPHA;
-
- // Indicates whether or not we have the settings key in option of settings
- private boolean mSettingsKeyEnabledInSettings;
- private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto;
- private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW =
- R.string.settings_key_mode_always_show;
- // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to
- // in the source code now.
- // Default is SETTINGS_KEY_MODE_AUTO.
- private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO;
-
- private int mThemeIndex = -1;
+
+ private KeyboardTheme mKeyboardTheme = KEYBOARD_THEMES[0];
private Context mThemeContext;
- private int mKeyboardWidth;
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
@@ -118,612 +96,251 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// Intentional empty constructor for singleton.
}
- public static void init(LatinIME ims, SharedPreferences prefs) {
- sInstance.mInputMethodService = ims;
- sInstance.mPrefs = prefs;
- sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- sInstance.setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
- prefs.registerOnSharedPreferenceChangeListener(sInstance);
+ public static void init(LatinIME latinIme, SharedPreferences prefs) {
+ sInstance.initInternal(latinIme, prefs);
+ }
+
+ private void initInternal(LatinIME latinIme, SharedPreferences prefs) {
+ mLatinIME = latinIme;
+ mResources = latinIme.getResources();
+ mPrefs = prefs;
+ mSubtypeSwitcher = SubtypeSwitcher.getInstance();
+ mState = new KeyboardState(this);
+ setContextThemeWrapper(latinIme, getKeyboardTheme(latinIme, prefs));
+ mForceNonDistinctMultitouch = prefs.getBoolean(
+ DebugSettings.FORCE_NON_DISTINCT_MULTITOUCH_KEY, false);
}
- private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) {
- final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id);
- final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId);
+ private static KeyboardTheme getKeyboardTheme(Context context, SharedPreferences prefs) {
+ final String defaultIndex = context.getString(R.string.config_default_keyboard_theme_index);
+ final String themeIndex = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultIndex);
try {
- final int themeIndex = Integer.valueOf(themeId);
- if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length)
- return themeIndex;
+ final int index = Integer.valueOf(themeIndex);
+ if (index >= 0 && index < KEYBOARD_THEMES.length) {
+ return KEYBOARD_THEMES[index];
+ }
} catch (NumberFormatException e) {
// Format error, keyboard theme is default to 0.
}
- Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0");
- return 0;
+ Log.w(TAG, "Illegal keyboard theme in preference: " + themeIndex + ", default to 0");
+ return KEYBOARD_THEMES[0];
}
- private void setContextThemeWrapper(Context context, int themeIndex) {
- if (mThemeIndex != themeIndex) {
- mThemeIndex = themeIndex;
- mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
- mKeyboardCache.clear();
+ private void setContextThemeWrapper(Context context, KeyboardTheme keyboardTheme) {
+ if (mKeyboardTheme.mThemeId != keyboardTheme.mThemeId) {
+ mKeyboardTheme = keyboardTheme;
+ mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId);
+ KeyboardLayoutSet.clearKeyboardCache();
}
}
- public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled,
- boolean voiceButtonOnPrimary) {
- mSwitchState = SWITCH_STATE_ALPHA;
+ public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
+ final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
+ mThemeContext, editorInfo);
+ builder.setScreenGeometry(mThemeContext.getResources().getConfiguration().orientation,
+ mThemeContext.getResources().getDisplayMetrics().widthPixels);
+ builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype());
+ builder.setOptions(
+ settingsValues.isVoiceKeyEnabled(editorInfo),
+ settingsValues.isVoiceKeyOnMain(),
+ settingsValues.isLanguageSwitchKeyEnabled(mThemeContext));
+ mKeyboardLayoutSet = builder.build();
try {
- loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false);
- } catch (RuntimeException e) {
- // Get KeyboardId to record which keyboard has been failed to load.
- final KeyboardId id = getKeyboardId(attribute, false);
- Log.w(TAG, "loading keyboard failed: " + id, e);
- LatinImeLogger.logOnException(id.toString(), e);
+ mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols));
+ } catch (KeyboardLayoutSetException e) {
+ Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
+ LatinImeLogger.logOnException(e.mKeyboardId.toString(), e.getCause());
+ return;
}
}
- private void loadKeyboardInternal(EditorInfo attribute, boolean voiceButtonEnabled,
- boolean voiceButtonOnPrimary, boolean isSymbols) {
- if (mKeyboardView == null) return;
-
- mAttribute = attribute;
- mVoiceKeyEnabled = voiceButtonEnabled;
- mVoiceButtonOnPrimary = voiceButtonOnPrimary;
- mIsSymbols = isSymbols;
- // Update the settings key state because number of enabled IMEs could have been changed
- mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService);
- final KeyboardId id = getKeyboardId(attribute, isSymbols);
-
- // Note: This comment is only applied for phone number keyboard layout.
- // On non-xlarge device, "@integer/key_switch_alpha_symbol" key code is used to switch
- // between "phone keyboard" and "phone symbols keyboard". But on xlarge device,
- // "@integer/key_shift" key code is used for that purpose in order to properly display
- // "more" and "locked more" key labels. To achieve these behavior, we should initialize
- // mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
- // respectively here for xlarge device's layout switching.
- mSymbolsId = makeSiblingKeyboardId(id, R.xml.kbd_symbols, R.xml.kbd_phone);
- mSymbolsShiftedId = makeSiblingKeyboardId(
- id, R.xml.kbd_symbols_shift, R.xml.kbd_phone_symbols);
+ public void saveKeyboardState() {
+ if (getKeyboard() != null) {
+ mState.onSaveKeyboardState();
+ }
+ }
- setKeyboard(getKeyboard(id));
+ public void onFinishInputView() {
+ mIsAutoCorrectionActive = false;
}
- public void onSizeChanged() {
- final int width = mInputMethodService.getWindow().getWindow().getDecorView().getWidth();
- if (width == 0 || mCurrentId == null)
- return;
- mKeyboardWidth = width;
- // Set keyboard with new width.
- final KeyboardId newId = mCurrentId.cloneWithNewGeometry(width);
- setKeyboard(getKeyboard(newId));
+ public void onHideWindow() {
+ mIsAutoCorrectionActive = false;
}
- private void setKeyboard(final Keyboard newKeyboard) {
+ private void setKeyboard(final Keyboard keyboard) {
final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
- mKeyboardView.setKeyboard(newKeyboard);
- mCurrentId = newKeyboard.mId;
- final Resources res = mInputMethodService.getResources();
+ mKeyboardView.setKeyboard(keyboard);
+ mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding);
mKeyboardView.setKeyPreviewPopupEnabled(
- Settings.Values.isKeyPreviewPopupEnabled(mPrefs, res),
- Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, res));
- final boolean localeChanged = (oldKeyboard == null)
- || !newKeyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
- mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged);
- }
-
- private LatinKeyboard getKeyboard(KeyboardId id) {
- final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
- LatinKeyboard keyboard = (ref == null) ? null : ref.get();
- if (keyboard == null) {
- final Resources res = mInputMethodService.getResources();
- final Locale savedLocale = Utils.setSystemLocale(res,
- mSubtypeSwitcher.getInputLocale());
-
- keyboard = new LatinKeyboard(mThemeContext, id, id.mWidth);
-
- if (id.mEnableShiftLock) {
- keyboard.enableShiftLock();
- }
-
- mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard));
- if (DEBUG_CACHE)
- Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
- + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
-
- Utils.setSystemLocale(res, savedLocale);
- } else if (DEBUG_CACHE) {
- Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id);
- }
-
- keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive);
- keyboard.setShifted(false);
- // If the cached keyboard had been switched to another keyboard while the language was
- // displayed on its spacebar, it might have had arbitrary text fade factor. In such case,
- // we should reset the text fade factor. It is also applicable to shortcut key.
- keyboard.setSpacebarTextFadeFactor(0.0f, null);
- keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null);
- keyboard.setSpacebarSlidingLanguageSwitchDiff(0);
- return keyboard;
- }
-
- private boolean hasVoiceKey(boolean isSymbols) {
- return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
- }
-
- private boolean hasSettingsKey(EditorInfo attribute) {
- return mSettingsKeyEnabledInSettings
- && !Utils.inPrivateImeOptions(mInputMethodService.getPackageName(),
- LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute);
- }
-
- private KeyboardId getKeyboardId(EditorInfo attribute, boolean isSymbols) {
- final int mode = Utils.getKeyboardMode(attribute);
- final boolean hasVoiceKey = hasVoiceKey(isSymbols);
- final int xmlId;
- final boolean enableShiftLock;
-
- if (isSymbols) {
- if (mode == KeyboardId.MODE_PHONE) {
- xmlId = R.xml.kbd_phone_symbols;
- } else if (mode == KeyboardId.MODE_NUMBER) {
- // Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key.
- xmlId = R.xml.kbd_number;
- } else {
- xmlId = R.xml.kbd_symbols;
- }
- enableShiftLock = false;
- } else {
- if (mode == KeyboardId.MODE_PHONE) {
- xmlId = R.xml.kbd_phone;
- enableShiftLock = false;
- } else if (mode == KeyboardId.MODE_NUMBER) {
- xmlId = R.xml.kbd_number;
- enableShiftLock = false;
- } else {
- xmlId = R.xml.kbd_qwerty;
- enableShiftLock = true;
- }
+ SettingsValues.isKeyPreviewPopupEnabled(mPrefs, mResources),
+ SettingsValues.getKeyPreviewPopupDismissDelay(mPrefs, mResources));
+ mKeyboardView.updateAutoCorrectionState(mIsAutoCorrectionActive);
+ mKeyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
+ final boolean subtypeChanged = (oldKeyboard == null)
+ || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
+ final boolean needsToDisplayLanguage = mSubtypeSwitcher.needsToDisplayLanguage(
+ keyboard.mId.mLocale);
+ mKeyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, needsToDisplayLanguage,
+ ImfUtils.hasMultipleEnabledIMEsOrSubtypes(mLatinIME, true));
+ }
+
+ public Keyboard getKeyboard() {
+ if (mKeyboardView != null) {
+ return mKeyboardView.getKeyboard();
}
- final boolean hasSettingsKey = hasSettingsKey(attribute);
- final int f2KeyMode = getF2KeyMode(mPrefs, mInputMethodService, attribute);
- final boolean clobberSettingsKey = Utils.inPrivateImeOptions(
- mInputMethodService.getPackageName(), LatinIME.IME_OPTION_NO_SETTINGS_KEY,
- attribute);
- final Resources res = mInputMethodService.getResources();
- final int orientation = res.getConfiguration().orientation;
- if (mKeyboardWidth == 0)
- mKeyboardWidth = res.getDisplayMetrics().widthPixels;
- final Locale locale = mSubtypeSwitcher.getInputLocale();
- return new KeyboardId(
- res.getResourceEntryName(xmlId), xmlId, locale, orientation, mKeyboardWidth,
- mode, attribute, hasSettingsKey, f2KeyMode, clobberSettingsKey, mVoiceKeyEnabled,
- hasVoiceKey, enableShiftLock);
- }
-
- private KeyboardId makeSiblingKeyboardId(KeyboardId base, int alphabet, int phone) {
- final int xmlId = base.mMode == KeyboardId.MODE_PHONE ? phone : alphabet;
- final String xmlName = mInputMethodService.getResources().getResourceEntryName(xmlId);
- return base.cloneWithNewLayout(xmlName, xmlId);
- }
-
- public int getKeyboardMode() {
- return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT;
- }
-
- public boolean isAlphabetMode() {
- return mCurrentId != null && mCurrentId.isAlphabetKeyboard();
+ return null;
}
- public boolean isInputViewShown() {
- return mCurrentInputView != null && mCurrentInputView.isShown();
+ /**
+ * Update keyboard shift state triggered by connected EditText status change.
+ */
+ public void updateShiftState() {
+ mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
}
- public boolean isKeyboardAvailable() {
- if (mKeyboardView != null)
- return mKeyboardView.getKeyboard() != null;
- return false;
+ public void onPressKey(int code) {
+ if (isVibrateAndSoundFeedbackRequired()) {
+ mLatinIME.hapticAndAudioFeedback(code);
+ }
+ mState.onPressKey(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
}
- public LatinKeyboard getLatinKeyboard() {
- if (mKeyboardView != null) {
- final Keyboard keyboard = mKeyboardView.getKeyboard();
- if (keyboard instanceof LatinKeyboard)
- return (LatinKeyboard)keyboard;
- }
- return null;
+ public void onReleaseKey(int code, boolean withSliding) {
+ mState.onReleaseKey(code, withSliding);
}
- public boolean isShiftedOrShiftLocked() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isShiftedOrShiftLocked();
- return false;
+ public void onCancelInput() {
+ mState.onCancelInput(isSinglePointer());
}
- public boolean isShiftLocked() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isShiftLocked();
- return false;
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setAlphabetKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET));
}
- public boolean isAutomaticTemporaryUpperCase() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isAutomaticTemporaryUpperCase();
- return false;
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setAlphabetManualShiftedKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED));
}
- public boolean isManualTemporaryUpperCase() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isManualTemporaryUpperCase();
- return false;
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setAlphabetAutomaticShiftedKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED));
}
- private boolean isManualTemporaryUpperCaseFromAuto() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null)
- return latinKeyboard.isManualTemporaryUpperCaseFromAuto();
- return false;
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setAlphabetShiftLockedKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED));
}
- private void setManualTemporaryUpperCase(boolean shifted) {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null) {
- // On non-distinct multi touch panel device, we should also turn off the shift locked
- // state when shift key is pressed to go to normal mode.
- // On the other hand, on distinct multi touch panel device, turning off the shift locked
- // state with shift key pressing is handled by onReleaseShift().
- if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) {
- latinKeyboard.setShiftLocked(false);
- }
- if (latinKeyboard.setShifted(shifted)) {
- mKeyboardView.invalidateAllKeys();
- }
- }
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setAlphabetShiftLockShiftedKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED));
}
- private void setShiftLocked(boolean shiftLocked) {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) {
- mKeyboardView.invalidateAllKeys();
- }
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setSymbolsKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
}
- /**
- * Toggle keyboard shift state triggered by user touch event.
- */
- public void toggleShift() {
- mInputMethodService.mHandler.cancelUpdateShiftState();
- if (DEBUG_STATE)
- Log.d(TAG, "toggleShift:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState);
- if (isAlphabetMode()) {
- setManualTemporaryUpperCase(!isShiftedOrShiftLocked());
- } else {
- toggleShiftInSymbol();
- }
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void setSymbolsShiftedKeyboard() {
+ setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED));
}
- public void toggleCapsLock() {
- mInputMethodService.mHandler.cancelUpdateShiftState();
- if (DEBUG_STATE)
- Log.d(TAG, "toggleCapsLock:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState);
- if (isAlphabetMode()) {
- if (isShiftLocked()) {
- // Shift key is long pressed while caps lock state, we will toggle back to normal
- // state. And mark as if shift key is released.
- setShiftLocked(false);
- mShiftKeyState.onRelease();
- } else {
- setShiftLocked(true);
- }
- }
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void requestUpdatingShiftState() {
+ mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
}
- private void setAutomaticTemporaryUpperCase() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null) {
- latinKeyboard.setAutomaticTemporaryUpperCase();
- mKeyboardView.invalidateAllKeys();
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void startDoubleTapTimer() {
+ final LatinKeyboardView keyboardView = getKeyboardView();
+ if (keyboardView != null) {
+ final TimerProxy timer = keyboardView.getTimerProxy();
+ timer.startDoubleTapTimer();
}
}
- /**
- * Update keyboard shift state triggered by connected EditText status change.
- */
- public void updateShiftState() {
- final ShiftKeyState shiftKeyState = mShiftKeyState;
- if (DEBUG_STATE)
- Log.d(TAG, "updateShiftState:"
- + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState()
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + shiftKeyState);
- if (isAlphabetMode()) {
- if (!isShiftLocked() && !shiftKeyState.isIgnoring()) {
- if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) {
- // Only when shift key is releasing, automatic temporary upper case will be set.
- setAutomaticTemporaryUpperCase();
- } else {
- setManualTemporaryUpperCase(shiftKeyState.isMomentary());
- }
- }
- } else {
- // In symbol keyboard mode, we should clear shift key state because only alphabet
- // keyboard has shift key.
- shiftKeyState.onRelease();
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void cancelDoubleTapTimer() {
+ final LatinKeyboardView keyboardView = getKeyboardView();
+ if (keyboardView != null) {
+ final TimerProxy timer = keyboardView.getTimerProxy();
+ timer.cancelDoubleTapTimer();
}
}
- public void changeKeyboardMode() {
- if (DEBUG_STATE)
- Log.d(TAG, "changeKeyboardMode:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState);
- toggleKeyboardMode();
- if (isShiftLocked() && isAlphabetMode())
- setShiftLocked(true);
- updateShiftState();
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public boolean isInDoubleTapTimeout() {
+ final LatinKeyboardView keyboardView = getKeyboardView();
+ return (keyboardView != null)
+ ? keyboardView.getTimerProxy().isInDoubleTapTimeout() : false;
}
- public void onPressShift(boolean withSliding) {
- if (!isKeyboardAvailable())
- return;
- ShiftKeyState shiftKeyState = mShiftKeyState;
- if (DEBUG_STATE)
- Log.d(TAG, "onPressShift:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
- if (isAlphabetMode()) {
- if (isShiftLocked()) {
- // Shift key is pressed while caps lock state, we will treat this state as shifted
- // caps lock state and mark as if shift key pressed while normal state.
- shiftKeyState.onPress();
- setManualTemporaryUpperCase(true);
- } else if (isAutomaticTemporaryUpperCase()) {
- // Shift key is pressed while automatic temporary upper case, we have to move to
- // manual temporary upper case.
- shiftKeyState.onPress();
- setManualTemporaryUpperCase(true);
- } else if (isShiftedOrShiftLocked()) {
- // In manual upper case state, we just record shift key has been pressing while
- // shifted state.
- shiftKeyState.onPressOnShifted();
- } else {
- // In base layout, chording or manual temporary upper case mode is started.
- shiftKeyState.onPress();
- toggleShift();
- }
- } else {
- // In symbol mode, just toggle symbol and symbol more keyboard.
- shiftKeyState.onPress();
- toggleShift();
- mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void startLongPressTimer(int code) {
+ final LatinKeyboardView keyboardView = getKeyboardView();
+ if (keyboardView != null) {
+ final TimerProxy timer = keyboardView.getTimerProxy();
+ timer.startLongPressTimer(code);
}
}
- public void onReleaseShift(boolean withSliding) {
- if (!isKeyboardAvailable())
- return;
- ShiftKeyState shiftKeyState = mShiftKeyState;
- if (DEBUG_STATE)
- Log.d(TAG, "onReleaseShift:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding);
- if (isAlphabetMode()) {
- if (shiftKeyState.isMomentary()) {
- // After chording input while normal state.
- toggleShift();
- } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) {
- // Shift has been pressed without chording while caps lock state.
- toggleCapsLock();
- // To be able to turn off caps lock by "double tap" on shift key, we should ignore
- // the second tap of the "double tap" from now for a while because we just have
- // already turned off caps lock above.
- mKeyboardView.startIgnoringDoubleTap();
- } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()
- && !withSliding) {
- // Shift has been pressed without chording while shifted state.
- toggleShift();
- } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing()
- && !withSliding) {
- // Shift has been pressed without chording while manual temporary upper case
- // transited from automatic temporary upper case.
- toggleShift();
- }
- } else {
- // In symbol mode, snap back to the previous keyboard mode if the user chords the shift
- // key and another key, then releases the shift key.
- if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) {
- toggleShift();
- }
- }
- shiftKeyState.onRelease();
- }
-
- public void onPressSymbol() {
- if (DEBUG_STATE)
- Log.d(TAG, "onPressSymbol:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " symbolKeyState=" + mSymbolKeyState);
- changeKeyboardMode();
- mSymbolKeyState.onPress();
- mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
- }
-
- public void onReleaseSymbol() {
- if (DEBUG_STATE)
- Log.d(TAG, "onReleaseSymbol:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " symbolKeyState=" + mSymbolKeyState);
- // Snap back to the previous keyboard mode if the user chords the mode change key and
- // another key, then releases the mode change key.
- if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) {
- changeKeyboardMode();
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void cancelLongPressTimer() {
+ final LatinKeyboardView keyboardView = getKeyboardView();
+ if (keyboardView != null) {
+ final TimerProxy timer = keyboardView.getTimerProxy();
+ timer.cancelLongPressTimer();
}
- mSymbolKeyState.onRelease();
}
- public void onOtherKeyPressed() {
- if (DEBUG_STATE)
- Log.d(TAG, "onOtherKeyPressed:"
- + " keyboard=" + getLatinKeyboard().getKeyboardShiftState()
- + " shiftKeyState=" + mShiftKeyState
- + " symbolKeyState=" + mSymbolKeyState);
- mShiftKeyState.onOtherKeyPressed();
- mSymbolKeyState.onOtherKeyPressed();
+ // Implements {@link KeyboardState.SwitchActions}.
+ @Override
+ public void hapticAndAudioFeedback(int code) {
+ mLatinIME.hapticAndAudioFeedback(code);
}
- public void onCancelInput() {
- // Snap back to the previous keyboard mode if the user cancels sliding input.
- if (getPointerCount() == 1) {
- if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
- changeKeyboardMode();
- } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) {
- toggleShift();
- }
- }
- }
-
- private void toggleShiftInSymbol() {
- if (isAlphabetMode())
- return;
- final LatinKeyboard keyboard;
- if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) {
- keyboard = getKeyboard(mSymbolsShiftedId);
- // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To
- // enable the indicator, we need to call setShiftLocked(true).
- keyboard.setShiftLocked(true);
- } else {
- keyboard = getKeyboard(mSymbolsId);
- // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the
- // indicator, we need to call setShiftLocked(false).
- keyboard.setShiftLocked(false);
- }
- setKeyboard(keyboard);
+ public void onLongPressTimeout(int code) {
+ mState.onLongPressTimeout(code);
}
public boolean isInMomentarySwitchState() {
- return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL
- || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
- }
-
- public boolean isVibrateAndSoundFeedbackRequired() {
- return mKeyboardView == null || !mKeyboardView.isInSlidingKeyInput();
+ return mState.isInMomentarySwitchState();
}
- private int getPointerCount() {
- return mKeyboardView == null ? 0 : mKeyboardView.getPointerCount();
+ private boolean isVibrateAndSoundFeedbackRequired() {
+ return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput();
}
- private void toggleKeyboardMode() {
- loadKeyboardInternal(mAttribute, mVoiceKeyEnabled, mVoiceButtonOnPrimary, !mIsSymbols);
- if (mIsSymbols) {
- mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
- } else {
- mSwitchState = SWITCH_STATE_ALPHA;
- }
+ private boolean isSinglePointer() {
+ return mKeyboardView != null && mKeyboardView.getPointerCount() == 1;
}
public boolean hasDistinctMultitouch() {
return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch();
}
- private static boolean isSpaceCharacter(int c) {
- return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER;
- }
-
- private static boolean isQuoteCharacter(int c) {
- // Apostrophe, quotation mark.
- if (c == Keyboard.CODE_SINGLE_QUOTE || c == Keyboard.CODE_DOUBLE_QUOTE)
- return true;
- // \u2018: Left single quotation mark
- // \u2019: Right single quotation mark
- // \u201a: Single low-9 quotation mark
- // \u201b: Single high-reversed-9 quotation mark
- // \u201c: Left double quotation mark
- // \u201d: Right double quotation mark
- // \u201e: Double low-9 quotation mark
- // \u201f: Double high-reversed-9 quotation mark
- if (c >= '\u2018' && c <= '\u201f')
- return true;
- // \u00ab: Left-pointing double angle quotation mark
- // \u00bb: Right-pointing double angle quotation mark
- if (c == '\u00ab' || c == '\u00bb')
- return true;
- return false;
- }
-
/**
- * Updates state machine to figure out when to automatically snap back to the previous mode.
+ * Updates state machine to figure out when to automatically switch back to the previous mode.
*/
- public void onKey(int code) {
- if (DEBUG_STATE)
- Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState
- + " pointers=" + getPointerCount());
- switch (mSwitchState) {
- case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
- // Only distinct multi touch devices can be in this state.
- // On non-distinct multi touch devices, mode change key is handled by
- // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and
- // {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts
- // from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from
- // {@link #SWITCH_STATE_MOMENTARY}.
- if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
- // Detected only the mode change key has been pressed, and then released.
- if (mIsSymbols) {
- mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
- } else {
- mSwitchState = SWITCH_STATE_ALPHA;
- }
- } else if (getPointerCount() == 1) {
- // Snap back to the previous keyboard mode if the user pressed the mode change key
- // and slid to other key, then released the finger.
- // If the user cancels the sliding input, snapping back to the previous keyboard
- // mode is handled by {@link #onCancelInput}.
- changeKeyboardMode();
- } else {
- // Chording input is being started. The keyboard mode will be snapped back to the
- // previous mode in {@link onReleaseSymbol} when the mode change key is released.
- mSwitchState = SWITCH_STATE_CHORDING_ALPHA;
- }
- break;
- case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE:
- if (code == Keyboard.CODE_SHIFT) {
- // Detected only the shift key has been pressed on symbol layout, and then released.
- mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
- } else if (getPointerCount() == 1) {
- // Snap back to the previous keyboard mode if the user pressed the shift key on
- // symbol mode and slid to other key, then released the finger.
- toggleShift();
- mSwitchState = SWITCH_STATE_SYMBOL;
- } else {
- // Chording input is being started. The keyboard mode will be snapped back to the
- // previous mode in {@link onReleaseShift} when the shift key is released.
- mSwitchState = SWITCH_STATE_CHORDING_SYMBOL;
- }
- break;
- case SWITCH_STATE_SYMBOL_BEGIN:
- if (!isSpaceCharacter(code) && code >= 0) {
- mSwitchState = SWITCH_STATE_SYMBOL;
- }
- // Snap back to alpha keyboard mode immediately if user types a quote character.
- if (isQuoteCharacter(code)) {
- changeKeyboardMode();
- }
- break;
- case SWITCH_STATE_SYMBOL:
- case SWITCH_STATE_CHORDING_SYMBOL:
- // Snap back to alpha keyboard mode if user types one or more non-space/enter
- // characters followed by a space/enter or a quote character.
- if (isSpaceCharacter(code) || isQuoteCharacter(code)) {
- changeKeyboardMode();
- }
- break;
- }
+ public void onCodeInput(int code) {
+ mState.onCodeInput(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
}
public LatinKeyboardView getKeyboardView() {
@@ -731,119 +348,52 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
public View onCreateInputView() {
- return createInputView(mThemeIndex, true);
- }
-
- private View createInputView(final int newThemeIndex, final boolean forceRecreate) {
- if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate)
- return mCurrentInputView;
-
if (mKeyboardView != null) {
mKeyboardView.closing();
}
- final int oldThemeIndex = mThemeIndex;
Utils.GCUtils.getInstance().reset();
boolean tryGC = true;
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
try {
- setContextThemeWrapper(mInputMethodService, newThemeIndex);
- mCurrentInputView = LayoutInflater.from(mThemeContext).inflate(
+ setContextThemeWrapper(mLatinIME, mKeyboardTheme);
+ mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
R.layout.input_view, null);
tryGC = false;
} catch (OutOfMemoryError e) {
Log.w(TAG, "load keyboard failed: " + e);
- tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
- oldThemeIndex + "," + newThemeIndex, e);
+ tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mKeyboardTheme.mName, e);
} catch (InflateException e) {
Log.w(TAG, "load keyboard failed: " + e);
- tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
- oldThemeIndex + "," + newThemeIndex, e);
+ tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mKeyboardTheme.mName, e);
}
}
mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
- mKeyboardView.setOnKeyboardActionListener(mInputMethodService);
+ mKeyboardView.setKeyboardActionListener(mLatinIME);
+ if (mForceNonDistinctMultitouch) {
+ mKeyboardView.setDistinctMultitouch(false);
+ }
// This always needs to be set since the accessibility state can
// potentially change without the input view being re-created.
- AccessibleKeyboardViewProxy.setView(mKeyboardView);
+ AccessibleKeyboardViewProxy.getInstance().setView(mKeyboardView);
return mCurrentInputView;
}
- private void postSetInputView(final View newInputView) {
- mInputMethodService.mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (newInputView != null) {
- mInputMethodService.setInputView(newInputView);
- }
- mInputMethodService.updateInputViewShown();
- }
- });
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (PREF_KEYBOARD_LAYOUT.equals(key)) {
- final int layoutId = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
- postSetInputView(createInputView(layoutId, false));
- } else if (Settings.PREF_SETTINGS_KEY.equals(key)) {
- mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences,
- mInputMethodService);
- postSetInputView(createInputView(mThemeIndex, true));
+ public void onNetworkStateChanged() {
+ if (mKeyboardView != null) {
+ mKeyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
}
}
public void onAutoCorrectionStateChanged(boolean isAutoCorrection) {
if (mIsAutoCorrectionActive != isAutoCorrection) {
mIsAutoCorrectionActive = isAutoCorrection;
- final LatinKeyboard keyboard = getLatinKeyboard();
- if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) {
- final Key invalidatedKey = keyboard.onAutoCorrectionStateChanged(isAutoCorrection);
- final LatinKeyboardView keyboardView = getKeyboardView();
- if (keyboardView != null)
- keyboardView.invalidateKey(invalidatedKey);
+ if (mKeyboardView != null) {
+ mKeyboardView.updateAutoCorrectionState(isAutoCorrection);
}
}
}
-
- private static boolean getSettingsKeyMode(SharedPreferences prefs, Context context) {
- final Resources res = context.getResources();
- final boolean showSettingsKeyOption = res.getBoolean(
- R.bool.config_enable_show_settings_key_option);
- if (showSettingsKeyOption) {
- final String settingsKeyMode = prefs.getString(Settings.PREF_SETTINGS_KEY,
- res.getString(DEFAULT_SETTINGS_KEY_MODE));
- // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or
- // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system
- if (settingsKeyMode.equals(res.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW))
- || (settingsKeyMode.equals(res.getString(SETTINGS_KEY_MODE_AUTO))
- && Utils.hasMultipleEnabledIMEsOrSubtypes(
- (InputMethodManagerCompatWrapper.getInstance(context))))) {
- return true;
- }
- return false;
- }
- // If the show settings key option is disabled, we always try showing the settings key.
- return true;
- }
-
- private static int getF2KeyMode(SharedPreferences prefs, Context context,
- EditorInfo attribute) {
- final boolean clobberSettingsKey = Utils.inPrivateImeOptions(
- context.getPackageName(), LatinIME.IME_OPTION_NO_SETTINGS_KEY, attribute);
- final Resources res = context.getResources();
- final String settingsKeyMode = prefs.getString(Settings.PREF_SETTINGS_KEY,
- res.getString(DEFAULT_SETTINGS_KEY_MODE));
- if (settingsKeyMode.equals(res.getString(SETTINGS_KEY_MODE_AUTO))) {
- return clobberSettingsKey ? KeyboardId.F2KEY_MODE_SHORTCUT_IME
- : KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
- } else if (settingsKeyMode.equals(res.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW))) {
- return clobberSettingsKey ? KeyboardId.F2KEY_MODE_NONE : KeyboardId.F2KEY_MODE_SETTINGS;
- } else { // SETTINGS_KEY_MODE_ALWAYS_HIDE
- return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
- }
- }
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 2a1b3fb7f..18e01fb49 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -17,8 +17,6 @@
package com.android.inputmethod.keyboard;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -32,45 +30,36 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Message;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.TypedValue;
-import android.view.GestureDetector;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.PopupWindow;
+import android.widget.RelativeLayout;
import android.widget.TextView;
-import com.android.inputmethod.accessibility.AccessibilityUtils;
-import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
-import com.android.inputmethod.compat.FrameLayoutCompatUtils;
-import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder;
-import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
-import com.android.inputmethod.keyboard.internal.SwipeTracker;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.StringUtils;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.WeakHashMap;
+import java.util.HashSet;
/**
- * A view that renders a virtual {@link Keyboard}. It handles rendering of keys and detecting key
- * presses and touch movements.
+ * A view that renders a virtual {@link Keyboard}.
*
- * @attr ref R.styleable#KeyboardView_backgroundDimAmount
+ * @attr ref R.styleable#KeyboardView_backgroundDimAlpha
* @attr ref R.styleable#KeyboardView_keyBackground
- * @attr ref R.styleable#KeyboardView_keyHysteresisDistance
* @attr ref R.styleable#KeyboardView_keyLetterRatio
* @attr ref R.styleable#KeyboardView_keyLargeLetterRatio
* @attr ref R.styleable#KeyboardView_keyLabelRatio
* @attr ref R.styleable#KeyboardView_keyHintLetterRatio
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterRatio
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintRatio
* @attr ref R.styleable#KeyboardView_keyHintLabelRatio
+ * @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding
+ * @attr ref R.styleable#KeyboardView_keyHintLetterPadding
+ * @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintPadding
* @attr ref R.styleable#KeyboardView_keyTextStyle
* @attr ref R.styleable#KeyboardView_keyPreviewLayout
* @attr ref R.styleable#KeyboardView_keyPreviewTextRatio
@@ -80,188 +69,91 @@ import java.util.WeakHashMap;
* @attr ref R.styleable#KeyboardView_keyTextColorDisabled
* @attr ref R.styleable#KeyboardView_keyHintLetterColor
* @attr ref R.styleable#KeyboardView_keyHintLabelColor
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterInactivatedColor
- * @attr ref R.styleable#KeyboardView_keyUppercaseLetterActivatedColor
- * @attr ref R.styleable#KeyboardView_verticalCorrection
- * @attr ref R.styleable#KeyboardView_popupLayout
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintInactivatedColor
+ * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintActivatedColor
* @attr ref R.styleable#KeyboardView_shadowColor
* @attr ref R.styleable#KeyboardView_shadowRadius
*/
-public class KeyboardView extends View implements PointerTracker.UIProxy {
- private static final String TAG = KeyboardView.class.getSimpleName();
- private static final boolean DEBUG_SHOW_ALIGN = false;
- private static final boolean DEBUG_KEYBOARD_GRID = false;
+public class KeyboardView extends View implements PointerTracker.DrawingProxy {
+ // Miscellaneous constants
+ private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };
- private static final boolean ENABLE_CAPSLOCK_BY_LONGPRESS = true;
- private static final boolean ENABLE_CAPSLOCK_BY_DOUBLETAP = true;
+ // XML attributes
+ protected final float mVerticalCorrection;
+ protected final int mMoreKeysLayout;
+ private final int mBackgroundDimAlpha;
- // Timing constants
- private final int mKeyRepeatInterval;
+ // HORIZONTAL ELLIPSIS "...", character for popup hint.
+ private static final String POPUP_HINT_CHAR = "\u2026";
- // Miscellaneous constants
- private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };
- private static final int HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL = -1;
-
- // XML attribute
- private final int mKeyTextColor;
- private final int mKeyTextInactivatedColor;
- private final Typeface mKeyTextStyle;
- private final float mKeyLetterRatio;
- private final float mKeyLargeLetterRatio;
- private final float mKeyLabelRatio;
- private final float mKeyHintLetterRatio;
- private final float mKeyUppercaseLetterRatio;
- private final float mKeyHintLabelRatio;
- private final int mShadowColor;
- private final float mShadowRadius;
- private final Drawable mKeyBackground;
- private final float mBackgroundDimAmount;
- private final float mKeyHysteresisDistance;
- private final float mVerticalCorrection;
- private final Drawable mPreviewBackground;
- private final Drawable mPreviewSpacebarBackground;
- private final int mPreviewTextColor;
- private final float mPreviewTextRatio;
- private final int mPreviewOffset;
- private final int mPreviewHeight;
- private final int mPopupLayout;
- private final Drawable mKeyPopupHintIcon;
- private final int mKeyHintLetterColor;
- private final int mKeyHintLabelColor;
- private final int mKeyUppercaseLetterInactivatedColor;
- private final int mKeyUppercaseLetterActivatedColor;
+ // Margin between the label and the icon on a key that has both of them.
+ // Specified by the fraction of the key width.
+ // TODO: Use resource parameter for this value.
+ private static final float LABEL_ICON_MARGIN = 0.05f;
+
+ // The maximum key label width in the proportion to the key width.
+ private static final float MAX_LABEL_RATIO = 0.90f;
+
+ private final static int ALPHA_OPAQUE = 255;
// Main keyboard
private Keyboard mKeyboard;
- private int mKeyLetterSize;
- private int mKeyLargeLetterSize;
- private int mKeyLabelSize;
- private int mKeyHintLetterSize;
- private int mKeyUppercaseLetterSize;
- private int mKeyHintLabelSize;
+ protected final KeyDrawParams mKeyDrawParams;
// Key preview
- private final TextView mPreviewText;
- private int mPreviewTextSize;
+ private final int mKeyPreviewLayoutId;
+ protected final KeyPreviewDrawParams mKeyPreviewDrawParams;
private boolean mShowKeyPreviewPopup = true;
- private final int mDelayBeforePreview;
private int mDelayAfterPreview;
private ViewGroup mPreviewPlacer;
- private final int[] mCoordinates = new int[2];
-
- // Mini keyboard
- private PopupWindow mPopupWindow;
- private PopupPanel mPopupMiniKeyboardPanel;
- private final WeakHashMap<Key, PopupPanel> mPopupPanelCache =
- new WeakHashMap<Key, PopupPanel>();
-
- /** Listener for {@link KeyboardActionListener}. */
- private KeyboardActionListener mKeyboardActionListener;
-
- private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
-
- // TODO: Let the PointerTracker class manage this pointer queue
- private final PointerTrackerQueue mPointerQueue = new PointerTrackerQueue();
-
- private final boolean mHasDistinctMultitouch;
- private int mOldPointerCount = 1;
- private int mOldKeyIndex;
-
- protected KeyDetector mKeyDetector = new KeyDetector();
-
- // Swipe gesture detector
- protected GestureDetector mGestureDetector;
- private final SwipeTracker mSwipeTracker = new SwipeTracker();
- private final int mSwipeThreshold;
- private final boolean mDisambiguateSwipe;
// Drawing
- /** Whether the keyboard bitmap needs to be redrawn before it's blitted. **/
- private boolean mDrawPending;
- /** Notes if the keyboard just changed, so that we could possibly reallocate the mBuffer. */
- private boolean mKeyboardChanged;
- /** The dirty region in the keyboard bitmap */
- private final Rect mDirtyRect = new Rect();
- /** The key to invalidate. */
- private Key mInvalidatedKey;
- /** The dirty region for single key drawing */
- private final Rect mInvalidatedKeyRect = new Rect();
- /** The keyboard bitmap for faster updates */
+ /** True if the entire keyboard needs to be dimmed. */
+ private boolean mNeedsToDimEntireKeyboard;
+ /** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/
+ private boolean mBufferNeedsUpdate;
+ /** True if all keys should be drawn */
+ private boolean mInvalidateAllKeys;
+ /** The keys that should be drawn */
+ private final HashSet<Key> mInvalidatedKeys = new HashSet<Key>();
+ /** The region of invalidated keys */
+ private final Rect mInvalidatedKeysRect = new Rect();
+ /** The keyboard bitmap buffer for faster updates */
private Bitmap mBuffer;
/** The canvas for the above mutable keyboard bitmap */
private Canvas mCanvas;
private final Paint mPaint = new Paint();
- private final Rect mPadding = new Rect();
+ private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
// This map caches key label text height in pixel as value and key label text size as map key.
- private final HashMap<Integer, Integer> mTextHeightCache = new HashMap<Integer, Integer>();
+ private static final HashMap<Integer, Float> sTextHeightCache =
+ new HashMap<Integer, Float>();
// This map caches key label text width in pixel as value and key label text size as map key.
- private final HashMap<Integer, Integer> mTextWidthCache = new HashMap<Integer, Integer>();
- // Distance from horizontal center of the key, proportional to key label text height and width.
- private static final float KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER = 0.45f;
- private static final float KEY_LABEL_VERTICAL_PADDING_FACTOR = 1.60f;
- private static final String KEY_LABEL_REFERENCE_CHAR = "M";
- private final int mKeyLabelHorizontalPadding;
-
- private final UIHandler mHandler = new UIHandler(this);
-
- public static class UIHandler extends StaticInnerHandlerWrapper<KeyboardView> {
- private static final int MSG_SHOW_KEY_PREVIEW = 1;
- private static final int MSG_DISMISS_KEY_PREVIEW = 2;
- private static final int MSG_REPEAT_KEY = 3;
- private static final int MSG_LONGPRESS_KEY = 4;
- private static final int MSG_LONGPRESS_SHIFT_KEY = 5;
- private static final int MSG_IGNORE_DOUBLE_TAP = 6;
-
- private boolean mInKeyRepeat;
-
- public UIHandler(KeyboardView outerInstance) {
+ private static final HashMap<Integer, Float> sTextWidthCache =
+ new HashMap<Integer, Float>();
+ private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
+ private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
+
+ private final DrawingHandler mDrawingHandler = new DrawingHandler(this);
+
+ public static class DrawingHandler extends StaticInnerHandlerWrapper<KeyboardView> {
+ private static final int MSG_DISMISS_KEY_PREVIEW = 1;
+
+ public DrawingHandler(KeyboardView outerInstance) {
super(outerInstance);
}
@Override
public void handleMessage(Message msg) {
final KeyboardView keyboardView = getOuterInstance();
+ if (keyboardView == null) return;
final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
- case MSG_SHOW_KEY_PREVIEW:
- keyboardView.showKey(msg.arg1, tracker);
- break;
case MSG_DISMISS_KEY_PREVIEW:
- keyboardView.mPreviewText.setVisibility(View.INVISIBLE);
- break;
- case MSG_REPEAT_KEY:
- tracker.onRepeatKey(msg.arg1);
- startKeyRepeatTimer(keyboardView.mKeyRepeatInterval, msg.arg1, tracker);
- break;
- case MSG_LONGPRESS_KEY:
- keyboardView.openMiniKeyboardIfRequired(msg.arg1, tracker);
- break;
- case MSG_LONGPRESS_SHIFT_KEY:
- keyboardView.onLongPressShiftKey(tracker);
+ tracker.getKeyPreviewText().setVisibility(View.INVISIBLE);
break;
}
}
- public void showKeyPreview(long delay, int keyIndex, PointerTracker tracker) {
- final KeyboardView keyboardView = getOuterInstance();
- removeMessages(MSG_SHOW_KEY_PREVIEW);
- if (keyboardView.mPreviewText.getVisibility() == VISIBLE || delay == 0) {
- // Show right away, if it's already visible and finger is moving around
- keyboardView.showKey(keyIndex, tracker);
- } else {
- sendMessageDelayed(
- obtainMessage(MSG_SHOW_KEY_PREVIEW, keyIndex, 0, tracker), delay);
- }
- }
-
- public void cancelShowKeyPreview(PointerTracker tracker) {
- removeMessages(MSG_SHOW_KEY_PREVIEW, tracker);
- }
-
- public void cancelAllShowKeyPreviews() {
- removeMessages(MSG_SHOW_KEY_PREVIEW);
- }
-
public void dismissKeyPreview(long delay, PointerTracker tracker) {
sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay);
}
@@ -274,57 +166,186 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
removeMessages(MSG_DISMISS_KEY_PREVIEW);
}
- public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {
- mInKeyRepeat = true;
- sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay);
- }
-
- public void cancelKeyRepeatTimer() {
- mInKeyRepeat = false;
- removeMessages(MSG_REPEAT_KEY);
- }
-
- public boolean isInKeyRepeat() {
- return mInKeyRepeat;
- }
-
- public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {
- cancelLongPressTimers();
- sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay);
+ public void cancelAllMessages() {
+ cancelAllDismissKeyPreviews();
}
+ }
- public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {
- cancelLongPressTimers();
- if (ENABLE_CAPSLOCK_BY_LONGPRESS) {
- sendMessageDelayed(
- obtainMessage(MSG_LONGPRESS_SHIFT_KEY, keyIndex, 0, tracker), delay);
+ protected static class KeyDrawParams {
+ // XML attributes
+ public final int mKeyTextColor;
+ public final int mKeyTextInactivatedColor;
+ public final Typeface mKeyTextStyle;
+ public final float mKeyLabelHorizontalPadding;
+ public final float mKeyHintLetterPadding;
+ public final float mKeyPopupHintLetterPadding;
+ public final float mKeyShiftedLetterHintPadding;
+ public final int mShadowColor;
+ public final float mShadowRadius;
+ public final Drawable mKeyBackground;
+ public final int mKeyHintLetterColor;
+ public final int mKeyHintLabelColor;
+ public final int mKeyShiftedLetterHintInactivatedColor;
+ public final int mKeyShiftedLetterHintActivatedColor;
+
+ /* package */ final float mKeyLetterRatio;
+ private final float mKeyLargeLetterRatio;
+ private final float mKeyLabelRatio;
+ private final float mKeyLargeLabelRatio;
+ private final float mKeyHintLetterRatio;
+ private final float mKeyShiftedLetterHintRatio;
+ private final float mKeyHintLabelRatio;
+ private static final float UNDEFINED_RATIO = -1.0f;
+
+ public final Rect mPadding = new Rect();
+ public int mKeyLetterSize;
+ public int mKeyLargeLetterSize;
+ public int mKeyLabelSize;
+ public int mKeyLargeLabelSize;
+ public int mKeyHintLetterSize;
+ public int mKeyShiftedLetterHintSize;
+ public int mKeyHintLabelSize;
+ public int mAnimAlpha;
+
+ public KeyDrawParams(TypedArray a) {
+ mKeyBackground = a.getDrawable(R.styleable.KeyboardView_keyBackground);
+ if (a.hasValue(R.styleable.KeyboardView_keyLetterSize)) {
+ mKeyLetterRatio = UNDEFINED_RATIO;
+ mKeyLetterSize = a.getDimensionPixelSize(R.styleable.KeyboardView_keyLetterSize, 0);
+ } else {
+ mKeyLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLetterRatio);
}
+ if (a.hasValue(R.styleable.KeyboardView_keyLabelSize)) {
+ mKeyLabelRatio = UNDEFINED_RATIO;
+ mKeyLabelSize = a.getDimensionPixelSize(R.styleable.KeyboardView_keyLabelSize, 0);
+ } else {
+ mKeyLabelRatio = getRatio(a, R.styleable.KeyboardView_keyLabelRatio);
+ }
+ mKeyLargeLabelRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLabelRatio);
+ mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio);
+ mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio);
+ mKeyShiftedLetterHintRatio = getRatio(a,
+ R.styleable.KeyboardView_keyShiftedLetterHintRatio);
+ mKeyHintLabelRatio = getRatio(a, R.styleable.KeyboardView_keyHintLabelRatio);
+ mKeyLabelHorizontalPadding = a.getDimension(
+ R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
+ mKeyHintLetterPadding = a.getDimension(
+ R.styleable.KeyboardView_keyHintLetterPadding, 0);
+ mKeyPopupHintLetterPadding = a.getDimension(
+ R.styleable.KeyboardView_keyPopupHintLetterPadding, 0);
+ mKeyShiftedLetterHintPadding = a.getDimension(
+ R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0);
+ mKeyTextColor = a.getColor(R.styleable.KeyboardView_keyTextColor, 0xFF000000);
+ mKeyTextInactivatedColor = a.getColor(
+ R.styleable.KeyboardView_keyTextInactivatedColor, 0xFF000000);
+ mKeyHintLetterColor = a.getColor(R.styleable.KeyboardView_keyHintLetterColor, 0);
+ mKeyHintLabelColor = a.getColor(R.styleable.KeyboardView_keyHintLabelColor, 0);
+ mKeyShiftedLetterHintInactivatedColor = a.getColor(
+ R.styleable.KeyboardView_keyShiftedLetterHintInactivatedColor, 0);
+ mKeyShiftedLetterHintActivatedColor = a.getColor(
+ R.styleable.KeyboardView_keyShiftedLetterHintActivatedColor, 0);
+ mKeyTextStyle = Typeface.defaultFromStyle(
+ a.getInt(R.styleable.KeyboardView_keyTextStyle, Typeface.NORMAL));
+ mShadowColor = a.getColor(R.styleable.KeyboardView_shadowColor, 0);
+ mShadowRadius = a.getFloat(R.styleable.KeyboardView_shadowRadius, 0f);
+
+ mKeyBackground.getPadding(mPadding);
}
- public void cancelLongPressTimers() {
- removeMessages(MSG_LONGPRESS_KEY);
- removeMessages(MSG_LONGPRESS_SHIFT_KEY);
+ public void updateKeyHeight(int keyHeight) {
+ if (mKeyLetterRatio >= 0.0f)
+ mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
+ if (mKeyLabelRatio >= 0.0f)
+ mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
+ mKeyLargeLabelSize = (int)(keyHeight * mKeyLargeLabelRatio);
+ mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
+ mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
+ mKeyShiftedLetterHintSize = (int)(keyHeight * mKeyShiftedLetterHintRatio);
+ mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio);
}
- public void cancelKeyTimers() {
- cancelKeyRepeatTimer();
- cancelLongPressTimers();
- removeMessages(MSG_IGNORE_DOUBLE_TAP);
+ public void blendAlpha(Paint paint) {
+ final int color = paint.getColor();
+ paint.setARGB((paint.getAlpha() * mAnimAlpha) / ALPHA_OPAQUE,
+ Color.red(color), Color.green(color), Color.blue(color));
}
+ }
- public void startIgnoringDoubleTap() {
- sendMessageDelayed(obtainMessage(MSG_IGNORE_DOUBLE_TAP),
- ViewConfiguration.getDoubleTapTimeout());
+ /* package */ static class KeyPreviewDrawParams {
+ // XML attributes.
+ public final Drawable mPreviewBackground;
+ public final Drawable mPreviewLeftBackground;
+ public final Drawable mPreviewRightBackground;
+ public final int mPreviewTextColor;
+ public final int mPreviewOffset;
+ public final int mPreviewHeight;
+ public final Typeface mKeyTextStyle;
+ public final int mLingerTimeout;
+
+ private final float mPreviewTextRatio;
+ private final float mKeyLetterRatio;
+
+ // The graphical geometry of the key preview.
+ // <-width->
+ // +-------+ ^
+ // | | |
+ // |preview| height (visible)
+ // | | |
+ // + + ^ v
+ // \ / |offset
+ // +-\ /-+ v
+ // | +-+ |
+ // |parent |
+ // | key|
+ // +-------+
+ // The background of a {@link TextView} being used for a key preview may have invisible
+ // paddings. To align the more keys keyboard panel's visible part with the visible part of
+ // the background, we need to record the width and height of key preview that don't include
+ // invisible paddings.
+ public int mPreviewVisibleWidth;
+ public int mPreviewVisibleHeight;
+ // The key preview may have an arbitrary offset and its background that may have a bottom
+ // padding. To align the more keys keyboard and the key preview we also need to record the
+ // offset between the top edge of parent key and the bottom of the visible part of key
+ // preview background.
+ public int mPreviewVisibleOffset;
+
+ public int mPreviewTextSize;
+ public int mKeyLetterSize;
+ public final int[] mCoordinates = new int[2];
+
+ private static final int PREVIEW_ALPHA = 240;
+
+ public KeyPreviewDrawParams(TypedArray a, KeyDrawParams keyDrawParams) {
+ mPreviewBackground = a.getDrawable(R.styleable.KeyboardView_keyPreviewBackground);
+ mPreviewLeftBackground = a.getDrawable(
+ R.styleable.KeyboardView_keyPreviewLeftBackground);
+ mPreviewRightBackground = a.getDrawable(
+ R.styleable.KeyboardView_keyPreviewRightBackground);
+ setAlpha(mPreviewBackground, PREVIEW_ALPHA);
+ setAlpha(mPreviewLeftBackground, PREVIEW_ALPHA);
+ setAlpha(mPreviewRightBackground, PREVIEW_ALPHA);
+ mPreviewOffset = a.getDimensionPixelOffset(
+ R.styleable.KeyboardView_keyPreviewOffset, 0);
+ mPreviewHeight = a.getDimensionPixelSize(
+ R.styleable.KeyboardView_keyPreviewHeight, 80);
+ mPreviewTextRatio = getRatio(a, R.styleable.KeyboardView_keyPreviewTextRatio);
+ mPreviewTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0);
+ mLingerTimeout = a.getInt(R.styleable.KeyboardView_keyPreviewLingerTimeout, 0);
+
+ mKeyLetterRatio = keyDrawParams.mKeyLetterRatio;
+ mKeyTextStyle = keyDrawParams.mKeyTextStyle;
}
- public boolean isIgnoringDoubleTap() {
- return hasMessages(MSG_IGNORE_DOUBLE_TAP);
+ public void updateKeyHeight(int keyHeight) {
+ mPreviewTextSize = (int)(keyHeight * mPreviewTextRatio);
+ mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
}
- public void cancelAllMessages() {
- cancelKeyTimers();
- cancelAllShowKeyPreviews();
- cancelAllDismissKeyPreviews();
+ private static void setAlpha(Drawable drawable, int alpha) {
+ if (drawable == null)
+ return;
+ drawable.setAlpha(alpha);
}
}
@@ -338,173 +359,28 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
- mKeyBackground = a.getDrawable(R.styleable.KeyboardView_keyBackground);
- mKeyHysteresisDistance = a.getDimensionPixelOffset(
- R.styleable.KeyboardView_keyHysteresisDistance, 0);
- mVerticalCorrection = a.getDimensionPixelOffset(
- R.styleable.KeyboardView_verticalCorrection, 0);
- mPreviewTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0);
- final int previewLayout = a.getResourceId(R.styleable.KeyboardView_keyPreviewLayout, 0);
- if (previewLayout != 0) {
- mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null);
- mPreviewText.setTextColor(mPreviewTextColor);
- } else {
- mPreviewText = null;
+ mKeyDrawParams = new KeyDrawParams(a);
+ mKeyPreviewDrawParams = new KeyPreviewDrawParams(a, mKeyDrawParams);
+ mKeyPreviewLayoutId = a.getResourceId(R.styleable.KeyboardView_keyPreviewLayout, 0);
+ if (mKeyPreviewLayoutId == 0) {
mShowKeyPreviewPopup = false;
}
- mPreviewBackground = a.getDrawable(R.styleable.KeyboardView_keyPreviewBackground);
- mPreviewSpacebarBackground = a.getDrawable(
- R.styleable.KeyboardView_keyPreviewSpacebarBackground);
- mPreviewOffset = a.getDimensionPixelOffset(R.styleable.KeyboardView_keyPreviewOffset, 0);
- mPreviewHeight = a.getDimensionPixelSize(R.styleable.KeyboardView_keyPreviewHeight, 80);
- mKeyLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLetterRatio);
- mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio);
- mKeyLabelRatio = getRatio(a, R.styleable.KeyboardView_keyLabelRatio);
- mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio);
- mKeyUppercaseLetterRatio = getRatio(a,
- R.styleable.KeyboardView_keyUppercaseLetterRatio);
- mKeyHintLabelRatio = getRatio(a, R.styleable.KeyboardView_keyHintLabelRatio);
- mPreviewTextRatio = getRatio(a, R.styleable.KeyboardView_keyPreviewTextRatio);
- mKeyTextColor = a.getColor(R.styleable.KeyboardView_keyTextColor, 0xFF000000);
- mKeyTextInactivatedColor = a.getColor(
- R.styleable.KeyboardView_keyTextInactivatedColor, 0xFF000000);
- mKeyPopupHintIcon = a.getDrawable(R.styleable.KeyboardView_keyPopupHintIcon);
- mKeyHintLetterColor = a.getColor(R.styleable.KeyboardView_keyHintLetterColor, 0);
- mKeyHintLabelColor = a.getColor(R.styleable.KeyboardView_keyHintLabelColor, 0);
- mKeyUppercaseLetterInactivatedColor = a.getColor(
- R.styleable.KeyboardView_keyUppercaseLetterInactivatedColor, 0);
- mKeyUppercaseLetterActivatedColor = a.getColor(
- R.styleable.KeyboardView_keyUppercaseLetterActivatedColor, 0);
- mKeyTextStyle = Typeface.defaultFromStyle(
- a.getInt(R.styleable.KeyboardView_keyTextStyle, Typeface.NORMAL));
- mPopupLayout = a.getResourceId(R.styleable.KeyboardView_popupLayout, 0);
- mShadowColor = a.getColor(R.styleable.KeyboardView_shadowColor, 0);
- mShadowRadius = a.getFloat(R.styleable.KeyboardView_shadowRadius, 0f);
- // TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
- mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f);
+ mVerticalCorrection = a.getDimensionPixelOffset(
+ R.styleable.KeyboardView_verticalCorrection, 0);
+ mMoreKeysLayout = a.getResourceId(R.styleable.KeyboardView_moreKeysLayout, 0);
+ mBackgroundDimAlpha = a.getInt(R.styleable.KeyboardView_backgroundDimAlpha, 0);
a.recycle();
- final Resources res = getResources();
-
- mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview);
- mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview);
- mKeyLabelHorizontalPadding = (int)res.getDimension(
- R.dimen.key_label_horizontal_alignment_padding);
+ mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout;
mPaint.setAntiAlias(true);
- mPaint.setTextAlign(Align.CENTER);
- mPaint.setAlpha(255);
-
- mKeyBackground.getPadding(mPadding);
-
- mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density);
- // TODO: Refer to frameworks/base/core/res/res/values/config.xml
- mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation);
-
- GestureDetector.SimpleOnGestureListener listener =
- new GestureDetector.SimpleOnGestureListener() {
- private boolean mProcessingShiftDoubleTapEvent = false;
-
- @Override
- public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX,
- float velocityY) {
- final float absX = Math.abs(velocityX);
- final float absY = Math.abs(velocityY);
- float deltaY = me2.getY() - me1.getY();
- int travelY = getHeight() / 2; // Half the keyboard height
- mSwipeTracker.computeCurrentVelocity(1000);
- final float endingVelocityY = mSwipeTracker.getYVelocity();
- if (velocityY > mSwipeThreshold && absX < absY / 2 && deltaY > travelY) {
- if (mDisambiguateSwipe && endingVelocityY >= velocityY / 4) {
- onSwipeDown();
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onDoubleTap(MotionEvent firstDown) {
- if (ENABLE_CAPSLOCK_BY_DOUBLETAP && mKeyboard instanceof LatinKeyboard
- && ((LatinKeyboard) mKeyboard).isAlphaKeyboard()) {
- final int pointerIndex = firstDown.getActionIndex();
- final int id = firstDown.getPointerId(pointerIndex);
- final PointerTracker tracker = getPointerTracker(id);
- // If the first down event is on shift key.
- if (tracker.isOnShiftKey((int)firstDown.getX(), (int)firstDown.getY())) {
- mProcessingShiftDoubleTapEvent = true;
- return true;
- }
- }
- mProcessingShiftDoubleTapEvent = false;
- return false;
- }
-
- @Override
- public boolean onDoubleTapEvent(MotionEvent secondTap) {
- if (mProcessingShiftDoubleTapEvent
- && secondTap.getAction() == MotionEvent.ACTION_DOWN) {
- final MotionEvent secondDown = secondTap;
- final int pointerIndex = secondDown.getActionIndex();
- final int id = secondDown.getPointerId(pointerIndex);
- final PointerTracker tracker = getPointerTracker(id);
- // If the second down event is also on shift key.
- if (tracker.isOnShiftKey((int)secondDown.getX(), (int)secondDown.getY())) {
- // Detected a double tap on shift key. If we are in the ignoring double tap
- // mode, it means we have already turned off caps lock in
- // {@link KeyboardSwitcher#onReleaseShift} .
- final boolean ignoringDoubleTap = mHandler.isIgnoringDoubleTap();
- if (!ignoringDoubleTap)
- onDoubleTapShiftKey(tracker);
- return true;
- }
- // Otherwise these events should not be handled as double tap.
- mProcessingShiftDoubleTapEvent = false;
- }
- return mProcessingShiftDoubleTapEvent;
- }
- };
-
- final boolean ignoreMultitouch = true;
- mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch);
- mGestureDetector.setIsLongpressEnabled(false);
-
- mHasDistinctMultitouch = context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
- mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
}
// Read fraction value in TypedArray as float.
- private static float getRatio(TypedArray a, int index) {
+ /* package */ static float getRatio(TypedArray a, int index) {
return a.getFraction(index, 1000, 1000, 1) / 1000.0f;
}
- public void startIgnoringDoubleTap() {
- if (ENABLE_CAPSLOCK_BY_DOUBLETAP)
- mHandler.startIgnoringDoubleTap();
- }
-
- public void setOnKeyboardActionListener(KeyboardActionListener listener) {
- mKeyboardActionListener = listener;
- for (PointerTracker tracker : mPointerTrackers) {
- tracker.setOnKeyboardActionListener(listener);
- }
- }
-
- /**
- * Returns the {@link KeyboardActionListener} object.
- * @return the listener attached to this keyboard
- */
- protected KeyboardActionListener getOnKeyboardActionListener() {
- return mKeyboardActionListener;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // TODO: Should notify InputMethodService instead?
- KeyboardSwitcher.getInstance().onSizeChanged();
- }
-
/**
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
* view will re-layout itself to accommodate the keyboard.
@@ -513,33 +389,13 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
* @param keyboard the keyboard to display in this view
*/
public void setKeyboard(Keyboard keyboard) {
- if (mKeyboard != null) {
- dismissAllKeyPreviews();
- }
- // Remove any pending messages, except dismissing preview
- mHandler.cancelKeyTimers();
- mHandler.cancelAllShowKeyPreviews();
mKeyboard = keyboard;
LatinImeLogger.onSetKeyboard(keyboard);
- mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
- -getPaddingTop() + mVerticalCorrection);
- for (PointerTracker tracker : mPointerTrackers) {
- tracker.setKeyboard(keyboard, mKeyHysteresisDistance);
- }
requestLayout();
- mKeyboardChanged = true;
invalidateAllKeys();
- mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
- mPopupPanelCache.clear();
- final int keyHeight = keyboard.getRowHeight() - keyboard.getVerticalGap();
- mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
- mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
- mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
- mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
- mKeyUppercaseLetterSize = (int)(
- keyHeight * mKeyUppercaseLetterRatio);
- mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio);
- mPreviewTextSize = (int)(keyHeight * mPreviewTextRatio);
+ final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
+ mKeyDrawParams.updateKeyHeight(keyHeight);
+ mKeyPreviewDrawParams.updateKeyHeight(keyHeight);
}
/**
@@ -552,15 +408,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
/**
- * Returns whether the device has distinct multi-touch panel.
- * @return true if the device has distinct multi-touch panel.
- */
- @Override
- public boolean hasDistinctMultitouch() {
- return mHasDistinctMultitouch;
- }
-
- /**
* Enables or disables the key feedback popup. This is a popup that shows a magnified
* version of the depressed key. By default the preview is enabled.
* @param previewEnabled whether or not to enable the key feedback preview
@@ -581,51 +428,22 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
return mShowKeyPreviewPopup;
}
- /**
- * When enabled, calls to {@link KeyboardActionListener#onCodeInput} will include key
- * codes for adjacent keys. When disabled, only the primary key code will be
- * reported.
- * @param enabled whether or not the proximity correction is enabled
- */
- public void setProximityCorrectionEnabled(boolean enabled) {
- mKeyDetector.setProximityCorrectionEnabled(enabled);
- }
-
- /**
- * Returns true if proximity correction is enabled.
- */
- public boolean isProximityCorrectionEnabled() {
- return mKeyDetector.isProximityCorrectionEnabled();
- }
-
- protected CharSequence adjustCase(CharSequence label) {
- if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3
- && Character.isLowerCase(label.charAt(0))) {
- return label.toString().toUpperCase(mKeyboard.mId.mLocale);
- }
- return label;
- }
-
@Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Round up a little
- if (mKeyboard == null) {
- setMeasuredDimension(
- getPaddingLeft() + getPaddingRight(), getPaddingTop() + getPaddingBottom());
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mKeyboard != null) {
+ // The main keyboard expands to the display width.
+ final int height = mKeyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
+ setMeasuredDimension(widthMeasureSpec, height);
} else {
- int width = mKeyboard.getMinWidth() + getPaddingLeft() + getPaddingRight();
- if (MeasureSpec.getSize(widthMeasureSpec) < width + 10) {
- width = MeasureSpec.getSize(widthMeasureSpec);
- }
- setMeasuredDimension(
- width, mKeyboard.getHeight() + getPaddingTop() + getPaddingBottom());
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- if (mDrawPending || mBuffer == null || mKeyboardChanged) {
+ if (mBufferNeedsUpdate || mBuffer == null) {
+ mBufferNeedsUpdate = false;
onBufferDraw();
}
canvas.drawBitmap(mBuffer, 0, 0, null);
@@ -636,273 +454,347 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final int height = getHeight();
if (width == 0 || height == 0)
return;
- if (mBuffer == null || mKeyboardChanged) {
- mKeyboardChanged = false;
- mDirtyRect.union(0, 0, width, height);
- }
if (mBuffer == null || mBuffer.getWidth() != width || mBuffer.getHeight() != height) {
if (mBuffer != null)
mBuffer.recycle();
mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ mInvalidateAllKeys = true;
if (mCanvas != null) {
mCanvas.setBitmap(mBuffer);
} else {
mCanvas = new Canvas(mBuffer);
}
}
- final Canvas canvas = mCanvas;
- canvas.clipRect(mDirtyRect, Op.REPLACE);
- canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
if (mKeyboard == null) return;
- if (mInvalidatedKey != null && mInvalidatedKeyRect.contains(mDirtyRect)) {
- // Draw a single key.
- onBufferDrawKey(canvas, mInvalidatedKey);
- } else {
+ final Canvas canvas = mCanvas;
+ final Paint paint = mPaint;
+ final KeyDrawParams params = mKeyDrawParams;
+
+ if (mInvalidateAllKeys || mInvalidatedKeys.isEmpty()) {
+ mInvalidatedKeysRect.set(0, 0, width, height);
+ canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE);
+ canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
// Draw all keys.
- for (final Key key : mKeyboard.getKeys()) {
- onBufferDrawKey(canvas, key);
+ for (final Key key : mKeyboard.mKeys) {
+ onDrawKey(key, canvas, paint, params);
+ }
+ if (mNeedsToDimEntireKeyboard) {
+ drawDimRectangle(canvas, mInvalidatedKeysRect, mBackgroundDimAlpha, paint);
+ }
+ } else {
+ // Draw invalidated keys.
+ for (final Key key : mInvalidatedKeys) {
+ if (!mKeyboard.hasKey(key)) {
+ continue;
+ }
+ final int x = key.mX + getPaddingLeft();
+ final int y = key.mY + getPaddingTop();
+ mInvalidatedKeysRect.set(x, y, x + key.mWidth, y + key.mHeight);
+ canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE);
+ canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
+ onDrawKey(key, canvas, paint, params);
+ if (mNeedsToDimEntireKeyboard) {
+ drawDimRectangle(canvas, mInvalidatedKeysRect, mBackgroundDimAlpha, paint);
+ }
}
}
- // TODO: Move this function to ProximityInfo for getting rid of
- // public declarations for
- // GRID_WIDTH and GRID_HEIGHT
- if (DEBUG_KEYBOARD_GRID) {
- Paint p = new Paint();
- p.setStyle(Paint.Style.STROKE);
- p.setStrokeWidth(1.0f);
- p.setColor(0x800000c0);
- int cw = (mKeyboard.getMinWidth() + mKeyboard.GRID_WIDTH - 1)
- / mKeyboard.GRID_WIDTH;
- int ch = (mKeyboard.getHeight() + mKeyboard.GRID_HEIGHT - 1)
- / mKeyboard.GRID_HEIGHT;
- for (int i = 0; i <= mKeyboard.GRID_WIDTH; i++)
- canvas.drawLine(i * cw, 0, i * cw, ch * mKeyboard.GRID_HEIGHT, p);
- for (int i = 0; i <= mKeyboard.GRID_HEIGHT; i++)
- canvas.drawLine(0, i * ch, cw * mKeyboard.GRID_WIDTH, i * ch, p);
+ mInvalidatedKeys.clear();
+ mInvalidatedKeysRect.setEmpty();
+ mInvalidateAllKeys = false;
+ }
+
+ public void dimEntireKeyboard(boolean dimmed) {
+ final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed;
+ mNeedsToDimEntireKeyboard = dimmed;
+ if (needsRedrawing) {
+ invalidateAllKeys();
}
+ }
+
+ private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
+ final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft();
+ final int keyDrawY = key.mY + getPaddingTop();
+ canvas.translate(keyDrawX, keyDrawY);
- // Overlay a dark rectangle to dim the keyboard
- if (mPopupMiniKeyboardPanel != null) {
- mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
- canvas.drawRect(0, 0, width, height, mPaint);
+ params.mAnimAlpha = ALPHA_OPAQUE;
+ if (!key.isSpacer()) {
+ onDrawKeyBackground(key, canvas, params);
}
+ onDrawKeyTopVisuals(key, canvas, paint, params);
- mInvalidatedKey = null;
- mDrawPending = false;
- mDirtyRect.setEmpty();
+ canvas.translate(-keyDrawX, -keyDrawY);
}
- private void onBufferDrawKey(final Canvas canvas, final Key key) {
- final Paint paint = mPaint;
- final Drawable keyBackground = mKeyBackground;
- final Rect padding = mPadding;
- final int kbdPaddingLeft = getPaddingLeft();
- final int kbdPaddingTop = getPaddingTop();
- final int keyDrawX = key.mX + key.mVisualInsetsLeft;
- final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
- final int centerX = (keyDrawWidth + padding.left - padding.right) / 2;
- final float centerY = (key.mHeight + padding.top - padding.bottom) / 2;
- final int rowHeight = padding.top + key.mHeight;
- final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase();
+ // Draw key background.
+ protected void onDrawKeyBackground(Key key, Canvas canvas, KeyDrawParams params) {
+ final int bgWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight
+ + params.mPadding.left + params.mPadding.right;
+ final int bgHeight = key.mHeight + params.mPadding.top + params.mPadding.bottom;
+ final int bgX = -params.mPadding.left;
+ final int bgY = -params.mPadding.top;
+ final int[] drawableState = key.getCurrentDrawableState();
+ final Drawable background = params.mKeyBackground;
+ background.setState(drawableState);
+ final Rect bounds = background.getBounds();
+ if (bgWidth != bounds.right || bgHeight != bounds.bottom) {
+ background.setBounds(0, 0, bgWidth, bgHeight);
+ }
+ canvas.translate(bgX, bgY);
+ background.draw(canvas);
+ if (LatinImeLogger.sVISUALDEBUG) {
+ drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint());
+ }
+ canvas.translate(-bgX, -bgY);
+ }
- canvas.translate(keyDrawX + kbdPaddingLeft, key.mY + kbdPaddingTop);
+ // Draw key top visuals.
+ protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
+ final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
+ final int keyHeight = key.mHeight;
+ final float centerX = keyWidth * 0.5f;
+ final float centerY = keyHeight * 0.5f;
- // Draw key background.
- final int[] drawableState = key.getCurrentDrawableState();
- keyBackground.setState(drawableState);
- final Rect bounds = keyBackground.getBounds();
- if (keyDrawWidth != bounds.right || key.mHeight != bounds.bottom) {
- keyBackground.setBounds(0, 0, keyDrawWidth, key.mHeight);
+ if (LatinImeLogger.sVISUALDEBUG) {
+ drawRectangle(canvas, 0, 0, keyWidth, keyHeight, 0x800000c0, new Paint());
}
- keyBackground.draw(canvas);
// Draw key label.
- int positionX = centerX;
+ final Drawable icon = key.getIcon(mKeyboard.mIconsSet, params.mAnimAlpha);
+ float positionX = centerX;
if (key.mLabel != null) {
- // Switch the character to uppercase if shift is pressed
- final CharSequence label = key.mLabel == null ? null : adjustCase(key.mLabel);
+ final String label = key.mLabel;
// For characters, use large font. For labels like "Done", use smaller font.
- paint.setTypeface(key.selectTypeface(mKeyTextStyle));
- final int labelSize = key.selectTextSize(mKeyLetterSize, mKeyLargeLetterSize,
- mKeyLabelSize, mKeyHintLabelSize);
+ paint.setTypeface(key.selectTypeface(params.mKeyTextStyle));
+ final int labelSize = key.selectTextSize(params.mKeyLetterSize,
+ params.mKeyLargeLetterSize, params.mKeyLabelSize, params.mKeyLargeLabelSize,
+ params.mKeyHintLabelSize);
paint.setTextSize(labelSize);
- final int labelCharHeight = getLabelCharHeight(paint);
- final int labelCharWidth = getLabelCharWidth(paint);
+ final float labelCharHeight = getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint);
+ final float labelCharWidth = getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint);
// Vertical label text alignment.
- final float baseline;
- // TODO: Generalize the following calculations.
- if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_BOTTOM) != 0) {
- baseline = key.mHeight - labelCharHeight * KEY_LABEL_VERTICAL_PADDING_FACTOR;
- } else { // Align center
- baseline = centerY + labelCharHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER;
- }
+ final float baseline = centerY + labelCharHeight / 2;
// Horizontal label text alignment
- if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_LEFT) != 0) {
- positionX = padding.left + mKeyLabelHorizontalPadding;
+ float labelWidth = 0;
+ if (key.isAlignLeft()) {
+ positionX = (int)params.mKeyLabelHorizontalPadding;
paint.setTextAlign(Align.LEFT);
- } else if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_RIGHT) != 0) {
- positionX = keyDrawWidth - mKeyLabelHorizontalPadding - padding.right;
+ } else if (key.isAlignRight()) {
+ positionX = keyWidth - (int)params.mKeyLabelHorizontalPadding;
paint.setTextAlign(Align.RIGHT);
- } else if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_LEFT_OF_CENTER) != 0) {
+ } else if (key.isAlignLeftOfCenter()) {
// TODO: Parameterise this?
positionX = centerX - labelCharWidth * 7 / 4;
paint.setTextAlign(Align.LEFT);
+ } else if (key.hasLabelWithIconLeft() && icon != null) {
+ labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth()
+ + LABEL_ICON_MARGIN * keyWidth;
+ positionX = centerX + labelWidth / 2;
+ paint.setTextAlign(Align.RIGHT);
+ } else if (key.hasLabelWithIconRight() && icon != null) {
+ labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth()
+ + LABEL_ICON_MARGIN * keyWidth;
+ positionX = centerX - labelWidth / 2;
+ paint.setTextAlign(Align.LEFT);
} else {
positionX = centerX;
paint.setTextAlign(Align.CENTER);
}
- if (DEBUG_SHOW_ALIGN) {
- final Paint line = new Paint();
- drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000, line);
- drawVerticalLine(canvas, positionX, rowHeight, 0xc0800080, line);
+ if (key.needsXScale()) {
+ paint.setTextScaleX(
+ Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint)));
}
- if (key.hasUppercaseLetter() && isManualTemporaryUpperCase) {
- paint.setColor(mKeyTextInactivatedColor);
- } else {
- paint.setColor(mKeyTextColor);
- }
+ paint.setColor(key.isShiftedLetterActivated()
+ ? params.mKeyTextInactivatedColor : params.mKeyTextColor);
if (key.isEnabled()) {
// Set a drop shadow for the text
- paint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor);
+ paint.setShadowLayer(params.mShadowRadius, 0, 0, params.mShadowColor);
} else {
// Make label invisible
paint.setColor(Color.TRANSPARENT);
}
+ params.blendAlpha(paint);
canvas.drawText(label, 0, label.length(), positionX, baseline, paint);
- // Turn off drop shadow
+ // Turn off drop shadow and reset x-scale.
paint.setShadowLayer(0, 0, 0, 0);
+ paint.setTextScaleX(1.0f);
+
+ if (icon != null) {
+ final int iconWidth = icon.getIntrinsicWidth();
+ final int iconHeight = icon.getIntrinsicHeight();
+ final int iconY = (keyHeight - iconHeight) / 2;
+ if (key.hasLabelWithIconLeft()) {
+ final int iconX = (int)(centerX - labelWidth / 2);
+ drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
+ } else if (key.hasLabelWithIconRight()) {
+ final int iconX = (int)(centerX + labelWidth / 2 - iconWidth);
+ drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
+ }
+ }
+ if (LatinImeLogger.sVISUALDEBUG) {
+ final Paint line = new Paint();
+ drawHorizontalLine(canvas, baseline, keyWidth, 0xc0008000, line);
+ drawVerticalLine(canvas, positionX, keyHeight, 0xc0800080, line);
+ }
}
// Draw hint label.
if (key.mHintLabel != null) {
- final CharSequence hint = key.mHintLabel;
+ final String hint = key.mHintLabel;
final int hintColor;
final int hintSize;
- if (key.hasUppercaseLetter()) {
- hintColor = isManualTemporaryUpperCase ? mKeyUppercaseLetterActivatedColor
- : mKeyUppercaseLetterInactivatedColor;
- hintSize = mKeyUppercaseLetterSize;
- } else if (key.hasHintLabel()) {
- hintColor = mKeyHintLabelColor;
- hintSize = mKeyHintLabelSize;
+ if (key.hasHintLabel()) {
+ hintColor = params.mKeyHintLabelColor;
+ hintSize = params.mKeyHintLabelSize;
paint.setTypeface(Typeface.DEFAULT);
- } else {
- hintColor = mKeyHintLetterColor;
- hintSize = mKeyHintLetterSize;
+ } else if (key.hasShiftedLetterHint()) {
+ hintColor = key.isShiftedLetterActivated()
+ ? params.mKeyShiftedLetterHintActivatedColor
+ : params.mKeyShiftedLetterHintInactivatedColor;
+ hintSize = params.mKeyShiftedLetterHintSize;
+ } else { // key.hasHintLetter()
+ hintColor = params.mKeyHintLetterColor;
+ hintSize = params.mKeyHintLetterSize;
}
paint.setColor(hintColor);
+ params.blendAlpha(paint);
paint.setTextSize(hintSize);
- // Note: padding.right for drawX?
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 + getLabelCharWidth(paint) * 2;
- hintY = centerY + getLabelCharHeight(paint) / 2;
- } else {
- hintX = keyDrawWidth - getLabelCharWidth(paint);
- hintY = -paint.ascent() + padding.top;
+ hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2;
+ hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+ 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 - params.mKeyShiftedLetterHintPadding
+ - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+ 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.
+ hintX = keyWidth - params.mKeyHintLetterPadding
+ - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2;
+ hintY = -paint.ascent();
+ paint.setTextAlign(Align.CENTER);
}
canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint);
+
+ if (LatinImeLogger.sVISUALDEBUG) {
+ final Paint line = new Paint();
+ drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line);
+ drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line);
+ }
}
// Draw key icon.
- final Drawable icon = key.getIcon();
if (key.mLabel == null && icon != null) {
final int iconWidth = icon.getIntrinsicWidth();
final int iconHeight = icon.getIntrinsicHeight();
final int iconX, alignX;
- final int iconY = (key.mHeight + padding.top - padding.bottom - iconHeight) / 2;
- if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_LEFT) != 0) {
- iconX = padding.left + mKeyLabelHorizontalPadding;
+ final int iconY = (keyHeight - iconHeight) / 2;
+ if (key.isAlignLeft()) {
+ iconX = (int)params.mKeyLabelHorizontalPadding;
alignX = iconX;
- } else if ((key.mLabelOption & Key.LABEL_OPTION_ALIGN_RIGHT) != 0) {
- iconX = keyDrawWidth - padding.right - mKeyLabelHorizontalPadding - iconWidth;
+ } else if (key.isAlignRight()) {
+ iconX = keyWidth - (int)params.mKeyLabelHorizontalPadding - iconWidth;
alignX = iconX + iconWidth;
} else { // Align center
- iconX = (keyDrawWidth + padding.left - padding.right - iconWidth) / 2;
+ iconX = (keyWidth - iconWidth) / 2;
alignX = iconX + iconWidth / 2;
}
drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
- if (DEBUG_SHOW_ALIGN) {
+
+ if (LatinImeLogger.sVISUALDEBUG) {
final Paint line = new Paint();
- drawVerticalLine(canvas, alignX, rowHeight, 0xc0800080, line);
+ drawVerticalLine(canvas, alignX, keyHeight, 0xc0800080, line);
drawRectangle(canvas, iconX, iconY, iconWidth, iconHeight, 0x80c00000, line);
}
}
- // Draw popup hint icon "...".
- // TODO: Draw "..." by text.
- if (key.hasPopupHint()) {
- final int drawableWidth = keyDrawWidth;
- final int drawableHeight = key.mHeight;
- final int drawableX = 0;
- final int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL;
- final Drawable hintIcon = mKeyPopupHintIcon;
- drawIcon(canvas, hintIcon, drawableX, drawableY, drawableWidth, drawableHeight);
- if (DEBUG_SHOW_ALIGN) {
- drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
- 0x80c0c000, new Paint());
- }
+ if (key.hasPopupHint() && key.mMoreKeys != null && key.mMoreKeys.length > 0) {
+ drawKeyPopupHint(key, canvas, paint, params);
}
+ }
- canvas.translate(-keyDrawX - kbdPaddingLeft, -key.mY - kbdPaddingTop);
+ // Draw popup hint "..." at the bottom right corner of the key.
+ protected void drawKeyPopupHint(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
+ final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
+ final int keyHeight = key.mHeight;
+
+ paint.setTypeface(params.mKeyTextStyle);
+ paint.setTextSize(params.mKeyHintLetterSize);
+ paint.setColor(params.mKeyHintLabelColor);
+ paint.setTextAlign(Align.CENTER);
+ final float hintX = keyWidth - params.mKeyHintLetterPadding
+ - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+ final float hintY = keyHeight - params.mKeyPopupHintLetterPadding;
+ canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint);
+
+ if (LatinImeLogger.sVISUALDEBUG) {
+ final Paint line = new Paint();
+ drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line);
+ drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line);
+ }
}
- // This method is currently being used only by MiniKeyboardBuilder
- public int getDefaultLabelSizeAndSetPaint(Paint paint) {
- // For characters, use large font. For labels like "Done", use small font.
- final int labelSize = mKeyLabelSize;
- paint.setTextSize(labelSize);
- paint.setTypeface(mKeyTextStyle);
- return labelSize;
+ private static int getCharGeometryCacheKey(char referenceChar, Paint paint) {
+ final int labelSize = (int)paint.getTextSize();
+ final Typeface face = paint.getTypeface();
+ final int codePointOffset = referenceChar << 15;
+ if (face == Typeface.DEFAULT) {
+ return codePointOffset + labelSize;
+ } else if (face == Typeface.DEFAULT_BOLD) {
+ return codePointOffset + labelSize + 0x1000;
+ } else if (face == Typeface.MONOSPACE) {
+ return codePointOffset + labelSize + 0x2000;
+ } else {
+ return codePointOffset + labelSize;
+ }
}
+ // Working variable for the following methods.
private final Rect mTextBounds = new Rect();
- private int getLabelCharHeight(Paint paint) {
- final int labelSize = (int)paint.getTextSize();
- final Integer cachedValue = mTextHeightCache.get(labelSize);
+ private float getCharHeight(char[] referenceChar, Paint paint) {
+ final Integer key = getCharGeometryCacheKey(referenceChar[0], paint);
+ final Float cachedValue = sTextHeightCache.get(key);
if (cachedValue != null)
return cachedValue;
- paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, mTextBounds);
- final int height = mTextBounds.height();
- mTextHeightCache.put(labelSize, height);
+ paint.getTextBounds(referenceChar, 0, 1, mTextBounds);
+ final float height = mTextBounds.height();
+ sTextHeightCache.put(key, height);
return height;
}
- private int getLabelCharWidth(Paint paint) {
- final int labelSize = (int)paint.getTextSize();
- final Typeface face = paint.getTypeface();
- final Integer key;
- if (face == Typeface.DEFAULT) {
- key = labelSize;
- } else if (face == Typeface.DEFAULT_BOLD) {
- key = labelSize + 1000;
- } else if (face == Typeface.MONOSPACE) {
- key = labelSize + 2000;
- } else {
- key = labelSize;
- }
-
- final Integer cached = mTextWidthCache.get(key);
- if (cached != null)
- return cached;
+ private float getCharWidth(char[] referenceChar, Paint paint) {
+ final Integer key = getCharGeometryCacheKey(referenceChar[0], paint);
+ final Float cachedValue = sTextWidthCache.get(key);
+ if (cachedValue != null)
+ return cachedValue;
- paint.getTextBounds(KEY_LABEL_REFERENCE_CHAR, 0, 1, mTextBounds);
- final int width = mTextBounds.width();
- mTextWidthCache.put(key, width);
+ paint.getTextBounds(referenceChar, 0, 1, mTextBounds);
+ final float width = mTextBounds.width();
+ sTextWidthCache.put(key, width);
return width;
}
- private static void drawIcon(Canvas canvas, Drawable icon, int x, int y, int width,
+ public float getLabelWidth(String label, Paint paint) {
+ paint.getTextBounds(label.toString(), 0, label.length(), mTextBounds);
+ return mTextBounds.width();
+ }
+
+ protected static void drawIcon(Canvas canvas, Drawable icon, int x, int y, int width,
int height) {
canvas.translate(x, y);
icon.setBounds(0, 0, width, height);
@@ -910,21 +802,22 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
canvas.translate(-x, -y);
}
- private static void drawHorizontalLine(Canvas canvas, int y, int w, int color, Paint paint) {
+ private static void drawHorizontalLine(Canvas canvas, float y, float w, int color,
+ Paint paint) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1.0f);
paint.setColor(color);
canvas.drawLine(0, y, w, y, paint);
}
- private static void drawVerticalLine(Canvas canvas, int x, int h, int color, Paint paint) {
+ private static void drawVerticalLine(Canvas canvas, float x, float h, int color, Paint paint) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1.0f);
paint.setColor(color);
canvas.drawLine(x, 0, x, h, paint);
}
- private static void drawRectangle(Canvas canvas, int x, int y, int w, int h, int color,
+ private static void drawRectangle(Canvas canvas, float x, float y, float w, float h, int color,
Paint paint) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1.0f);
@@ -934,108 +827,134 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
canvas.translate(-x, -y);
}
- // TODO: clean up this method.
- private void dismissAllKeyPreviews() {
- for (PointerTracker tracker : mPointerTrackers) {
- tracker.setReleasedKeyGraphics();
- dismissKeyPreview(tracker);
- }
+ // Overlay a dark rectangle to dim.
+ private static void drawDimRectangle(Canvas canvas, Rect rect, int alpha, Paint paint) {
+ paint.setColor(Color.BLACK);
+ paint.setAlpha(alpha);
+ canvas.drawRect(rect, paint);
}
- public void cancelAllMessage() {
- mHandler.cancelAllMessages();
+ public Paint newDefaultLabelPaint() {
+ final Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTypeface(mKeyDrawParams.mKeyTextStyle);
+ paint.setTextSize(mKeyDrawParams.mKeyLabelSize);
+ return paint;
}
+ public void cancelAllMessages() {
+ mDrawingHandler.cancelAllMessages();
+ }
+
+ // Called by {@link PointerTracker} constructor to create a TextView.
@Override
- public void showKeyPreview(int keyIndex, PointerTracker tracker) {
- if (mShowKeyPreviewPopup) {
- mHandler.showKeyPreview(mDelayBeforePreview, keyIndex, tracker);
- } else if (mKeyboard.needSpacebarPreview(keyIndex)) {
- // Show key preview (in this case, slide language switcher) without any delay.
- showKey(keyIndex, tracker);
+ public TextView inflateKeyPreviewText() {
+ final Context context = getContext();
+ if (mKeyPreviewLayoutId != 0) {
+ return (TextView)LayoutInflater.from(context).inflate(mKeyPreviewLayoutId, null);
+ } else {
+ return new TextView(context);
}
}
@Override
public void dismissKeyPreview(PointerTracker tracker) {
- if (mShowKeyPreviewPopup) {
- mHandler.cancelShowKeyPreview(tracker);
- mHandler.dismissKeyPreview(mDelayAfterPreview, tracker);
- } else if (mKeyboard.needSpacebarPreview(KeyDetector.NOT_A_KEY)) {
- // Dismiss key preview (in this case, slide language switcher) without any delay.
- mPreviewText.setVisibility(View.INVISIBLE);
- }
+ mDrawingHandler.dismissKeyPreview(mDelayAfterPreview, tracker);
}
private void addKeyPreview(TextView keyPreview) {
if (mPreviewPlacer == null) {
- mPreviewPlacer = FrameLayoutCompatUtils.getPlacer(
- (ViewGroup)getRootView().findViewById(android.R.id.content));
+ mPreviewPlacer = new RelativeLayout(getContext());
+ final ViewGroup windowContentView =
+ (ViewGroup)getRootView().findViewById(android.R.id.content);
+ windowContentView.addView(mPreviewPlacer);
}
- final ViewGroup placer = mPreviewPlacer;
- placer.addView(keyPreview, FrameLayoutCompatUtils.newLayoutParam(placer, 0, 0));
+ mPreviewPlacer.addView(
+ keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacer, 0, 0));
}
- // TODO: Introduce minimum duration for displaying key previews
- // TODO: Display up to two key previews when the user presses two keys at the same time
- private void showKey(final int keyIndex, PointerTracker tracker) {
- final TextView previewText = mPreviewText;
+ @SuppressWarnings("deprecation") // setBackgroundDrawable is replaced by setBackground in API16
+ @Override
+ public void showKeyPreview(PointerTracker tracker) {
+ if (!mShowKeyPreviewPopup) return;
+
+ final TextView previewText = tracker.getKeyPreviewText();
// If the key preview has no parent view yet, add it to the ViewGroup which can place
// key preview absolutely in SoftInputWindow.
if (previewText.getParent() == null) {
addKeyPreview(previewText);
}
- final Key key = tracker.getKey(keyIndex);
- // If keyIndex is invalid or IME is already closed, we must not show key preview.
+ mDrawingHandler.cancelDismissKeyPreview(tracker);
+ final Key key = tracker.getKey();
+ // If key is invalid or IME is already closed, we must not show key preview.
// Trying to show key preview while root window is closed causes
// WindowManager.BadTokenException.
if (key == null)
return;
- mHandler.cancelAllDismissKeyPreviews();
-
- final int keyDrawX = key.mX + key.mVisualInsetsLeft;
- final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
- // What we show as preview should match what we show on key top in onBufferDraw().
- if (key.mLabel != null) {
+ final KeyPreviewDrawParams params = mKeyPreviewDrawParams;
+ final String label = key.isShiftedLetterActivated() ? key.mHintLabel : key.mLabel;
+ // What we show as preview should match what we show on a key top in onBufferDraw().
+ if (label != null) {
// TODO Should take care of temporaryShiftLabel here.
previewText.setCompoundDrawables(null, null, null, null);
- if (key.mLabel.length() > 1) {
- previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyLetterSize);
+ if (StringUtils.codePointCount(label) > 1) {
+ previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mKeyLetterSize);
previewText.setTypeface(Typeface.DEFAULT_BOLD);
} else {
- previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSize);
- previewText.setTypeface(mKeyTextStyle);
+ previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mPreviewTextSize);
+ previewText.setTypeface(params.mKeyTextStyle);
}
- previewText.setText(adjustCase(tracker.getPreviewText(key)));
+ previewText.setText(label);
} else {
- final Drawable previewIcon = key.getPreviewIcon();
previewText.setCompoundDrawables(null, null, null,
- previewIcon != null ? previewIcon : key.getIcon());
+ key.getPreviewIcon(mKeyboard.mIconsSet));
previewText.setText(null);
}
- if (key.mCode == Keyboard.CODE_SPACE) {
- previewText.setBackgroundDrawable(mPreviewSpacebarBackground);
- } else {
- previewText.setBackgroundDrawable(mPreviewBackground);
+ previewText.setBackgroundDrawable(params.mPreviewBackground);
+
+ previewText.measure(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
+ final int previewWidth = previewText.getMeasuredWidth();
+ final int previewHeight = params.mPreviewHeight;
+ // The width and height of visible part of the key preview background. The content marker
+ // of the background 9-patch have to cover the visible part of the background.
+ params.mPreviewVisibleWidth = previewWidth - previewText.getPaddingLeft()
+ - previewText.getPaddingRight();
+ params.mPreviewVisibleHeight = previewHeight - previewText.getPaddingTop()
+ - previewText.getPaddingBottom();
+ // The distance between the top edge of the parent key and the bottom of the visible part
+ // of the key preview background.
+ params.mPreviewVisibleOffset = params.mPreviewOffset - previewText.getPaddingBottom();
+ getLocationInWindow(params.mCoordinates);
+ // The key preview is horizontally aligned with the center of the visible part of the
+ // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and
+ // the left/right background is used if such background is specified.
+ int previewX = key.mX + key.mVisualInsetsLeft - (previewWidth - keyDrawWidth) / 2
+ + params.mCoordinates[0];
+ if (previewX < 0) {
+ previewX = 0;
+ if (params.mPreviewLeftBackground != null) {
+ previewText.setBackgroundDrawable(params.mPreviewLeftBackground);
+ }
+ } else if (previewX > getWidth() - previewWidth) {
+ previewX = getWidth() - previewWidth;
+ if (params.mPreviewRightBackground != null) {
+ previewText.setBackgroundDrawable(params.mPreviewRightBackground);
+ }
}
+ // The key preview is placed vertically above the top edge of the parent key with an
+ // arbitrary offset.
+ final int previewY = key.mY - previewHeight + params.mPreviewOffset
+ + params.mCoordinates[1];
+
// Set the preview background state
previewText.getBackground().setState(
- key.mPopupCharacters != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
-
- previewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- final int previewWidth = Math.max(previewText.getMeasuredWidth(), keyDrawWidth
- + previewText.getPaddingLeft() + previewText.getPaddingRight());
- final int previewHeight = mPreviewHeight;
- getLocationInWindow(mCoordinates);
- final int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + mCoordinates[0];
- final int previewY = key.mY - previewHeight + mCoordinates[1] + mPreviewOffset;
-
- // Place the key preview.
- // TODO: Adjust position of key previews which touch screen edges
- FrameLayoutCompatUtils.placeViewAt(
+ key.mMoreKeys != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
+ previewText.setTextColor(params.mPreviewTextColor);
+ ViewLayoutUtils.placeViewAt(
previewText, previewX, previewY, previewWidth, previewHeight);
previewText.setVisibility(VISIBLE);
}
@@ -1047,8 +966,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
* @see #invalidateKey(Key)
*/
public void invalidateAllKeys() {
- mDirtyRect.union(0, 0, getWidth(), getHeight());
- mDrawPending = true;
+ mInvalidatedKeys.clear();
+ mInvalidateAllKeys = true;
+ mBufferNeedsUpdate = true;
invalidate();
}
@@ -1061,278 +981,27 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
*/
@Override
public void invalidateKey(Key key) {
- if (key == null)
- return;
- mInvalidatedKey = key;
+ if (mInvalidateAllKeys) return;
+ if (key == null) return;
+ mInvalidatedKeys.add(key);
final int x = key.mX + getPaddingLeft();
final int y = key.mY + getPaddingTop();
- mInvalidatedKeyRect.set(x, y, x + key.mWidth, y + key.mHeight);
- mDirtyRect.union(mInvalidatedKeyRect);
- onBufferDraw();
- invalidate(mInvalidatedKeyRect);
- }
-
- private boolean openMiniKeyboardIfRequired(int keyIndex, PointerTracker tracker) {
- // Check if we have a popup layout specified first.
- if (mPopupLayout == 0) {
- return false;
- }
-
- final Key parentKey = tracker.getKey(keyIndex);
- if (parentKey == null)
- return false;
- boolean result = onLongPress(parentKey, tracker);
- if (result) {
- dismissAllKeyPreviews();
- tracker.onLongPressed(mPointerQueue);
- }
- return result;
- }
-
- private void onLongPressShiftKey(PointerTracker tracker) {
- tracker.onLongPressed(mPointerQueue);
- mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
- }
-
- private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker) {
- // When shift key is double tapped, the first tap is correctly processed as usual tap. And
- // the second tap is treated as this double tap event, so that we need not mark tracker
- // calling setAlreadyProcessed() nor remove the tracker from mPointerQueueueue.
- mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
+ mInvalidatedKeysRect.union(x, y, x + key.mWidth, y + key.mHeight);
+ mBufferNeedsUpdate = true;
+ invalidate(mInvalidatedKeysRect);
}
- // This default implementation returns a popup mini keyboard panel.
- // A derived class may return a language switcher popup panel, for instance.
- protected PopupPanel onCreatePopupPanel(Key parentKey) {
- if (parentKey.mPopupCharacters == null)
- return null;
-
- final View container = LayoutInflater.from(getContext()).inflate(mPopupLayout, null);
- if (container == null)
- throw new NullPointerException();
-
- final PopupMiniKeyboardView miniKeyboardView =
- (PopupMiniKeyboardView)container.findViewById(R.id.mini_keyboard_view);
- miniKeyboardView.setOnKeyboardActionListener(new KeyboardActionListener() {
- @Override
- public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
- mKeyboardActionListener.onCodeInput(primaryCode, keyCodes, x, y);
- dismissMiniKeyboard();
- }
-
- @Override
- public void onTextInput(CharSequence text) {
- mKeyboardActionListener.onTextInput(text);
- dismissMiniKeyboard();
- }
-
- @Override
- public void onCancelInput() {
- mKeyboardActionListener.onCancelInput();
- dismissMiniKeyboard();
- }
-
- @Override
- public void onSwipeDown() {
- // Nothing to do.
- }
- @Override
- public void onPress(int primaryCode, boolean withSliding) {
- mKeyboardActionListener.onPress(primaryCode, withSliding);
- }
- @Override
- public void onRelease(int primaryCode, boolean withSliding) {
- mKeyboardActionListener.onRelease(primaryCode, withSliding);
- }
- });
-
- final Keyboard keyboard = new MiniKeyboardBuilder(this, mKeyboard.getPopupKeyboardResId(),
- parentKey, mKeyboard).build();
- miniKeyboardView.setKeyboard(keyboard);
-
- container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-
- return miniKeyboardView;
- }
-
- /**
- * Called when a key is long pressed. By default this will open mini keyboard associated
- * with this key.
- * @param parentKey the key that was long pressed
- * @param tracker the pointer tracker which pressed the parent key
- * @return true if the long press is handled, false otherwise. Subclasses should call the
- * method on the base class if the subclass doesn't wish to handle the call.
- */
- protected boolean onLongPress(Key parentKey, PointerTracker tracker) {
- PopupPanel popupPanel = mPopupPanelCache.get(parentKey);
- if (popupPanel == null) {
- popupPanel = onCreatePopupPanel(parentKey);
- if (popupPanel == null)
- return false;
- mPopupPanelCache.put(parentKey, popupPanel);
- }
- if (mPopupWindow == null) {
- mPopupWindow = new PopupWindow(getContext());
- mPopupWindow.setBackgroundDrawable(null);
- mPopupWindow.setAnimationStyle(R.style.PopupMiniKeyboardAnimation);
- // Allow popup window to be drawn off the screen.
- mPopupWindow.setClippingEnabled(false);
- }
- mPopupMiniKeyboardPanel = popupPanel;
- popupPanel.showPanel(this, parentKey, tracker, mPopupWindow);
-
- invalidateAllKeys();
- return true;
- }
-
- private PointerTracker getPointerTracker(final int id) {
- final ArrayList<PointerTracker> pointers = mPointerTrackers;
- final KeyboardActionListener listener = mKeyboardActionListener;
-
- // Create pointer trackers until we can get 'id+1'-th tracker, if needed.
- for (int i = pointers.size(); i <= id; i++) {
- final PointerTracker tracker =
- new PointerTracker(i, this, mHandler, mKeyDetector, this);
- if (mKeyboard != null)
- tracker.setKeyboard(mKeyboard, mKeyHysteresisDistance);
- if (listener != null)
- tracker.setOnKeyboardActionListener(listener);
- pointers.add(tracker);
- }
-
- return pointers.get(id);
- }
-
- public boolean isInSlidingKeyInput() {
- if (mPopupMiniKeyboardPanel != null) {
- return mPopupMiniKeyboardPanel.isInSlidingKeyInput();
- } else {
- return mPointerQueue.isInSlidingKeyInput();
- }
- }
+ public void closing() {
+ PointerTracker.dismissAllKeyPreviews();
+ cancelAllMessages();
- public int getPointerCount() {
- return mOldPointerCount;
+ mInvalidateAllKeys = true;
+ requestLayout();
}
@Override
- public boolean onTouchEvent(MotionEvent me) {
- final int action = me.getActionMasked();
- final int pointerCount = me.getPointerCount();
- final int oldPointerCount = mOldPointerCount;
- mOldPointerCount = pointerCount;
-
- // TODO: cleanup this code into a multi-touch to single-touch event converter class?
- // If the device does not have distinct multi-touch support panel, ignore all multi-touch
- // events except a transition from/to single-touch.
- if (!mHasDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) {
- return true;
- }
-
- // Track the last few movements to look for spurious swipes.
- mSwipeTracker.addMovement(me);
-
- // Gesture detector must be enabled only when mini-keyboard is not on the screen.
- if (mPopupMiniKeyboardPanel == null && mGestureDetector != null
- && mGestureDetector.onTouchEvent(me)) {
- dismissAllKeyPreviews();
- mHandler.cancelKeyTimers();
- return true;
- }
-
- final long eventTime = me.getEventTime();
- final int index = me.getActionIndex();
- final int id = me.getPointerId(index);
- final int x = (int)me.getX(index);
- final int y = (int)me.getY(index);
-
- // Needs to be called after the gesture detector gets a turn, as it may have displayed the
- // mini keyboard
- if (mPopupMiniKeyboardPanel != null) {
- return mPopupMiniKeyboardPanel.onTouchEvent(me);
- }
-
- if (mHandler.isInKeyRepeat()) {
- final PointerTracker tracker = getPointerTracker(id);
- // Key repeating timer will be canceled if 2 or more keys are in action, and current
- // event (UP or DOWN) is non-modifier key.
- if (pointerCount > 1 && !tracker.isModifier()) {
- mHandler.cancelKeyRepeatTimer();
- }
- // Up event will pass through.
- }
-
- // TODO: cleanup this code into a multi-touch to single-touch event converter class?
- // Translate mutli-touch event to single-touch events on the device that has no distinct
- // multi-touch panel.
- if (!mHasDistinctMultitouch) {
- // Use only main (id=0) pointer tracker.
- PointerTracker tracker = getPointerTracker(0);
- if (pointerCount == 1 && oldPointerCount == 2) {
- // Multi-touch to single touch transition.
- // Send a down event for the latest pointer if the key is different from the
- // previous key.
- final int newKeyIndex = tracker.getKeyIndexOn(x, y);
- if (mOldKeyIndex != newKeyIndex) {
- tracker.onDownEvent(x, y, eventTime, null);
- if (action == MotionEvent.ACTION_UP)
- tracker.onUpEvent(x, y, eventTime, null);
- }
- } else if (pointerCount == 2 && oldPointerCount == 1) {
- // Single-touch to multi-touch transition.
- // Send an up event for the last pointer.
- final int lastX = tracker.getLastX();
- final int lastY = tracker.getLastY();
- mOldKeyIndex = tracker.getKeyIndexOn(lastX, lastY);
- tracker.onUpEvent(lastX, lastY, eventTime, null);
- } else if (pointerCount == 1 && oldPointerCount == 1) {
- tracker.onTouchEvent(action, x, y, eventTime, null);
- } else {
- Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
- + " (old " + oldPointerCount + ")");
- }
- return true;
- }
-
- final PointerTrackerQueue queue = mPointerQueue;
- if (action == MotionEvent.ACTION_MOVE) {
- for (int i = 0; i < pointerCount; i++) {
- final PointerTracker tracker = getPointerTracker(me.getPointerId(i));
- tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime, queue);
- }
- } else {
- final PointerTracker tracker = getPointerTracker(id);
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- tracker.onDownEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- tracker.onUpEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_CANCEL:
- tracker.onCancelEvent(x, y, eventTime, queue);
- break;
- }
- }
-
- return true;
- }
-
- protected void onSwipeDown() {
- mKeyboardActionListener.onSwipeDown();
- }
-
- public void closing() {
- mPreviewText.setVisibility(View.GONE);
- mHandler.cancelAllMessages();
-
- dismissMiniKeyboard();
- mDirtyRect.union(0, 0, getWidth(), getHeight());
- mPopupPanelCache.clear();
- requestLayout();
+ public boolean dismissMoreKeysPanel() {
+ return false;
}
public void purgeKeyboardAndClosing() {
@@ -1341,55 +1010,15 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
@Override
- public void onDetachedFromWindow() {
+ protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
closing();
- }
-
- private boolean dismissMiniKeyboard() {
- if (mPopupWindow != null && mPopupWindow.isShowing()) {
- mPopupWindow.dismiss();
- mPopupMiniKeyboardPanel = null;
- invalidateAllKeys();
- return true;
+ if (mPreviewPlacer != null) {
+ mPreviewPlacer.removeAllViews();
}
- return false;
- }
-
- public boolean handleBack() {
- return dismissMiniKeyboard();
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
- return AccessibleKeyboardViewProxy.getInstance().dispatchTouchEvent(event)
- || super.dispatchTouchEvent(event);
- }
-
- return super.dispatchTouchEvent(event);
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
- final PointerTracker tracker = getPointerTracker(0);
- return AccessibleKeyboardViewProxy.getInstance().dispatchPopulateAccessibilityEvent(
- event, tracker) || super.dispatchPopulateAccessibilityEvent(event);
- }
-
- return super.dispatchPopulateAccessibilityEvent(event);
- }
-
- public boolean onHoverEvent(MotionEvent event) {
- // Since reflection doesn't support calling superclass methods, this
- // method checks for the existence of onHoverEvent() in the View class
- // before returning a value.
- if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
- final PointerTracker tracker = getPointerTracker(0);
- return AccessibleKeyboardViewProxy.getInstance().onHoverEvent(event, tracker);
+ if (mBuffer != null) {
+ mBuffer.recycle();
+ mBuffer = null;
}
-
- return false;
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
deleted file mode 100644
index 1966d2d65..000000000
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-
-import com.android.inputmethod.keyboard.internal.SlidingLocaleDrawable;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-
-import java.lang.ref.SoftReference;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-
-// TODO: We should remove this class
-public class LatinKeyboard extends Keyboard {
- private static final int SPACE_LED_LENGTH_PERCENT = 80;
-
- public static final int CODE_NEXT_LANGUAGE = -100;
- public static final int CODE_PREV_LANGUAGE = -101;
-
- private final Resources mRes;
- private final Theme mTheme;
- private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance();
-
- /* Space key and its icons, drawables and colors. */
- private final Key mSpaceKey;
- private final Drawable mSpaceIcon;
- private final Drawable mSpacePreviewIcon;
- private final int mSpaceKeyIndex;
- private final boolean mAutoCorrectionSpacebarLedEnabled;
- private final Drawable mAutoCorrectionSpacebarLedIcon;
- private final Drawable mSpacebarArrowLeftIcon;
- private final Drawable mSpacebarArrowRightIcon;
- private final int mSpacebarTextColor;
- private final int mSpacebarTextShadowColor;
- private float mSpacebarTextFadeFactor = 0.0f;
- private final int mSpacebarLanguageSwitchThreshold;
- private int mSpacebarSlidingLanguageSwitchDiff;
- private final SlidingLocaleDrawable mSlidingLocaleIcon;
- private final HashMap<Integer, SoftReference<BitmapDrawable>> mSpaceDrawableCache =
- new HashMap<Integer, SoftReference<BitmapDrawable>>();
-
- /* Shortcut key and its icons if available */
- private final Key mShortcutKey;
- private final Drawable mEnabledShortcutIcon;
- private final Drawable mDisabledShortcutIcon;
-
- // Minimum width of spacebar dragging to trigger the language switch (represented by the number
- // of the most common key width of this keyboard).
- private static final int SPACEBAR_DRAG_WIDTH = 3;
- // Minimum width of space key preview (proportional to keyboard width).
- private static final float SPACEBAR_POPUP_MIN_RATIO = 0.5f;
- // Height in space key the language name will be drawn. (proportional to space key height)
- public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
- // If the full language name needs to be smaller than this value to be drawn on space key,
- // its short language name will be used instead.
- private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
-
- private static final String SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "small";
- private static final String MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "medium";
-
- public LatinKeyboard(Context context, KeyboardId id, int width) {
- super(context, id.getXmlId(), id, width);
- mRes = context.getResources();
- mTheme = context.getTheme();
-
- final List<Key> keys = getKeys();
- int spaceKeyIndex = -1;
- int shortcutKeyIndex = -1;
- final int keyCount = keys.size();
- for (int index = 0; index < keyCount; index++) {
- // For now, assuming there are up to one space key and one shortcut key respectively.
- switch (keys.get(index).mCode) {
- case CODE_SPACE:
- spaceKeyIndex = index;
- break;
- case CODE_SHORTCUT:
- shortcutKeyIndex = index;
- break;
- }
- }
-
- // The index of space key is available only after Keyboard constructor has finished.
- mSpaceKey = (spaceKeyIndex >= 0) ? keys.get(spaceKeyIndex) : null;
- mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon() : null;
- mSpacePreviewIcon = (mSpaceKey != null) ? mSpaceKey.getPreviewIcon() : null;
- mSpaceKeyIndex = spaceKeyIndex;
-
- mShortcutKey = (shortcutKeyIndex >= 0) ? keys.get(shortcutKeyIndex) : null;
- mEnabledShortcutIcon = (mShortcutKey != null) ? mShortcutKey.getIcon() : null;
-
- final TypedArray a = context.obtainStyledAttributes(
- null, R.styleable.LatinKeyboard, R.attr.latinKeyboardStyle, R.style.LatinKeyboard);
- mAutoCorrectionSpacebarLedEnabled = a.getBoolean(
- R.styleable.LatinKeyboard_autoCorrectionSpacebarLedEnabled, false);
- mAutoCorrectionSpacebarLedIcon = a.getDrawable(
- R.styleable.LatinKeyboard_autoCorrectionSpacebarLedIcon);
- mDisabledShortcutIcon = a.getDrawable(R.styleable.LatinKeyboard_disabledShortcutIcon);
- mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboard_spacebarTextColor, 0);
- mSpacebarTextShadowColor = a.getColor(
- R.styleable.LatinKeyboard_spacebarTextShadowColor, 0);
- mSpacebarArrowLeftIcon = a.getDrawable(
- R.styleable.LatinKeyboard_spacebarArrowLeftIcon);
- mSpacebarArrowRightIcon = a.getDrawable(
- R.styleable.LatinKeyboard_spacebarArrowRightIcon);
- a.recycle();
-
- // The threshold is "key width" x 1.25
- mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 5) / 4;
-
- if (mSpaceKey != null && mSpacePreviewIcon != null) {
- final int slidingIconWidth = Math.max(mSpaceKey.mWidth,
- (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
- final int spaceKeyheight = mSpacePreviewIcon.getIntrinsicHeight();
- mSlidingLocaleIcon = new SlidingLocaleDrawable(
- context, mSpacePreviewIcon, slidingIconWidth, spaceKeyheight);
- mSlidingLocaleIcon.setBounds(0, 0, slidingIconWidth, spaceKeyheight);
- } else {
- mSlidingLocaleIcon = null;
- }
- }
-
- public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) {
- mSpacebarTextFadeFactor = fadeFactor;
- updateSpacebarForLocale(false);
- if (view != null)
- view.invalidateKey(mSpaceKey);
- }
-
- private static int getSpacebarTextColor(int color, float fadeFactor) {
- final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor),
- Color.red(color), Color.green(color), Color.blue(color));
- return newColor;
- }
-
- private static ColorFilter getSpacebarDrawableFilter(float fadeFactor) {
- final ColorMatrix colorMatrix = new ColorMatrix();
- colorMatrix.setScale(1, 1, 1, fadeFactor);
- return new ColorMatrixColorFilter(colorMatrix);
- }
-
- public void updateShortcutKey(boolean available, LatinKeyboardView view) {
- if (mShortcutKey == null)
- return;
- mShortcutKey.setEnabled(available);
- mShortcutKey.setIcon(available ? mEnabledShortcutIcon : mDisabledShortcutIcon);
- if (view != null)
- view.invalidateKey(mShortcutKey);
- }
-
- public boolean needsAutoCorrectionSpacebarLed() {
- return mAutoCorrectionSpacebarLedEnabled;
- }
-
- /**
- * @return a key which should be invalidated.
- */
- public Key onAutoCorrectionStateChanged(boolean isAutoCorrection) {
- updateSpacebarForLocale(isAutoCorrection);
- return mSpaceKey;
- }
-
- private void updateSpacebarForLocale(boolean isAutoCorrection) {
- if (mSpaceKey == null)
- return;
- // If application locales are explicitly selected.
- if (mSubtypeSwitcher.needsToDisplayLanguage()) {
- mSpaceKey.setIcon(getSpaceDrawable(
- mSubtypeSwitcher.getInputLocale(), isAutoCorrection));
- } else if (isAutoCorrection) {
- mSpaceKey.setIcon(getSpaceDrawable(null, true));
- } else {
- mSpaceKey.setIcon(mSpaceIcon);
- }
- }
-
- // Compute width of text with specified text size using paint.
- private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) {
- paint.setTextSize(textSize);
- paint.getTextBounds(text, 0, text.length(), bounds);
- return bounds.width();
- }
-
- // Layout local language name and left and right arrow on spacebar.
- private static String layoutSpacebar(Paint paint, Locale locale, Drawable icon, Drawable lArrow,
- Drawable rArrow, int width, int height, float origTextSize) {
- final float arrowWidth;
- if (lArrow != null && rArrow != null) {
- arrowWidth = lArrow.getIntrinsicWidth();
- } else {
- arrowWidth = 0;
- }
- final float maxTextWidth = width - (arrowWidth + arrowWidth);
- final Rect bounds = new Rect();
-
- // Estimate appropriate language name text size to fit in maxTextWidth.
- String language = SubtypeSwitcher.getFullDisplayName(locale, true);
- int textWidth = getTextWidth(paint, language, origTextSize, bounds);
- // Assuming text width and text size are proportional to each other.
- float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
- // allow variable text size
- textWidth = getTextWidth(paint, language, textSize, bounds);
- // If text size goes too small or text does not fit, use middle or short name
- final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
- || (textWidth > maxTextWidth);
-
- final boolean useShortName;
- if (useMiddleName) {
- language = SubtypeSwitcher.getMiddleDisplayLanguage(locale);
- textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
- useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME)
- || (textWidth > maxTextWidth);
- } else {
- useShortName = false;
- }
-
- if (useShortName) {
- language = SubtypeSwitcher.getShortDisplayLanguage(locale);
- textWidth = getTextWidth(paint, language, origTextSize, bounds);
- textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f);
- }
- paint.setTextSize(textSize);
-
- // Place left and right arrow just before and after language text.
- if (lArrow != null && rArrow != null) {
- final float textHeight = -paint.ascent() + paint.descent();
- final float baseline = (icon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
- : height / 2 + textHeight / 2;
- final int arrowHeight = lArrow.getIntrinsicHeight();
- final int top = (int)(baseline - arrowHeight);
- final float remains = (width - textWidth) / 2;
- lArrow.setBounds((int)(remains - arrowWidth), top, (int)remains, (int)baseline);
- rArrow.setBounds((int)(remains + textWidth), top,
- (int)(remains + textWidth + arrowWidth), (int)baseline);
- }
-
- return language;
- }
-
- private BitmapDrawable getSpaceDrawable(Locale locale, boolean isAutoCorrection) {
- final Integer hashCode = Arrays.hashCode(
- new Object[] { locale, isAutoCorrection, mSpacebarTextFadeFactor });
- final SoftReference<BitmapDrawable> ref = mSpaceDrawableCache.get(hashCode);
- BitmapDrawable drawable = (ref == null) ? null : ref.get();
- if (drawable == null) {
- drawable = new BitmapDrawable(mRes, drawSpacebar(
- locale, isAutoCorrection, mSpacebarTextFadeFactor));
- mSpaceDrawableCache.put(hashCode, new SoftReference<BitmapDrawable>(drawable));
- }
- return drawable;
- }
-
- private Bitmap drawSpacebar(Locale inputLocale, boolean isAutoCorrection,
- float textFadeFactor) {
- final int width = mSpaceKey.mWidth;
- final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
- final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(buffer);
- final Resources res = mRes;
- canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
-
- // If application locales are explicitly selected.
- if (inputLocale != null) {
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setTextAlign(Align.CENTER);
-
- final String textSizeOfLanguageOnSpacebar = res.getString(
- R.string.config_text_size_of_language_on_spacebar,
- SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR);
- final int textStyle;
- final int defaultTextSize;
- if (MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR.equals(textSizeOfLanguageOnSpacebar)) {
- textStyle = android.R.style.TextAppearance_Medium;
- defaultTextSize = 18;
- } else {
- textStyle = android.R.style.TextAppearance_Small;
- defaultTextSize = 14;
- }
-
- final String language = layoutSpacebar(paint, inputLocale, mSpaceIcon,
- mSpacebarArrowLeftIcon, mSpacebarArrowRightIcon, width, height,
- getTextSizeFromTheme(mTheme, textStyle, defaultTextSize));
-
- // Draw language text with shadow
- // In case there is no space icon, we will place the language text at the center of
- // spacebar.
- final float descent = paint.descent();
- final float textHeight = -paint.ascent() + descent;
- final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
- : height / 2 + textHeight / 2;
- paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, textFadeFactor));
- canvas.drawText(language, width / 2, baseline - descent - 1, paint);
- paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor));
- canvas.drawText(language, width / 2, baseline - descent, paint);
-
- // Put arrows that are already laid out on either side of the text
- // Because language switch is disabled on phone and number layouts, hide arrows.
- // TODO: Sort out how to enable language switch on these layouts.
- if (mSpacebarArrowLeftIcon != null && mSpacebarArrowRightIcon != null
- && mSubtypeSwitcher.useSpacebarLanguageSwitcher()
- && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1
- && !(isPhoneKeyboard() || isNumberKeyboard())) {
- mSpacebarArrowLeftIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor));
- mSpacebarArrowRightIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor));
- mSpacebarArrowLeftIcon.draw(canvas);
- mSpacebarArrowRightIcon.draw(canvas);
- }
- }
-
- // Draw the spacebar icon at the bottom
- if (isAutoCorrection) {
- final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100;
- final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight();
- int x = (width - iconWidth) / 2;
- int y = height - iconHeight;
- mAutoCorrectionSpacebarLedIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
- mAutoCorrectionSpacebarLedIcon.draw(canvas);
- } else if (mSpaceIcon != null) {
- final int iconWidth = mSpaceIcon.getIntrinsicWidth();
- final int iconHeight = mSpaceIcon.getIntrinsicHeight();
- int x = (width - iconWidth) / 2;
- int y = height - iconHeight;
- mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight);
- mSpaceIcon.draw(canvas);
- }
- return buffer;
- }
-
- public void setSpacebarSlidingLanguageSwitchDiff(int diff) {
- mSpacebarSlidingLanguageSwitchDiff = diff;
- }
-
- public void updateSpacebarPreviewIcon(int diff) {
- if (mSpacebarSlidingLanguageSwitchDiff == diff)
- return;
- mSpacebarSlidingLanguageSwitchDiff = diff;
- if (mSlidingLocaleIcon == null)
- return;
- mSlidingLocaleIcon.setDiff(diff);
- if (Math.abs(diff) == Integer.MAX_VALUE) {
- mSpaceKey.setPreviewIcon(mSpacePreviewIcon);
- } else {
- mSpaceKey.setPreviewIcon(mSlidingLocaleIcon);
- }
- mSpaceKey.getPreviewIcon().invalidateSelf();
- }
-
- public boolean shouldTriggerSpacebarSlidingLanguageSwitch(int diff) {
- // On phone and number layouts, sliding language switch is disabled.
- // TODO: Sort out how to enable language switch on these layouts.
- if (isPhoneKeyboard() || isNumberKeyboard())
- return false;
- return Math.abs(diff) > mSpacebarLanguageSwitchThreshold;
- }
-
- /**
- * Return true if spacebar needs showing preview even when "popup on keypress" is off.
- * @param keyIndex index of the pressing key
- * @return true if spacebar needs showing preview
- */
- @Override
- public boolean needSpacebarPreview(int keyIndex) {
- // This method is called when "popup on keypress" is off.
- if (!mSubtypeSwitcher.useSpacebarLanguageSwitcher())
- return false;
- // Dismiss key preview.
- if (keyIndex == KeyDetector.NOT_A_KEY)
- return true;
- // Key is not a spacebar.
- if (keyIndex != mSpaceKeyIndex)
- return false;
- // The language switcher will be displayed only when the dragging distance is greater
- // than the threshold.
- return shouldTriggerSpacebarSlidingLanguageSwitch(mSpacebarSlidingLanguageSwitchDiff);
- }
-
- public int getLanguageChangeDirection() {
- if (mSpaceKey == null || mSubtypeSwitcher.getEnabledKeyboardLocaleCount() <= 1
- || Math.abs(mSpacebarSlidingLanguageSwitchDiff)
- < getMostCommonKeyWidth() * SPACEBAR_DRAG_WIDTH) {
- return 0; // No change
- }
- return mSpacebarSlidingLanguageSwitchDiff > 0 ? 1 : -1;
- }
-
- @Override
- public int[] getNearestKeys(int x, int y) {
- // Avoid dead pixels at edges of the keyboard
- return super.getNearestKeys(Math.max(0, Math.min(x, getMinWidth() - 1)),
- Math.max(0, Math.min(y, getHeight() - 1)));
- }
-
- public static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
- TypedArray array = theme.obtainStyledAttributes(
- style, new int[] { android.R.attr.textSize });
- int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
- return textSize;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 901df6ab7..383298de9 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -1,223 +1,806 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * 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
+ * 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.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package com.android.inputmethod.keyboard;
+import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.PopupWindow;
-import com.android.inputmethod.deprecated.VoiceProxy;
+import com.android.inputmethod.accessibility.AccessibilityUtils;
+import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
+import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
+import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.ResearchLogger;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SubtypeLocale;
import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
+import com.android.inputmethod.latin.define.ProductionFlag;
-// TODO: We should remove this class
-public class LatinKeyboardView extends KeyboardView {
+import java.util.Locale;
+import java.util.WeakHashMap;
+
+/**
+ * A view that is responsible for detecting key presses and touch movements.
+ *
+ * @attr ref R.styleable#KeyboardView_keyHysteresisDistance
+ * @attr ref R.styleable#KeyboardView_verticalCorrection
+ * @attr ref R.styleable#KeyboardView_popupLayout
+ */
+public class LatinKeyboardView extends KeyboardView implements PointerTracker.KeyEventHandler,
+ SuddenJumpingTouchEventHandler.ProcessMotionEvent {
private static final String TAG = LatinKeyboardView.class.getSimpleName();
- private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
- /** Whether we've started dropping move events because we found a big jump */
- private boolean mDroppingEvents;
- /**
- * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has
- * occured
- */
- private boolean mDisableDisambiguation;
- /** The distance threshold at which we start treating the touch session as a multi-touch */
- private int mJumpThresholdSquare = Integer.MAX_VALUE;
- /** The y coordinate of the last row */
- private int mLastRowY;
- private int mLastX;
- private int mLastY;
+ // TODO: Kill process when the usability study mode was changed.
+ private static final boolean ENABLE_USABILITY_STUDY_LOG = LatinImeLogger.sUsabilityStudy;
+
+ /** Listener for {@link KeyboardActionListener}. */
+ private KeyboardActionListener mKeyboardActionListener;
+
+ /* Space key and its icons */
+ private Key mSpaceKey;
+ private Drawable mSpaceIcon;
+ // Stuff to draw language name on spacebar.
+ private final int mLanguageOnSpacebarFinalAlpha;
+ private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator;
+ private static final int ALPHA_OPAQUE = 255;
+ private boolean mNeedsToDisplayLanguage;
+ private boolean mHasMultipleEnabledIMEsOrSubtypes;
+ private int mLanguageOnSpacebarAnimAlpha = ALPHA_OPAQUE;
+ private final float mSpacebarTextRatio;
+ private float mSpacebarTextSize;
+ private final int mSpacebarTextColor;
+ private final int mSpacebarTextShadowColor;
+ // The minimum x-scale to fit the language name on spacebar.
+ private static final float MINIMUM_XSCALE_OF_LANGUAGE_NAME = 0.8f;
+ // Stuff to draw auto correction LED on spacebar.
+ private boolean mAutoCorrectionSpacebarLedOn;
+ private final boolean mAutoCorrectionSpacebarLedEnabled;
+ private final Drawable mAutoCorrectionSpacebarLedIcon;
+ private static final int SPACE_LED_LENGTH_PERCENT = 80;
+
+ // Stuff to draw altCodeWhileTyping keys.
+ private ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator;
+ private ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator;
+ private int mAltCodeKeyWhileTypingAnimAlpha = ALPHA_OPAQUE;
+
+ // More keys keyboard
+ private PopupWindow mMoreKeysWindow;
+ private MoreKeysPanel mMoreKeysPanel;
+ private int mMoreKeysPanelPointerTrackerId;
+ private final WeakHashMap<Key, MoreKeysPanel> mMoreKeysPanelCache =
+ new WeakHashMap<Key, MoreKeysPanel>();
+ private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint;
+
+ private final PointerTrackerParams mPointerTrackerParams;
+ private final SuddenJumpingTouchEventHandler mTouchScreenRegulator;
+
+ protected KeyDetector mKeyDetector;
+ private boolean mHasDistinctMultitouch;
+ private int mOldPointerCount = 1;
+ private Key mOldKey;
+
+ private final KeyTimerHandler mKeyTimerHandler;
+
+ private static class KeyTimerHandler extends StaticInnerHandlerWrapper<LatinKeyboardView>
+ implements TimerProxy {
+ private static final int MSG_REPEAT_KEY = 1;
+ private static final int MSG_LONGPRESS_KEY = 2;
+ private static final int MSG_DOUBLE_TAP = 3;
+ private static final int MSG_TYPING_STATE_EXPIRED = 4;
+
+ private final KeyTimerParams mParams;
+ private boolean mInKeyRepeat;
+
+ public KeyTimerHandler(LatinKeyboardView outerInstance, KeyTimerParams params) {
+ super(outerInstance);
+ mParams = params;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final LatinKeyboardView keyboardView = getOuterInstance();
+ final PointerTracker tracker = (PointerTracker) msg.obj;
+ switch (msg.what) {
+ case MSG_REPEAT_KEY:
+ tracker.onRegisterKey(tracker.getKey());
+ startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+ break;
+ case MSG_LONGPRESS_KEY:
+ if (tracker != null) {
+ keyboardView.openMoreKeysKeyboardIfRequired(tracker.getKey(), tracker);
+ } else {
+ KeyboardSwitcher.getInstance().onLongPressTimeout(msg.arg1);
+ }
+ break;
+ case MSG_TYPING_STATE_EXPIRED:
+ cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator,
+ keyboardView.mAltCodeKeyWhileTypingFadeinAnimator);
+ break;
+ }
+ }
+
+ private void startKeyRepeatTimer(PointerTracker tracker, long delay) {
+ sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay);
+ }
+
+ @Override
+ public void startKeyRepeatTimer(PointerTracker tracker) {
+ mInKeyRepeat = true;
+ startKeyRepeatTimer(tracker, mParams.mKeyRepeatStartTimeout);
+ }
+
+ public void cancelKeyRepeatTimer() {
+ mInKeyRepeat = false;
+ removeMessages(MSG_REPEAT_KEY);
+ }
+
+ public boolean isInKeyRepeat() {
+ return mInKeyRepeat;
+ }
+
+ @Override
+ public void startLongPressTimer(int code) {
+ cancelLongPressTimer();
+ final int delay;
+ switch (code) {
+ case Keyboard.CODE_SHIFT:
+ delay = mParams.mLongPressShiftKeyTimeout;
+ break;
+ default:
+ delay = 0;
+ break;
+ }
+ if (delay > 0) {
+ sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, code, 0), delay);
+ }
+ }
+
+ @Override
+ public void startLongPressTimer(PointerTracker tracker) {
+ cancelLongPressTimer();
+ if (tracker == null) {
+ return;
+ }
+ final Key key = tracker.getKey();
+ final int delay;
+ switch (key.mCode) {
+ case Keyboard.CODE_SHIFT:
+ delay = mParams.mLongPressShiftKeyTimeout;
+ break;
+ default:
+ if (KeyboardSwitcher.getInstance().isInMomentarySwitchState()) {
+ // We use longer timeout for sliding finger input started from the symbols
+ // mode key.
+ delay = mParams.mLongPressKeyTimeout * 3;
+ } else {
+ delay = mParams.mLongPressKeyTimeout;
+ }
+ break;
+ }
+ if (delay > 0) {
+ sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay);
+ }
+ }
+
+ @Override
+ public void cancelLongPressTimer() {
+ removeMessages(MSG_LONGPRESS_KEY);
+ }
+
+ public static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel,
+ final ObjectAnimator animatorToStart) {
+ float startFraction = 0.0f;
+ if (animatorToCancel.isStarted()) {
+ animatorToCancel.cancel();
+ startFraction = 1.0f - animatorToCancel.getAnimatedFraction();
+ }
+ final long startTime = (long)(animatorToStart.getDuration() * startFraction);
+ animatorToStart.start();
+ animatorToStart.setCurrentPlayTime(startTime);
+ }
+
+ @Override
+ public void startTypingStateTimer() {
+ final boolean isTyping = isTypingState();
+ removeMessages(MSG_TYPING_STATE_EXPIRED);
+ sendMessageDelayed(
+ obtainMessage(MSG_TYPING_STATE_EXPIRED), mParams.mIgnoreAltCodeKeyTimeout);
+ if (isTyping) {
+ return;
+ }
+ final LatinKeyboardView keyboardView = getOuterInstance();
+ cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeinAnimator,
+ keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator);
+ }
+
+ @Override
+ public boolean isTypingState() {
+ return hasMessages(MSG_TYPING_STATE_EXPIRED);
+ }
+
+ @Override
+ public void startDoubleTapTimer() {
+ sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP),
+ ViewConfiguration.getDoubleTapTimeout());
+ }
+
+ @Override
+ public void cancelDoubleTapTimer() {
+ removeMessages(MSG_DOUBLE_TAP);
+ }
+
+ @Override
+ public boolean isInDoubleTapTimeout() {
+ return hasMessages(MSG_DOUBLE_TAP);
+ }
+
+ @Override
+ public void cancelKeyTimers() {
+ cancelKeyRepeatTimer();
+ cancelLongPressTimer();
+ }
+
+ public void cancelAllMessages() {
+ cancelKeyTimers();
+ }
+ }
+
+ public static class PointerTrackerParams {
+ public final boolean mSlidingKeyInputEnabled;
+ public final int mTouchNoiseThresholdTime;
+ public final float mTouchNoiseThresholdDistance;
+
+ public static final PointerTrackerParams DEFAULT = new PointerTrackerParams();
+
+ private PointerTrackerParams() {
+ mSlidingKeyInputEnabled = false;
+ mTouchNoiseThresholdTime =0;
+ mTouchNoiseThresholdDistance = 0;
+ }
+
+ public PointerTrackerParams(TypedArray latinKeyboardViewAttr) {
+ mSlidingKeyInputEnabled = latinKeyboardViewAttr.getBoolean(
+ R.styleable.LatinKeyboardView_slidingKeyInputEnable, false);
+ mTouchNoiseThresholdTime = latinKeyboardViewAttr.getInt(
+ R.styleable.LatinKeyboardView_touchNoiseThresholdTime, 0);
+ mTouchNoiseThresholdDistance = latinKeyboardViewAttr.getDimension(
+ R.styleable.LatinKeyboardView_touchNoiseThresholdDistance, 0);
+ }
+ }
+
+ static class KeyTimerParams {
+ public final int mKeyRepeatStartTimeout;
+ public final int mKeyRepeatInterval;
+ public final int mLongPressKeyTimeout;
+ public final int mLongPressShiftKeyTimeout;
+ public final int mIgnoreAltCodeKeyTimeout;
+
+ public KeyTimerParams(TypedArray latinKeyboardViewAttr) {
+ mKeyRepeatStartTimeout = latinKeyboardViewAttr.getInt(
+ R.styleable.LatinKeyboardView_keyRepeatStartTimeout, 0);
+ mKeyRepeatInterval = latinKeyboardViewAttr.getInt(
+ R.styleable.LatinKeyboardView_keyRepeatInterval, 0);
+ mLongPressKeyTimeout = latinKeyboardViewAttr.getInt(
+ R.styleable.LatinKeyboardView_longPressKeyTimeout, 0);
+ mLongPressShiftKeyTimeout = latinKeyboardViewAttr.getInt(
+ R.styleable.LatinKeyboardView_longPressShiftKeyTimeout, 0);
+ mIgnoreAltCodeKeyTimeout = latinKeyboardViewAttr.getInt(
+ R.styleable.LatinKeyboardView_ignoreAltCodeKeyTimeout, 0);
+ }
+ }
public LatinKeyboardView(Context context, AttributeSet attrs) {
- super(context, attrs);
+ this(context, attrs, R.attr.latinKeyboardViewStyle);
}
public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+
+ mTouchScreenRegulator = new SuddenJumpingTouchEventHandler(getContext(), this);
+
+ mHasDistinctMultitouch = context.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
+ final boolean needsPhantomSuddenMoveEventHack = Boolean.parseBoolean(
+ Utils.getDeviceOverrideValue(context.getResources(),
+ R.array.phantom_sudden_move_event_device_list, "false"));
+ PointerTracker.init(mHasDistinctMultitouch, needsPhantomSuddenMoveEventHack);
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.LatinKeyboardView, defStyle, R.style.LatinKeyboardView);
+ mAutoCorrectionSpacebarLedEnabled = a.getBoolean(
+ R.styleable.LatinKeyboardView_autoCorrectionSpacebarLedEnabled, false);
+ mAutoCorrectionSpacebarLedIcon = a.getDrawable(
+ R.styleable.LatinKeyboardView_autoCorrectionSpacebarLedIcon);
+ mSpacebarTextRatio = a.getFraction(R.styleable.LatinKeyboardView_spacebarTextRatio,
+ 1000, 1000, 1) / 1000.0f;
+ mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboardView_spacebarTextColor, 0);
+ mSpacebarTextShadowColor = a.getColor(
+ R.styleable.LatinKeyboardView_spacebarTextShadowColor, 0);
+ mLanguageOnSpacebarFinalAlpha = a.getInt(
+ R.styleable.LatinKeyboardView_languageOnSpacebarFinalAlpha, ALPHA_OPAQUE);
+ final int languageOnSpacebarFadeoutAnimatorResId = a.getResourceId(
+ R.styleable.LatinKeyboardView_languageOnSpacebarFadeoutAnimator, 0);
+ final int altCodeKeyWhileTypingFadeoutAnimatorResId = a.getResourceId(
+ R.styleable.LatinKeyboardView_altCodeKeyWhileTypingFadeoutAnimator, 0);
+ final int altCodeKeyWhileTypingFadeinAnimatorResId = a.getResourceId(
+ R.styleable.LatinKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0);
+
+ final KeyTimerParams keyTimerParams = new KeyTimerParams(a);
+ mPointerTrackerParams = new PointerTrackerParams(a);
+
+ final float keyHysteresisDistance = a.getDimension(
+ R.styleable.LatinKeyboardView_keyHysteresisDistance, 0);
+ mKeyDetector = new KeyDetector(keyHysteresisDistance);
+ mKeyTimerHandler = new KeyTimerHandler(this, keyTimerParams);
+ mConfigShowMoreKeysKeyboardAtTouchedPoint = a.getBoolean(
+ R.styleable.LatinKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false);
+ a.recycle();
+
+ PointerTracker.setParameters(mPointerTrackerParams);
+
+ mLanguageOnSpacebarFadeoutAnimator = loadObjectAnimator(
+ languageOnSpacebarFadeoutAnimatorResId, this);
+ mAltCodeKeyWhileTypingFadeoutAnimator = loadObjectAnimator(
+ altCodeKeyWhileTypingFadeoutAnimatorResId, this);
+ mAltCodeKeyWhileTypingFadeinAnimator = loadObjectAnimator(
+ altCodeKeyWhileTypingFadeinAnimatorResId, this);
}
- @Override
- public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null
- && (latinKeyboard.isPhoneKeyboard() || latinKeyboard.isNumberKeyboard())) {
- // Phone and number keyboard never shows popup preview (except language switch).
- super.setKeyPreviewPopupEnabled(false, delay);
- } else {
- super.setKeyPreviewPopupEnabled(previewEnabled, delay);
+ private ObjectAnimator loadObjectAnimator(int resId, Object target) {
+ if (resId == 0) return null;
+ final ObjectAnimator animator = (ObjectAnimator)AnimatorInflater.loadAnimator(
+ getContext(), resId);
+ if (animator != null) {
+ animator.setTarget(target);
}
+ return animator;
+ }
+
+ // Getter/setter methods for {@link ObjectAnimator}.
+ public int getLanguageOnSpacebarAnimAlpha() {
+ return mLanguageOnSpacebarAnimAlpha;
+ }
+
+ public void setLanguageOnSpacebarAnimAlpha(int alpha) {
+ mLanguageOnSpacebarAnimAlpha = alpha;
+ invalidateKey(mSpaceKey);
+ }
+
+ public int getAltCodeKeyWhileTypingAnimAlpha() {
+ return mAltCodeKeyWhileTypingAnimAlpha;
}
+ public void setAltCodeKeyWhileTypingAnimAlpha(int alpha) {
+ mAltCodeKeyWhileTypingAnimAlpha = alpha;
+ updateAltCodeKeyWhileTyping();
+ }
+
+ public void setKeyboardActionListener(KeyboardActionListener listener) {
+ mKeyboardActionListener = listener;
+ PointerTracker.setKeyboardActionListener(listener);
+ }
+
+ /**
+ * Returns the {@link KeyboardActionListener} object.
+ * @return the listener attached to this keyboard
+ */
@Override
- public void setKeyboard(Keyboard newKeyboard) {
- super.setKeyboard(newKeyboard);
- // One-seventh of the keyboard width seems like a reasonable threshold
- mJumpThresholdSquare = newKeyboard.getMinWidth() / 7;
- mJumpThresholdSquare *= mJumpThresholdSquare;
- // Assuming there are 4 rows, this is the coordinate of the last row
- mLastRowY = (newKeyboard.getHeight() * 3) / 4;
- }
-
- private LatinKeyboard getLatinKeyboard() {
- Keyboard keyboard = getKeyboard();
- if (keyboard instanceof LatinKeyboard) {
- return (LatinKeyboard)keyboard;
- } else {
- return null;
- }
+ public KeyboardActionListener getKeyboardActionListener() {
+ return mKeyboardActionListener;
}
- public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboard oldKeyboard) {
- final LatinKeyboard currentKeyboard = getLatinKeyboard();
- // We should not set text fade factor to the keyboard which does not display the language on
- // its spacebar.
- if (currentKeyboard != null && currentKeyboard == oldKeyboard)
- currentKeyboard.setSpacebarTextFadeFactor(fadeFactor, this);
+ @Override
+ public KeyDetector getKeyDetector() {
+ return mKeyDetector;
}
@Override
- protected boolean onLongPress(Key key, PointerTracker tracker) {
- int primaryCode = key.mCode;
- if (primaryCode == Keyboard.CODE_SETTINGS) {
- return invokeOnKey(Keyboard.CODE_SETTINGS_LONGPRESS);
- } else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
- // Long pressing on 0 in phone number keypad gives you a '+'.
- return invokeOnKey('+');
- } else {
- return super.onLongPress(key, tracker);
- }
+ public DrawingProxy getDrawingProxy() {
+ return this;
}
- private boolean invokeOnKey(int primaryCode) {
- getOnKeyboardActionListener().onCodeInput(primaryCode, null,
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
- return true;
+ @Override
+ public TimerProxy getTimerProxy() {
+ return mKeyTimerHandler;
}
+ /**
+ * Attaches a keyboard to this view. The keyboard can be switched at any time and the
+ * view will re-layout itself to accommodate the keyboard.
+ * @see Keyboard
+ * @see #getKeyboard()
+ * @param keyboard the keyboard to display in this view
+ */
@Override
- protected CharSequence adjustCase(CharSequence label) {
- LatinKeyboard keyboard = getLatinKeyboard();
- if (keyboard.isAlphaKeyboard()
- && keyboard.isShiftedOrShiftLocked()
- && !TextUtils.isEmpty(label) && label.length() < 3
- && Character.isLowerCase(label.charAt(0))) {
- return label.toString().toUpperCase(keyboard.mId.mLocale);
+ public void setKeyboard(Keyboard keyboard) {
+ // Remove any pending messages, except dismissing preview
+ mKeyTimerHandler.cancelKeyTimers();
+ super.setKeyboard(keyboard);
+ mKeyDetector.setKeyboard(
+ keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
+ PointerTracker.setKeyDetector(mKeyDetector);
+ mTouchScreenRegulator.setKeyboard(keyboard);
+ mMoreKeysPanelCache.clear();
+
+ mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE);
+ mSpaceIcon = (mSpaceKey != null)
+ ? mSpaceKey.getIcon(keyboard.mIconsSet, ALPHA_OPAQUE) : null;
+ final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
+ mSpacebarTextSize = keyHeight * mSpacebarTextRatio;
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinKeyboardView_setKeyboard(keyboard);
}
- return label;
+
+ // This always needs to be set since the accessibility state can
+ // potentially change without the keyboard being set again.
+ AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard);
}
/**
- * This function checks to see if we need to handle any sudden jumps in the pointer location
- * that could be due to a multi-touch being treated as a move by the firmware or hardware.
- * Once a sudden jump is detected, all subsequent move events are discarded
- * until an UP is received.<P>
- * When a sudden jump is detected, an UP event is simulated at the last position and when
- * the sudden moves subside, a DOWN event is simulated for the second key.
- * @param me the motion event
- * @return true if the event was consumed, so that it doesn't continue to be handled by
- * KeyboardView.
+ * Returns whether the device has distinct multi-touch panel.
+ * @return true if the device has distinct multi-touch panel.
*/
- private boolean handleSuddenJump(MotionEvent me) {
- // If device has distinct multi touch panel, there is no need to check sudden jump.
- if (hasDistinctMultitouch())
+ public boolean hasDistinctMultitouch() {
+ return mHasDistinctMultitouch;
+ }
+
+ public void setDistinctMultitouch(boolean hasDistinctMultitouch) {
+ mHasDistinctMultitouch = hasDistinctMultitouch;
+ }
+
+ /**
+ * When enabled, calls to {@link KeyboardActionListener#onCodeInput} will include key
+ * codes for adjacent keys. When disabled, only the primary key code will be
+ * reported.
+ * @param enabled whether or not the proximity correction is enabled
+ */
+ public void setProximityCorrectionEnabled(boolean enabled) {
+ mKeyDetector.setProximityCorrectionEnabled(enabled);
+ }
+
+ /**
+ * Returns true if proximity correction is enabled.
+ */
+ public boolean isProximityCorrectionEnabled() {
+ return mKeyDetector.isProximityCorrectionEnabled();
+ }
+
+ @Override
+ public void cancelAllMessages() {
+ mKeyTimerHandler.cancelAllMessages();
+ super.cancelAllMessages();
+ }
+
+ private boolean openMoreKeysKeyboardIfRequired(Key parentKey, PointerTracker tracker) {
+ // Check if we have a popup layout specified first.
+ if (mMoreKeysLayout == 0) {
return false;
- final int action = me.getAction();
- final int x = (int) me.getX();
- final int y = (int) me.getY();
- boolean result = false;
-
- // Real multi-touch event? Stop looking for sudden jumps
- if (me.getPointerCount() > 1) {
- mDisableDisambiguation = true;
- }
- if (mDisableDisambiguation) {
- // If UP, reset the multi-touch flag
- if (action == MotionEvent.ACTION_UP) mDisableDisambiguation = false;
+ }
+
+ // Check if we are already displaying popup panel.
+ if (mMoreKeysPanel != null)
+ return false;
+ if (parentKey == null)
return false;
+ return onLongPress(parentKey, tracker);
+ }
+
+ // This default implementation returns a more keys panel.
+ protected MoreKeysPanel onCreateMoreKeysPanel(Key parentKey) {
+ if (parentKey.mMoreKeys == null)
+ return null;
+
+ final View container = LayoutInflater.from(getContext()).inflate(mMoreKeysLayout, null);
+ if (container == null)
+ throw new NullPointerException();
+
+ final MoreKeysKeyboardView moreKeysKeyboardView =
+ (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view);
+ final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder(container, parentKey, this)
+ .build();
+ moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
+ container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ return moreKeysKeyboardView;
+ }
+
+ /**
+ * Called when a key is long pressed. By default this will open more keys keyboard associated
+ * with this key.
+ * @param parentKey the key that was long pressed
+ * @param tracker the pointer tracker which pressed the parent key
+ * @return true if the long press is handled, false otherwise. Subclasses should call the
+ * method on the base class if the subclass doesn't wish to handle the call.
+ */
+ protected boolean onLongPress(Key parentKey, PointerTracker tracker) {
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinKeyboardView_onLongPress();
+ }
+ final int primaryCode = parentKey.mCode;
+ if (parentKey.hasEmbeddedMoreKey()) {
+ final int embeddedCode = parentKey.mMoreKeys[0].mCode;
+ tracker.onLongPressed();
+ invokeCodeInput(embeddedCode);
+ invokeReleaseKey(primaryCode);
+ KeyboardSwitcher.getInstance().hapticAndAudioFeedback(primaryCode);
+ return true;
+ }
+ if (primaryCode == Keyboard.CODE_SPACE || primaryCode == Keyboard.CODE_LANGUAGE_SWITCH) {
+ // Long pressing the space key invokes IME switcher dialog.
+ if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
+ tracker.onLongPressed();
+ invokeReleaseKey(primaryCode);
+ return true;
+ }
}
+ return openMoreKeysPanel(parentKey, tracker);
+ }
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Reset the "session"
- mDroppingEvents = false;
- mDisableDisambiguation = false;
- break;
- case MotionEvent.ACTION_MOVE:
- // Is this a big jump?
- final int distanceSquare = (mLastX - x) * (mLastX - x) + (mLastY - y) * (mLastY - y);
- // Check the distance and also if the move is not entirely within the bottom row
- // If it's only in the bottom row, it might be an intentional slide gesture
- // for language switching
- if (distanceSquare > mJumpThresholdSquare
- && (mLastY < mLastRowY || y < mLastRowY)) {
- // If we're not yet dropping events, start dropping and send an UP event
- if (!mDroppingEvents) {
- mDroppingEvents = true;
- // Send an up event
- MotionEvent translated = MotionEvent.obtain(
- me.getEventTime(), me.getEventTime(),
- MotionEvent.ACTION_UP,
- mLastX, mLastY, me.getMetaState());
- super.onTouchEvent(translated);
- translated.recycle();
- }
- result = true;
- } else if (mDroppingEvents) {
- // If moves are small and we're already dropping events, continue dropping
- result = true;
- }
- break;
- case MotionEvent.ACTION_UP:
- if (mDroppingEvents) {
- // Send a down event first, as we dropped a bunch of sudden jumps and assume that
- // the user is releasing the touch on the second key.
- MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
- MotionEvent.ACTION_DOWN,
- x, y, me.getMetaState());
- super.onTouchEvent(translated);
- translated.recycle();
- mDroppingEvents = false;
- // Let the up event get processed as well, result = false
- }
- break;
- }
- // Track the previous coordinate
- mLastX = x;
- mLastY = y;
- return result;
+ private boolean invokeCustomRequest(int code) {
+ return mKeyboardActionListener.onCustomRequest(code);
+ }
+
+ private void invokeCodeInput(int primaryCode) {
+ mKeyboardActionListener.onCodeInput(primaryCode,
+ KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
+ KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
+ }
+
+ private void invokeReleaseKey(int primaryCode) {
+ mKeyboardActionListener.onReleaseKey(primaryCode, false);
+ }
+
+ private boolean openMoreKeysPanel(Key parentKey, PointerTracker tracker) {
+ MoreKeysPanel moreKeysPanel = mMoreKeysPanelCache.get(parentKey);
+ if (moreKeysPanel == null) {
+ moreKeysPanel = onCreateMoreKeysPanel(parentKey);
+ if (moreKeysPanel == null)
+ return false;
+ mMoreKeysPanelCache.put(parentKey, moreKeysPanel);
+ }
+ if (mMoreKeysWindow == null) {
+ mMoreKeysWindow = new PopupWindow(getContext());
+ mMoreKeysWindow.setBackgroundDrawable(null);
+ mMoreKeysWindow.setAnimationStyle(R.style.MoreKeysKeyboardAnimation);
+ }
+ mMoreKeysPanel = moreKeysPanel;
+ mMoreKeysPanelPointerTrackerId = tracker.mPointerId;
+
+ final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !parentKey.noKeyPreview();
+ // The more keys keyboard is usually horizontally aligned with the center of the parent key.
+ // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more
+ // keys keyboard is placed at the touch point of the parent key.
+ final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled)
+ ? tracker.getLastX()
+ : parentKey.mX + parentKey.mWidth / 2;
+ // The more keys keyboard is usually vertically aligned with the top edge of the parent key
+ // (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically
+ // aligned with the bottom edge of the visible part of the key preview.
+ final int pointY = parentKey.mY + (keyPreviewEnabled
+ ? mKeyPreviewDrawParams.mPreviewVisibleOffset
+ : -parentKey.mVerticalGap);
+ moreKeysPanel.showMoreKeysPanel(
+ this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener);
+ final int translatedX = moreKeysPanel.translateX(tracker.getLastX());
+ final int translatedY = moreKeysPanel.translateY(tracker.getLastY());
+ tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel);
+ dimEntireKeyboard(true);
+ return true;
+ }
+
+ public boolean isInSlidingKeyInput() {
+ if (mMoreKeysPanel != null) {
+ return true;
+ } else {
+ return PointerTracker.isAnyInSlidingKeyInput();
+ }
+ }
+
+ public int getPointerCount() {
+ return mOldPointerCount;
}
@Override
public boolean onTouchEvent(MotionEvent me) {
- if (getLatinKeyboard() == null) return true;
+ if (getKeyboard() == null) {
+ return false;
+ }
+ return mTouchScreenRegulator.onTouchEvent(me);
+ }
+
+ @Override
+ public boolean processMotionEvent(MotionEvent me) {
+ final boolean nonDistinctMultitouch = !mHasDistinctMultitouch;
+ final int action = me.getActionMasked();
+ final int pointerCount = me.getPointerCount();
+ final int oldPointerCount = mOldPointerCount;
+ mOldPointerCount = pointerCount;
- // If there was a sudden jump, return without processing the actual motion event.
- if (handleSuddenJump(me)) {
- if (DEBUG_MODE)
- Log.w(TAG, "onTouchEvent: ignore sudden jump " + me);
+ // TODO: cleanup this code into a multi-touch to single-touch event converter class?
+ // If the device does not have distinct multi-touch support panel, ignore all multi-touch
+ // events except a transition from/to single-touch.
+ if (nonDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) {
return true;
}
- return super.onTouchEvent(me);
+ final long eventTime = me.getEventTime();
+ final int index = me.getActionIndex();
+ final int id = me.getPointerId(index);
+ final int x, y;
+ if (mMoreKeysPanel != null && id == mMoreKeysPanelPointerTrackerId) {
+ x = mMoreKeysPanel.translateX((int)me.getX(index));
+ y = mMoreKeysPanel.translateY((int)me.getY(index));
+ } else {
+ x = (int)me.getX(index);
+ y = (int)me.getY(index);
+ }
+ if (ENABLE_USABILITY_STUDY_LOG) {
+ final String eventTag;
+ switch (action) {
+ case MotionEvent.ACTION_UP:
+ eventTag = "[Up]";
+ break;
+ case MotionEvent.ACTION_DOWN:
+ eventTag = "[Down]";
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ eventTag = "[PointerUp]";
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ eventTag = "[PointerDown]";
+ break;
+ case MotionEvent.ACTION_MOVE: // Skip this as being logged below
+ eventTag = "";
+ break;
+ default:
+ eventTag = "[Action" + action + "]";
+ break;
+ }
+ if (!TextUtils.isEmpty(eventTag)) {
+ final float size = me.getSize(index);
+ final float pressure = me.getPressure(index);
+ UsabilityStudyLogUtils.getInstance().write(
+ eventTag + eventTime + "," + id + "," + x + "," + y + ","
+ + size + "," + pressure);
+ }
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, index, id,
+ x, y);
+ }
+
+ if (mKeyTimerHandler.isInKeyRepeat()) {
+ final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
+ // Key repeating timer will be canceled if 2 or more keys are in action, and current
+ // event (UP or DOWN) is non-modifier key.
+ if (pointerCount > 1 && !tracker.isModifier()) {
+ mKeyTimerHandler.cancelKeyRepeatTimer();
+ }
+ // Up event will pass through.
+ }
+
+ // TODO: cleanup this code into a multi-touch to single-touch event converter class?
+ // Translate mutli-touch event to single-touch events on the device that has no distinct
+ // multi-touch panel.
+ if (nonDistinctMultitouch) {
+ // Use only main (id=0) pointer tracker.
+ final PointerTracker tracker = PointerTracker.getPointerTracker(0, this);
+ if (pointerCount == 1 && oldPointerCount == 2) {
+ // Multi-touch to single touch transition.
+ // Send a down event for the latest pointer if the key is different from the
+ // previous key.
+ final Key newKey = tracker.getKeyOn(x, y);
+ if (mOldKey != newKey) {
+ tracker.onDownEvent(x, y, eventTime, this);
+ if (action == MotionEvent.ACTION_UP)
+ tracker.onUpEvent(x, y, eventTime);
+ }
+ } else if (pointerCount == 2 && oldPointerCount == 1) {
+ // Single-touch to multi-touch transition.
+ // Send an up event for the last pointer.
+ final int lastX = tracker.getLastX();
+ final int lastY = tracker.getLastY();
+ mOldKey = tracker.getKeyOn(lastX, lastY);
+ tracker.onUpEvent(lastX, lastY, eventTime);
+ } else if (pointerCount == 1 && oldPointerCount == 1) {
+ tracker.processMotionEvent(action, x, y, eventTime, this);
+ } else {
+ Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
+ + " (old " + oldPointerCount + ")");
+ }
+ return true;
+ }
+
+ if (action == MotionEvent.ACTION_MOVE) {
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = me.getPointerId(i);
+ final PointerTracker tracker = PointerTracker.getPointerTracker(
+ pointerId, this);
+ final int px, py;
+ if (mMoreKeysPanel != null
+ && tracker.mPointerId == mMoreKeysPanelPointerTrackerId) {
+ px = mMoreKeysPanel.translateX((int)me.getX(i));
+ py = mMoreKeysPanel.translateY((int)me.getY(i));
+ } else {
+ px = (int)me.getX(i);
+ py = (int)me.getY(i);
+ }
+ tracker.onMoveEvent(px, py, eventTime);
+ if (ENABLE_USABILITY_STUDY_LOG) {
+ final float pointerSize = me.getSize(i);
+ final float pointerPressure = me.getPressure(i);
+ UsabilityStudyLogUtils.getInstance().write("[Move]" + eventTime + ","
+ + pointerId + "," + px + "," + py + ","
+ + pointerSize + "," + pointerPressure);
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime,
+ i, pointerId, px, py);
+ }
+ }
+ } else {
+ final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
+ tracker.processMotionEvent(action, x, y, eventTime, this);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void closing() {
+ super.closing();
+ dismissMoreKeysPanel();
+ mMoreKeysPanelCache.clear();
+ }
+
+ @Override
+ public boolean dismissMoreKeysPanel() {
+ if (mMoreKeysWindow != null && mMoreKeysWindow.isShowing()) {
+ mMoreKeysWindow.dismiss();
+ mMoreKeysPanel = null;
+ mMoreKeysPanelPointerTrackerId = -1;
+ dimEntireKeyboard(false);
+ return true;
+ }
+ return false;
}
@Override
@@ -229,14 +812,206 @@ public class LatinKeyboardView extends KeyboardView {
super.draw(c);
tryGC = false;
} catch (OutOfMemoryError e) {
- tryGC = Utils.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e);
+ tryGC = Utils.GCUtils.getInstance().tryGCOrWait(TAG, e);
}
}
}
+ /**
+ * Receives hover events from the input framework.
+ *
+ * @param event The motion event to be dispatched.
+ * @return {@code true} if the event was handled by the view, {@code false}
+ * otherwise
+ */
@Override
- protected void onAttachedToWindow() {
- // Token is available from here.
- VoiceProxy.getInstance().onAttachedToWindow();
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
+ final PointerTracker tracker = PointerTracker.getPointerTracker(0, this);
+ return AccessibleKeyboardViewProxy.getInstance().dispatchHoverEvent(event, tracker);
+ }
+
+ // Reflection doesn't support calling superclass methods.
+ return false;
+ }
+
+ public void updateShortcutKey(boolean available) {
+ final Keyboard keyboard = getKeyboard();
+ if (keyboard == null) return;
+ final Key shortcutKey = keyboard.getKey(Keyboard.CODE_SHORTCUT);
+ if (shortcutKey == null) return;
+ shortcutKey.setEnabled(available);
+ invalidateKey(shortcutKey);
+ }
+
+ private void updateAltCodeKeyWhileTyping() {
+ final Keyboard keyboard = getKeyboard();
+ if (keyboard == null) return;
+ for (final Key key : keyboard.mAltCodeKeysWhileTyping) {
+ invalidateKey(key);
+ }
+ }
+
+ public void startDisplayLanguageOnSpacebar(boolean subtypeChanged,
+ boolean needsToDisplayLanguage, boolean hasMultipleEnabledIMEsOrSubtypes) {
+ mNeedsToDisplayLanguage = needsToDisplayLanguage;
+ mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes;
+ final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator;
+ if (animator == null) {
+ mNeedsToDisplayLanguage = false;
+ } else {
+ if (subtypeChanged && needsToDisplayLanguage) {
+ setLanguageOnSpacebarAnimAlpha(ALPHA_OPAQUE);
+ if (animator.isStarted()) {
+ animator.cancel();
+ }
+ animator.start();
+ } else {
+ if (!animator.isStarted()) {
+ mLanguageOnSpacebarAnimAlpha = mLanguageOnSpacebarFinalAlpha;
+ }
+ }
+ }
+ invalidateKey(mSpaceKey);
+ }
+
+ public void updateAutoCorrectionState(boolean isAutoCorrection) {
+ if (!mAutoCorrectionSpacebarLedEnabled) return;
+ mAutoCorrectionSpacebarLedOn = isAutoCorrection;
+ invalidateKey(mSpaceKey);
+ }
+
+ @Override
+ protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
+ if (key.altCodeWhileTyping() && key.isEnabled()) {
+ params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha;
+ }
+ if (key.mCode == Keyboard.CODE_SPACE) {
+ drawSpacebar(key, canvas, paint);
+ // Whether space key needs to show the "..." popup hint for special purposes
+ if (key.isLongPressEnabled() && mHasMultipleEnabledIMEsOrSubtypes) {
+ drawKeyPopupHint(key, canvas, paint, params);
+ }
+ } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) {
+ super.onDrawKeyTopVisuals(key, canvas, paint, params);
+ drawKeyPopupHint(key, canvas, paint, params);
+ } else {
+ super.onDrawKeyTopVisuals(key, canvas, paint, params);
+ }
+ }
+
+ private boolean fitsTextIntoWidth(final int width, String text, Paint paint) {
+ paint.setTextScaleX(1.0f);
+ final float textWidth = getLabelWidth(text, paint);
+ if (textWidth < width) return true;
+
+ final float scaleX = width / textWidth;
+ if (scaleX < MINIMUM_XSCALE_OF_LANGUAGE_NAME) return false;
+
+ paint.setTextScaleX(scaleX);
+ return getLabelWidth(text, paint) < width;
+ }
+
+ // Layout language name on spacebar.
+ private String layoutLanguageOnSpacebar(Paint paint, InputMethodSubtype subtype,
+ final int width) {
+ // Choose appropriate language name to fit into the width.
+ String text = getFullDisplayName(subtype, getResources());
+ if (fitsTextIntoWidth(width, text, paint)) {
+ return text;
+ }
+
+ text = getMiddleDisplayName(subtype);
+ if (fitsTextIntoWidth(width, text, paint)) {
+ return text;
+ }
+
+ text = getShortDisplayName(subtype);
+ if (fitsTextIntoWidth(width, text, paint)) {
+ return text;
+ }
+
+ return "";
+ }
+
+ private void drawSpacebar(Key key, Canvas canvas, Paint paint) {
+ final int width = key.mWidth;
+ final int height = key.mHeight;
+
+ // If input language are explicitly selected.
+ if (mNeedsToDisplayLanguage) {
+ paint.setTextAlign(Align.CENTER);
+ paint.setTypeface(Typeface.DEFAULT);
+ paint.setTextSize(mSpacebarTextSize);
+ final InputMethodSubtype subtype = getKeyboard().mId.mSubtype;
+ final String language = layoutLanguageOnSpacebar(paint, subtype, width);
+ // Draw language text with shadow
+ final float descent = paint.descent();
+ final float textHeight = -paint.ascent() + descent;
+ final float baseline = height / 2 + textHeight / 2;
+ paint.setColor(mSpacebarTextShadowColor);
+ paint.setAlpha(mLanguageOnSpacebarAnimAlpha);
+ canvas.drawText(language, width / 2, baseline - descent - 1, paint);
+ paint.setColor(mSpacebarTextColor);
+ paint.setAlpha(mLanguageOnSpacebarAnimAlpha);
+ canvas.drawText(language, width / 2, baseline - descent, paint);
+ }
+
+ // Draw the spacebar icon at the bottom
+ if (mAutoCorrectionSpacebarLedOn) {
+ final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100;
+ final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight();
+ int x = (width - iconWidth) / 2;
+ int y = height - iconHeight;
+ drawIcon(canvas, mAutoCorrectionSpacebarLedIcon, x, y, iconWidth, iconHeight);
+ } else if (mSpaceIcon != null) {
+ final int iconWidth = mSpaceIcon.getIntrinsicWidth();
+ final int iconHeight = mSpaceIcon.getIntrinsicHeight();
+ int x = (width - iconWidth) / 2;
+ int y = height - iconHeight;
+ drawIcon(canvas, mSpaceIcon, x, y, iconWidth, iconHeight);
+ }
+ }
+
+ // InputMethodSubtype's display name for spacebar text in its locale.
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | Short Middle Full
+ // ------ ------ - ---- --------- ----------------------
+ // en_US qwerty F En English English (US) exception
+ // en_GB qwerty F En English English (UK) exception
+ // fr azerty F Fr Français Français
+ // fr_CA qwerty F Fr Français Français (Canada)
+ // de qwertz F De Deutsch Deutsch
+ // zz qwerty F QWERTY QWERTY
+ // fr qwertz T Fr Français Français (QWERTZ)
+ // de qwerty T De Deutsch Deutsch (QWERTY)
+ // en_US azerty T En English English (US) (AZERTY)
+ // zz azerty T AZERTY AZERTY
+
+ // Get InputMethodSubtype's full display name in its locale.
+ static String getFullDisplayName(InputMethodSubtype subtype, Resources res) {
+ if (SubtypeLocale.isNoLanguage(subtype)) {
+ return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
+ }
+
+ return SubtypeLocale.getSubtypeDisplayName(subtype, res);
+ }
+
+ // Get InputMethodSubtype's short display name in its locale.
+ static String getShortDisplayName(InputMethodSubtype subtype) {
+ if (SubtypeLocale.isNoLanguage(subtype)) {
+ return "";
+ }
+ final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+ return StringUtils.toTitleCase(locale.getLanguage(), locale);
+ }
+
+ // Get InputMethodSubtype's middle display name in its locale.
+ static String getMiddleDisplayName(InputMethodSubtype subtype) {
+ if (SubtypeLocale.isNoLanguage(subtype)) {
+ return SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype);
+ }
+ final Locale locale = SubtypeLocale.getSubtypeLocale(subtype);
+ return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
deleted file mode 100644
index 2d6766f2d..000000000
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard;
-
-import android.content.Context;
-
-import java.util.List;
-
-public class MiniKeyboard extends Keyboard {
- private int mDefaultKeyCoordX;
-
- public MiniKeyboard(Context context, int xmlLayoutResId, Keyboard parentKeyboard) {
- super(context, xmlLayoutResId, null, parentKeyboard.getMinWidth());
- }
-
- public void setDefaultCoordX(int pos) {
- mDefaultKeyCoordX = pos;
- }
-
- public int getDefaultCoordX() {
- return mDefaultKeyCoordX;
- }
-
- public boolean isOneRowKeyboard() {
- final List<Key> keys = getKeys();
- if (keys.size() == 0) return false;
- final int edgeFlags = keys.get(0).mEdgeFlags;
- // HACK: The first key of mini keyboard which was inflated from xml and has multiple rows,
- // does not have both top and bottom edge flags on at the same time. On the other hand,
- // the first key of mini keyboard that was created with popupCharacters must have both top
- // and bottom edge flags on.
- // When you want to use one row mini-keyboard from xml file, make sure that the row has
- // both top and bottom edge flags set.
- return (edgeFlags & Keyboard.EDGE_TOP) != 0
- && (edgeFlags & Keyboard.EDGE_BOTTOM) != 0;
-
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
deleted file mode 100644
index cc5c3bbfe..000000000
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard;
-
-import java.util.List;
-
-public class MiniKeyboardKeyDetector extends KeyDetector {
- private final int mSlideAllowanceSquare;
- private final int mSlideAllowanceSquareTop;
-
- public MiniKeyboardKeyDetector(float slideAllowance) {
- super();
- mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance);
- // Top slide allowance is slightly longer (sqrt(2) times) than other edges.
- mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2;
- }
-
- @Override
- protected int getMaxNearbyKeys() {
- // No nearby key will be returned.
- return 1;
- }
-
- @Override
- public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
- final List<Key> keys = getKeys();
- final int touchX = getTouchX(x);
- final int touchY = getTouchY(y);
-
- int nearestIndex = NOT_A_KEY;
- int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
- final int keyCount = keys.size();
- for (int index = 0; index < keyCount; index++) {
- final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY);
- if (dist < nearestDist) {
- nearestIndex = index;
- nearestDist = dist;
- }
- }
-
- if (allCodes != null && nearestIndex != NOT_A_KEY)
- allCodes[0] = keys.get(nearestIndex).mCode;
- return nearestIndex;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
new file mode 100644
index 000000000..cd4e3001e
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+public class MoreKeysDetector extends KeyDetector {
+ private final int mSlideAllowanceSquare;
+ private final int mSlideAllowanceSquareTop;
+
+ public MoreKeysDetector(float slideAllowance) {
+ super(/* keyHysteresisDistance */0);
+ mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance);
+ // Top slide allowance is slightly longer (sqrt(2) times) than other edges.
+ mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2;
+ }
+
+ @Override
+ public boolean alwaysAllowsSlidingInput() {
+ return true;
+ }
+
+ @Override
+ public Key detectHitKey(int x, int y) {
+ final int touchX = getTouchX(x);
+ final int touchY = getTouchY(y);
+
+ Key nearestKey = null;
+ int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
+ for (final Key key : getKeyboard().mKeys) {
+ final int dist = key.squaredDistanceToEdge(touchX, touchY);
+ if (dist < nearestDist) {
+ nearestKey = key;
+ nearestDist = dist;
+ }
+ }
+ return nearestKey;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
new file mode 100644
index 000000000..a3741a2d8
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import com.android.inputmethod.keyboard.internal.KeySpecParser.MoreKeySpec;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StringUtils;
+
+public class MoreKeysKeyboard extends Keyboard {
+ private final int mDefaultKeyCoordX;
+
+ MoreKeysKeyboard(Builder.MoreKeysKeyboardParams params) {
+ super(params);
+ mDefaultKeyCoordX = params.getDefaultKeyCoordX() + params.mDefaultKeyWidth / 2;
+ }
+
+ public int getDefaultCoordX() {
+ return mDefaultKeyCoordX;
+ }
+
+ public static class Builder extends Keyboard.Builder<Builder.MoreKeysKeyboardParams> {
+ private final Key mParentKey;
+ private final Drawable mDivider;
+
+ private static final float LABEL_PADDING_RATIO = 0.2f;
+ private static final float DIVIDER_RATIO = 0.2f;
+
+ public static class MoreKeysKeyboardParams extends Keyboard.Params {
+ public boolean mIsFixedOrder;
+ /* package */int mTopRowAdjustment;
+ public int mNumRows;
+ public int mNumColumns;
+ public int mTopKeys;
+ public int mLeftKeys;
+ public int mRightKeys; // includes default key.
+ public int mDividerWidth;
+ public int mColumnWidth;
+
+ public MoreKeysKeyboardParams() {
+ super();
+ }
+
+ /**
+ * Set keyboard parameters of more keys keyboard.
+ *
+ * @param numKeys number of keys in this more keys keyboard.
+ * @param maxColumns number of maximum columns of this more keys keyboard.
+ * @param keyWidth more keys keyboard key width in pixel, including horizontal gap.
+ * @param rowHeight more keys keyboard row height in pixel, including vertical gap.
+ * @param coordXInParent coordinate x of the key preview in parent keyboard.
+ * @param parentKeyboardWidth parent keyboard width in pixel.
+ * @param isFixedColumnOrder if true, more keys should be laid out in fixed order.
+ * @param dividerWidth width of divider, zero for no dividers.
+ */
+ public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight,
+ int coordXInParent, int parentKeyboardWidth, boolean isFixedColumnOrder,
+ int dividerWidth) {
+ mIsFixedOrder = isFixedColumnOrder;
+ if (parentKeyboardWidth / keyWidth < maxColumns) {
+ throw new IllegalArgumentException(
+ "Keyboard is too small to hold more keys keyboard: "
+ + parentKeyboardWidth + " " + keyWidth + " " + maxColumns);
+ }
+ mDefaultKeyWidth = keyWidth;
+ mDefaultRowHeight = rowHeight;
+
+ final int numRows = (numKeys + maxColumns - 1) / maxColumns;
+ mNumRows = numRows;
+ final int numColumns = mIsFixedOrder ? Math.min(numKeys, maxColumns)
+ : getOptimizedColumns(numKeys, maxColumns);
+ mNumColumns = numColumns;
+ final int topKeys = numKeys % numColumns;
+ mTopKeys = topKeys == 0 ? numColumns : topKeys;
+
+ final int numLeftKeys = (numColumns - 1) / 2;
+ final int numRightKeys = numColumns - numLeftKeys; // including default key.
+ // Maximum number of keys we can layout both side of the parent key
+ final int maxLeftKeys = coordXInParent / keyWidth;
+ final int maxRightKeys = (parentKeyboardWidth - coordXInParent) / keyWidth;
+ int leftKeys, rightKeys;
+ if (numLeftKeys > maxLeftKeys) {
+ leftKeys = maxLeftKeys;
+ rightKeys = numColumns - leftKeys;
+ } else if (numRightKeys > maxRightKeys + 1) {
+ rightKeys = maxRightKeys + 1; // include default key
+ leftKeys = numColumns - rightKeys;
+ } else {
+ leftKeys = numLeftKeys;
+ rightKeys = numRightKeys;
+ }
+ // If the left keys fill the left side of the parent key, entire more keys keyboard
+ // should be shifted to the right unless the parent key is on the left edge.
+ if (maxLeftKeys == leftKeys && leftKeys > 0) {
+ leftKeys--;
+ rightKeys++;
+ }
+ // If the right keys fill the right side of the parent key, entire more keys
+ // should be shifted to the left unless the parent key is on the right edge.
+ if (maxRightKeys == rightKeys - 1 && rightKeys > 1) {
+ leftKeys++;
+ rightKeys--;
+ }
+ mLeftKeys = leftKeys;
+ mRightKeys = rightKeys;
+
+ // Adjustment of the top row.
+ mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment()
+ : getAutoOrderTopRowAdjustment();
+ mDividerWidth = dividerWidth;
+ mColumnWidth = mDefaultKeyWidth + mDividerWidth;
+ mBaseWidth = mOccupiedWidth = mNumColumns * mColumnWidth - mDividerWidth;
+ // Need to subtract the bottom row's gutter only.
+ mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
+ + mTopPadding + mBottomPadding;
+ }
+
+ private int getFixedOrderTopRowAdjustment() {
+ if (mNumRows == 1 || mTopKeys % 2 == 1 || mTopKeys == mNumColumns
+ || mLeftKeys == 0 || mRightKeys == 1) {
+ return 0;
+ }
+ return -1;
+ }
+
+ private int getAutoOrderTopRowAdjustment() {
+ if (mNumRows == 1 || mTopKeys == 1 || mNumColumns % 2 == mTopKeys % 2
+ || mLeftKeys == 0 || mRightKeys == 1) {
+ return 0;
+ }
+ return -1;
+ }
+
+ // Return key position according to column count (0 is default).
+ /* package */int getColumnPos(int n) {
+ return mIsFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n);
+ }
+
+ private int getFixedOrderColumnPos(int n) {
+ final int col = n % mNumColumns;
+ final int row = n / mNumColumns;
+ if (!isTopRow(row)) {
+ return col - mLeftKeys;
+ }
+ final int rightSideKeys = mTopKeys / 2;
+ final int leftSideKeys = mTopKeys - (rightSideKeys + 1);
+ final int pos = col - leftSideKeys;
+ final int numLeftKeys = mLeftKeys + mTopRowAdjustment;
+ final int numRightKeys = mRightKeys - 1;
+ if (numRightKeys >= rightSideKeys && numLeftKeys >= leftSideKeys) {
+ return pos;
+ } else if (numRightKeys < rightSideKeys) {
+ return pos - (rightSideKeys - numRightKeys);
+ } else { // numLeftKeys < leftSideKeys
+ return pos + (leftSideKeys - numLeftKeys);
+ }
+ }
+
+ private int getAutomaticColumnPos(int n) {
+ final int col = n % mNumColumns;
+ final int row = n / mNumColumns;
+ int leftKeys = mLeftKeys;
+ if (isTopRow(row)) {
+ leftKeys += mTopRowAdjustment;
+ }
+ if (col == 0) {
+ // default position.
+ return 0;
+ }
+
+ int pos = 0;
+ int right = 1; // include default position key.
+ int left = 0;
+ int i = 0;
+ while (true) {
+ // Assign right key if available.
+ if (right < mRightKeys) {
+ pos = right;
+ right++;
+ i++;
+ }
+ if (i >= col)
+ break;
+ // Assign left key if available.
+ if (left < leftKeys) {
+ left++;
+ pos = -left;
+ i++;
+ }
+ if (i >= col)
+ break;
+ }
+ return pos;
+ }
+
+ private static int getTopRowEmptySlots(int numKeys, int numColumns) {
+ final int remainings = numKeys % numColumns;
+ return remainings == 0 ? 0 : numColumns - remainings;
+ }
+
+ private int getOptimizedColumns(int numKeys, int maxColumns) {
+ int numColumns = Math.min(numKeys, maxColumns);
+ while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) {
+ numColumns--;
+ }
+ return numColumns;
+ }
+
+ public int getDefaultKeyCoordX() {
+ return mLeftKeys * mColumnWidth;
+ }
+
+ public int getX(int n, int row) {
+ final int x = getColumnPos(n) * mColumnWidth + getDefaultKeyCoordX();
+ if (isTopRow(row)) {
+ return x + mTopRowAdjustment * (mColumnWidth / 2);
+ }
+ return x;
+ }
+
+ public int getY(int row) {
+ return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding;
+ }
+
+ public void markAsEdgeKey(Key key, int row) {
+ if (row == 0)
+ key.markAsTopEdge(this);
+ if (isTopRow(row))
+ key.markAsBottomEdge(this);
+ }
+
+ private boolean isTopRow(int rowCount) {
+ return mNumRows > 1 && rowCount == mNumRows - 1;
+ }
+ }
+
+ /**
+ * The builder of MoreKeysKeyboard.
+ * @param containerView the container of {@link MoreKeysKeyboardView}.
+ * @param parentKey the {@link Key} that invokes more keys keyboard.
+ * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey.
+ */
+ public Builder(View containerView, Key parentKey, KeyboardView parentKeyboardView) {
+ super(containerView.getContext(), new MoreKeysKeyboardParams());
+ final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
+ load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId);
+
+ // TODO: More keys keyboard's vertical gap is currently calculated heuristically.
+ // Should revise the algorithm.
+ mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2;
+ mParentKey = parentKey;
+
+ final int width, height;
+ final boolean singleMoreKeyWithPreview = parentKeyboardView.isKeyPreviewPopupEnabled()
+ && !parentKey.noKeyPreview() && parentKey.mMoreKeys.length == 1;
+ if (singleMoreKeyWithPreview) {
+ // Use pre-computed width and height if this more keys keyboard has only one key to
+ // mitigate visual flicker between key preview and more keys keyboard.
+ // Caveats for the visual assets: To achieve this effect, both the key preview
+ // backgrounds and the more keys keyboard panel background have the exact same
+ // left/right/top paddings. The bottom paddings of both backgrounds don't need to
+ // be considered because the vertical positions of both backgrounds were already
+ // adjusted with their bottom paddings deducted.
+ width = parentKeyboardView.mKeyPreviewDrawParams.mPreviewVisibleWidth;
+ height = parentKeyboardView.mKeyPreviewDrawParams.mPreviewVisibleHeight
+ + mParams.mVerticalGap;
+ } else {
+ width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth);
+ height = parentKeyboard.mMostCommonKeyHeight;
+ }
+ final int dividerWidth;
+ if (parentKey.needsDividersInMoreKeys()) {
+ mDivider = mResources.getDrawable(R.drawable.more_keys_divider);
+ dividerWidth = (int)(width * DIVIDER_RATIO);
+ } else {
+ mDivider = null;
+ dividerWidth = 0;
+ }
+ mParams.setParameters(parentKey.mMoreKeys.length, parentKey.getMoreKeysColumn(),
+ width, height, parentKey.mX + parentKey.mWidth / 2,
+ parentKeyboardView.getMeasuredWidth(), parentKey.isFixedColumnOrderMoreKeys(),
+ dividerWidth);
+ }
+
+ private static int getMaxKeyWidth(KeyboardView view, Key parentKey, int minKeyWidth) {
+ final int padding = (int)(view.getResources()
+ .getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding)
+ + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0));
+ final Paint paint = view.newDefaultLabelPaint();
+ paint.setTextSize(parentKey.hasLabelsInMoreKeys()
+ ? view.mKeyDrawParams.mKeyLabelSize
+ : view.mKeyDrawParams.mKeyLetterSize);
+ int maxWidth = minKeyWidth;
+ for (final MoreKeySpec spec : parentKey.mMoreKeys) {
+ final String label = spec.mLabel;
+ // If the label is single letter, minKeyWidth is enough to hold the label.
+ if (label != null && StringUtils.codePointCount(label) > 1) {
+ final int width = (int)view.getLabelWidth(label, paint) + padding;
+ if (maxWidth < width) {
+ maxWidth = width;
+ }
+ }
+ }
+ return maxWidth;
+ }
+
+ private static class MoreKeyDivider extends Key.Spacer {
+ private final Drawable mIcon;
+
+ public MoreKeyDivider(MoreKeysKeyboardParams params, Drawable icon, int x, int y) {
+ super(params, x, y, params.mDividerWidth, params.mDefaultRowHeight);
+ mIcon = icon;
+ }
+
+ @Override
+ public Drawable getIcon(KeyboardIconsSet iconSet, int alpha) {
+ // KeyboardIconsSet and alpha are unused. Use the icon that has been passed to the
+ // constructor.
+ // TODO: Drawable itself should have an alpha value.
+ mIcon.setAlpha(128);
+ return mIcon;
+ }
+ }
+
+ @Override
+ public MoreKeysKeyboard build() {
+ final MoreKeysKeyboardParams params = mParams;
+ final int moreKeyFlags = mParentKey.getMoreKeyLabelFlags();
+ final MoreKeySpec[] moreKeys = mParentKey.mMoreKeys;
+ for (int n = 0; n < moreKeys.length; n++) {
+ final MoreKeySpec moreKeySpec = moreKeys[n];
+ final int row = n / params.mNumColumns;
+ final int x = params.getX(n, row);
+ final int y = params.getY(row);
+ final Key key = new Key(params, moreKeySpec, x, y,
+ params.mDefaultKeyWidth, params.mDefaultRowHeight, moreKeyFlags);
+ params.markAsEdgeKey(key, row);
+ params.onAddKey(key);
+
+ final int pos = params.getColumnPos(n);
+ // The "pos" value represents the offset from the default position. Negative means
+ // left of the default position.
+ if (params.mDividerWidth > 0 && pos != 0) {
+ final int dividerX = (pos > 0) ? x - params.mDividerWidth
+ : x + params.mDefaultKeyWidth;
+ final Key divider = new MoreKeyDivider(params, mDivider, dividerX, y);
+ params.onAddKey(divider);
+ }
+ }
+ return new MoreKeysKeyboard(params);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
new file mode 100644
index 000000000..be7644fb5
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.PopupWindow;
+
+import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
+import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.latin.R;
+
+/**
+ * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and
+ * detecting key presses and touch movements.
+ */
+public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel {
+ private final int[] mCoordinates = new int[2];
+
+ private final KeyDetector mKeyDetector;
+
+ private Controller mController;
+ private KeyboardActionListener mListener;
+ private int mOriginX;
+ private int mOriginY;
+
+ private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter();
+
+ private final KeyboardActionListener mMoreKeysKeyboardListener =
+ new KeyboardActionListener.Adapter() {
+ @Override
+ public void onCodeInput(int primaryCode, int x, int y) {
+ // Because a more keys keyboard doesn't need proximity characters correction, we don't
+ // send touch event coordinates.
+ mListener.onCodeInput(primaryCode, NOT_A_TOUCH_COORDINATE, NOT_A_TOUCH_COORDINATE);
+ }
+
+ @Override
+ public void onTextInput(CharSequence text) {
+ mListener.onTextInput(text);
+ }
+
+ @Override
+ public void onCancelInput() {
+ mListener.onCancelInput();
+ }
+
+ @Override
+ public void onPressKey(int primaryCode) {
+ mListener.onPressKey(primaryCode);
+ }
+
+ @Override
+ public void onReleaseKey(int primaryCode, boolean withSliding) {
+ mListener.onReleaseKey(primaryCode, withSliding);
+ }
+ };
+
+ public MoreKeysKeyboardView(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
+ }
+
+ public MoreKeysKeyboardView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final Resources res = context.getResources();
+ mKeyDetector = new MoreKeysDetector(
+ res.getDimension(R.dimen.more_keys_keyboard_slide_allowance));
+ setKeyPreviewPopupEnabled(false, 0);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final Keyboard keyboard = getKeyboard();
+ if (keyboard != null) {
+ final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
+ final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
+ setMeasuredDimension(width, height);
+ } else {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ @Override
+ public void setKeyboard(Keyboard keyboard) {
+ super.setKeyboard(keyboard);
+ mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
+ -getPaddingTop() + mVerticalCorrection);
+ }
+
+ @Override
+ public KeyDetector getKeyDetector() {
+ return mKeyDetector;
+ }
+
+ @Override
+ public KeyboardActionListener getKeyboardActionListener() {
+ return mMoreKeysKeyboardListener;
+ }
+
+ @Override
+ public DrawingProxy getDrawingProxy() {
+ return this;
+ }
+
+ @Override
+ public TimerProxy getTimerProxy() {
+ return EMPTY_TIMER_PROXY;
+ }
+
+ @Override
+ public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
+ // More keys keyboard needs no pop-up key preview displayed, so we pass always false with a
+ // delay of 0. The delay does not matter actually since the popup is not shown anyway.
+ super.setKeyPreviewPopupEnabled(false, 0);
+ }
+
+ @Override
+ public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
+ PopupWindow window, KeyboardActionListener listener) {
+ mController = controller;
+ mListener = listener;
+ final View container = (View)getParent();
+ final MoreKeysKeyboard pane = (MoreKeysKeyboard)getKeyboard();
+ final int defaultCoordX = pane.getDefaultCoordX();
+ // The coordinates of panel's left-top corner in parentView's coordinate system.
+ final int x = pointX - defaultCoordX - container.getPaddingLeft();
+ final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom();
+
+ window.setContentView(container);
+ window.setWidth(container.getMeasuredWidth());
+ window.setHeight(container.getMeasuredHeight());
+ parentView.getLocationInWindow(mCoordinates);
+ window.showAtLocation(parentView, Gravity.NO_GRAVITY,
+ x + mCoordinates[0], y + mCoordinates[1]);
+
+ mOriginX = x + container.getPaddingLeft();
+ mOriginY = y + container.getPaddingTop();
+ }
+
+ private boolean mIsDismissing;
+
+ @Override
+ public boolean dismissMoreKeysPanel() {
+ if (mIsDismissing || mController == null) return false;
+ mIsDismissing = true;
+ final boolean dismissed = mController.dismissMoreKeysPanel();
+ mIsDismissing = false;
+ return dismissed;
+ }
+
+ @Override
+ public int translateX(int x) {
+ return x - mOriginX;
+ }
+
+ @Override
+ public int translateY(int y) {
+ return y - mOriginY;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
new file mode 100644
index 000000000..f9a196d24
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.view.View;
+import android.widget.PopupWindow;
+
+public interface MoreKeysPanel extends PointerTracker.KeyEventHandler {
+ public interface Controller {
+ public boolean dismissMoreKeysPanel();
+ }
+
+ /**
+ * Show more keys panel.
+ *
+ * @param parentView the parent view of this more keys panel
+ * @param controller the controller that can dismiss this more keys panel
+ * @param pointX x coordinate of this more keys panel
+ * @param pointY y coordinate of this more keys panel
+ * @param window PopupWindow to be used to show this more keys panel
+ * @param listener the listener that will receive keyboard action from this more keys panel.
+ */
+ public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
+ PopupWindow window, KeyboardActionListener listener);
+
+ /**
+ * Translate X-coordinate of touch event to the local X-coordinate of this
+ * {@link MoreKeysPanel}.
+ *
+ * @param x the global X-coordinate
+ * @return the local X-coordinate to this {@link MoreKeysPanel}
+ */
+ public int translateX(int x);
+
+ /**
+ * Translate Y-coordinate of touch event to the local Y-coordinate of this
+ * {@link MoreKeysPanel}.
+ *
+ * @param y the global Y-coordinate
+ * @return the local Y-coordinate to this {@link MoreKeysPanel}
+ */
+ public int translateY(int y);
+}
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 8b03360bf..34e428e82 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -16,73 +16,143 @@
package com.android.inputmethod.keyboard;
-import android.content.res.Resources;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
-import com.android.inputmethod.keyboard.KeyboardView.UIHandler;
-import com.android.inputmethod.keyboard.internal.PointerTrackerKeyState;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.ResearchLogger;
+import com.android.inputmethod.latin.define.ProductionFlag;
-import java.util.Arrays;
-import java.util.List;
+import java.util.ArrayList;
public class PointerTracker {
private static final String TAG = PointerTracker.class.getSimpleName();
- private static final boolean ENABLE_ASSERTION = false;
private static final boolean DEBUG_EVENT = false;
private static final boolean DEBUG_MOVE_EVENT = false;
private static final boolean DEBUG_LISTENER = false;
private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
- public interface UIProxy {
+ public interface KeyEventHandler {
+ /**
+ * Get KeyDetector object that is used for this PointerTracker.
+ * @return the KeyDetector object that is used for this PointerTracker
+ */
+ public KeyDetector getKeyDetector();
+
+ /**
+ * Get KeyboardActionListener object that is used to register key code and so on.
+ * @return the KeyboardActionListner for this PointerTracker
+ */
+ public KeyboardActionListener getKeyboardActionListener();
+
+ /**
+ * Get DrawingProxy object that is used for this PointerTracker.
+ * @return the DrawingProxy object that is used for this PointerTracker
+ */
+ public DrawingProxy getDrawingProxy();
+
+ /**
+ * Get TimerProxy object that handles key repeat and long press timer event for this
+ * PointerTracker.
+ * @return the TimerProxy object that handles key repeat and long press timer event.
+ */
+ public TimerProxy getTimerProxy();
+ }
+
+ public interface DrawingProxy extends MoreKeysPanel.Controller {
public void invalidateKey(Key key);
- public void showKeyPreview(int keyIndex, PointerTracker tracker);
+ public TextView inflateKeyPreviewText();
+ public void showKeyPreview(PointerTracker tracker);
public void dismissKeyPreview(PointerTracker tracker);
- public boolean hasDistinctMultitouch();
}
- public final int mPointerId;
+ public interface TimerProxy {
+ public void startTypingStateTimer();
+ public boolean isTypingState();
+ public void startKeyRepeatTimer(PointerTracker tracker);
+ public void startLongPressTimer(PointerTracker tracker);
+ public void startLongPressTimer(int code);
+ public void cancelLongPressTimer();
+ public void startDoubleTapTimer();
+ public void cancelDoubleTapTimer();
+ public boolean isInDoubleTapTimeout();
+ public void cancelKeyTimers();
+
+ public static class Adapter implements TimerProxy {
+ @Override
+ public void startTypingStateTimer() {}
+ @Override
+ public boolean isTypingState() { return false; }
+ @Override
+ public void startKeyRepeatTimer(PointerTracker tracker) {}
+ @Override
+ public void startLongPressTimer(PointerTracker tracker) {}
+ @Override
+ public void startLongPressTimer(int code) {}
+ @Override
+ public void cancelLongPressTimer() {}
+ @Override
+ public void startDoubleTapTimer() {}
+ @Override
+ public void cancelDoubleTapTimer() {}
+ @Override
+ public boolean isInDoubleTapTimeout() { return false; }
+ @Override
+ public void cancelKeyTimers() {}
+ }
+ }
- // Timing constants
- private final int mDelayBeforeKeyRepeatStart;
- private final int mLongPressKeyTimeout;
- private final int mLongPressShiftKeyTimeout;
+ // Parameters for pointer handling.
+ private static LatinKeyboardView.PointerTrackerParams sParams;
+ private static int sTouchNoiseThresholdDistanceSquared;
+ private static boolean sNeedsPhantomSuddenMoveEventHack;
- private final KeyboardView mKeyboardView;
- private final UIProxy mProxy;
- private final UIHandler mHandler;
- private final KeyDetector mKeyDetector;
- private KeyboardActionListener mListener = EMPTY_LISTENER;
- private final KeyboardSwitcher mKeyboardSwitcher;
- private final boolean mHasDistinctMultitouch;
- private final boolean mConfigSlidingKeyInputEnabled;
+ private static final ArrayList<PointerTracker> sTrackers = new ArrayList<PointerTracker>();
+ private static PointerTrackerQueue sPointerTrackerQueue;
+
+ public final int mPointerId;
- private final int mTouchNoiseThresholdMillis;
- private final int mTouchNoiseThresholdDistanceSquared;
+ private DrawingProxy mDrawingProxy;
+ private TimerProxy mTimerProxy;
+ private KeyDetector mKeyDetector;
+ private KeyboardActionListener mListener = EMPTY_LISTENER;
private Keyboard mKeyboard;
- private List<Key> mKeys;
- private int mKeyHysteresisDistanceSquared = -1;
private int mKeyQuarterWidthSquared;
+ private final TextView mKeyPreviewText;
+
+ // The position and time at which first down event occurred.
+ private long mDownTime;
+ private long mUpTime;
- private final PointerTrackerKeyState mKeyState;
+ // The current key where this pointer is.
+ private Key mCurrentKey = null;
+ // The position where the current key was recognized for the first time.
+ private int mKeyX;
+ private int mKeyY;
+
+ // Last pointer position.
+ private int mLastX;
+ private int mLastY;
// true if keyboard layout has been changed.
private boolean mKeyboardLayoutHasBeenChanged;
- // true if event is already translated to a key action (long press or mini-keyboard)
+ // true if event is already translated to a key action.
private boolean mKeyAlreadyProcessed;
+ // true if this pointer has been long-pressed and is showing a more keys panel.
+ private boolean mIsShowingMoreKeysPanel;
+
// true if this pointer is repeatable key
private boolean mIsRepeatableKey;
// true if this pointer is in sliding key input
- private boolean mIsInSlidingKeyInput;
+ boolean mIsInSlidingKeyInput;
// true if sliding key is allowed.
private boolean mIsAllowedSlidingKeyInput;
@@ -90,69 +160,98 @@ public class PointerTracker {
// ignore modifier key if true
private boolean mIgnoreModifierKey;
- // TODO: Remove these hacking variables
- // true if this pointer is in sliding language switch
- private boolean mIsInSlidingLanguageSwitch;
- private int mSpaceKeyIndex;
- private final SubtypeSwitcher mSubtypeSwitcher;
-
// Empty {@link KeyboardActionListener}
- private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener() {
- @Override
- public void onPress(int primaryCode, boolean withSliding) {}
- @Override
- public void onRelease(int primaryCode, boolean withSliding) {}
- @Override
- public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {}
- @Override
- public void onTextInput(CharSequence text) {}
- @Override
- public void onCancelInput() {}
- @Override
- public void onSwipeDown() {}
- };
-
- public PointerTracker(int id, KeyboardView keyboardView, UIHandler handler,
- KeyDetector keyDetector, UIProxy proxy) {
- if (proxy == null || handler == null || keyDetector == null)
+ private static final KeyboardActionListener EMPTY_LISTENER =
+ new KeyboardActionListener.Adapter();
+
+ public static void init(boolean hasDistinctMultitouch,
+ boolean needsPhantomSuddenMoveEventHack) {
+ if (hasDistinctMultitouch) {
+ sPointerTrackerQueue = new PointerTrackerQueue();
+ } else {
+ sPointerTrackerQueue = null;
+ }
+ sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack;
+
+ setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT);
+ }
+
+ public static void setParameters(LatinKeyboardView.PointerTrackerParams params) {
+ sParams = params;
+ sTouchNoiseThresholdDistanceSquared = (int)(
+ params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance);
+ }
+
+ public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) {
+ final ArrayList<PointerTracker> trackers = sTrackers;
+
+ // Create pointer trackers until we can get 'id+1'-th tracker, if needed.
+ for (int i = trackers.size(); i <= id; i++) {
+ final PointerTracker tracker = new PointerTracker(i, handler);
+ trackers.add(tracker);
+ }
+
+ return trackers.get(id);
+ }
+
+ public static boolean isAnyInSlidingKeyInput() {
+ return sPointerTrackerQueue != null ? sPointerTrackerQueue.isAnyInSlidingKeyInput() : false;
+ }
+
+ public static void setKeyboardActionListener(KeyboardActionListener listener) {
+ for (final PointerTracker tracker : sTrackers) {
+ tracker.mListener = listener;
+ }
+ }
+
+ public static void setKeyDetector(KeyDetector keyDetector) {
+ for (final PointerTracker tracker : sTrackers) {
+ tracker.setKeyDetectorInner(keyDetector);
+ // Mark that keyboard layout has been changed.
+ tracker.mKeyboardLayoutHasBeenChanged = true;
+ }
+ }
+
+ public static void dismissAllKeyPreviews() {
+ for (final PointerTracker tracker : sTrackers) {
+ tracker.getKeyPreviewText().setVisibility(View.INVISIBLE);
+ tracker.setReleasedKeyGraphics(tracker.mCurrentKey);
+ }
+ }
+
+ public PointerTracker(int id, KeyEventHandler handler) {
+ if (handler == null)
throw new NullPointerException();
mPointerId = id;
- mKeyboardView = keyboardView;
- mProxy = proxy;
- mHandler = handler;
- mKeyDetector = keyDetector;
- mKeyboardSwitcher = KeyboardSwitcher.getInstance();
- mKeyState = new PointerTrackerKeyState(keyDetector);
- mHasDistinctMultitouch = proxy.hasDistinctMultitouch();
- final Resources res = mKeyboardView.getResources();
- mConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled);
- mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
- mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout);
- mLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout);
- mTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis);
- final float touchNoiseThresholdDistance = res.getDimension(
- R.dimen.config_touch_noise_threshold_distance);
- mTouchNoiseThresholdDistanceSquared = (int)(
- touchNoiseThresholdDistance * touchNoiseThresholdDistance);
- mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- }
-
- public void setOnKeyboardActionListener(KeyboardActionListener listener) {
- mListener = listener;
+ setKeyDetectorInner(handler.getKeyDetector());
+ mListener = handler.getKeyboardActionListener();
+ mDrawingProxy = handler.getDrawingProxy();
+ mTimerProxy = handler.getTimerProxy();
+ mKeyPreviewText = mDrawingProxy.inflateKeyPreviewText();
+ }
+
+ public TextView getKeyPreviewText() {
+ return mKeyPreviewText;
}
// Returns true if keyboard has been changed by this callback.
- private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key, boolean withSliding) {
- final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode);
- if (DEBUG_LISTENER)
- Log.d(TAG, "onPress : " + keyCodePrintable(key.mCode) + " sliding=" + withSliding
- + " ignoreModifier=" + ignoreModifierKey);
- if (ignoreModifierKey)
+ private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) {
+ final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+ if (DEBUG_LISTENER) {
+ Log.d(TAG, "onPress : " + KeyDetector.printableCode(key)
+ + " ignoreModifier=" + ignoreModifierKey
+ + " enabled=" + key.isEnabled());
+ }
+ if (ignoreModifierKey) {
return false;
+ }
if (key.isEnabled()) {
- mListener.onPress(key.mCode, withSliding);
+ mListener.onPressKey(key.mCode);
final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged;
mKeyboardLayoutHasBeenChanged = false;
+ if (!key.altCodeWhileTyping() && !key.isModifier()) {
+ mTimerProxy.startTypingStateTimer();
+ }
return keyboardLayoutHasBeenChanged;
}
return false;
@@ -160,170 +259,250 @@ public class PointerTracker {
// Note that we need primaryCode argument because the keyboard may in shifted state and the
// primaryCode is different from {@link Key#mCode}.
- private void callListenerOnCodeInput(Key key, int primaryCode, int[] keyCodes, int x, int y) {
- final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode);
- if (DEBUG_LISTENER)
- Log.d(TAG, "onCodeInput: " + keyCodePrintable(primaryCode)
- + " codes="+ Arrays.toString(keyCodes) + " x=" + x + " y=" + y
- + " ignoreModifier=" + ignoreModifierKey);
- if (ignoreModifierKey)
+ private void callListenerOnCodeInput(Key key, int primaryCode, int x, int y) {
+ final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+ final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState();
+ final int code = altersCode ? key.mAltCode : primaryCode;
+ if (DEBUG_LISTENER) {
+ Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText
+ + " x=" + x + " y=" + y
+ + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode
+ + " enabled=" + key.isEnabled());
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey,
+ altersCode, code);
+ }
+ if (ignoreModifierKey) {
return;
- if (key.isEnabled())
- mListener.onCodeInput(primaryCode, keyCodes, x, y);
- }
-
- private void callListenerOnTextInput(Key key) {
- if (DEBUG_LISTENER)
- Log.d(TAG, "onTextInput: text=" + key.mOutputText);
- if (key.isEnabled())
- mListener.onTextInput(key.mOutputText);
+ }
+ // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state.
+ if (key.isEnabled() || altersCode) {
+ if (code == Keyboard.CODE_OUTPUT_TEXT) {
+ mListener.onTextInput(key.mOutputText);
+ } else if (code != Keyboard.CODE_UNSPECIFIED) {
+ mListener.onCodeInput(code, x, y);
+ }
+ }
}
// Note that we need primaryCode argument because the keyboard may in shifted state and the
// primaryCode is different from {@link Key#mCode}.
private void callListenerOnRelease(Key key, int primaryCode, boolean withSliding) {
- final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode);
- if (DEBUG_LISTENER)
- Log.d(TAG, "onRelease : " + keyCodePrintable(primaryCode) + " sliding="
- + withSliding + " ignoreModifier=" + ignoreModifierKey);
- if (ignoreModifierKey)
+ final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
+ if (DEBUG_LISTENER) {
+ Log.d(TAG, "onRelease : " + Keyboard.printableCode(primaryCode)
+ + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
+ + " enabled="+ key.isEnabled());
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding,
+ ignoreModifierKey);
+ }
+ if (ignoreModifierKey) {
return;
- if (key.isEnabled())
- mListener.onRelease(primaryCode, withSliding);
+ }
+ if (key.isEnabled()) {
+ mListener.onReleaseKey(primaryCode, withSliding);
+ }
}
private void callListenerOnCancelInput() {
if (DEBUG_LISTENER)
Log.d(TAG, "onCancelInput");
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.pointerTracker_callListenerOnCancelInput();
+ }
mListener.onCancelInput();
}
- public void setKeyboard(Keyboard keyboard, float keyHysteresisDistance) {
- if (keyboard == null || keyHysteresisDistance < 0)
- throw new IllegalArgumentException();
- mKeyboard = keyboard;
- mKeys = keyboard.getKeys();
- mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
- final int keyQuarterWidth = keyboard.getKeyWidth() / 4;
+ private void setKeyDetectorInner(KeyDetector keyDetector) {
+ mKeyDetector = keyDetector;
+ mKeyboard = keyDetector.getKeyboard();
+ final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4;
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
- // Mark that keyboard layout has been changed.
- mKeyboardLayoutHasBeenChanged = true;
}
public boolean isInSlidingKeyInput() {
return mIsInSlidingKeyInput;
}
- private boolean isValidKeyIndex(int keyIndex) {
- return keyIndex >= 0 && keyIndex < mKeys.size();
+ public Key getKey() {
+ return mCurrentKey;
}
- public Key getKey(int keyIndex) {
- return isValidKeyIndex(keyIndex) ? mKeys.get(keyIndex) : null;
+ public boolean isModifier() {
+ return mCurrentKey != null && mCurrentKey.isModifier();
}
- private static boolean isModifierCode(int primaryCode) {
- return primaryCode == Keyboard.CODE_SHIFT
- || primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
+ public Key getKeyOn(int x, int y) {
+ return mKeyDetector.detectHitKey(x, y);
}
- private boolean isModifierInternal(int keyIndex) {
- final Key key = getKey(keyIndex);
- return key == null ? false : isModifierCode(key.mCode);
+ private void setReleasedKeyGraphics(Key key) {
+ mDrawingProxy.dismissKeyPreview(this);
+ if (key == null) {
+ return;
+ }
+
+ // Even if the key is disabled, update the key release graphics just in case.
+ updateReleaseKeyGraphics(key);
+
+ if (key.isShift()) {
+ for (final Key shiftKey : mKeyboard.mShiftKeys) {
+ if (shiftKey != key) {
+ updateReleaseKeyGraphics(shiftKey);
+ }
+ }
+ }
+
+ if (key.altCodeWhileTyping()) {
+ final int altCode = key.mAltCode;
+ final Key altKey = mKeyboard.getKey(altCode);
+ if (altKey != null) {
+ updateReleaseKeyGraphics(altKey);
+ }
+ for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
+ if (k != key && k.mAltCode == altCode) {
+ updateReleaseKeyGraphics(k);
+ }
+ }
+ }
}
- public boolean isModifier() {
- return isModifierInternal(mKeyState.getKeyIndex());
+ private void setPressedKeyGraphics(Key key) {
+ if (key == null) {
+ return;
+ }
+
+ // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state.
+ final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState();
+ final boolean needsToUpdateGraphics = key.isEnabled() || altersCode;
+ if (!needsToUpdateGraphics) {
+ return;
+ }
+
+ if (!key.noKeyPreview()) {
+ mDrawingProxy.showKeyPreview(this);
+ }
+ updatePressKeyGraphics(key);
+
+ if (key.isShift()) {
+ for (final Key shiftKey : mKeyboard.mShiftKeys) {
+ if (shiftKey != key) {
+ updatePressKeyGraphics(shiftKey);
+ }
+ }
+ }
+
+ if (key.altCodeWhileTyping() && mTimerProxy.isTypingState()) {
+ final int altCode = key.mAltCode;
+ final Key altKey = mKeyboard.getKey(altCode);
+ if (altKey != null) {
+ updatePressKeyGraphics(altKey);
+ }
+ for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
+ if (k != key && k.mAltCode == altCode) {
+ updatePressKeyGraphics(k);
+ }
+ }
+ }
}
- private boolean isOnModifierKey(int x, int y) {
- return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null));
+ private void updateReleaseKeyGraphics(Key key) {
+ key.onReleased();
+ mDrawingProxy.invalidateKey(key);
}
- public boolean isOnShiftKey(int x, int y) {
- final Key key = getKey(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null));
- return key != null && key.mCode == Keyboard.CODE_SHIFT;
+ private void updatePressKeyGraphics(Key key) {
+ key.onPressed();
+ mDrawingProxy.invalidateKey(key);
}
- public int getKeyIndexOn(int x, int y) {
- return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
+ public int getLastX() {
+ return mLastX;
}
- public boolean isSpaceKey(int keyIndex) {
- Key key = getKey(keyIndex);
- return key != null && key.mCode == Keyboard.CODE_SPACE;
+ public int getLastY() {
+ return mLastY;
}
- public void setReleasedKeyGraphics() {
- setReleasedKeyGraphics(mKeyState.getKeyIndex());
+ public long getDownTime() {
+ return mDownTime;
}
- private void setReleasedKeyGraphics(int keyIndex) {
- final Key key = getKey(keyIndex);
- if (key != null) {
- key.onReleased();
- mProxy.invalidateKey(key);
- }
+ private Key onDownKey(int x, int y, long eventTime) {
+ mDownTime = eventTime;
+ return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
}
- private void setPressedKeyGraphics(int keyIndex) {
- final Key key = getKey(keyIndex);
- if (key != null && key.isEnabled()) {
- key.onPressed();
- mProxy.invalidateKey(key);
- }
+ private Key onMoveKeyInternal(int x, int y) {
+ mLastX = x;
+ mLastY = y;
+ return mKeyDetector.detectHitKey(x, y);
}
- private void checkAssertion(PointerTrackerQueue queue) {
- if (mHasDistinctMultitouch && queue == null)
- throw new RuntimeException(
- "PointerTrackerQueue must be passed on distinct multi touch device");
- if (!mHasDistinctMultitouch && queue != null)
- throw new RuntimeException(
- "PointerTrackerQueue must be null on non-distinct multi touch device");
+ private Key onMoveKey(int x, int y) {
+ return onMoveKeyInternal(x, y);
}
- public void onTouchEvent(int action, int x, int y, long eventTime, PointerTrackerQueue queue) {
+ private Key onMoveToNewKey(Key newKey, int x, int y) {
+ mCurrentKey = newKey;
+ mKeyX = x;
+ mKeyY = y;
+ return newKey;
+ }
+
+ public void processMotionEvent(int action, int x, int y, long eventTime,
+ KeyEventHandler handler) {
switch (action) {
- case MotionEvent.ACTION_MOVE:
- onMoveEvent(x, y, eventTime, queue);
- break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
- onDownEvent(x, y, eventTime, queue);
+ onDownEvent(x, y, eventTime, handler);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
- onUpEvent(x, y, eventTime, queue);
+ onUpEvent(x, y, eventTime);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ onMoveEvent(x, y, eventTime);
break;
case MotionEvent.ACTION_CANCEL:
- onCancelEvent(x, y, eventTime, queue);
+ onCancelEvent(x, y, eventTime);
break;
}
}
- public void onDownEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onDownEvent(int x, int y, long eventTime, KeyEventHandler handler) {
if (DEBUG_EVENT)
printTouchEvent("onDownEvent:", x, y, eventTime);
+ mDrawingProxy = handler.getDrawingProxy();
+ mTimerProxy = handler.getTimerProxy();
+ setKeyboardActionListener(handler.getKeyboardActionListener());
+ setKeyDetectorInner(handler.getKeyDetector());
// Naive up-to-down noise filter.
- final long deltaT = eventTime - mKeyState.getUpTime();
- if (deltaT < mTouchNoiseThresholdMillis) {
- final int dx = x - mKeyState.getLastX();
- final int dy = y - mKeyState.getLastY();
+ final long deltaT = eventTime - mUpTime;
+ if (deltaT < sParams.mTouchNoiseThresholdTime) {
+ final int dx = x - mLastX;
+ final int dy = y - mLastY;
final int distanceSquared = (dx * dx + dy * dy);
- if (distanceSquared < mTouchNoiseThresholdDistanceSquared) {
+ if (distanceSquared < sTouchNoiseThresholdDistanceSquared) {
if (DEBUG_MODE)
Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT
+ " distance=" + distanceSquared);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared);
+ }
mKeyAlreadyProcessed = true;
return;
}
}
+ final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
- if (isOnModifierKey(x, y)) {
+ final Key key = getKeyOn(x, y);
+ if (key != null && key.isModifier()) {
// Before processing a down event of modifier key, all pointers already being
// tracked should be released.
queue.releaseAllPointers(eventTime);
@@ -334,88 +513,80 @@ public class PointerTracker {
}
private void onDownEventInternal(int x, int y, long eventTime) {
- int keyIndex = mKeyState.onDownKey(x, y, eventTime);
+ Key key = onDownKey(x, y, eventTime);
// Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding
- // from modifier key, or 3) this pointer is on mini-keyboard.
- mIsAllowedSlidingKeyInput = mConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex)
- || mKeyDetector instanceof MiniKeyboardKeyDetector;
+ // from modifier key, or 3) this pointer's KeyDetector always allows sliding input.
+ mIsAllowedSlidingKeyInput = sParams.mSlidingKeyInputEnabled
+ || (key != null && key.isModifier())
+ || mKeyDetector.alwaysAllowsSlidingInput();
mKeyboardLayoutHasBeenChanged = false;
mKeyAlreadyProcessed = false;
mIsRepeatableKey = false;
mIsInSlidingKeyInput = false;
- mIsInSlidingLanguageSwitch = false;
mIgnoreModifierKey = false;
- if (isValidKeyIndex(keyIndex)) {
+ if (key != null) {
// This onPress call may have changed keyboard layout. Those cases are detected at
- // {@link #setKeyboard}. In those cases, we should update keyIndex according to the new
+ // {@link #setKeyboard}. In those cases, we should update key according to the new
// keyboard layout.
- if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false))
- keyIndex = mKeyState.onDownKey(x, y, eventTime);
+ if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) {
+ key = onDownKey(x, y, eventTime);
+ }
- startRepeatKey(keyIndex);
- startLongPressTimer(keyIndex);
- showKeyPreview(keyIndex);
- setPressedKeyGraphics(keyIndex);
+ startRepeatKey(key);
+ startLongPressTimer(key);
+ setPressedKeyGraphics(key);
}
}
private void startSlidingKeyInput(Key key) {
- if (!mIsInSlidingKeyInput)
- mIgnoreModifierKey = isModifierCode(key.mCode);
+ if (!mIsInSlidingKeyInput) {
+ mIgnoreModifierKey = key.isModifier();
+ }
mIsInSlidingKeyInput = true;
}
- public void onMoveEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onMoveEvent(int x, int y, long eventTime) {
if (DEBUG_MOVE_EVENT)
printTouchEvent("onMoveEvent:", x, y, eventTime);
if (mKeyAlreadyProcessed)
return;
- final PointerTrackerKeyState keyState = mKeyState;
- // TODO: Remove this hacking code
- if (mIsInSlidingLanguageSwitch) {
- ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(x - keyState.getKeyX());
- showKeyPreview(mSpaceKeyIndex);
- return;
- }
- final int lastX = keyState.getLastX();
- final int lastY = keyState.getLastY();
- final int oldKeyIndex = keyState.getKeyIndex();
- final Key oldKey = getKey(oldKeyIndex);
- int keyIndex = keyState.onMoveKey(x, y);
- if (isValidKeyIndex(keyIndex)) {
+ final int lastX = mLastX;
+ final int lastY = mLastY;
+ final Key oldKey = mCurrentKey;
+ Key key = onMoveKey(x, y);
+ if (key != null) {
if (oldKey == null) {
// The pointer has been slid in to the new key, but the finger was not on any keys.
// In this case, we must call onPress() to notify that the new key is being pressed.
// This onPress call may have changed keyboard layout. Those cases are detected at
- // {@link #setKeyboard}. In those cases, we should update keyIndex according to the
+ // {@link #setKeyboard}. In those cases, we should update key according to the
// new keyboard layout.
- if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
- keyIndex = keyState.onMoveKey(x, y);
- keyState.onMoveToNewKey(keyIndex, x, y);
- startLongPressTimer(keyIndex);
- showKeyPreview(keyIndex);
- setPressedKeyGraphics(keyIndex);
- } else if (isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) {
+ if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) {
+ key = onMoveKey(x, y);
+ }
+ onMoveToNewKey(key, x, y);
+ startLongPressTimer(key);
+ setPressedKeyGraphics(key);
+ } else if (isMajorEnoughMoveToBeOnNewKey(x, y, key)) {
// The pointer has been slid in to the new key from the previous key, we must call
// onRelease() first to notify that the previous key has been released, then call
// onPress() to notify that the new key is being pressed.
- setReleasedKeyGraphics(oldKeyIndex);
+ setReleasedKeyGraphics(oldKey);
callListenerOnRelease(oldKey, oldKey.mCode, true);
startSlidingKeyInput(oldKey);
- mHandler.cancelKeyTimers();
- startRepeatKey(keyIndex);
+ mTimerProxy.cancelKeyTimers();
+ startRepeatKey(key);
if (mIsAllowedSlidingKeyInput) {
// This onPress call may have changed keyboard layout. Those cases are detected
- // at {@link #setKeyboard}. In those cases, we should update keyIndex according
+ // at {@link #setKeyboard}. In those cases, we should update key according
// to the new keyboard layout.
- if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
- keyIndex = keyState.onMoveKey(x, y);
- keyState.onMoveToNewKey(keyIndex, x, y);
- startLongPressTimer(keyIndex);
- setPressedKeyGraphics(keyIndex);
- showKeyPreview(keyIndex);
+ if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) {
+ key = onMoveKey(x, y);
+ }
+ onMoveToNewKey(key, x, y);
+ startLongPressTimer(key);
+ setPressedKeyGraphics(key);
} else {
// HACK: On some devices, quick successive touches may be translated to sudden
// move by touch panel firmware. This hack detects the case and translates the
@@ -423,287 +594,180 @@ public class PointerTracker {
final int dx = x - lastX;
final int dy = y - lastY;
final int lastMoveSquared = dx * dx + dy * dy;
- if (lastMoveSquared >= mKeyQuarterWidthSquared) {
- if (DEBUG_MODE)
- Log.w(TAG, String.format("onMoveEvent: sudden move is translated to "
+ if (sNeedsPhantomSuddenMoveEventHack
+ && lastMoveSquared >= mKeyQuarterWidthSquared) {
+ if (DEBUG_MODE) {
+ Log.w(TAG, String.format("onMoveEvent:"
+ + " phantom sudden move event is translated to "
+ "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y));
- onUpEventInternal(lastX, lastY, eventTime, true);
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY);
+ }
+ onUpEventInternal();
onDownEventInternal(x, y, eventTime);
} else {
mKeyAlreadyProcessed = true;
- dismissKeyPreview();
- setReleasedKeyGraphics(oldKeyIndex);
- }
- }
- }
- // TODO: Remove this hack code
- else if (isSpaceKey(keyIndex) && !mIsInSlidingLanguageSwitch
- && mKeyboard instanceof LatinKeyboard) {
- final LatinKeyboard keyboard = ((LatinKeyboard)mKeyboard);
- if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()
- && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
- final int diff = x - keyState.getKeyX();
- if (keyboard.shouldTriggerSpacebarSlidingLanguageSwitch(diff)) {
- // Detect start sliding language switch.
- mIsInSlidingLanguageSwitch = true;
- mSpaceKeyIndex = keyIndex;
- keyboard.updateSpacebarPreviewIcon(diff);
- // Display spacebar slide language switcher.
- showKeyPreview(keyIndex);
- if (queue != null)
- queue.releaseAllPointersExcept(this, eventTime, true);
+ setReleasedKeyGraphics(oldKey);
}
}
}
} else {
- if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) {
+ if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, key)) {
// The pointer has been slid out from the previous key, we must call onRelease() to
// notify that the previous key has been released.
- setReleasedKeyGraphics(oldKeyIndex);
+ setReleasedKeyGraphics(oldKey);
callListenerOnRelease(oldKey, oldKey.mCode, true);
startSlidingKeyInput(oldKey);
- mHandler.cancelLongPressTimers();
+ mTimerProxy.cancelLongPressTimer();
if (mIsAllowedSlidingKeyInput) {
- keyState.onMoveToNewKey(keyIndex, x, y);
+ onMoveToNewKey(key, x, y);
} else {
mKeyAlreadyProcessed = true;
- dismissKeyPreview();
}
}
}
}
- public void onUpEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onUpEvent(int x, int y, long eventTime) {
if (DEBUG_EVENT)
printTouchEvent("onUpEvent :", x, y, eventTime);
+ final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
- if (isModifier()) {
+ if (mCurrentKey != null && mCurrentKey.isModifier()) {
// Before processing an up event of modifier key, all pointers already being
// tracked should be released.
- queue.releaseAllPointersExcept(this, eventTime, true);
+ queue.releaseAllPointersExcept(this, eventTime);
} else {
queue.releaseAllPointersOlderThan(this, eventTime);
}
queue.remove(this);
}
- onUpEventInternal(x, y, eventTime, true);
+ onUpEventInternal();
}
// Let this pointer tracker know that one of newer-than-this pointer trackers got an up event.
// This pointer tracker needs to keep the key top graphics "pressed", but needs to get a
// "virtual" up event.
- public void onPhantomUpEvent(int x, int y, long eventTime, boolean updateReleasedKeyGraphics) {
+ public void onPhantomUpEvent(int x, int y, long eventTime) {
if (DEBUG_EVENT)
printTouchEvent("onPhntEvent:", x, y, eventTime);
- onUpEventInternal(x, y, eventTime, updateReleasedKeyGraphics);
+ onUpEventInternal();
mKeyAlreadyProcessed = true;
}
- private void onUpEventInternal(int x, int y, long eventTime,
- boolean updateReleasedKeyGraphics) {
- mHandler.cancelKeyTimers();
- mHandler.cancelShowKeyPreview(this);
+ private void onUpEventInternal() {
+ mTimerProxy.cancelKeyTimers();
mIsInSlidingKeyInput = false;
- final PointerTrackerKeyState keyState = mKeyState;
- final int keyX, keyY;
- if (isMajorEnoughMoveToBeOnNewKey(x, y, keyState.onMoveKey(x, y))) {
- keyX = x;
- keyY = y;
- } else {
- // Use previous fixed key coordinates.
- keyX = keyState.getKeyX();
- keyY = keyState.getKeyY();
- }
- final int keyIndex = keyState.onUpKey(keyX, keyY, eventTime);
- dismissKeyPreview();
- if (updateReleasedKeyGraphics)
- setReleasedKeyGraphics(keyIndex);
+ // Release the last pressed key.
+ setReleasedKeyGraphics(mCurrentKey);
+ if (mIsShowingMoreKeysPanel) {
+ mDrawingProxy.dismissMoreKeysPanel();
+ mIsShowingMoreKeysPanel = false;
+ }
if (mKeyAlreadyProcessed)
return;
- // TODO: Remove this hacking code
- if (mIsInSlidingLanguageSwitch) {
- setReleasedKeyGraphics(mSpaceKeyIndex);
- final int languageDir = ((LatinKeyboard)mKeyboard).getLanguageChangeDirection();
- if (languageDir != 0) {
- final int code = (languageDir == 1)
- ? LatinKeyboard.CODE_NEXT_LANGUAGE : LatinKeyboard.CODE_PREV_LANGUAGE;
- // This will change keyboard layout.
- mListener.onCodeInput(code, new int[] {code}, keyX, keyY);
- }
- mIsInSlidingLanguageSwitch = false;
- ((LatinKeyboard)mKeyboard).setSpacebarSlidingLanguageSwitchDiff(0);
- return;
- }
if (!mIsRepeatableKey) {
- detectAndSendKey(keyIndex, keyX, keyY);
+ detectAndSendKey(mCurrentKey, mKeyX, mKeyY);
}
}
- public void onLongPressed(PointerTrackerQueue queue) {
+ public void onShowMoreKeysPanel(int x, int y, KeyEventHandler handler) {
+ onLongPressed();
+ onDownEvent(x, y, SystemClock.uptimeMillis(), handler);
+ mIsShowingMoreKeysPanel = true;
+ }
+
+ public void onLongPressed() {
mKeyAlreadyProcessed = true;
+ setReleasedKeyGraphics(mCurrentKey);
+ final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
- // TODO: Support chording + long-press input.
- queue.releaseAllPointersExcept(this, SystemClock.uptimeMillis(), true);
queue.remove(this);
}
}
- public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onCancelEvent(int x, int y, long eventTime) {
if (DEBUG_EVENT)
printTouchEvent("onCancelEvt:", x, y, eventTime);
+ final PointerTrackerQueue queue = sPointerTrackerQueue;
if (queue != null) {
- queue.releaseAllPointersExcept(this, eventTime, true);
+ queue.releaseAllPointersExcept(this, eventTime);
queue.remove(this);
}
onCancelEventInternal();
}
private void onCancelEventInternal() {
- mHandler.cancelKeyTimers();
- mHandler.cancelShowKeyPreview(this);
- dismissKeyPreview();
- setReleasedKeyGraphics(mKeyState.getKeyIndex());
+ mTimerProxy.cancelKeyTimers();
+ setReleasedKeyGraphics(mCurrentKey);
mIsInSlidingKeyInput = false;
+ if (mIsShowingMoreKeysPanel) {
+ mDrawingProxy.dismissMoreKeysPanel();
+ mIsShowingMoreKeysPanel = false;
+ }
}
- private void startRepeatKey(int keyIndex) {
- final Key key = getKey(keyIndex);
- if (key != null && key.mRepeatable) {
- dismissKeyPreview();
- onRepeatKey(keyIndex);
- mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
+ private void startRepeatKey(Key key) {
+ if (key != null && key.isRepeatable()) {
+ onRegisterKey(key);
+ mTimerProxy.startKeyRepeatTimer(this);
mIsRepeatableKey = true;
} else {
mIsRepeatableKey = false;
}
}
- public void onRepeatKey(int keyIndex) {
- Key key = getKey(keyIndex);
+ public void onRegisterKey(Key key) {
if (key != null) {
- detectAndSendKey(keyIndex, key.mX, key.mY);
+ detectAndSendKey(key, key.mX, key.mY);
+ if (!key.altCodeWhileTyping() && !key.isModifier()) {
+ mTimerProxy.startTypingStateTimer();
+ }
}
}
- public int getLastX() {
- return mKeyState.getLastX();
- }
-
- public int getLastY() {
- return mKeyState.getLastY();
- }
-
- public long getDownTime() {
- return mKeyState.getDownTime();
- }
-
- private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, int newKey) {
- if (mKeys == null || mKeyHysteresisDistanceSquared < 0)
- throw new IllegalStateException("keyboard and/or hysteresis not set");
- int curKey = mKeyState.getKeyIndex();
+ private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, Key newKey) {
+ if (mKeyDetector == null)
+ throw new NullPointerException("keyboard and/or key detector not set");
+ Key curKey = mCurrentKey;
if (newKey == curKey) {
return false;
- } else if (isValidKeyIndex(curKey)) {
- return mKeys.get(curKey).squaredDistanceToEdge(x, y) >= mKeyHysteresisDistanceSquared;
+ } else if (curKey != null) {
+ return curKey.squaredDistanceToEdge(x, y)
+ >= mKeyDetector.getKeyHysteresisDistanceSquared();
} else {
return true;
}
}
- // The modifier key, such as shift key, should not show its key preview.
- private boolean isKeyPreviewNotRequired(int keyIndex) {
- final Key key = getKey(keyIndex);
- if (key == null || !key.isEnabled())
- return true;
- // Such as spacebar sliding language switch.
- if (mKeyboard.needSpacebarPreview(keyIndex))
- return false;
- final int code = key.mCode;
- return isModifierCode(code) || code == Keyboard.CODE_DELETE
- || code == Keyboard.CODE_ENTER || code == Keyboard.CODE_SPACE;
- }
-
- private void showKeyPreview(int keyIndex) {
- if (isKeyPreviewNotRequired(keyIndex))
- return;
- mProxy.showKeyPreview(keyIndex, this);
- }
-
- private void dismissKeyPreview() {
- mProxy.dismissKeyPreview(this);
- }
-
- private void startLongPressTimer(int keyIndex) {
- Key key = getKey(keyIndex);
- if (key.mCode == Keyboard.CODE_SHIFT) {
- mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
- } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
- // We need not start long press timer on the key which has manual temporary upper case
- // code defined and the keyboard is in manual temporary upper case mode.
- return;
- } else if (mKeyboardSwitcher.isInMomentarySwitchState()) {
- // We use longer timeout for sliding finger input started from the symbols mode key.
- mHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this);
- } else {
- mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
+ private void startLongPressTimer(Key key) {
+ if (key != null && key.isLongPressEnabled()) {
+ mTimerProxy.startLongPressTimer(this);
}
}
- private void detectAndSendKey(int index, int x, int y) {
- final Key key = getKey(index);
+ private void detectAndSendKey(Key key, int x, int y) {
if (key == null) {
callListenerOnCancelInput();
return;
}
- if (key.mOutputText != null) {
- callListenerOnTextInput(key);
- callListenerOnRelease(key, key.mCode, false);
- } else {
- int code = key.mCode;
- final int[] codes = mKeyDetector.newCodeArray();
- mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
-
- // If keyboard is in manual temporary upper case state and key has manual temporary
- // uppercase letter as key hint letter, alternate character code should be sent.
- if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) {
- code = key.mHintLabel.charAt(0);
- codes[0] = code;
- }
- // Swap the first and second values in the codes array if the primary code is not the
- // first value but the second value in the array. This happens when key debouncing is
- // in effect.
- if (codes.length >= 2 && codes[0] != code && codes[1] == code) {
- codes[1] = codes[0];
- codes[0] = code;
- }
- callListenerOnCodeInput(key, code, codes, x, y);
- callListenerOnRelease(key, code, false);
- }
- }
-
- public CharSequence getPreviewText(Key key) {
- return key.mLabel;
+ int code = key.mCode;
+ callListenerOnCodeInput(key, code, x, y);
+ callListenerOnRelease(key, code, false);
}
private long mPreviousEventTime;
private void printTouchEvent(String title, int x, int y, long eventTime) {
- final int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
- final Key key = getKey(keyIndex);
- final String code = (key == null) ? "----" : keyCodePrintable(key.mCode);
+ final Key key = mKeyDetector.detectHitKey(x, y);
+ final String code = KeyDetector.printableCode(key);
final long delta = eventTime - mPreviousEventTime;
- Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %3d(%s)", title,
- (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, keyIndex, code));
+ Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title,
+ (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, code));
mPreviousEventTime = eventTime;
}
-
- private static String keyCodePrintable(int primaryCode) {
- final String modifier = isModifierCode(primaryCode) ? " modifier" : "";
- return String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode) + modifier;
- }
}
diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
deleted file mode 100644
index 3b8c36487..000000000
--- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.keyboard;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.PopupWindow;
-
-import com.android.inputmethod.latin.R;
-
-/**
- * A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting
- * key presses and touch movements.
- */
-public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel {
- private final int[] mCoordinates = new int[2];
- private final boolean mConfigShowMiniKeyboardAtTouchedPoint;
-
- private int mOriginX;
- private int mOriginY;
- private long mDownTime;
-
- public PopupMiniKeyboardView(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.popupMiniKeyboardViewStyle);
- }
-
- public PopupMiniKeyboardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- final Resources res = context.getResources();
- mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean(
- R.bool.config_show_mini_keyboard_at_touched_point);
- // Override default ProximityKeyDetector.
- mKeyDetector = new MiniKeyboardKeyDetector(res.getDimension(
- R.dimen.mini_keyboard_slide_allowance));
- // Remove gesture detector on mini-keyboard
- mGestureDetector = null;
- setKeyPreviewPopupEnabled(false, 0);
- }
-
- @Override
- public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
- // Mini keyboard needs no pop-up key preview displayed, so we pass always false with a
- // delay of 0. The delay does not matter actually since the popup is not shown anyway.
- super.setKeyPreviewPopupEnabled(false, 0);
- }
-
- @Override
- public void showPanel(KeyboardView parentKeyboardView, Key parentKey,
- PointerTracker tracker, PopupWindow window) {
- final View container = (View)getParent();
- final MiniKeyboard miniKeyboard = (MiniKeyboard)getKeyboard();
- final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
-
- parentKeyboardView.getLocationInWindow(mCoordinates);
- final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX()
- : parentKey.mX + parentKey.mWidth / 2;
- final int pointY = parentKey.mY;
- final int miniKeyboardLeft = pointX - miniKeyboard.getDefaultCoordX()
- + parentKeyboardView.getPaddingLeft();
- final int x = Math.max(0, Math.min(miniKeyboardLeft,
- parentKeyboardView.getWidth() - miniKeyboard.getMinWidth()))
- - container.getPaddingLeft() + mCoordinates[0];
- final int y = pointY - parentKeyboard.getVerticalGap()
- - (container.getMeasuredHeight() - container.getPaddingBottom())
- + parentKeyboardView.getPaddingTop() + mCoordinates[1];
-
- if (miniKeyboard.setShifted(parentKeyboard.isShiftedOrShiftLocked())) {
- invalidateAllKeys();
- }
- window.setContentView(container);
- window.setWidth(container.getMeasuredWidth());
- window.setHeight(container.getMeasuredHeight());
- window.showAtLocation(parentKeyboardView, Gravity.NO_GRAVITY, x, y);
-
- mOriginX = x + container.getPaddingLeft() - mCoordinates[0];
- mOriginY = y + container.getPaddingTop() - mCoordinates[1];
- mDownTime = SystemClock.uptimeMillis();
-
- // Inject down event on the key to mini keyboard.
- final MotionEvent downEvent = MotionEvent.obtain(mDownTime, mDownTime,
- MotionEvent.ACTION_DOWN, pointX - mOriginX,
- pointY + parentKey.mHeight / 2 - mOriginY, 0);
- onTouchEvent(downEvent);
- downEvent.recycle();
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- me.offsetLocation(-mOriginX, -mOriginY);
- return super.onTouchEvent(me);
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/PopupPanel.java b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
deleted file mode 100644
index 386e11f2c..000000000
--- a/java/src/com/android/inputmethod/keyboard/PopupPanel.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.keyboard;
-
-import android.view.MotionEvent;
-import android.widget.PopupWindow;
-
-public interface PopupPanel {
- /**
- * Show popup panel.
- * @param parentKeyboardView the parent KeyboardView that has the parent key.
- * @param parentKey the parent key that is the source of this popup panel
- * @param tracker the pointer tracker that pressesd the parent key
- * @param window PopupWindow to be used to show this popup panel
- */
- public void showPanel(KeyboardView parentKeyboardView, Key parentKey,
- PointerTracker tracker, PopupWindow window);
-
- /**
- * Check if the pointer is in siding key input mode.
- * @return true if the pointer is sliding key input mode.
- */
- public boolean isInSlidingKeyInput();
-
- /**
- * The motion event handler.
- * @param me the MotionEvent to be processed.
- * @return true if the motion event is processed and should be consumed.
- */
- public boolean onTouchEvent(MotionEvent me);
-}
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 33acc6907..1bc825479 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -16,53 +16,162 @@
package com.android.inputmethod.keyboard;
-import com.android.inputmethod.latin.Utils;
+import android.graphics.Rect;
+import android.text.TextUtils;
+import android.util.FloatMath;
+
+import com.android.inputmethod.keyboard.Keyboard.Params.TouchPositionCorrection;
+import com.android.inputmethod.latin.JniUtils;
import java.util.Arrays;
-import java.util.List;
+import java.util.HashMap;
public class ProximityInfo {
+ /** MAX_PROXIMITY_CHARS_SIZE must be the same as MAX_PROXIMITY_CHARS_SIZE_INTERNAL
+ * in defines.h */
public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
+ /** Number of key widths from current touch point to search for nearest keys. */
+ private static float SEARCH_DISTANCE = 1.2f;
+ private static final Key[] EMPTY_KEY_ARRAY = new Key[0];
+ private final int mKeyHeight;
private final int mGridWidth;
private final int mGridHeight;
private final int mGridSize;
+ private final int mCellWidth;
+ private final int mCellHeight;
+ // TODO: Find a proper name for mKeyboardMinWidth
+ private final int mKeyboardMinWidth;
+ private final int mKeyboardHeight;
+ private final int mMostCommonKeyWidth;
+ private final Key[] mKeys;
+ private final TouchPositionCorrection mTouchPositionCorrection;
+ private final Key[][] mGridNeighbors;
+ private final String mLocaleStr;
- ProximityInfo(int gridWidth, int gridHeight) {
+ ProximityInfo(String localeStr, int gridWidth, int gridHeight, int minWidth, int height,
+ int mostCommonKeyWidth, int mostCommonKeyHeight, final Key[] keys,
+ TouchPositionCorrection touchPositionCorrection) {
+ if (TextUtils.isEmpty(localeStr)) {
+ mLocaleStr = "";
+ } else {
+ mLocaleStr = localeStr;
+ }
mGridWidth = gridWidth;
mGridHeight = gridHeight;
mGridSize = mGridWidth * mGridHeight;
+ mCellWidth = (minWidth + mGridWidth - 1) / mGridWidth;
+ mCellHeight = (height + mGridHeight - 1) / mGridHeight;
+ mKeyboardMinWidth = minWidth;
+ mKeyboardHeight = height;
+ mKeyHeight = mostCommonKeyHeight;
+ mMostCommonKeyWidth = mostCommonKeyWidth;
+ mKeys = keys;
+ mTouchPositionCorrection = touchPositionCorrection;
+ mGridNeighbors = new Key[mGridSize][];
+ if (minWidth == 0 || height == 0) {
+ // No proximity required. Keyboard might be more keys keyboard.
+ return;
+ }
+ computeNearestNeighbors();
+ mNativeProximityInfo = createNativeProximityInfo();
+ }
+
+ public static ProximityInfo createDummyProximityInfo() {
+ return new ProximityInfo("", 1, 1, 1, 1, 1, 1, EMPTY_KEY_ARRAY, null);
}
- private int mNativeProximityInfo;
+ public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity,
+ int rowSize, int gridWidth, int gridHeight) {
+ final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo();
+ spellCheckerProximityInfo.mNativeProximityInfo =
+ spellCheckerProximityInfo.setProximityInfoNative("",
+ rowSize, gridWidth, gridHeight, gridWidth, gridHeight,
+ 1, proximity, 0, null, null, null, null, null, null, null, null);
+ return spellCheckerProximityInfo;
+ }
+
+ private long mNativeProximityInfo;
static {
- Utils.loadNativeLibrary();
+ JniUtils.loadNativeLibrary();
}
- private native int setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
- int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray);
- private native void releaseProximityInfoNative(int nativeProximityInfo);
- public final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
- int keyboardHeight, List<Key> keys) {
- int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
+ private native long setProximityInfoNative(
+ String locale, int maxProximityCharsSize, int displayWidth,
+ int displayHeight, int gridWidth, int gridHeight,
+ int mostCommonKeyWidth, int[] proximityCharsArray,
+ int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
+ int[] keyWidths, int[] keyHeights, int[] keyCharCodes,
+ float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii);
+
+ private native void releaseProximityInfoNative(long nativeProximityInfo);
+
+ private final long createNativeProximityInfo() {
+ final Key[][] gridNeighborKeys = mGridNeighbors;
+ final int keyboardWidth = mKeyboardMinWidth;
+ final int keyboardHeight = mKeyboardHeight;
+ final Key[] keys = mKeys;
+ final TouchPositionCorrection touchPositionCorrection = mTouchPositionCorrection;
+ final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE);
for (int i = 0; i < mGridSize; ++i) {
- final int proximityCharsLength = gridNeighborKeyIndexes[i].length;
+ final int proximityCharsLength = gridNeighborKeys[i].length;
for (int j = 0; j < proximityCharsLength; ++j) {
proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] =
- keys.get(gridNeighborKeyIndexes[i][j]).mCode;
+ gridNeighborKeys[i][j].mCode;
}
}
- mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
- keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray);
- }
+ final int keyCount = keys.length;
+ final int[] keyXCoordinates = new int[keyCount];
+ final int[] keyYCoordinates = new int[keyCount];
+ final int[] keyWidths = new int[keyCount];
+ final int[] keyHeights = new int[keyCount];
+ final int[] keyCharCodes = new int[keyCount];
+ final float[] sweetSpotCenterXs;
+ final float[] sweetSpotCenterYs;
+ final float[] sweetSpotRadii;
+
+ for (int i = 0; i < keyCount; ++i) {
+ final Key key = keys[i];
+ keyXCoordinates[i] = key.mX;
+ keyYCoordinates[i] = key.mY;
+ keyWidths[i] = key.mWidth;
+ keyHeights[i] = key.mHeight;
+ keyCharCodes[i] = key.mCode;
+ }
- // TODO: Get rid of this function's input (keyboard).
- public int getNativeProximityInfo(Keyboard keyboard) {
- if (mNativeProximityInfo == 0) {
- // TODO: Move this function to ProximityInfo and make this private.
- keyboard.computeNearestNeighbors();
+ if (touchPositionCorrection != null && touchPositionCorrection.isValid()) {
+ sweetSpotCenterXs = new float[keyCount];
+ sweetSpotCenterYs = new float[keyCount];
+ sweetSpotRadii = new float[keyCount];
+ for (int i = 0; i < keyCount; i++) {
+ final Key key = keys[i];
+ final Rect hitBox = key.mHitBox;
+ final int row = hitBox.top / mKeyHeight;
+ if (row < touchPositionCorrection.mRadii.length) {
+ final int hitBoxWidth = hitBox.width();
+ final int hitBoxHeight = hitBox.height();
+ final float x = touchPositionCorrection.mXs[row];
+ final float y = touchPositionCorrection.mYs[row];
+ final float radius = touchPositionCorrection.mRadii[row];
+ sweetSpotCenterXs[i] = hitBox.exactCenterX() + x * hitBoxWidth;
+ sweetSpotCenterYs[i] = hitBox.exactCenterY() + y * hitBoxHeight;
+ sweetSpotRadii[i] = radius * FloatMath.sqrt(
+ hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight);
+ }
+ }
+ } else {
+ sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null;
}
+
+ return setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE,
+ keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth,
+ proximityCharsArray,
+ keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes,
+ sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
+ }
+
+ public long getNativeProximityInfo() {
return mNativeProximityInfo;
}
@@ -77,4 +186,72 @@ public class ProximityInfo {
super.finalize();
}
}
+
+ private void computeNearestNeighbors() {
+ final int defaultWidth = mMostCommonKeyWidth;
+ final Key[] keys = mKeys;
+ final HashMap<Integer, Key> keyCodeMap = new HashMap<Integer, Key>();
+ for (final Key key : keys) {
+ keyCodeMap.put(key.mCode, key);
+ }
+ final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
+ final int threshold = thresholdBase * thresholdBase;
+ // Round-up so we don't have any pixels outside the grid
+ final Key[] neighborKeys = new Key[keys.length];
+ final int gridWidth = mGridWidth * mCellWidth;
+ final int gridHeight = mGridHeight * mCellHeight;
+ for (int x = 0; x < gridWidth; x += mCellWidth) {
+ for (int y = 0; y < gridHeight; y += mCellHeight) {
+ final int centerX = x + mCellWidth / 2;
+ final int centerY = y + mCellHeight / 2;
+ int count = 0;
+ for (final Key key : keys) {
+ if (key.isSpacer()) continue;
+ if (key.squaredDistanceToEdge(centerX, centerY) < threshold) {
+ neighborKeys[count++] = key;
+ }
+ }
+ mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] =
+ Arrays.copyOfRange(neighborKeys, 0, count);
+ }
+ }
+ }
+
+ public void fillArrayWithNearestKeyCodes(int x, int y, int primaryKeyCode, int[] dest) {
+ final int destLength = dest.length;
+ if (destLength < 1) {
+ return;
+ }
+ int index = 0;
+ if (primaryKeyCode > Keyboard.CODE_SPACE) {
+ dest[index++] = primaryKeyCode;
+ }
+ final Key[] nearestKeys = getNearestKeys(x, y);
+ for (Key key : nearestKeys) {
+ if (index >= destLength) {
+ break;
+ }
+ final int code = key.mCode;
+ if (code <= Keyboard.CODE_SPACE) {
+ break;
+ }
+ dest[index++] = code;
+ }
+ if (index < destLength) {
+ dest[index] = KeyDetector.NOT_A_CODE;
+ }
+ }
+
+ public Key[] getNearestKeys(int x, int y) {
+ if (mGridNeighbors == null) {
+ return EMPTY_KEY_ARRAY;
+ }
+ if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) {
+ int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth);
+ if (index < mGridSize) {
+ return mGridNeighbors[index];
+ }
+ }
+ return EMPTY_KEY_ARRAY;
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java
new file mode 100644
index 000000000..107138395
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.ResearchLogger;
+import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.define.ProductionFlag;
+
+public class SuddenJumpingTouchEventHandler {
+ private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName();
+ private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
+
+ public interface ProcessMotionEvent {
+ public boolean processMotionEvent(MotionEvent me);
+ }
+
+ private final ProcessMotionEvent mView;
+ private final boolean mNeedsSuddenJumpingHack;
+
+ /** Whether we've started dropping move events because we found a big jump */
+ private boolean mDroppingEvents;
+ /**
+ * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has
+ * occured
+ */
+ private boolean mDisableDisambiguation;
+ /** The distance threshold at which we start treating the touch session as a multi-touch */
+ private int mJumpThresholdSquare = Integer.MAX_VALUE;
+ private int mLastX;
+ private int mLastY;
+
+ public SuddenJumpingTouchEventHandler(Context context, ProcessMotionEvent view) {
+ mView = view;
+ mNeedsSuddenJumpingHack = Boolean.parseBoolean(Utils.getDeviceOverrideValue(
+ context.getResources(), R.array.sudden_jumping_touch_event_device_list, "false"));
+ }
+
+ public void setKeyboard(Keyboard newKeyboard) {
+ // One-seventh of the keyboard width seems like a reasonable threshold
+ final int jumpThreshold = newKeyboard.mOccupiedWidth / 7;
+ mJumpThresholdSquare = jumpThreshold * jumpThreshold;
+ }
+
+ /**
+ * This function checks to see if we need to handle any sudden jumps in the pointer location
+ * that could be due to a multi-touch being treated as a move by the firmware or hardware.
+ * Once a sudden jump is detected, all subsequent move events are discarded
+ * until an UP is received.<P>
+ * When a sudden jump is detected, an UP event is simulated at the last position and when
+ * the sudden moves subside, a DOWN event is simulated for the second key.
+ * @param me the motion event
+ * @return true if the event was consumed, so that it doesn't continue to be handled by
+ * {@link LatinKeyboardView}.
+ */
+ private boolean handleSuddenJumping(MotionEvent me) {
+ if (!mNeedsSuddenJumpingHack)
+ return false;
+ final int action = me.getAction();
+ final int x = (int) me.getX();
+ final int y = (int) me.getY();
+ boolean result = false;
+
+ // Real multi-touch event? Stop looking for sudden jumps
+ if (me.getPointerCount() > 1) {
+ mDisableDisambiguation = true;
+ }
+ if (mDisableDisambiguation) {
+ // If UP, reset the multi-touch flag
+ if (action == MotionEvent.ACTION_UP) mDisableDisambiguation = false;
+ return false;
+ }
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ // Reset the "session"
+ mDroppingEvents = false;
+ mDisableDisambiguation = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ // Is this a big jump?
+ final int distanceSquare = (mLastX - x) * (mLastX - x) + (mLastY - y) * (mLastY - y);
+ // Check the distance.
+ if (distanceSquare > mJumpThresholdSquare) {
+ // If we're not yet dropping events, start dropping and send an UP event
+ if (!mDroppingEvents) {
+ mDroppingEvents = true;
+ // Send an up event
+ MotionEvent translated = MotionEvent.obtain(
+ me.getEventTime(), me.getEventTime(),
+ MotionEvent.ACTION_UP,
+ mLastX, mLastY, me.getMetaState());
+ mView.processMotionEvent(translated);
+ translated.recycle();
+ }
+ result = true;
+ } else if (mDroppingEvents) {
+ // If moves are small and we're already dropping events, continue dropping
+ result = true;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mDroppingEvents) {
+ // Send a down event first, as we dropped a bunch of sudden jumps and assume that
+ // the user is releasing the touch on the second key.
+ MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
+ MotionEvent.ACTION_DOWN,
+ x, y, me.getMetaState());
+ mView.processMotionEvent(translated);
+ translated.recycle();
+ mDroppingEvents = false;
+ // Let the up event get processed as well, result = false
+ }
+ break;
+ }
+ // Track the previous coordinate
+ mLastX = x;
+ mLastY = y;
+ return result;
+ }
+
+ public boolean onTouchEvent(MotionEvent me) {
+ // If there was a sudden jump, return without processing the actual motion event.
+ if (handleSuddenJumping(me)) {
+ if (DEBUG_MODE)
+ Log.w(TAG, "onTouchEvent: ignore sudden jump " + me);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.suddenJumpingTouchEventHandler_onTouchEvent(me);
+ }
+ return true;
+ }
+ return mView.processMotionEvent(me);
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java b/java/src/com/android/inputmethod/keyboard/ViewLayoutUtils.java
index 523bf7d0e..ee5047083 100644
--- a/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java
+++ b/java/src/com/android/inputmethod/keyboard/ViewLayoutUtils.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.inputmethod.compat;
+package com.android.inputmethod.keyboard;
import android.view.View;
import android.view.ViewGroup;
@@ -22,20 +22,9 @@ import android.view.ViewGroup.MarginLayoutParams;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
-public class FrameLayoutCompatUtils {
- private static final boolean NEEDS_FRAME_LAYOUT_HACK = (
- android.os.Build.VERSION.SDK_INT < 11 /* Honeycomb */);
-
- public static ViewGroup getPlacer(ViewGroup container) {
- if (NEEDS_FRAME_LAYOUT_HACK) {
- // Insert RelativeLayout to be able to setMargin because pre-Honeycomb FrameLayout
- // could not handle setMargin properly.
- final ViewGroup placer = new RelativeLayout(container.getContext());
- container.addView(placer);
- return placer;
- } else {
- return container;
- }
+public class ViewLayoutUtils {
+ private ViewLayoutUtils() {
+ // This utility class is not publicly instantiable.
}
public static MarginLayoutParams newLayoutParam(ViewGroup placer, int width, int height) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
index 0cde4e5b5..5712df1fc 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java
@@ -18,29 +18,27 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
+public class AlphabetShiftState {
+ private static final String TAG = AlphabetShiftState.class.getSimpleName();
+ private static final boolean DEBUG = false;
-public class KeyboardShiftState {
- private static final String TAG = "KeyboardShiftState";
- private static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
-
- private static final int NORMAL = 0;
+ private static final int UNSHIFTED = 0;
private static final int MANUAL_SHIFTED = 1;
private static final int MANUAL_SHIFTED_FROM_AUTO = 2;
- private static final int AUTO_SHIFTED = 3;
+ private static final int AUTOMATIC_SHIFTED = 3;
private static final int SHIFT_LOCKED = 4;
private static final int SHIFT_LOCK_SHIFTED = 5;
- private int mState = NORMAL;
+ private int mState = UNSHIFTED;
- public boolean setShifted(boolean newShiftState) {
+ public void setShifted(boolean newShiftState) {
final int oldState = mState;
if (newShiftState) {
switch (oldState) {
- case NORMAL:
+ case UNSHIFTED:
mState = MANUAL_SHIFTED;
break;
- case AUTO_SHIFTED:
+ case AUTOMATIC_SHIFTED:
mState = MANUAL_SHIFTED_FROM_AUTO;
break;
case SHIFT_LOCKED:
@@ -51,8 +49,8 @@ public class KeyboardShiftState {
switch (oldState) {
case MANUAL_SHIFTED:
case MANUAL_SHIFTED_FROM_AUTO:
- case AUTO_SHIFTED:
- mState = NORMAL;
+ case AUTOMATIC_SHIFTED:
+ mState = UNSHIFTED;
break;
case SHIFT_LOCK_SHIFTED:
mState = SHIFT_LOCKED;
@@ -61,58 +59,56 @@ public class KeyboardShiftState {
}
if (DEBUG)
Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this);
- return mState != oldState;
}
public void setShiftLocked(boolean newShiftLockState) {
final int oldState = mState;
if (newShiftLockState) {
switch (oldState) {
- case NORMAL:
+ case UNSHIFTED:
case MANUAL_SHIFTED:
case MANUAL_SHIFTED_FROM_AUTO:
- case AUTO_SHIFTED:
+ case AUTOMATIC_SHIFTED:
mState = SHIFT_LOCKED;
break;
}
} else {
- switch (oldState) {
- case SHIFT_LOCKED:
- case SHIFT_LOCK_SHIFTED:
- mState = NORMAL;
- break;
- }
+ mState = UNSHIFTED;
}
if (DEBUG)
Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState)
+ " > " + this);
}
- public void setAutomaticTemporaryUpperCase() {
+ public void setAutomaticShifted() {
final int oldState = mState;
- mState = AUTO_SHIFTED;
+ mState = AUTOMATIC_SHIFTED;
if (DEBUG)
- Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this);
+ Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this);
}
public boolean isShiftedOrShiftLocked() {
- return mState != NORMAL;
+ return mState != UNSHIFTED;
}
public boolean isShiftLocked() {
return mState == SHIFT_LOCKED || mState == SHIFT_LOCK_SHIFTED;
}
- public boolean isAutomaticTemporaryUpperCase() {
- return mState == AUTO_SHIFTED;
+ public boolean isShiftLockShifted() {
+ return mState == SHIFT_LOCK_SHIFTED;
+ }
+
+ public boolean isAutomaticShifted() {
+ return mState == AUTOMATIC_SHIFTED;
}
- public boolean isManualTemporaryUpperCase() {
+ public boolean isManualShifted() {
return mState == MANUAL_SHIFTED || mState == MANUAL_SHIFTED_FROM_AUTO
|| mState == SHIFT_LOCK_SHIFTED;
}
- public boolean isManualTemporaryUpperCaseFromAuto() {
+ public boolean isManualShiftedFromAutomaticShifted() {
return mState == MANUAL_SHIFTED_FROM_AUTO;
}
@@ -123,13 +119,13 @@ public class KeyboardShiftState {
private static String toString(int state) {
switch (state) {
- case NORMAL: return "NORMAL";
+ case UNSHIFTED: return "UNSHIFTED";
case MANUAL_SHIFTED: return "MANUAL_SHIFTED";
case MANUAL_SHIFTED_FROM_AUTO: return "MANUAL_SHIFTED_FROM_AUTO";
- case AUTO_SHIFTED: return "AUTO_SHIFTED";
+ case AUTOMATIC_SHIFTED: return "AUTOMATIC_SHIFTED";
case SHIFT_LOCKED: return "SHIFT_LOCKED";
case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED";
- default: return "UKNOWN";
+ default: return "UNKNOWN";
}
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
new file mode 100644
index 000000000..c4452a5f5
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2010 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 static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED;
+
+import android.text.TextUtils;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * The string parser of more keys specification.
+ * The specification is comma separated texts each of which represents one "more key".
+ * The specification might have label or string resource reference in it. These references are
+ * expanded before parsing comma.
+ * - Label reference should be a string representation of label (!text/label_name)
+ * - String resource reference should be a string representation of resource (!text/resource_name)
+ * Each "more key" specification is one of the following:
+ * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText).
+ * - Icon followed by keyOutputText or code (!icon/icon_name|!code/code_name)
+ * - Icon should be a string representation of icon (!icon/icon_name).
+ * - Code should be a code point presented by hexadecimal string prefixed with "0x", or a string
+ * representation of code (!code/code_name).
+ * Special character, comma ',' backslash '\', and bar '|' can be escaped by '\' character.
+ * Note that the '\' is also parsed by XML parser and CSV parser as well.
+ * See {@link KeyboardIconsSet} about icon_name.
+ */
+public class KeySpecParser {
+ private static final boolean DEBUG = LatinImeLogger.sDBG;
+
+ private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
+
+ // Constants for parsing.
+ private static int COMMA = ',';
+ private static final char ESCAPE_CHAR = '\\';
+ private static final char LABEL_END = '|';
+ private static final String PREFIX_TEXT = "!text/";
+ private static final String PREFIX_ICON = "!icon/";
+ private static final String PREFIX_CODE = "!code/";
+ private static final String PREFIX_HEX = "0x";
+ private static final String ADDITIONAL_MORE_KEY_MARKER = "%";
+
+ public static class MoreKeySpec {
+ public final int mCode;
+ public final String mLabel;
+ public final String mOutputText;
+ public final int mIconId;
+
+ public MoreKeySpec(final String moreKeySpec, boolean needsToUpperCase, Locale locale,
+ final KeyboardCodesSet codesSet) {
+ mCode = toUpperCaseOfCodeForLocale(getCode(moreKeySpec, codesSet),
+ needsToUpperCase, locale);
+ mLabel = toUpperCaseOfStringForLocale(getLabel(moreKeySpec),
+ needsToUpperCase, locale);
+ mOutputText = toUpperCaseOfStringForLocale(getOutputText(moreKeySpec),
+ needsToUpperCase, locale);
+ mIconId = getIconId(moreKeySpec);
+ }
+ }
+
+ private KeySpecParser() {
+ // Intentional empty constructor for utility class.
+ }
+
+ private static boolean hasIcon(String moreKeySpec) {
+ return moreKeySpec.startsWith(PREFIX_ICON);
+ }
+
+ private static boolean hasCode(String moreKeySpec) {
+ final int end = indexOfLabelEnd(moreKeySpec, 0);
+ if (end > 0 && end + 1 < moreKeySpec.length() && moreKeySpec.startsWith(
+ PREFIX_CODE, end + 1)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static String parseEscape(String text) {
+ if (text.indexOf(ESCAPE_CHAR) < 0) {
+ return text;
+ }
+ final int length = text.length();
+ final StringBuilder sb = new StringBuilder();
+ for (int pos = 0; pos < length; pos++) {
+ final char c = text.charAt(pos);
+ if (c == ESCAPE_CHAR && pos + 1 < length) {
+ // Skip escape char
+ pos++;
+ sb.append(text.charAt(pos));
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ private static int indexOfLabelEnd(String moreKeySpec, int start) {
+ if (moreKeySpec.indexOf(ESCAPE_CHAR, start) < 0) {
+ final int end = moreKeySpec.indexOf(LABEL_END, start);
+ if (end == 0) {
+ throw new KeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec);
+ }
+ return end;
+ }
+ final int length = moreKeySpec.length();
+ for (int pos = start; pos < length; pos++) {
+ final char c = moreKeySpec.charAt(pos);
+ if (c == ESCAPE_CHAR && pos + 1 < length) {
+ // Skip escape char
+ pos++;
+ } else if (c == LABEL_END) {
+ return pos;
+ }
+ }
+ return -1;
+ }
+
+ public static String getLabel(String moreKeySpec) {
+ if (hasIcon(moreKeySpec)) {
+ return null;
+ }
+ final int end = indexOfLabelEnd(moreKeySpec, 0);
+ final String label = (end > 0) ? parseEscape(moreKeySpec.substring(0, end))
+ : parseEscape(moreKeySpec);
+ if (TextUtils.isEmpty(label)) {
+ throw new KeySpecParserError("Empty label: " + moreKeySpec);
+ }
+ return label;
+ }
+
+ private static String getOutputTextInternal(String moreKeySpec) {
+ final int end = indexOfLabelEnd(moreKeySpec, 0);
+ if (end <= 0) {
+ return null;
+ }
+ if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
+ throw new KeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec);
+ }
+ return parseEscape(moreKeySpec.substring(end + /* LABEL_END */1));
+ }
+
+ static String getOutputText(String moreKeySpec) {
+ if (hasCode(moreKeySpec)) {
+ return null;
+ }
+ final String outputText = getOutputTextInternal(moreKeySpec);
+ if (outputText != null) {
+ if (StringUtils.codePointCount(outputText) == 1) {
+ // If output text is one code point, it should be treated as a code.
+ // See {@link #getCode(Resources, String)}.
+ return null;
+ }
+ if (!TextUtils.isEmpty(outputText)) {
+ return outputText;
+ }
+ throw new KeySpecParserError("Empty outputText: " + moreKeySpec);
+ }
+ final String label = getLabel(moreKeySpec);
+ if (label == null) {
+ throw new KeySpecParserError("Empty label: " + moreKeySpec);
+ }
+ // Code is automatically generated for one letter label. See {@link getCode()}.
+ return (StringUtils.codePointCount(label) == 1) ? null : label;
+ }
+
+ static int getCode(String moreKeySpec, KeyboardCodesSet codesSet) {
+ if (hasCode(moreKeySpec)) {
+ final int end = indexOfLabelEnd(moreKeySpec, 0);
+ if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) {
+ throw new KeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec);
+ }
+ return parseCode(moreKeySpec.substring(end + 1), codesSet, Keyboard.CODE_UNSPECIFIED);
+ }
+ final String outputText = getOutputTextInternal(moreKeySpec);
+ if (outputText != null) {
+ // If output text is one code point, it should be treated as a code.
+ // See {@link #getOutputText(String)}.
+ if (StringUtils.codePointCount(outputText) == 1) {
+ return outputText.codePointAt(0);
+ }
+ return Keyboard.CODE_OUTPUT_TEXT;
+ }
+ final String label = getLabel(moreKeySpec);
+ // Code is automatically generated for one letter label.
+ if (StringUtils.codePointCount(label) == 1) {
+ return label.codePointAt(0);
+ }
+ return Keyboard.CODE_OUTPUT_TEXT;
+ }
+
+ public static int parseCode(String text, KeyboardCodesSet codesSet, int defCode) {
+ if (text == null) return defCode;
+ if (text.startsWith(PREFIX_CODE)) {
+ return codesSet.getCode(text.substring(PREFIX_CODE.length()));
+ } else if (text.startsWith(PREFIX_HEX)) {
+ return Integer.parseInt(text.substring(PREFIX_HEX.length()), 16);
+ } else {
+ return Integer.parseInt(text);
+ }
+ }
+
+ public static int getIconId(String moreKeySpec) {
+ if (moreKeySpec != null && hasIcon(moreKeySpec)) {
+ final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length());
+ final String name = (end < 0) ? moreKeySpec.substring(PREFIX_ICON.length())
+ : moreKeySpec.substring(PREFIX_ICON.length(), end);
+ return KeyboardIconsSet.getIconId(name);
+ }
+ return KeyboardIconsSet.ICON_UNDEFINED;
+ }
+
+ private static <T> ArrayList<T> arrayAsList(T[] array, int start, int end) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ if (start < 0 || start > end || end > array.length) {
+ throw new IllegalArgumentException();
+ }
+
+ final ArrayList<T> list = new ArrayList<T>(end - start);
+ for (int i = start; i < end; i++) {
+ list.add(array[i]);
+ }
+ return list;
+ }
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ private static String[] filterOutEmptyString(String[] array) {
+ if (array == null) {
+ return EMPTY_STRING_ARRAY;
+ }
+ ArrayList<String> out = null;
+ for (int i = 0; i < array.length; i++) {
+ final String entry = array[i];
+ if (TextUtils.isEmpty(entry)) {
+ if (out == null) {
+ out = arrayAsList(array, 0, i);
+ }
+ } else if (out != null) {
+ out.add(entry);
+ }
+ }
+ if (out == null) {
+ return array;
+ }
+ return out.toArray(new String[out.size()]);
+ }
+
+ public static String[] insertAdditionalMoreKeys(String[] moreKeySpecs,
+ String[] additionalMoreKeySpecs) {
+ final String[] moreKeys = filterOutEmptyString(moreKeySpecs);
+ final String[] additionalMoreKeys = filterOutEmptyString(additionalMoreKeySpecs);
+ final int moreKeysCount = moreKeys.length;
+ final int additionalCount = additionalMoreKeys.length;
+ ArrayList<String> out = null;
+ int additionalIndex = 0;
+ for (int moreKeyIndex = 0; moreKeyIndex < moreKeysCount; moreKeyIndex++) {
+ final String moreKeySpec = moreKeys[moreKeyIndex];
+ if (moreKeySpec.equals(ADDITIONAL_MORE_KEY_MARKER)) {
+ if (additionalIndex < additionalCount) {
+ // Replace '%' marker with additional more key specification.
+ final String additionalMoreKey = additionalMoreKeys[additionalIndex];
+ if (out != null) {
+ out.add(additionalMoreKey);
+ } else {
+ moreKeys[moreKeyIndex] = additionalMoreKey;
+ }
+ additionalIndex++;
+ } else {
+ // Filter out excessive '%' marker.
+ if (out == null) {
+ out = arrayAsList(moreKeys, 0, moreKeyIndex);
+ }
+ }
+ } else {
+ if (out != null) {
+ out.add(moreKeySpec);
+ }
+ }
+ }
+ if (additionalCount > 0 && additionalIndex == 0) {
+ // No '%' marker is found in more keys.
+ // Insert all additional more keys to the head of more keys.
+ if (DEBUG && out != null) {
+ throw new RuntimeException("Internal logic error:"
+ + " moreKeys=" + Arrays.toString(moreKeys)
+ + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
+ }
+ out = arrayAsList(additionalMoreKeys, additionalIndex, additionalCount);
+ for (int i = 0; i < moreKeysCount; i++) {
+ out.add(moreKeys[i]);
+ }
+ } else if (additionalIndex < additionalCount) {
+ // The number of '%' markers are less than additional more keys.
+ // Append remained additional more keys to the tail of more keys.
+ if (DEBUG && out != null) {
+ throw new RuntimeException("Internal logic error:"
+ + " moreKeys=" + Arrays.toString(moreKeys)
+ + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
+ }
+ out = arrayAsList(moreKeys, 0, moreKeysCount);
+ for (int i = additionalIndex; i < additionalCount; i++) {
+ out.add(additionalMoreKeys[additionalIndex]);
+ }
+ }
+ if (out == null && moreKeysCount > 0) {
+ return moreKeys;
+ } else if (out != null && out.size() > 0) {
+ return out.toArray(new String[out.size()]);
+ } else {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class KeySpecParserError extends RuntimeException {
+ public KeySpecParserError(String message) {
+ super(message);
+ }
+ }
+
+ public static String resolveTextReference(String rawText, KeyboardTextsSet textsSet) {
+ int level = 0;
+ String text = rawText;
+ StringBuilder sb;
+ do {
+ level++;
+ if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
+ throw new RuntimeException("too many @string/resource indirection: " + text);
+ }
+
+ final int prefixLen = PREFIX_TEXT.length();
+ final int size = text.length();
+ if (size < prefixLen) {
+ return text;
+ }
+
+ sb = null;
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (text.startsWith(PREFIX_TEXT, pos) && textsSet != null) {
+ if (sb == null) {
+ sb = new StringBuilder(text.substring(0, pos));
+ }
+ final int end = searchTextNameEnd(text, pos + prefixLen);
+ final String name = text.substring(pos + prefixLen, end);
+ sb.append(textsSet.getText(name));
+ pos = end - 1;
+ } else if (c == ESCAPE_CHAR) {
+ if (sb != null) {
+ // Append both escape character and escaped character.
+ sb.append(text.substring(pos, Math.min(pos + 2, size)));
+ }
+ pos++;
+ } else if (sb != null) {
+ sb.append(c);
+ }
+ }
+
+ if (sb != null) {
+ text = sb.toString();
+ }
+ } while (sb != null);
+
+ return text;
+ }
+
+ private static int searchTextNameEnd(String text, int start) {
+ final int size = text.length();
+ for (int pos = start; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ // Label name should be consisted of [a-zA-Z_0-9].
+ if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
+ continue;
+ }
+ return pos;
+ }
+ return size;
+ }
+
+ public static String[] parseCsvString(String rawText, KeyboardTextsSet textsSet) {
+ final String text = resolveTextReference(rawText, textsSet);
+ final int size = text.length();
+ if (size == 0) {
+ return null;
+ }
+ if (StringUtils.codePointCount(text) == 1) {
+ return text.codePointAt(0) == COMMA ? null : new String[] { text };
+ }
+
+ ArrayList<String> list = null;
+ int start = 0;
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (c == COMMA) {
+ // Skip empty entry.
+ if (pos - start > 0) {
+ if (list == null) {
+ list = new ArrayList<String>();
+ }
+ list.add(text.substring(start, pos));
+ }
+ // Skip comma
+ start = pos + 1;
+ } else if (c == ESCAPE_CHAR) {
+ // Skip escape character and escaped character.
+ pos++;
+ }
+ }
+ final String remain = (size - start > 0) ? text.substring(start) : null;
+ if (list == null) {
+ return remain != null ? new String[] { remain } : null;
+ }
+ if (remain != null) {
+ list.add(remain);
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ public static int getIntValue(String[] moreKeys, String key, int defaultValue) {
+ if (moreKeys == null) {
+ return defaultValue;
+ }
+ final int keyLen = key.length();
+ boolean foundValue = false;
+ int value = defaultValue;
+ for (int i = 0; i < moreKeys.length; i++) {
+ final String moreKeySpec = moreKeys[i];
+ if (moreKeySpec == null || !moreKeySpec.startsWith(key)) {
+ continue;
+ }
+ moreKeys[i] = null;
+ try {
+ if (!foundValue) {
+ value = Integer.parseInt(moreKeySpec.substring(keyLen));
+ foundValue = true;
+ }
+ } catch (NumberFormatException e) {
+ throw new RuntimeException(
+ "integer should follow after " + key + ": " + moreKeySpec);
+ }
+ }
+ return value;
+ }
+
+ public static boolean getBooleanValue(String[] moreKeys, String key) {
+ if (moreKeys == null) {
+ return false;
+ }
+ boolean value = false;
+ for (int i = 0; i < moreKeys.length; i++) {
+ final String moreKeySpec = moreKeys[i];
+ if (moreKeySpec == null || !moreKeySpec.equals(key)) {
+ continue;
+ }
+ moreKeys[i] = null;
+ value = true;
+ }
+ return value;
+ }
+
+ public static int toUpperCaseOfCodeForLocale(int code, boolean needsToUpperCase,
+ Locale locale) {
+ if (!Keyboard.isLetterCode(code) || !needsToUpperCase) return code;
+ final String text = new String(new int[] { code } , 0, 1);
+ final String casedText = KeySpecParser.toUpperCaseOfStringForLocale(
+ text, needsToUpperCase, locale);
+ return StringUtils.codePointCount(casedText) == 1
+ ? casedText.codePointAt(0) : CODE_UNSPECIFIED;
+ }
+
+ public static String toUpperCaseOfStringForLocale(String text, boolean needsToUpperCase,
+ Locale locale) {
+ if (text == null || !needsToUpperCase) return text;
+ return text.toUpperCase(locale);
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 30d9692a8..80f4f259b 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -17,225 +17,208 @@
package com.android.inputmethod.keyboard.internal;
import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
import android.util.Log;
-import com.android.inputmethod.keyboard.internal.KeyboardParser.ParseException;
+import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.XmlParseUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
-import java.util.ArrayList;
import java.util.HashMap;
public class KeyStyles {
- private static final String TAG = "KeyStyles";
+ private static final String TAG = KeyStyles.class.getSimpleName();
private static final boolean DEBUG = false;
- private final HashMap<String, DeclaredKeyStyle> mStyles =
- new HashMap<String, DeclaredKeyStyle>();
- private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle();
+ final HashMap<String, KeyStyle> mStyles = new HashMap<String, KeyStyle>();
+
+ final KeyboardTextsSet mTextsSet;
+ private final KeyStyle mEmptyKeyStyle;
+ private static final String EMPTY_STYLE_NAME = "<empty>";
- public interface KeyStyle {
- public CharSequence[] getTextArray(TypedArray a, int index);
- public CharSequence getText(TypedArray a, int index);
- public int getInt(TypedArray a, int index, int defaultValue);
- public int getFlag(TypedArray a, int index, int defaultValue);
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue);
+ public KeyStyles(KeyboardTextsSet textsSet) {
+ mTextsSet = textsSet;
+ mEmptyKeyStyle = new EmptyKeyStyle();
+ mStyles.put(EMPTY_STYLE_NAME, mEmptyKeyStyle);
}
- /* package */ static class EmptyKeyStyle implements KeyStyle {
- private EmptyKeyStyle() {
- // Nothing to do.
+ public abstract class KeyStyle {
+ public abstract String[] getStringArray(TypedArray a, int index);
+ public abstract String getString(TypedArray a, int index);
+ public abstract int getInt(TypedArray a, int index, int defaultValue);
+ public abstract int getFlag(TypedArray a, int index);
+
+ protected String parseString(TypedArray a, int index) {
+ if (a.hasValue(index)) {
+ return KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
+ }
+ return null;
}
- @Override
- public CharSequence[] getTextArray(TypedArray a, int index) {
- return parseTextArray(a, index);
+ protected String[] parseStringArray(TypedArray a, int index) {
+ if (a.hasValue(index)) {
+ return KeySpecParser.parseCsvString(a.getString(index), mTextsSet);
+ }
+ return null;
}
+ }
+ class EmptyKeyStyle extends KeyStyle {
@Override
- public CharSequence getText(TypedArray a, int index) {
- return a.getText(index);
+ public String[] getStringArray(TypedArray a, int index) {
+ return parseStringArray(a, index);
}
@Override
- public int getInt(TypedArray a, int index, int defaultValue) {
- return a.getInt(index, defaultValue);
+ public String getString(TypedArray a, int index) {
+ return parseString(a, index);
}
@Override
- public int getFlag(TypedArray a, int index, int defaultValue) {
+ public int getInt(TypedArray a, int index, int defaultValue) {
return a.getInt(index, defaultValue);
}
@Override
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
- return a.getBoolean(index, defaultValue);
- }
-
- protected static CharSequence[] parseTextArray(TypedArray a, int index) {
- if (!a.hasValue(index))
- return null;
- final CharSequence text = a.getText(index);
- return parseCsvText(text);
- }
-
- /* package */ static CharSequence[] parseCsvText(CharSequence text) {
- final int size = text.length();
- if (size == 0) return null;
- if (size == 1) return new CharSequence[] { text };
- final StringBuilder sb = new StringBuilder();
- ArrayList<CharSequence> list = null;
- int start = 0;
- for (int pos = 0; pos < size; pos++) {
- final char c = text.charAt(pos);
- if (c == ',') {
- if (list == null) list = new ArrayList<CharSequence>();
- if (sb.length() == 0) {
- list.add(text.subSequence(start, pos));
- } else {
- list.add(sb.toString());
- sb.setLength(0);
- }
- start = pos + 1;
- continue;
- } else if (c == '\\') {
- if (start == pos) {
- // Skip escape character at the beginning of the value.
- start++;
- pos++;
- } else {
- if (start < pos && sb.length() == 0)
- sb.append(text.subSequence(start, pos));
- pos++;
- if (pos < size)
- sb.append(text.charAt(pos));
- }
- } else if (sb.length() > 0) {
- sb.append(c);
- }
- }
- if (list == null) {
- return new CharSequence[] { sb.length() > 0 ? sb : text.subSequence(start, size) };
- } else {
- list.add(sb.length() > 0 ? sb : text.subSequence(start, size));
- return list.toArray(new CharSequence[list.size()]);
- }
+ public int getFlag(TypedArray a, int index) {
+ return a.getInt(index, 0);
}
}
- private static class DeclaredKeyStyle extends EmptyKeyStyle {
- private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
+ private class DeclaredKeyStyle extends KeyStyle {
+ private final String mParentStyleName;
+ private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>();
- @Override
- public CharSequence[] getTextArray(TypedArray a, int index) {
- return a.hasValue(index)
- ? super.getTextArray(a, index) : (CharSequence[])mAttributes.get(index);
+ public DeclaredKeyStyle(String parentStyleName) {
+ mParentStyleName = parentStyleName;
}
@Override
- public CharSequence getText(TypedArray a, int index) {
- return a.hasValue(index)
- ? super.getText(a, index) : (CharSequence)mAttributes.get(index);
+ public String[] getStringArray(TypedArray a, int index) {
+ if (a.hasValue(index)) {
+ return parseStringArray(a, index);
+ }
+ if (mStyleAttributes.containsKey(index)) {
+ return (String[])mStyleAttributes.get(index);
+ }
+ final KeyStyle parentStyle = mStyles.get(mParentStyleName);
+ return parentStyle.getStringArray(a, index);
}
@Override
- public int getInt(TypedArray a, int index, int defaultValue) {
- final Integer value = (Integer)mAttributes.get(index);
- return super.getInt(a, index, (value != null) ? value : defaultValue);
+ public String getString(TypedArray a, int index) {
+ if (a.hasValue(index)) {
+ return parseString(a, index);
+ }
+ if (mStyleAttributes.containsKey(index)) {
+ return (String)mStyleAttributes.get(index);
+ }
+ final KeyStyle parentStyle = mStyles.get(mParentStyleName);
+ return parentStyle.getString(a, index);
}
@Override
- public int getFlag(TypedArray a, int index, int defaultValue) {
- final Integer value = (Integer)mAttributes.get(index);
- return super.getFlag(a, index, defaultValue) | (value != null ? value : 0);
+ public int getInt(TypedArray a, int index, int defaultValue) {
+ if (a.hasValue(index)) {
+ return a.getInt(index, defaultValue);
+ }
+ if (mStyleAttributes.containsKey(index)) {
+ return (Integer)mStyleAttributes.get(index);
+ }
+ final KeyStyle parentStyle = mStyles.get(mParentStyleName);
+ return parentStyle.getInt(a, index, defaultValue);
}
@Override
- public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
- final Boolean value = (Boolean)mAttributes.get(index);
- return super.getBoolean(a, index, (value != null) ? value : defaultValue);
- }
-
- private DeclaredKeyStyle() {
- super();
+ public int getFlag(TypedArray a, int index) {
+ int value = a.getInt(index, 0);
+ if (mStyleAttributes.containsKey(index)) {
+ value |= (Integer)mStyleAttributes.get(index);
+ }
+ final KeyStyle parentStyle = mStyles.get(mParentStyleName);
+ return value | parentStyle.getFlag(a, index);
}
- private void parseKeyStyleAttributes(TypedArray keyAttr) {
+ void readKeyAttributes(TypedArray keyAttr) {
// TODO: Currently not all Key attributes can be declared as style.
- readInt(keyAttr, R.styleable.Keyboard_Key_code);
- readText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
- readText(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
- readText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
- readTextArray(keyAttr, R.styleable.Keyboard_Key_popupCharacters);
- readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIconPreview);
- readInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted);
- readInt(keyAttr, R.styleable.Keyboard_Key_maxPopupKeyboardColumn);
- readBoolean(keyAttr, R.styleable.Keyboard_Key_isFunctional);
- readBoolean(keyAttr, R.styleable.Keyboard_Key_isSticky);
- readBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable);
- readBoolean(keyAttr, R.styleable.Keyboard_Key_enabled);
- }
-
- private void readText(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getText(index));
+ readString(keyAttr, R.styleable.Keyboard_Key_code);
+ readString(keyAttr, R.styleable.Keyboard_Key_altCode);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyLabel);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyOutputText);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
+ readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
+ readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
+ readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyIcon);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
+ readString(keyAttr, R.styleable.Keyboard_Key_keyIconPreview);
+ readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
+ readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
+ readFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
+ }
+
+ private void readString(TypedArray a, int index) {
+ if (a.hasValue(index)) {
+ mStyleAttributes.put(index, parseString(a, index));
+ }
}
private void readInt(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getInt(index, 0));
+ if (a.hasValue(index)) {
+ mStyleAttributes.put(index, a.getInt(index, 0));
+ }
}
private void readFlag(TypedArray a, int index) {
- final Integer value = (Integer)mAttributes.get(index);
- if (a.hasValue(index))
- mAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0));
- }
-
- private void readBoolean(TypedArray a, int index) {
- if (a.hasValue(index))
- mAttributes.put(index, a.getBoolean(index, false));
- }
-
- private void readTextArray(TypedArray a, int index) {
- final CharSequence[] value = parseTextArray(a, index);
- if (value != null)
- mAttributes.put(index, value);
+ if (a.hasValue(index)) {
+ final Integer value = (Integer)mStyleAttributes.get(index);
+ mStyleAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0));
+ }
}
- private void addParent(DeclaredKeyStyle parentStyle) {
- mAttributes.putAll(parentStyle.mAttributes);
+ private void readStringArray(TypedArray a, int index) {
+ if (a.hasValue(index)) {
+ mStyleAttributes.put(index, parseStringArray(a, index));
+ }
}
}
public void parseKeyStyleAttributes(TypedArray keyStyleAttr, TypedArray keyAttrs,
- XmlResourceParser parser) {
- String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
- if (DEBUG) Log.d(TAG, String.format("<%s styleName=%s />",
- KeyboardParser.TAG_KEY_STYLE, styleName));
- if (mStyles.containsKey(styleName))
- throw new ParseException("duplicate key style declared: " + styleName, parser);
-
- final DeclaredKeyStyle style = new DeclaredKeyStyle();
+ XmlPullParser parser) throws XmlPullParserException {
+ final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
+ if (DEBUG) {
+ Log.d(TAG, String.format("<%s styleName=%s />",
+ Keyboard.Builder.TAG_KEY_STYLE, styleName));
+ if (mStyles.containsKey(styleName)) {
+ Log.d(TAG, "key-style " + styleName + " is overridden at "
+ + parser.getPositionDescription());
+ }
+ }
+
+ String parentStyleName = EMPTY_STYLE_NAME;
if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) {
- String parentStyle = keyStyleAttr.getString(
- R.styleable.Keyboard_KeyStyle_parentStyle);
- final DeclaredKeyStyle parent = mStyles.get(parentStyle);
- if (parent == null)
- throw new ParseException("Unknown parentStyle " + parent, parser);
- style.addParent(parent);
- }
- style.parseKeyStyleAttributes(keyAttrs);
+ parentStyleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_parentStyle);
+ if (!mStyles.containsKey(parentStyleName)) {
+ throw new XmlParseUtils.ParseException(
+ "Unknown parentStyle " + parentStyleName, parser);
+ }
+ }
+ final DeclaredKeyStyle style = new DeclaredKeyStyle(parentStyleName);
+ style.readKeyAttributes(keyAttrs);
mStyles.put(styleName, style);
}
- public KeyStyle getKeyStyle(String styleName) {
+ public KeyStyle getKeyStyle(TypedArray keyAttr, XmlPullParser parser)
+ throws XmlParseUtils.ParseException {
+ if (!keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
+ return mEmptyKeyStyle;
+ }
+ final String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
+ if (!mStyles.containsKey(styleName)) {
+ throw new XmlParseUtils.ParseException("Unknown key style: " + styleName, parser);
+ }
return mStyles.get(styleName);
}
-
- public KeyStyle getEmptyKeyStyle() {
- return EMPTY_KEY_STYLE;
- }
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
new file mode 100644
index 000000000..f7981a320
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import com.android.inputmethod.keyboard.Keyboard;
+
+import java.util.HashMap;
+
+public class KeyboardCodesSet {
+ private static final HashMap<String, int[]> sLanguageToCodesMap =
+ new HashMap<String, int[]>();
+ private static final HashMap<String, Integer> sNameToIdMap = new HashMap<String, Integer>();
+
+ private int[] mCodes = DEFAULT;
+
+ public void setLanguage(final String language) {
+ final int[] codes = sLanguageToCodesMap.get(language);
+ mCodes = (codes != null) ? codes : DEFAULT;
+ }
+
+ public int getCode(final String name) {
+ Integer id = sNameToIdMap.get(name);
+ if (id == null) throw new RuntimeException("Unknown key code: " + name);
+ return mCodes[id];
+ }
+
+ private static final String[] ID_TO_NAME = {
+ "key_tab",
+ "key_enter",
+ "key_space",
+ "key_shift",
+ "key_switch_alpha_symbol",
+ "key_output_text",
+ "key_delete",
+ "key_settings",
+ "key_shortcut",
+ "key_action_enter",
+ "key_action_next",
+ "key_action_previous",
+ "key_language_switch",
+ "key_research",
+ "key_unspecified",
+ "key_left_parenthesis",
+ "key_right_parenthesis",
+ "key_less_than",
+ "key_greater_than",
+ "key_left_square_bracket",
+ "key_right_square_bracket",
+ "key_left_curly_bracket",
+ "key_right_curly_bracket",
+ };
+
+ private static final int CODE_LEFT_PARENTHESIS = '(';
+ private static final int CODE_RIGHT_PARENTHESIS = ')';
+ private static final int CODE_LESS_THAN_SIGN = '<';
+ private static final int CODE_GREATER_THAN_SIGN = '>';
+ private static final int CODE_LEFT_SQUARE_BRACKET = '[';
+ private static final int CODE_RIGHT_SQUARE_BRACKET = ']';
+ private static final int CODE_LEFT_CURLY_BRACKET = '{';
+ private static final int CODE_RIGHT_CURLY_BRACKET = '}';
+
+ private static final int[] DEFAULT = {
+ Keyboard.CODE_TAB,
+ Keyboard.CODE_ENTER,
+ Keyboard.CODE_SPACE,
+ Keyboard.CODE_SHIFT,
+ Keyboard.CODE_SWITCH_ALPHA_SYMBOL,
+ Keyboard.CODE_OUTPUT_TEXT,
+ Keyboard.CODE_DELETE,
+ Keyboard.CODE_SETTINGS,
+ Keyboard.CODE_SHORTCUT,
+ Keyboard.CODE_ACTION_ENTER,
+ Keyboard.CODE_ACTION_NEXT,
+ Keyboard.CODE_ACTION_PREVIOUS,
+ Keyboard.CODE_LANGUAGE_SWITCH,
+ Keyboard.CODE_RESEARCH,
+ Keyboard.CODE_UNSPECIFIED,
+ CODE_LEFT_PARENTHESIS,
+ CODE_RIGHT_PARENTHESIS,
+ CODE_LESS_THAN_SIGN,
+ CODE_GREATER_THAN_SIGN,
+ CODE_LEFT_SQUARE_BRACKET,
+ CODE_RIGHT_SQUARE_BRACKET,
+ CODE_LEFT_CURLY_BRACKET,
+ CODE_RIGHT_CURLY_BRACKET,
+ };
+
+ private static final int[] RTL = {
+ DEFAULT[0],
+ DEFAULT[1],
+ DEFAULT[2],
+ DEFAULT[3],
+ DEFAULT[4],
+ DEFAULT[5],
+ DEFAULT[6],
+ DEFAULT[7],
+ DEFAULT[8],
+ DEFAULT[9],
+ DEFAULT[10],
+ DEFAULT[11],
+ DEFAULT[12],
+ DEFAULT[13],
+ DEFAULT[14],
+ CODE_RIGHT_PARENTHESIS,
+ CODE_LEFT_PARENTHESIS,
+ CODE_GREATER_THAN_SIGN,
+ CODE_LESS_THAN_SIGN,
+ CODE_RIGHT_SQUARE_BRACKET,
+ CODE_LEFT_SQUARE_BRACKET,
+ CODE_RIGHT_CURLY_BRACKET,
+ CODE_LEFT_CURLY_BRACKET,
+ };
+
+ private static final String LANGUAGE_DEFAULT = "DEFAULT";
+ private static final String LANGUAGE_ARABIC = "ar";
+ private static final String LANGUAGE_PERSIAN = "fa";
+ private static final String LANGUAGE_HEBREW = "iw";
+
+ private static final Object[] LANGUAGE_AND_CODES = {
+ LANGUAGE_DEFAULT, DEFAULT,
+ LANGUAGE_ARABIC, RTL,
+ LANGUAGE_PERSIAN, RTL,
+ LANGUAGE_HEBREW, RTL,
+ };
+
+ static {
+ for (int i = 0; i < ID_TO_NAME.length; i++) {
+ sNameToIdMap.put(ID_TO_NAME[i], i);
+ }
+
+ for (int i = 0; i < LANGUAGE_AND_CODES.length; i += 2) {
+ final String language = (String)LANGUAGE_AND_CODES[i];
+ final int[] codes = (int[])LANGUAGE_AND_CODES[i + 1];
+ sLanguageToCodesMap.put(language, codes);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 1530fed6f..540e63b3f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -21,96 +21,101 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.Log;
-import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.R;
+import java.util.HashMap;
+
public class KeyboardIconsSet {
private static final String TAG = KeyboardIconsSet.class.getSimpleName();
public static final int ICON_UNDEFINED = 0;
+ private static final int ATTR_UNDEFINED = 0;
+
+ private static final HashMap<Integer, Integer> ATTR_ID_TO_ICON_ID
+ = new HashMap<Integer, Integer>();
+
+ // Icon name to icon id map.
+ private static final HashMap<String, Integer> sNameToIdsMap = new HashMap<String, Integer>();
+
+ private static final Object[] NAMES_AND_ATTR_IDS = {
+ "undefined", ATTR_UNDEFINED,
+ "shift_key", R.styleable.Keyboard_iconShiftKey,
+ "delete_key", R.styleable.Keyboard_iconDeleteKey,
+ "settings_key", R.styleable.Keyboard_iconSettingsKey,
+ "space_key", R.styleable.Keyboard_iconSpaceKey,
+ "enter_key", R.styleable.Keyboard_iconEnterKey,
+ "search_key", R.styleable.Keyboard_iconSearchKey,
+ "tab_key", R.styleable.Keyboard_iconTabKey,
+ "shortcut_key", R.styleable.Keyboard_iconShortcutKey,
+ "shortcut_for_label", R.styleable.Keyboard_iconShortcutForLabel,
+ "space_key_for_number_layout", R.styleable.Keyboard_iconSpaceKeyForNumberLayout,
+ "shift_key_shifted", R.styleable.Keyboard_iconShiftKeyShifted,
+ "shortcut_key_disabled", R.styleable.Keyboard_iconShortcutKeyDisabled,
+ "tab_key_preview", R.styleable.Keyboard_iconTabKeyPreview,
+ "language_switch_key", R.styleable.Keyboard_iconLanguageSwitchKey,
+ "zwnj_key", R.styleable.Keyboard_iconZwnjKey,
+ "zwj_key", R.styleable.Keyboard_iconZwjKey,
+ };
+
+ private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
+ private static final String[] ICON_NAMES = new String[NUM_ICONS];
+ private final Drawable[] mIcons = new Drawable[NUM_ICONS];
- // This should be aligned with Keyboard.keyIcon enum.
- private static final int ICON_SHIFT_KEY = 1;
- private static final int ICON_TO_SYMBOL_KEY = 2;
- private static final int ICON_TO_SYMBOL_KEY_WITH_SHORTCUT = 3;
- private static final int ICON_DELETE_KEY = 4;
- private static final int ICON_SETTINGS_KEY = 5;
- private static final int ICON_SHORTCUT_KEY = 6;
- private static final int ICON_SPACE_KEY = 7;
- private static final int ICON_RETURN_KEY = 8;
- private static final int ICON_SEARCH_KEY = 9;
- private static final int ICON_TAB_KEY = 10;
- // This should be aligned with Keyboard.keyIconShifted enum.
- private static final int ICON_SHIFTED_SHIFT_KEY = 11;
- // This should be aligned with Keyboard.keyIconPreview enum.
- private static final int ICON_PREVIEW_SPACE_KEY = 12;
- private static final int ICON_PREVIEW_TAB_KEY = 13;
- private static final int ICON_PREVIEW_SETTINGS_KEY = 14;
- private static final int ICON_PREVIEW_SHORTCUT_KEY = 15;
-
- private static final int ICON_LAST = 15;
-
- private final Drawable mIcons[] = new Drawable[ICON_LAST + 1];
-
- private static final int getIconId(int attrIndex) {
- switch (attrIndex) {
- case R.styleable.Keyboard_iconShiftKey:
- return ICON_SHIFT_KEY;
- case R.styleable.Keyboard_iconToSymbolKey:
- return ICON_TO_SYMBOL_KEY;
- case R.styleable.Keyboard_iconToSymbolKeyWithShortcut:
- return ICON_TO_SYMBOL_KEY_WITH_SHORTCUT;
- case R.styleable.Keyboard_iconDeleteKey:
- return ICON_DELETE_KEY;
- case R.styleable.Keyboard_iconSettingsKey:
- return ICON_SETTINGS_KEY;
- case R.styleable.Keyboard_iconShortcutKey:
- return ICON_SHORTCUT_KEY;
- case R.styleable.Keyboard_iconSpaceKey:
- return ICON_SPACE_KEY;
- case R.styleable.Keyboard_iconReturnKey:
- return ICON_RETURN_KEY;
- case R.styleable.Keyboard_iconSearchKey:
- return ICON_SEARCH_KEY;
- case R.styleable.Keyboard_iconTabKey:
- return ICON_TAB_KEY;
- case R.styleable.Keyboard_iconShiftedShiftKey:
- return ICON_SHIFTED_SHIFT_KEY;
- case R.styleable.Keyboard_iconPreviewSpaceKey:
- return ICON_PREVIEW_SPACE_KEY;
- case R.styleable.Keyboard_iconPreviewTabKey:
- return ICON_PREVIEW_TAB_KEY;
- case R.styleable.Keyboard_iconPreviewSettingsKey:
- return ICON_PREVIEW_SETTINGS_KEY;
- case R.styleable.Keyboard_iconPreviewShortcutKey:
- return ICON_PREVIEW_SHORTCUT_KEY;
- default:
- return ICON_UNDEFINED;
+ static {
+ int iconId = ICON_UNDEFINED;
+ for (int i = 0; i < NAMES_AND_ATTR_IDS.length; i += 2) {
+ final String name = (String)NAMES_AND_ATTR_IDS[i];
+ final Integer attrId = (Integer)NAMES_AND_ATTR_IDS[i + 1];
+ if (attrId != ATTR_UNDEFINED) {
+ ATTR_ID_TO_ICON_ID.put(attrId, iconId);
+ }
+ sNameToIdsMap.put(name, iconId);
+ ICON_NAMES[iconId] = name;
+ iconId++;
}
}
- public void loadIcons(TypedArray keyboardAttrs) {
- final int count = keyboardAttrs.getIndexCount();
- for (int i = 0; i < count; i++) {
- final int attrIndex = keyboardAttrs.getIndex(i);
- final int iconId = getIconId(attrIndex);
- if (iconId != ICON_UNDEFINED) {
- try {
- final Drawable icon = keyboardAttrs.getDrawable(attrIndex);
- Keyboard.setDefaultBounds(icon);
- mIcons[iconId] = icon;
- } catch (Resources.NotFoundException e) {
- Log.w(TAG, "Drawable resource for icon #" + iconId + " not found");
- }
+ public void loadIcons(final TypedArray keyboardAttrs) {
+ for (final Integer attrId : ATTR_ID_TO_ICON_ID.keySet()) {
+ try {
+ final Drawable icon = keyboardAttrs.getDrawable(attrId);
+ setDefaultBounds(icon);
+ final Integer iconId = ATTR_ID_TO_ICON_ID.get(attrId);
+ mIcons[iconId] = icon;
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "Drawable resource for icon #"
+ + keyboardAttrs.getResources().getResourceEntryName(attrId)
+ + " not found");
}
}
}
- public Drawable getIcon(int iconId) {
- if (iconId == ICON_UNDEFINED)
- return null;
- if (iconId < 0 || iconId >= mIcons.length)
- throw new IllegalArgumentException("icon id is out of range: " + iconId);
- return mIcons[iconId];
+ private static boolean isValidIconId(final int iconId) {
+ return iconId >= 0 && iconId < ICON_NAMES.length;
+ }
+
+ public static String getIconName(final int iconId) {
+ return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">";
+ }
+
+ static int getIconId(final String name) {
+ Integer iconId = sNameToIdsMap.get(name);
+ if (iconId != null) {
+ return iconId;
+ }
+ throw new RuntimeException("unknown icon name: " + name);
+ }
+
+ public Drawable getIconDrawable(final int iconId) {
+ if (isValidIconId(iconId)) {
+ return mIcons[iconId];
+ }
+ throw new RuntimeException("unknown icon id: " + getIconName(iconId));
+ }
+
+ private static void setDefaultBounds(final Drawable icon) {
+ if (icon != null) {
+ icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+ }
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java
deleted file mode 100644
index a6708171f..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParser.java
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard.internal;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.util.Log;
-import android.util.TypedValue;
-import android.util.Xml;
-import android.view.InflateException;
-
-import com.android.inputmethod.compat.EditorInfoCompatUtils;
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Parser for BaseKeyboard.
- *
- * This class parses Keyboard XML file and fill out keys in Keyboard.
- * The Keyboard XML file looks like:
- * <pre>
- * &gt;!-- xml/keyboard.xml --&lt;
- * &gt;Keyboard keyboard_attributes*&lt;
- * &gt;!-- Keyboard Content --&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;!-- Row Content --&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;Spacer horizontalGap="0.2in" /&lt;
- * &gt;include keyboardLayout="@xml/other_keys"&lt;
- * ...
- * &gt;/Row&lt;
- * &gt;include keyboardLayout="@xml/other_rows"&lt;
- * ...
- * &gt;/Keyboard&lt;
- * </pre>
- * The XML file which is included in other file must have &gt;merge&lt; as root element, such as:
- * <pre>
- * &gt;!-- xml/other_keys.xml --&lt;
- * &gt;merge&lt;
- * &gt;Key key_attributes* /&lt;
- * ...
- * &gt;/merge&lt;
- * </pre>
- * and
- * <pre>
- * &gt;!-- xml/other_rows.xml --&lt;
- * &gt;merge&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;/Row&lt;
- * ...
- * &gt;/merge&lt;
- * </pre>
- * You can also use switch-case-default tags to select Rows and Keys.
- * <pre>
- * &gt;switch&lt;
- * &gt;case case_attribute*&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/case&lt;
- * ...
- * &gt;default&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/default&lt;
- * &gt;/switch&lt;
- * </pre>
- * You can declare Key style and specify styles within Key tags.
- * <pre>
- * &gt;switch&lt;
- * &gt;case mode="email"&lt;
- * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
- * keyLabel=".com"
- * /&lt;
- * &gt;/case&lt;
- * &gt;case mode="url"&lt;
- * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
- * keyLabel="http://"
- * /&lt;
- * &gt;/case&lt;
- * &gt;/switch&lt;
- * ...
- * &gt;Key keyStyle="shift-key" ... /&lt;
- * </pre>
- */
-
-public class KeyboardParser {
- private static final String TAG = KeyboardParser.class.getSimpleName();
- private static final boolean DEBUG = false;
-
- // Keyboard XML Tags
- private static final String TAG_KEYBOARD = "Keyboard";
- private static final String TAG_ROW = "Row";
- private static final String TAG_KEY = "Key";
- private static final String TAG_SPACER = "Spacer";
- private static final String TAG_INCLUDE = "include";
- private static final String TAG_MERGE = "merge";
- private static final String TAG_SWITCH = "switch";
- private static final String TAG_CASE = "case";
- private static final String TAG_DEFAULT = "default";
- public static final String TAG_KEY_STYLE = "key-style";
-
- private final Keyboard mKeyboard;
- private final Context mContext;
- private final Resources mResources;
-
- private int mKeyboardTopPadding;
- private int mKeyboardBottomPadding;
- private int mHorizontalEdgesPadding;
- private int mCurrentX = 0;
- private int mCurrentY = 0;
- private int mMaxRowWidth = 0;
- private int mTotalHeight = 0;
- private Row mCurrentRow = null;
- private final KeyStyles mKeyStyles = new KeyStyles();
-
- public KeyboardParser(Keyboard keyboard, Context context) {
- mKeyboard = keyboard;
- mContext = context;
- final Resources res = context.getResources();
- mResources = res;
- mHorizontalEdgesPadding = (int)res.getDimension(R.dimen.keyboard_horizontal_edges_padding);
- }
-
- public int getMaxRowWidth() {
- return mMaxRowWidth;
- }
-
- public int getTotalHeight() {
- return mTotalHeight;
- }
-
- public void parseKeyboard(int resId) throws XmlPullParserException, IOException {
- if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_KEYBOARD, mKeyboard.mId));
- final XmlResourceParser parser = mResources.getXml(resId);
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- parseKeyboardAttributes(parser);
- startKeyboard();
- parseKeyboardContent(parser, mKeyboard.getKeys());
- break;
- } else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
- }
- }
- }
- }
-
- public static String parseKeyboardLocale(
- Context context, int resId) throws XmlPullParserException, IOException {
- final Resources res = context.getResources();
- final XmlResourceParser parser = res.getXml(resId);
- if (parser == null) return "";
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- return keyboardAttr.getString(R.styleable.Keyboard_keyboardLocale);
- } else {
- throw new IllegalStartTag(parser, TAG_KEYBOARD);
- }
- }
- }
- return "";
- }
-
- private void parseKeyboardAttributes(XmlResourceParser parser) {
- final Keyboard keyboard = mKeyboard;
- final TypedArray keyboardAttr = mContext.obtainStyledAttributes(
- Xml.asAttributeSet(parser), R.styleable.Keyboard, R.attr.keyboardStyle,
- R.style.Keyboard);
- final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- try {
- final int displayHeight = keyboard.getDisplayHeight();
- final int keyboardHeight = (int)keyboardAttr.getDimension(
- R.styleable.Keyboard_keyboardHeight, displayHeight / 2);
- final int maxKeyboardHeight = getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2);
- int minKeyboardHeight = getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2);
- if (minKeyboardHeight < 0) {
- // Specified fraction was negative, so it should be calculated against display
- // width.
- final int displayWidth = keyboard.getDisplayWidth();
- minKeyboardHeight = -getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2);
- }
- // Keyboard height will not exceed maxKeyboardHeight and will not be less than
- // minKeyboardHeight.
- final int height = Math.max(
- Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight);
- final int width = keyboard.getDisplayWidth();
-
- keyboard.setKeyboardHeight(height);
- keyboard.setKeyWidth(getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_keyWidth, width, width / 10));
- keyboard.setRowHeight(getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_rowHeight, height, 50));
- keyboard.setHorizontalGap(getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_horizontalGap, width, 0));
- keyboard.setVerticalGap(getDimensionOrFraction(keyboardAttr,
- R.styleable.Keyboard_verticalGap, height, 0));
- keyboard.setPopupKeyboardResId(keyboardAttr.getResourceId(
- R.styleable.Keyboard_popupKeyboardTemplate, 0));
-
- keyboard.setMaxPopupKeyboardColumn(keyAttr.getInt(
- R.styleable.Keyboard_Key_maxPopupKeyboardColumn, 5));
-
- mKeyboard.mIconsSet.loadIcons(keyboardAttr);
- mKeyboardTopPadding = keyboardAttr.getDimensionPixelSize(
- R.styleable.Keyboard_keyboardTopPadding, 0);
- mKeyboardBottomPadding = keyboardAttr.getDimensionPixelSize(
- R.styleable.Keyboard_keyboardBottomPadding, 0);
- } finally {
- keyAttr.recycle();
- keyboardAttr.recycle();
- }
- }
-
- private void parseKeyboardContent(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_ROW.equals(tag)) {
- Row row = new Row(mResources, mKeyboard, parser);
- if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_ROW));
- if (keys != null)
- startRow(row);
- parseRowContent(parser, row, keys);
- } else if (TAG_INCLUDE.equals(tag)) {
- parseIncludeKeyboardContent(parser, keys);
- } else if (TAG_SWITCH.equals(tag)) {
- parseSwitchKeyboardContent(parser, keys);
- } else if (TAG_KEY_STYLE.equals(tag)) {
- parseKeyStyle(parser, keys);
- } else {
- throw new IllegalStartTag(parser, TAG_ROW);
- }
- } else if (event == XmlPullParser.END_TAG) {
- final String tag = parser.getName();
- if (TAG_KEYBOARD.equals(tag)) {
- endKeyboard(mKeyboard.getVerticalGap());
- break;
- } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
- || TAG_MERGE.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
- break;
- } else if (TAG_KEY_STYLE.equals(tag)) {
- continue;
- } else {
- throw new IllegalEndTag(parser, TAG_ROW);
- }
- }
- }
- }
-
- private void parseRowContent(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_KEY.equals(tag)) {
- parseKey(parser, row, keys);
- } else if (TAG_SPACER.equals(tag)) {
- parseSpacer(parser, row, keys);
- } else if (TAG_INCLUDE.equals(tag)) {
- parseIncludeRowContent(parser, row, keys);
- } else if (TAG_SWITCH.equals(tag)) {
- parseSwitchRowContent(parser, row, keys);
- } else if (TAG_KEY_STYLE.equals(tag)) {
- parseKeyStyle(parser, keys);
- } else {
- throw new IllegalStartTag(parser, TAG_KEY);
- }
- } else if (event == XmlPullParser.END_TAG) {
- final String tag = parser.getName();
- if (TAG_ROW.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_ROW));
- if (keys != null)
- endRow();
- break;
- } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
- || TAG_MERGE.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
- break;
- } else if (TAG_KEY_STYLE.equals(tag)) {
- continue;
- } else {
- throw new IllegalEndTag(parser, TAG_KEY);
- }
- }
- }
- }
-
- private void parseKey(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (keys == null) {
- checkEndTag(TAG_KEY, parser);
- } else {
- Key key = new Key(mResources, row, mCurrentX, mCurrentY, parser, mKeyStyles);
- if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d popupCharacters=%s />",
- TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode,
- Arrays.toString(key.mPopupCharacters)));
- checkEndTag(TAG_KEY, parser);
- keys.add(key);
- if (key.mCode == Keyboard.CODE_SHIFT)
- mKeyboard.getShiftKeys().add(key);
- endKey(key);
- }
- }
-
- private void parseSpacer(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (keys == null) {
- checkEndTag(TAG_SPACER, parser);
- } else {
- if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER));
- final TypedArray keyboardAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- if (keyboardAttr.hasValue(R.styleable.Keyboard_horizontalGap))
- throw new IllegalAttribute(parser, "horizontalGap");
- final int defaultWidth = (row != null) ? row.mDefaultWidth : 0;
- final int keyWidth = getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_keyWidth,
- mKeyboard.getDisplayWidth(), defaultWidth);
- keyboardAttr.recycle();
-
- final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- int keyXPos = KeyboardParser.getDimensionOrFraction(keyAttr,
- R.styleable.Keyboard_Key_keyXPos, mKeyboard.getDisplayWidth(), mCurrentX);
- if (keyXPos < 0) {
- // If keyXPos is negative, the actual x-coordinate will be display_width + keyXPos.
- keyXPos += mKeyboard.getDisplayWidth();
- }
-
- checkEndTag(TAG_SPACER, parser);
- setSpacer(keyXPos, keyWidth);
- }
- }
-
- private void parseIncludeKeyboardContent(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseIncludeInternal(parser, null, keys);
- }
-
- private void parseIncludeRowContent(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseIncludeInternal(parser, row, keys);
- }
-
- private void parseIncludeInternal(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (keys == null) {
- checkEndTag(TAG_INCLUDE, parser);
- } else {
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Include);
- final int keyboardLayout = a.getResourceId(
- R.styleable.Keyboard_Include_keyboardLayout, 0);
- a.recycle();
-
- checkEndTag(TAG_INCLUDE, parser);
- if (keyboardLayout == 0)
- throw new ParseException("No keyboardLayout attribute in <include/>", parser);
- if (DEBUG) Log.d(TAG, String.format("<%s keyboardLayout=%s />",
- TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout)));
- parseMerge(mResources.getLayout(keyboardLayout), row, keys);
- }
- }
-
- private void parseMerge(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_MERGE.equals(tag)) {
- if (row == null) {
- parseKeyboardContent(parser, keys);
- } else {
- parseRowContent(parser, row, keys);
- }
- break;
- } else {
- throw new ParseException(
- "Included keyboard layout must have <merge> root element", parser);
- }
- }
- }
- }
-
- private void parseSwitchKeyboardContent(XmlResourceParser parser, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseSwitchInternal(parser, null, keys);
- }
-
- private void parseSwitchRowContent(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- parseSwitchInternal(parser, row, keys);
- }
-
- private void parseSwitchInternal(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_SWITCH, mKeyboard.mId));
- boolean selected = false;
- int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final String tag = parser.getName();
- if (TAG_CASE.equals(tag)) {
- selected |= parseCase(parser, row, selected ? null : keys);
- } else if (TAG_DEFAULT.equals(tag)) {
- selected |= parseDefault(parser, row, selected ? null : keys);
- } else {
- throw new IllegalStartTag(parser, TAG_KEY);
- }
- } else if (event == XmlPullParser.END_TAG) {
- final String tag = parser.getName();
- if (TAG_SWITCH.equals(tag)) {
- if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_SWITCH));
- break;
- } else {
- throw new IllegalEndTag(parser, TAG_KEY);
- }
- }
- }
- }
-
- private boolean parseCase(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- final boolean selected = parseCaseCondition(parser);
- if (row == null) {
- // Processing Rows.
- parseKeyboardContent(parser, selected ? keys : null);
- } else {
- // Processing Keys.
- parseRowContent(parser, row, selected ? keys : null);
- }
- return selected;
- }
-
- private boolean parseCaseCondition(XmlResourceParser parser) {
- final KeyboardId id = mKeyboard.mId;
- if (id == null)
- return true;
-
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Case);
- final TypedArray viewAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.KeyboardView);
- try {
- final boolean modeMatched = matchTypedValue(a,
- R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
- final boolean navigateActionMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_navigateAction, id.mNavigateAction);
- final boolean passwordInputMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_passwordInput, id.mPasswordInput);
- final boolean hasSettingsKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey);
- final boolean f2KeyModeMatched = matchInteger(a,
- R.styleable.Keyboard_Case_f2KeyMode, id.mF2KeyMode);
- final boolean clobberSettingsKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
- final boolean voiceEnabledMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_voiceKeyEnabled, id.mVoiceKeyEnabled);
- final boolean voiceKeyMatched = matchBoolean(a,
- R.styleable.Keyboard_Case_hasVoiceKey, id.mHasVoiceKey);
- // As noted at {@link KeyboardId} class, we are interested only in enum value masked by
- // {@link android.view.inputmethod.EditorInfo#IME_MASK_ACTION} and
- // {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. So matching
- // this attribute with id.mImeOptions as integer value is enough for our purpose.
- final boolean imeActionMatched = matchInteger(a,
- R.styleable.Keyboard_Case_imeAction, id.mImeAction);
- final boolean localeCodeMatched = matchString(a,
- R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
- final boolean languageCodeMatched = matchString(a,
- R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage());
- final boolean countryCodeMatched = matchString(a,
- R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
- final boolean selected = modeMatched && navigateActionMatched && passwordInputMatched
- && hasSettingsKeyMatched && f2KeyModeMatched && clobberSettingsKeyMatched
- && voiceEnabledMatched && voiceKeyMatched && imeActionMatched &&
- localeCodeMatched && languageCodeMatched && countryCodeMatched;
-
- if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s%s%s%s%s%s> %s", TAG_CASE,
- textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"),
- booleanAttr(a, R.styleable.Keyboard_Case_navigateAction, "navigateAction"),
- booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"),
- booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"),
- textAttr(KeyboardId.f2KeyModeName(
- a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)), "f2KeyMode"),
- booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey,
- "clobberSettingsKey"),
- booleanAttr(a, R.styleable.Keyboard_Case_voiceKeyEnabled, "voiceKeyEnabled"),
- booleanAttr(a, R.styleable.Keyboard_Case_hasVoiceKey, "hasVoiceKey"),
- textAttr(EditorInfoCompatUtils.imeOptionsName(
- a.getInt(R.styleable.Keyboard_Case_imeAction, -1)), "imeAction"),
- textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), "localeCode"),
- textAttr(a.getString(R.styleable.Keyboard_Case_languageCode), "languageCode"),
- textAttr(a.getString(R.styleable.Keyboard_Case_countryCode), "countryCode"),
- Boolean.toString(selected)));
-
- return selected;
- } finally {
- a.recycle();
- viewAttr.recycle();
- }
- }
-
- private static boolean matchInteger(TypedArray a, int index, int value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || a.getInt(index, 0) == value;
- }
-
- private static boolean matchBoolean(TypedArray a, int index, boolean value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || a.getBoolean(index, false) == value;
- }
-
- private static boolean matchString(TypedArray a, int index, String value) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- return !a.hasValue(index) || stringArrayContains(a.getString(index).split("\\|"), value);
- }
-
- private static boolean matchTypedValue(TypedArray a, int index, int intValue, String strValue) {
- // If <case> does not have "index" attribute, that means this <case> is wild-card for the
- // attribute.
- final TypedValue v = a.peekValue(index);
- if (v == null)
- return true;
-
- if (isIntegerValue(v)) {
- return intValue == a.getInt(index, 0);
- } else if (isStringValue(v)) {
- return stringArrayContains(a.getString(index).split("\\|"), strValue);
- }
- return false;
- }
-
- private static boolean stringArrayContains(String[] array, String value) {
- for (final String elem : array) {
- if (elem.equals(value))
- return true;
- }
- return false;
- }
-
- private boolean parseDefault(XmlResourceParser parser, Row row, List<Key> keys)
- throws XmlPullParserException, IOException {
- if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_DEFAULT));
- if (row == null) {
- parseKeyboardContent(parser, keys);
- } else {
- parseRowContent(parser, row, keys);
- }
- return true;
- }
-
- private void parseKeyStyle(XmlResourceParser parser, List<Key> keys) {
- TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_KeyStyle);
- TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Key);
- try {
- if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
- throw new ParseException("<" + TAG_KEY_STYLE
- + "/> needs styleName attribute", parser);
- if (keys != null)
- mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
- } finally {
- keyStyleAttr.recycle();
- keyAttrs.recycle();
- }
- }
-
- private static void checkEndTag(String tag, XmlResourceParser parser)
- throws XmlPullParserException, IOException {
- if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
- return;
- throw new NonEmptyTag(tag, parser);
- }
-
- private void startKeyboard() {
- mCurrentY += mKeyboardTopPadding;
- }
-
- private void startRow(Row row) {
- mCurrentX = 0;
- setSpacer(mCurrentX, mHorizontalEdgesPadding);
- mCurrentRow = row;
- }
-
- private void endRow() {
- if (mCurrentRow == null)
- throw new InflateException("orphant end row tag");
- setSpacer(mCurrentX, mHorizontalEdgesPadding);
- if (mCurrentX > mMaxRowWidth)
- mMaxRowWidth = mCurrentX;
- mCurrentY += mCurrentRow.mDefaultHeight;
- mCurrentRow = null;
- }
-
- private void endKey(Key key) {
- mCurrentX = key.mX - key.mGap / 2 + key.mWidth + key.mGap;
- }
-
- private void endKeyboard(int defaultVerticalGap) {
- mCurrentY += mKeyboardBottomPadding;
- mTotalHeight = mCurrentY - defaultVerticalGap;
- }
-
- private void setSpacer(int keyXPos, int width) {
- mCurrentX = keyXPos + width;
- }
-
- public static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
- final TypedValue value = a.peekValue(index);
- if (value == null)
- return defValue;
- if (isFractionValue(value)) {
- // Round it to avoid values like 47.9999 from getting truncated
- return Math.round(a.getFraction(index, base, base, defValue));
- } else if (isDimensionValue(value)) {
- return a.getDimensionPixelOffset(index, defValue);
- } else if (isIntegerValue(value)) {
- // For enum value.
- return a.getInt(index, defValue);
- }
- return defValue;
- }
-
- private static boolean isFractionValue(TypedValue v) {
- return v.type == TypedValue.TYPE_FRACTION;
- }
-
- private static boolean isDimensionValue(TypedValue v) {
- return v.type == TypedValue.TYPE_DIMENSION;
- }
-
- private static boolean isIntegerValue(TypedValue v) {
- return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT;
- }
-
- private static boolean isStringValue(TypedValue v) {
- return v.type == TypedValue.TYPE_STRING;
- }
-
- @SuppressWarnings("serial")
- public static class ParseException extends InflateException {
- public ParseException(String msg, XmlResourceParser parser) {
- super(msg + " at line " + parser.getLineNumber());
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalStartTag extends ParseException {
- public IllegalStartTag(XmlResourceParser parser, String parent) {
- super("Illegal start tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalEndTag extends ParseException {
- public IllegalEndTag(XmlResourceParser parser, String parent) {
- super("Illegal end tag " + parser.getName() + " in " + parent, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class IllegalAttribute extends ParseException {
- public IllegalAttribute(XmlResourceParser parser, String attribute) {
- super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
- }
- }
-
- @SuppressWarnings("serial")
- private static class NonEmptyTag extends ParseException {
- public NonEmptyTag(String tag, XmlResourceParser parser) {
- super(tag + " must be empty tag", parser);
- }
- }
-
- private static String textAttr(String value, String name) {
- return value != null ? String.format(" %s=%s", name, value) : "";
- }
-
- private static String booleanAttr(TypedArray a, int index, String name) {
- return a.hasValue(index) ? String.format(" %s=%s", name, a.getBoolean(index, false)) : "";
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
new file mode 100644
index 000000000..4ab6832c3
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Constants;
+
+/**
+ * Keyboard state machine.
+ *
+ * This class contains all keyboard state transition logic.
+ *
+ * The input events are {@link #onLoadKeyboard(String)}, {@link #onSaveKeyboardState()},
+ * {@link #onPressKey(int, boolean, int)}, {@link #onReleaseKey(int, boolean)},
+ * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
+ * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}.
+ *
+ * The actions are {@link SwitchActions}'s methods.
+ */
+public class KeyboardState {
+ private static final String TAG = KeyboardState.class.getSimpleName();
+ private static final boolean DEBUG_EVENT = false;
+ private static final boolean DEBUG_ACTION = false;
+
+ public interface SwitchActions {
+ public void setAlphabetKeyboard();
+ public void setAlphabetManualShiftedKeyboard();
+ public void setAlphabetAutomaticShiftedKeyboard();
+ public void setAlphabetShiftLockedKeyboard();
+ public void setAlphabetShiftLockShiftedKeyboard();
+ public void setSymbolsKeyboard();
+ public void setSymbolsShiftedKeyboard();
+
+ /**
+ * Request to call back {@link KeyboardState#onUpdateShiftState(int)}.
+ */
+ public void requestUpdatingShiftState();
+
+ public void startDoubleTapTimer();
+ public boolean isInDoubleTapTimeout();
+ public void cancelDoubleTapTimer();
+ public void startLongPressTimer(int code);
+ public void cancelLongPressTimer();
+ public void hapticAndAudioFeedback(int code);
+ }
+
+ private final SwitchActions mSwitchActions;
+
+ private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift");
+ private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol");
+
+ // TODO: Merge {@link #mSwitchState}, {@link #mIsAlphabetMode}, {@link #mAlphabetShiftState},
+ // {@link #mIsSymbolShifted}, {@link #mPrevMainKeyboardWasShiftLocked}, and
+ // {@link #mPrevSymbolsKeyboardWasShifted} into single state variable.
+ private static final int SWITCH_STATE_ALPHA = 0;
+ private static final int SWITCH_STATE_SYMBOL_BEGIN = 1;
+ private static final int SWITCH_STATE_SYMBOL = 2;
+ private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3;
+ private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4;
+ private int mSwitchState = SWITCH_STATE_ALPHA;
+ private String mLayoutSwitchBackSymbols;
+
+ private boolean mIsAlphabetMode;
+ private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
+ private boolean mIsSymbolShifted;
+ private boolean mPrevMainKeyboardWasShiftLocked;
+ private boolean mPrevSymbolsKeyboardWasShifted;
+
+ // For handling long press.
+ private boolean mLongPressShiftLockFired;
+
+ // For handling double tap.
+ private boolean mIsInAlphabetUnshiftedFromShifted;
+ private boolean mIsInDoubleTapShiftKey;
+
+ private final SavedKeyboardState mSavedKeyboardState = new SavedKeyboardState();
+
+ static class SavedKeyboardState {
+ public boolean mIsValid;
+ public boolean mIsAlphabetMode;
+ public boolean mIsAlphabetShiftLocked;
+ public boolean mIsShifted;
+
+ @Override
+ public String toString() {
+ if (!mIsValid) return "INVALID";
+ if (mIsAlphabetMode) {
+ if (mIsAlphabetShiftLocked) return "ALPHABET_SHIFT_LOCKED";
+ return mIsShifted ? "ALPHABET_SHIFTED" : "ALPHABET";
+ } else {
+ return mIsShifted ? "SYMBOLS_SHIFTED" : "SYMBOLS";
+ }
+ }
+ }
+
+ public KeyboardState(SwitchActions switchActions) {
+ mSwitchActions = switchActions;
+ }
+
+ public void onLoadKeyboard(String layoutSwitchBackSymbols) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onLoadKeyboard: " + this);
+ }
+ mLayoutSwitchBackSymbols = layoutSwitchBackSymbols;
+ // Reset alphabet shift state.
+ mAlphabetShiftState.setShiftLocked(false);
+ mPrevMainKeyboardWasShiftLocked = false;
+ mPrevSymbolsKeyboardWasShifted = false;
+ mShiftKeyState.onRelease();
+ mSymbolKeyState.onRelease();
+ onRestoreKeyboardState();
+ }
+
+ public void onSaveKeyboardState() {
+ final SavedKeyboardState state = mSavedKeyboardState;
+ state.mIsAlphabetMode = mIsAlphabetMode;
+ if (mIsAlphabetMode) {
+ state.mIsAlphabetShiftLocked = mAlphabetShiftState.isShiftLocked();
+ state.mIsShifted = !state.mIsAlphabetShiftLocked
+ && mAlphabetShiftState.isShiftedOrShiftLocked();
+ } else {
+ state.mIsAlphabetShiftLocked = mPrevMainKeyboardWasShiftLocked;
+ state.mIsShifted = mIsSymbolShifted;
+ }
+ state.mIsValid = true;
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this);
+ }
+ }
+
+ private void onRestoreKeyboardState() {
+ final SavedKeyboardState state = mSavedKeyboardState;
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this);
+ }
+ if (!state.mIsValid || state.mIsAlphabetMode) {
+ setAlphabetKeyboard();
+ } else {
+ if (state.mIsShifted) {
+ setSymbolsShiftedKeyboard();
+ } else {
+ setSymbolsKeyboard();
+ }
+ }
+
+ if (!state.mIsValid) return;
+ state.mIsValid = false;
+
+ if (state.mIsAlphabetMode) {
+ setShiftLocked(state.mIsAlphabetShiftLocked);
+ if (!state.mIsAlphabetShiftLocked) {
+ setShifted(state.mIsShifted ? MANUAL_SHIFT : UNSHIFT);
+ }
+ } else {
+ mPrevMainKeyboardWasShiftLocked = state.mIsAlphabetShiftLocked;
+ }
+ }
+
+ private static final int UNSHIFT = 0;
+ private static final int MANUAL_SHIFT = 1;
+ private static final int AUTOMATIC_SHIFT = 2;
+ private static final int SHIFT_LOCK_SHIFTED = 3;
+
+ private void setShifted(int shiftMode) {
+ if (DEBUG_ACTION) {
+ Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this);
+ }
+ if (!mIsAlphabetMode) return;
+ final int prevShiftMode;
+ if (mAlphabetShiftState.isAutomaticShifted()) {
+ prevShiftMode = AUTOMATIC_SHIFT;
+ } else if (mAlphabetShiftState.isManualShifted()) {
+ prevShiftMode = MANUAL_SHIFT;
+ } else {
+ prevShiftMode = UNSHIFT;
+ }
+ switch (shiftMode) {
+ case AUTOMATIC_SHIFT:
+ mAlphabetShiftState.setAutomaticShifted();
+ if (shiftMode != prevShiftMode) {
+ mSwitchActions.setAlphabetAutomaticShiftedKeyboard();
+ }
+ break;
+ case MANUAL_SHIFT:
+ mAlphabetShiftState.setShifted(true);
+ if (shiftMode != prevShiftMode) {
+ mSwitchActions.setAlphabetManualShiftedKeyboard();
+ }
+ break;
+ case UNSHIFT:
+ mAlphabetShiftState.setShifted(false);
+ if (shiftMode != prevShiftMode) {
+ mSwitchActions.setAlphabetKeyboard();
+ }
+ break;
+ case SHIFT_LOCK_SHIFTED:
+ mAlphabetShiftState.setShifted(true);
+ mSwitchActions.setAlphabetShiftLockShiftedKeyboard();
+ break;
+ }
+ }
+
+ private void setShiftLocked(boolean shiftLocked) {
+ if (DEBUG_ACTION) {
+ Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this);
+ }
+ if (!mIsAlphabetMode) return;
+ if (shiftLocked && (!mAlphabetShiftState.isShiftLocked()
+ || mAlphabetShiftState.isShiftLockShifted())) {
+ mSwitchActions.setAlphabetShiftLockedKeyboard();
+ }
+ if (!shiftLocked && mAlphabetShiftState.isShiftLocked()) {
+ mSwitchActions.setAlphabetKeyboard();
+ }
+ mAlphabetShiftState.setShiftLocked(shiftLocked);
+ }
+
+ private void toggleAlphabetAndSymbols() {
+ if (DEBUG_ACTION) {
+ Log.d(TAG, "toggleAlphabetAndSymbols: " + this);
+ }
+ if (mIsAlphabetMode) {
+ mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
+ if (mPrevSymbolsKeyboardWasShifted) {
+ setSymbolsShiftedKeyboard();
+ } else {
+ setSymbolsKeyboard();
+ }
+ mPrevSymbolsKeyboardWasShifted = false;
+ } else {
+ mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
+ setAlphabetKeyboard();
+ if (mPrevMainKeyboardWasShiftLocked) {
+ setShiftLocked(true);
+ }
+ mPrevMainKeyboardWasShiftLocked = false;
+ }
+ }
+
+ private void toggleShiftInSymbols() {
+ if (mIsSymbolShifted) {
+ setSymbolsKeyboard();
+ } else {
+ setSymbolsShiftedKeyboard();
+ }
+ }
+
+ private void setAlphabetKeyboard() {
+ if (DEBUG_ACTION) {
+ Log.d(TAG, "setAlphabetKeyboard");
+ }
+
+ mSwitchActions.setAlphabetKeyboard();
+ mIsAlphabetMode = true;
+ mIsSymbolShifted = false;
+ mSwitchState = SWITCH_STATE_ALPHA;
+ mSwitchActions.requestUpdatingShiftState();
+ }
+
+ private void setSymbolsKeyboard() {
+ if (DEBUG_ACTION) {
+ Log.d(TAG, "setSymbolsKeyboard");
+ }
+ mSwitchActions.setSymbolsKeyboard();
+ mIsAlphabetMode = false;
+ mIsSymbolShifted = false;
+ // Reset alphabet shift state.
+ mAlphabetShiftState.setShiftLocked(false);
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ }
+
+ private void setSymbolsShiftedKeyboard() {
+ if (DEBUG_ACTION) {
+ Log.d(TAG, "setSymbolsShiftedKeyboard");
+ }
+ mSwitchActions.setSymbolsShiftedKeyboard();
+ mIsAlphabetMode = false;
+ mIsSymbolShifted = true;
+ // Reset alphabet shift state.
+ mAlphabetShiftState.setShiftLocked(false);
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ }
+
+ public void onPressKey(int code, boolean isSinglePointer, int autoCaps) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
+ + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
+ }
+ if (code == Keyboard.CODE_SHIFT) {
+ onPressShift();
+ } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
+ onPressSymbol();
+ } else {
+ mSwitchActions.cancelDoubleTapTimer();
+ mSwitchActions.cancelLongPressTimer();
+ mLongPressShiftLockFired = false;
+ mShiftKeyState.onOtherKeyPressed();
+ mSymbolKeyState.onOtherKeyPressed();
+ // It is required to reset the auto caps state when all of the following conditions
+ // are met:
+ // 1) two or more fingers are in action
+ // 2) in alphabet layout
+ // 3) not in all characters caps mode
+ // As for #3, please note that it's required to check even when the auto caps mode is
+ // off because, for example, we may be in the #1 state within the manual temporary
+ // shifted mode.
+ if (!isSinglePointer && mIsAlphabetMode && autoCaps != TextUtils.CAP_MODE_CHARACTERS) {
+ final boolean needsToResetAutoCaps = mAlphabetShiftState.isAutomaticShifted()
+ || (mAlphabetShiftState.isManualShifted() && mShiftKeyState.isReleasing());
+ if (needsToResetAutoCaps) {
+ mSwitchActions.setAlphabetKeyboard();
+ }
+ }
+ }
+ }
+
+ public void onReleaseKey(int code, boolean withSliding) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code)
+ + " sliding=" + withSliding + " " + this);
+ }
+ if (code == Keyboard.CODE_SHIFT) {
+ onReleaseShift(withSliding);
+ } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
+ onReleaseSymbol(withSliding);
+ }
+ }
+
+ private void onPressSymbol() {
+ toggleAlphabetAndSymbols();
+ mSymbolKeyState.onPress();
+ mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
+ }
+
+ private void onReleaseSymbol(boolean withSliding) {
+ if (mSymbolKeyState.isChording()) {
+ // Switch back to the previous keyboard mode if the user chords the mode change key and
+ // another key, then releases the mode change key.
+ toggleAlphabetAndSymbols();
+ } else if (!withSliding) {
+ // If the mode change key is being released without sliding, we should forget the
+ // previous symbols keyboard shift state and simply switch back to symbols layout
+ // (never symbols shifted) next time the mode gets changed to symbols layout.
+ mPrevSymbolsKeyboardWasShifted = false;
+ }
+ mSymbolKeyState.onRelease();
+ }
+
+ public void onLongPressTimeout(int code) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this);
+ }
+ if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) {
+ mLongPressShiftLockFired = true;
+ mSwitchActions.hapticAndAudioFeedback(code);
+ }
+ }
+
+ public void onUpdateShiftState(int autoCaps) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
+ }
+ updateAlphabetShiftState(autoCaps);
+ }
+
+ private void updateAlphabetShiftState(int autoCaps) {
+ if (!mIsAlphabetMode) return;
+ if (!mShiftKeyState.isReleasing()) {
+ // Ignore update shift state event while the shift key is being pressed (including
+ // chording).
+ return;
+ }
+ if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
+ if (mShiftKeyState.isReleasing() && autoCaps != Constants.TextUtils.CAP_MODE_OFF) {
+ // Only when shift key is releasing, automatic temporary upper case will be set.
+ setShifted(AUTOMATIC_SHIFT);
+ } else {
+ setShifted(mShiftKeyState.isChording() ? MANUAL_SHIFT : UNSHIFT);
+ }
+ }
+ }
+
+ private void onPressShift() {
+ mLongPressShiftLockFired = false;
+ if (mIsAlphabetMode) {
+ mIsInDoubleTapShiftKey = mSwitchActions.isInDoubleTapTimeout();
+ if (!mIsInDoubleTapShiftKey) {
+ // This is first tap.
+ mSwitchActions.startDoubleTapTimer();
+ }
+ if (mIsInDoubleTapShiftKey) {
+ if (mAlphabetShiftState.isManualShifted() || mIsInAlphabetUnshiftedFromShifted) {
+ // Shift key has been double tapped while in manual shifted or automatic
+ // shifted state.
+ setShiftLocked(true);
+ } else {
+ // Shift key has been double tapped while in normal state. This is the second
+ // tap to disable shift locked state, so just ignore this.
+ }
+ } else {
+ if (mAlphabetShiftState.isShiftLocked()) {
+ // Shift key is pressed while shift locked state, we will treat this state as
+ // shift lock shifted state and mark as if shift key pressed while normal state.
+ setShifted(SHIFT_LOCK_SHIFTED);
+ mShiftKeyState.onPress();
+ } else if (mAlphabetShiftState.isAutomaticShifted()) {
+ // Shift key is pressed while automatic shifted, we have to move to manual
+ // shifted.
+ setShifted(MANUAL_SHIFT);
+ mShiftKeyState.onPress();
+ } else if (mAlphabetShiftState.isShiftedOrShiftLocked()) {
+ // In manual shifted state, we just record shift key has been pressing while
+ // shifted state.
+ mShiftKeyState.onPressOnShifted();
+ } else {
+ // In base layout, chording or manual shifted mode is started.
+ setShifted(MANUAL_SHIFT);
+ mShiftKeyState.onPress();
+ }
+ mSwitchActions.startLongPressTimer(Keyboard.CODE_SHIFT);
+ }
+ } else {
+ // In symbol mode, just toggle symbol and symbol more keyboard.
+ toggleShiftInSymbols();
+ mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+ mShiftKeyState.onPress();
+ }
+ }
+
+ private void onReleaseShift(boolean withSliding) {
+ if (mIsAlphabetMode) {
+ final boolean isShiftLocked = mAlphabetShiftState.isShiftLocked();
+ mIsInAlphabetUnshiftedFromShifted = false;
+ if (mIsInDoubleTapShiftKey) {
+ // Double tap shift key has been handled in {@link #onPressShift}, so that just
+ // ignore this release shift key here.
+ mIsInDoubleTapShiftKey = false;
+ } else if (mLongPressShiftLockFired) {
+ setShiftLocked(!mAlphabetShiftState.isShiftLocked());
+ } else if (mShiftKeyState.isChording()) {
+ if (mAlphabetShiftState.isShiftLockShifted()) {
+ // After chording input while shift locked state.
+ setShiftLocked(true);
+ } else {
+ // After chording input while normal state.
+ setShifted(UNSHIFT);
+ }
+ } else if (mAlphabetShiftState.isShiftLockShifted() && withSliding) {
+ // In shift locked state, shift has been pressed and slid out to other key.
+ setShiftLocked(true);
+ } else if (isShiftLocked && !mAlphabetShiftState.isShiftLockShifted()
+ && (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted())
+ && !withSliding) {
+ // Shift has been long pressed, ignore this release.
+ } else if (isShiftLocked && !mShiftKeyState.isIgnoring() && !withSliding) {
+ // Shift has been pressed without chording while shift locked state.
+ setShiftLocked(false);
+ } else if (mAlphabetShiftState.isShiftedOrShiftLocked()
+ && mShiftKeyState.isPressingOnShifted() && !withSliding) {
+ // Shift has been pressed without chording while shifted state.
+ setShifted(UNSHIFT);
+ mIsInAlphabetUnshiftedFromShifted = true;
+ } else if (mAlphabetShiftState.isManualShiftedFromAutomaticShifted()
+ && mShiftKeyState.isPressing() && !withSliding) {
+ // Shift has been pressed without chording while manual shifted transited from
+ // automatic shifted
+ setShifted(UNSHIFT);
+ mIsInAlphabetUnshiftedFromShifted = true;
+ }
+ } else {
+ // In symbol mode, switch back to the previous keyboard mode if the user chords the
+ // shift key and another key, then releases the shift key.
+ if (mShiftKeyState.isChording()) {
+ toggleShiftInSymbols();
+ }
+ }
+ mShiftKeyState.onRelease();
+ }
+
+ public void onCancelInput(boolean isSinglePointer) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
+ }
+ // Switch back to the previous keyboard mode if the user cancels sliding input.
+ if (isSinglePointer) {
+ if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
+ toggleAlphabetAndSymbols();
+ } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) {
+ toggleShiftInSymbols();
+ }
+ }
+ }
+
+ public boolean isInMomentarySwitchState() {
+ return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL
+ || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE;
+ }
+
+ private static boolean isSpaceCharacter(int c) {
+ return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER;
+ }
+
+ private boolean isLayoutSwitchBackCharacter(int c) {
+ if (TextUtils.isEmpty(mLayoutSwitchBackSymbols)) return false;
+ if (mLayoutSwitchBackSymbols.indexOf(c) >= 0) return true;
+ return false;
+ }
+
+ public void onCodeInput(int code, boolean isSinglePointer, int autoCaps) {
+ if (DEBUG_EVENT) {
+ Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code)
+ + " single=" + isSinglePointer
+ + " autoCaps=" + autoCaps + " " + this);
+ }
+
+ switch (mSwitchState) {
+ case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
+ if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
+ // Detected only the mode change key has been pressed, and then released.
+ if (mIsAlphabetMode) {
+ mSwitchState = SWITCH_STATE_ALPHA;
+ } else {
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ }
+ } else if (isSinglePointer) {
+ // Switch back to the previous keyboard mode if the user pressed the mode change key
+ // and slid to other key, then released the finger.
+ // If the user cancels the sliding input, switching back to the previous keyboard
+ // mode is handled by {@link #onCancelInput}.
+ toggleAlphabetAndSymbols();
+ }
+ break;
+ case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE:
+ if (code == Keyboard.CODE_SHIFT) {
+ // Detected only the shift key has been pressed on symbol layout, and then released.
+ mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
+ } else if (isSinglePointer) {
+ // Switch back to the previous keyboard mode if the user pressed the shift key on
+ // symbol mode and slid to other key, then released the finger.
+ toggleShiftInSymbols();
+ mSwitchState = SWITCH_STATE_SYMBOL;
+ }
+ break;
+ case SWITCH_STATE_SYMBOL_BEGIN:
+ if (!isSpaceCharacter(code) && (Keyboard.isLetterCode(code)
+ || code == Keyboard.CODE_OUTPUT_TEXT)) {
+ mSwitchState = SWITCH_STATE_SYMBOL;
+ }
+ // Switch back to alpha keyboard mode immediately if user types one of the switch back
+ // characters.
+ if (isLayoutSwitchBackCharacter(code)) {
+ toggleAlphabetAndSymbols();
+ mPrevSymbolsKeyboardWasShifted = false;
+ }
+ break;
+ case SWITCH_STATE_SYMBOL:
+ // Switch back to alpha keyboard mode if user types one or more non-space/enter
+ // characters followed by a space/enter or one of the switch back characters.
+ if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) {
+ toggleAlphabetAndSymbols();
+ mPrevSymbolsKeyboardWasShifted = false;
+ }
+ break;
+ }
+
+ // If the code is a letter, update keyboard shift state.
+ if (Keyboard.isLetterCode(code)) {
+ updateAlphabetShiftState(autoCaps);
+ }
+ }
+
+ private static String shiftModeToString(int shiftMode) {
+ switch (shiftMode) {
+ case UNSHIFT: return "UNSHIFT";
+ case MANUAL_SHIFT: return "MANUAL";
+ case AUTOMATIC_SHIFT: return "AUTOMATIC";
+ default: return null;
+ }
+ }
+
+ private static String switchStateToString(int switchState) {
+ switch (switchState) {
+ case SWITCH_STATE_ALPHA: return "ALPHA";
+ case SWITCH_STATE_SYMBOL_BEGIN: return "SYMBOL-BEGIN";
+ case SWITCH_STATE_SYMBOL: return "SYMBOL";
+ case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: return "MOMENTARY-ALPHA-SYMBOL";
+ case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: return "MOMENTARY-SYMBOL-MORE";
+ default: return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[keyboard=" + (mIsAlphabetMode ? mAlphabetShiftState.toString()
+ : (mIsSymbolShifted ? "SYMBOLS_SHIFTED" : "SYMBOLS"))
+ + " shift=" + mShiftKeyState
+ + " symbol=" + mSymbolKeyState
+ + " switch=" + switchStateToString(mSwitchState) + "]";
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
new file mode 100644
index 000000000..8c218c6d3
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -0,0 +1,2511 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import com.android.inputmethod.latin.R;
+
+import java.util.HashMap;
+
+/**
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file is generated by tools/maketext. The base template file is
+ * tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl
+ *
+ * This file must be updated when any text resources in keyboard layout files have been changed.
+ * These text resources are referred as "!text/<resource_name>" in keyboard XML definitions,
+ * and should be defined in
+ * tools/maketext/res/values-<locale>/donottranslate-more-keys.xml
+ *
+ * To update this file, please run the following commands.
+ * $ cd $ANDROID_BUILD_TOP
+ * $ mmm packages/inputmethods/LatinIME/tools/maketext
+ * $ maketext -java packages/inputmethods/LatinIME/java/src
+ *
+ * The updated source file will be generated to the following path (this file).
+ * packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/internal/
+ * KeyboardTextsSet.java
+ */
+public final class KeyboardTextsSet {
+ // Language to texts map.
+ private static final HashMap<String, String[]> sLocaleToTextsMap =
+ new HashMap<String, String[]>();
+ private static final HashMap<String, Integer> sNameToIdsMap =
+ new HashMap<String, Integer>();
+
+ private String[] mTexts;
+ // Resource name to text map.
+ private HashMap<String, String> mResourceNameToTextsMap = new HashMap<String, String>();
+
+ public void setLanguage(final String language) {
+ mTexts = sLocaleToTextsMap.get(language);
+ if (mTexts == null) {
+ mTexts = LANGUAGE_DEFAULT;
+ }
+ }
+
+ public void loadStringResources(Context context) {
+ loadStringResourcesInternal(context, RESOURCE_NAMES, R.string.english_ime_name);
+ }
+
+ /* package for test */
+ void loadStringResourcesInternal(Context context, final String[] resourceNames,
+ int referenceId) {
+ final Resources res = context.getResources();
+ final String packageName = res.getResourcePackageName(referenceId);
+ for (final String resName : resourceNames) {
+ final int resId = res.getIdentifier(resName, "string", packageName);
+ mResourceNameToTextsMap.put(resName, res.getString(resId));
+ }
+ }
+
+ public String getText(final String name) {
+ String text = mResourceNameToTextsMap.get(name);
+ if (text != null) {
+ return text;
+ }
+ final Integer id = sNameToIdsMap.get(name);
+ if (id == null) throw new RuntimeException("Unknown label: " + name);
+ text = (id < mTexts.length) ? mTexts[id] : null;
+ return (text == null) ? LANGUAGE_DEFAULT[id] : text;
+ }
+
+ 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",
+ "label_previous_key",
+ // Other labels.
+ "label_to_alpha_key",
+ "label_to_symbol_key",
+ "label_to_symbol_with_microphone_key",
+ "label_pause_key",
+ "label_wait_key",
+ };
+
+ private static final String[] NAMES = {
+ /* 0 */ "more_keys_for_a",
+ /* 1 */ "more_keys_for_e",
+ /* 2 */ "more_keys_for_i",
+ /* 3 */ "more_keys_for_o",
+ /* 4 */ "more_keys_for_u",
+ /* 5 */ "more_keys_for_s",
+ /* 6 */ "more_keys_for_n",
+ /* 7 */ "more_keys_for_c",
+ /* 8 */ "more_keys_for_y",
+ /* 9 */ "more_keys_for_d",
+ /* 10 */ "more_keys_for_r",
+ /* 11 */ "more_keys_for_t",
+ /* 12 */ "more_keys_for_z",
+ /* 13 */ "more_keys_for_k",
+ /* 14 */ "more_keys_for_l",
+ /* 15 */ "more_keys_for_g",
+ /* 16 */ "more_keys_for_v",
+ /* 17 */ "more_keys_for_h",
+ /* 18 */ "more_keys_for_j",
+ /* 19 */ "more_keys_for_w",
+ /* 20 */ "keylabel_for_nordic_row1_11",
+ /* 21 */ "keylabel_for_nordic_row2_10",
+ /* 22 */ "keylabel_for_nordic_row2_11",
+ /* 23 */ "more_keys_for_nordic_row2_10",
+ /* 24 */ "more_keys_for_nordic_row2_11",
+ /* 25 */ "keylabel_for_east_slavic_row1_9",
+ /* 26 */ "keylabel_for_east_slavic_row2_1",
+ /* 27 */ "keylabel_for_east_slavic_row3_5",
+ /* 28 */ "more_keys_for_cyrillic_u",
+ /* 29 */ "more_keys_for_cyrillic_ye",
+ /* 30 */ "more_keys_for_cyrillic_en",
+ /* 31 */ "more_keys_for_cyrillic_ha",
+ /* 32 */ "more_keys_for_east_slavic_row2_1",
+ /* 33 */ "more_keys_for_cyrillic_o",
+ /* 34 */ "more_keys_for_cyrillic_soft_sign",
+ /* 35 */ "keylabel_for_south_slavic_row1_6",
+ /* 36 */ "keylabel_for_south_slavic_row2_11",
+ /* 37 */ "keylabel_for_south_slavic_row3_1",
+ /* 38 */ "keylabel_for_south_slavic_row3_8",
+ /* 39 */ "more_keys_for_cyrillic_ie",
+ /* 40 */ "more_keys_for_cyrillic_i",
+ /* 41 */ "more_keys_for_single_quote",
+ /* 42 */ "more_keys_for_double_quote",
+ /* 43 */ "more_keys_for_tablet_double_quote",
+ /* 44 */ "more_keys_for_currency_dollar",
+ /* 45 */ "more_keys_for_currency_euro",
+ /* 46 */ "more_keys_for_currency_pound",
+ /* 47 */ "more_keys_for_currency_general",
+ /* 48 */ "more_keys_for_punctuation",
+ /* 49 */ "more_keys_for_star",
+ /* 50 */ "more_keys_for_bullet",
+ /* 51 */ "more_keys_for_plus",
+ /* 52 */ "more_keys_for_left_parenthesis",
+ /* 53 */ "more_keys_for_right_parenthesis",
+ /* 54 */ "more_keys_for_less_than",
+ /* 55 */ "more_keys_for_greater_than",
+ /* 56 */ "more_keys_for_arabic_diacritics",
+ /* 57 */ "keyhintlabel_for_arabic_diacritics",
+ /* 58 */ "keylabel_for_symbols_1",
+ /* 59 */ "keylabel_for_symbols_2",
+ /* 60 */ "keylabel_for_symbols_3",
+ /* 61 */ "keylabel_for_symbols_4",
+ /* 62 */ "keylabel_for_symbols_5",
+ /* 63 */ "keylabel_for_symbols_6",
+ /* 64 */ "keylabel_for_symbols_7",
+ /* 65 */ "keylabel_for_symbols_8",
+ /* 66 */ "keylabel_for_symbols_9",
+ /* 67 */ "keylabel_for_symbols_0",
+ /* 68 */ "additional_more_keys_for_symbols_1",
+ /* 69 */ "additional_more_keys_for_symbols_2",
+ /* 70 */ "additional_more_keys_for_symbols_3",
+ /* 71 */ "additional_more_keys_for_symbols_4",
+ /* 72 */ "additional_more_keys_for_symbols_5",
+ /* 73 */ "additional_more_keys_for_symbols_6",
+ /* 74 */ "additional_more_keys_for_symbols_7",
+ /* 75 */ "additional_more_keys_for_symbols_8",
+ /* 76 */ "additional_more_keys_for_symbols_9",
+ /* 77 */ "additional_more_keys_for_symbols_0",
+ /* 78 */ "more_keys_for_symbols_1",
+ /* 79 */ "more_keys_for_symbols_2",
+ /* 80 */ "more_keys_for_symbols_3",
+ /* 81 */ "more_keys_for_symbols_4",
+ /* 82 */ "more_keys_for_symbols_5",
+ /* 83 */ "more_keys_for_symbols_6",
+ /* 84 */ "more_keys_for_symbols_7",
+ /* 85 */ "more_keys_for_symbols_8",
+ /* 86 */ "more_keys_for_symbols_9",
+ /* 87 */ "more_keys_for_symbols_0",
+ /* 88 */ "keylabel_for_comma",
+ /* 89 */ "more_keys_for_comma",
+ /* 90 */ "keylabel_for_symbols_exclamation",
+ /* 91 */ "keylabel_for_symbols_question",
+ /* 92 */ "keylabel_for_symbols_semicolon",
+ /* 93 */ "keylabel_for_symbols_percent",
+ /* 94 */ "more_keys_for_symbols_exclamation",
+ /* 95 */ "more_keys_for_symbols_question",
+ /* 96 */ "more_keys_for_symbols_semicolon",
+ /* 97 */ "more_keys_for_symbols_percent",
+ /* 98 */ "keylabel_for_tablet_comma",
+ /* 99 */ "keyhintlabel_for_tablet_comma",
+ /* 100 */ "more_keys_for_tablet_comma",
+ /* 101 */ "keyhintlabel_for_tablet_period",
+ /* 102 */ "more_keys_for_tablet_period",
+ /* 103 */ "keylabel_for_apostrophe",
+ /* 104 */ "keyhintlabel_for_apostrophe",
+ /* 105 */ "more_keys_for_apostrophe",
+ /* 106 */ "more_keys_for_am_pm",
+ /* 107 */ "settings_as_more_key",
+ /* 108 */ "shortcut_as_more_key",
+ /* 109 */ "action_next_as_more_key",
+ /* 110 */ "action_previous_as_more_key",
+ /* 111 */ "label_to_more_symbol_key",
+ /* 112 */ "label_to_more_symbol_for_tablet_key",
+ /* 113 */ "label_tab_key",
+ /* 114 */ "label_to_phone_numeric_key",
+ /* 115 */ "label_to_phone_symbols_key",
+ /* 116 */ "label_time_am",
+ /* 117 */ "label_time_pm",
+ /* 118 */ "label_to_symbol_key_pcqwerty",
+ /* 119 */ "keylabel_for_popular_domain",
+ /* 120 */ "more_keys_for_popular_domain",
+ /* 121 */ "more_keys_for_smiley",
+ };
+
+ private static final String EMPTY = "";
+
+ /* Default texts */
+ private static final String[] LANGUAGE_DEFAULT = {
+ /* 0~ */
+ 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,
+ /* ~40 */
+ /* 41 */ "!fixedColumnOrder!4,\u2018,\u2019,\u201A,\u201B",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;</string>
+ /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
+ // U+00A2: "¢" CENT SIGN
+ // U+00A3: "£" POUND SIGN
+ // U+20AC: "€" EURO SIGN
+ // U+00A5: "¥" YEN SIGN
+ // U+20B1: "₱" PESO SIGN
+ /* 44 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
+ /* 45 */ "\u00A2,\u00A3,$,\u00A5,\u20B1",
+ /* 46 */ "\u00A2,$,\u20AC,\u00A5,\u20B1",
+ /* 47 */ "\u00A2,$,\u20AC,\u00A3,\u00A5,\u20B1",
+ /* 48 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\\,,?,@,&,\\%,+,;,/,(,)",
+ // U+2020: "†" DAGGER
+ // U+2021: "‡" DOUBLE DAGGER
+ // U+2605: "★" BLACK STAR
+ /* 49 */ "\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
+ /* 50 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
+ // U+00B1: "±" PLUS-MINUS SIGN
+ /* 51 */ "\u00B1",
+ // The all letters need to be mirrored are found at
+ // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
+ /* 52 */ "!fixedColumnOrder!3,<,{,[",
+ /* 53 */ "!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
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 54 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
+ /* 55 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
+ /* 56 */ EMPTY,
+ /* 57 */ EMPTY,
+ /* 58 */ "1",
+ /* 59 */ "2",
+ /* 60 */ "3",
+ /* 61 */ "4",
+ /* 62 */ "5",
+ /* 63 */ "6",
+ /* 64 */ "7",
+ /* 65 */ "8",
+ /* 66 */ "9",
+ /* 67 */ "0",
+ /* 68~ */
+ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
+ /* ~77 */
+ // 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
+ /* 78 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
+ // U+00B2: "²" SUPERSCRIPT TWO
+ // U+2154: "⅔" VULGAR FRACTION TWO THIRDS
+ /* 79 */ "\u00B2,\u2154",
+ // U+00B3: "³" SUPERSCRIPT THREE
+ // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS
+ // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS
+ /* 80 */ "\u00B3,\u00BE,\u215C",
+ // U+2074: "⁴" SUPERSCRIPT FOUR
+ /* 81 */ "\u2074",
+ // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS
+ /* 82 */ "\u215D",
+ /* 83 */ EMPTY,
+ // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS
+ /* 84 */ "\u215E",
+ /* 85 */ EMPTY,
+ /* 86 */ EMPTY,
+ // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
+ // U+2205: "∅" EMPTY SET
+ /* 87 */ "\u207F,\u2205",
+ /* 88 */ ",",
+ /* 89 */ EMPTY,
+ /* 90 */ "!",
+ /* 91 */ "?",
+ /* 92 */ ";",
+ /* 93 */ "%",
+ // U+00A1: "¡" INVERTED EXCLAMATION MARK
+ /* 94 */ "\u00A1",
+ // U+00BF: "¿" INVERTED QUESTION MARK
+ /* 95 */ "\u00BF",
+ /* 96 */ EMPTY,
+ // U+2030: "‰" PER MILLE SIGN
+ /* 97 */ "\u2030",
+ /* 98 */ ",",
+ /* 99 */ "!",
+ /* 100 */ "!",
+ /* 101 */ "?",
+ /* 102 */ "?",
+ /* 103 */ "\'",
+ /* 104 */ "\"",
+ /* 105 */ "\"",
+ /* 106 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm",
+ /* 107 */ "!icon/settings_key|!code/key_settings",
+ /* 108 */ "!icon/shortcut_key|!code/key_shortcut",
+ /* 109 */ "!hasLabels!,!text/label_next_key|!code/key_action_next",
+ /* 110 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous",
+ // Label for "switch to more symbol" modifier key. Must be short to fit on key!
+ /* 111 */ "= \\ <",
+ // Label for "switch to more symbol" modifier key on tablets. Must be short to fit on key!
+ /* 112 */ "~ \\ {",
+ // Label for "Tab" key. Must be short to fit on key!
+ /* 113 */ "Tab",
+ // Label for "switch to phone numeric" key. Must be short to fit on key!
+ /* 114 */ "123",
+ // Label for "switch to phone symbols" key. Must be short to fit on key!
+ // U+FF0A: "*" FULLWIDTH ASTERISK
+ // U+FF03: "#" FULLWIDTH NUMBER SIGN
+ /* 115 */ "\uFF0A\uFF03",
+ // Key label for "ante meridiem"
+ /* 116 */ "AM",
+ // Key label for "post meridiem"
+ /* 117 */ "PM",
+ // Label for "switch to symbols" key on PC QWERTY layout
+ /* 118 */ "Sym",
+ /* 119 */ ".com",
+ // popular web domains for the locale - most popular, displayed on the keyboard
+ /* 120 */ "!hasLabels!,.net,.org,.gov,.edu",
+ /* 121 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ",
+ };
+
+ /* Language ar: Arabic */
+ private static final String[] LANGUAGE_ar = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~41 */
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
+ /* 44~ */
+ null, null, null, null,
+ /* ~47 */
+ // U+061F: "؟" ARABIC QUESTION MARK
+ // U+060C: "،" ARABIC COMMA
+ // U+061B: "؛" ARABIC SEMICOLON
+ /* 48 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
+ // U+2605: "★" BLACK STAR
+ // U+066D: "٭" ARABIC FIVE POINTED STAR
+ /* 49 */ "\u2605,\u066D",
+ // U+266A: "♪" EIGHTH NOTE
+ /* 50 */ "\u266A",
+ /* 51 */ 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
+ /* 52 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 53 */ "!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
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 54 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 55 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ // U+0655: "ٕ" ARABIC HAMZA BELOW
+ // U+0654: "ٔ" ARABIC HAMZA ABOVE
+ // U+0652: "ْ" ARABIC SUKUN
+ // U+064D: "ٍ" ARABIC KASRATAN
+ // U+064C: "ٌ" ARABIC DAMMATAN
+ // U+064B: "ً" ARABIC FATHATAN
+ // U+0651: "ّ" ARABIC SHADDA
+ // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF
+ // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
+ // U+0653: "ٓ" ARABIC MADDAH ABOVE
+ // U+0650: "ِ" ARABIC KASRA
+ // U+064F: "ُ" ARABIC DAMMA
+ // U+064E: "َ" ARABIC FATHA
+ // U+0640: "ـ" ARABIC TATWEEL
+ // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
+ /* 56 */ "!fixedColumnOrder!7,\u0655,\u0654,\u0652,\u064D,\u064C,\u064B,\u0651,\u0656,\u0670,\u0653,\u0650,\u064F,\u064E,\u0640\u0640\u0640|\u0640",
+ /* 57 */ "\u0651",
+ // U+0661: "١" ARABIC-INDIC DIGIT ONE
+ /* 58 */ "\u0661",
+ // U+0662: "٢" ARABIC-INDIC DIGIT TWO
+ /* 59 */ "\u0662",
+ // U+0663: "٣" ARABIC-INDIC DIGIT THREE
+ /* 60 */ "\u0663",
+ // U+0664: "٤" ARABIC-INDIC DIGIT FOUR
+ /* 61 */ "\u0664",
+ // U+0665: "٥" ARABIC-INDIC DIGIT FIVE
+ /* 62 */ "\u0665",
+ // U+0666: "٦" ARABIC-INDIC DIGIT SIX
+ /* 63 */ "\u0666",
+ // U+0667: "٧" ARABIC-INDIC DIGIT SEVEN
+ /* 64 */ "\u0667",
+ // U+0668: "٨" ARABIC-INDIC DIGIT EIGHT
+ /* 65 */ "\u0668",
+ // U+0669: "٩" ARABIC-INDIC DIGIT NINE
+ /* 66 */ "\u0669",
+ // U+0660: "٠" ARABIC-INDIC DIGIT ZERO
+ /* 67 */ "\u0660",
+ /* 68 */ "1",
+ /* 69 */ "2",
+ /* 70 */ "3",
+ /* 71 */ "4",
+ /* 72 */ "5",
+ /* 73 */ "6",
+ /* 74 */ "7",
+ /* 75 */ "8",
+ /* 76 */ "9",
+ // U+066B: "٫" ARABIC DECIMAL SEPARATOR
+ // U+066C: "٬" ARABIC THOUSANDS SEPARATOR
+ /* 77 */ "0,\u066B,\u066C",
+ /* 78~ */
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~87 */
+ // U+060C: "،" ARABIC COMMA
+ /* 88 */ "\u060C",
+ /* 89 */ "\\,",
+ /* 90 */ null,
+ /* 91 */ "\u061F",
+ /* 92 */ "\u061B",
+ // U+066A: "٪" ARABIC PERCENT SIGN
+ /* 93 */ "\u066A",
+ /* 94 */ null,
+ /* 95 */ "?",
+ /* 96 */ ";",
+ // U+2030: "‰" PER MILLE SIGN
+ /* 97 */ "\\%,\u2030",
+ /* 98~ */
+ null, null, null, null, null,
+ /* ~102 */
+ // U+060C: "،" ARABIC COMMA
+ // U+061B: "؛" ARABIC SEMICOLON
+ // U+061F: "؟" ARABIC QUESTION MARK
+ /* 103 */ "\u060C",
+ /* 104 */ "\u061F",
+ /* 105 */ "\u061F,\u061B,!,:,-,/,\',\"",
+ };
+
+ /* Language be: Belarusian */
+ private static final String[] LANGUAGE_be = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~24 */
+ // U+045E: "ў" CYRILLIC SMALL LETTER SHORT U
+ /* 25 */ "\u045E",
+ // U+044B: "ы" CYRILLIC SMALL LETTER YERU
+ /* 26 */ "\u044B",
+ // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+ /* 27 */ "\u0456",
+ /* 28~ */
+ null, null, null,
+ /* ~30 */
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 31 */ "\u044A",
+ /* 32 */ null,
+ /* 33 */ null,
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 34 */ "\u044A",
+ };
+
+ /* Language ca: Catalan */
+ private static final String[] LANGUAGE_ca = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+ /* 0 */ "\u00E0,\u00E1,\u00E4,\u00E2,\u00E3,\u00E5,\u0105,\u00E6,\u0101,\u00AA",
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E8,\u00E9,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+ /* 3 */ "\u00F2,\u00F3,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+ /* 5 */ null,
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u00F1,\u0144",
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u00E7,\u0107,\u010D",
+ /* 8~ */
+ null, null, null, null, null, null,
+ /* ~13 */
+ // U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ /* 14 */ "\u0140,\u0142",
+ };
+
+ /* Language cs: Czech */
+ private static final String[] LANGUAGE_cs = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E1,\u00E0,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u011B,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00ED,\u00EE,\u00EF,\u00EC,\u012F,\u012B",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u016F,\u00FB,\u00FC,\u00F9,\u016B",
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ /* 5 */ "\u0161,\u00DF,\u015B",
+ // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u0148,\u00F1,\u0144",
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u010D,\u00E7,\u0107",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ /* 9 */ "\u010F",
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ /* 10 */ "\u0159",
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ /* 11 */ "\u0165",
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ /* 12 */ "\u017E,\u017A,\u017C",
+ };
+
+ /* Language da: Danish */
+ private static final String[] LANGUAGE_da = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E1,\u00E4,\u00E0,\u00E2,\u00E3,\u0101",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ /* 1 */ "\u00E9,\u00EB",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ /* 2 */ "\u00ED,\u00EF",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F3,\u00F4,\u00F2,\u00F5,\u0153,\u014D",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u00DF,\u015B,\u0161",
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u00F1,\u0144",
+ /* 7 */ null,
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+00F0: "ð" LATIN SMALL LETTER ETH
+ /* 9 */ "\u00F0",
+ /* 10~ */
+ null, null, null, null,
+ /* ~13 */
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ /* 14 */ "\u0142",
+ /* 15~ */
+ null, null, null, null, null,
+ /* ~19 */
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ /* 20 */ "\u00E5",
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ /* 21 */ "\u00E6",
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 22 */ "\u00F8",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 23 */ "\u00E4",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 24 */ "\u00F6",
+ };
+
+ /* Language de: German */
+ private static final String[] LANGUAGE_de = {
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E4,\u00E2,\u00E0,\u00E1,\u00E6,\u00E3,\u00E5,\u0101",
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ /* 1 */ "\u0117",
+ /* 2 */ null,
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F6,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u00F8,\u014D",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u00DF,\u015B,\u0161",
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u00F1,\u0144",
+ };
+
+ /* Language en: English */
+ private static final String[] LANGUAGE_en = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E0,\u00E1,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101",
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113",
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ /* 2 */ "\u00EE,\u00EF,\u00ED,\u012B,\u00EC",
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ /* 3 */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8,\u014D,\u00F5",
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FB,\u00FC,\u00F9,\u00FA,\u016B",
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ /* 5 */ "\u00DF",
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ /* 6 */ "\u00F1",
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ /* 7 */ "\u00E7",
+ };
+
+ /* Language es: Spanish */
+ private static final String[] LANGUAGE_es = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+ /* 0 */ "\u00E1,\u00E0,\u00E4,\u00E2,\u00E3,\u00E5,\u0105,\u00E6,\u0101,\u00AA",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u00E8,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+ /* 3 */ "\u00F3,\u00F2,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+ /* 5 */ null,
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u00F1,\u0144",
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u00E7,\u0107,\u010D",
+ /* 8~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~47 */
+ // U+00A1: "¡" INVERTED EXCLAMATION MARK
+ // U+00BF: "¿" INVERTED QUESTION MARK
+ /* 48 */ "!fixedColumnOrder!9,\",\',#,-,\u00A1,!,\u00BF,\\,,?,@,&,\\%,+,;,:,/,(,)",
+ /* 49~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null,
+ /* ~89 */
+ // U+00A1: "¡" INVERTED EXCLAMATION MARK
+ /* 90 */ "\u00A1",
+ // U+00BF: "¿" INVERTED QUESTION MARK
+ /* 91 */ "\u00BF",
+ /* 92 */ null,
+ /* 93 */ null,
+ /* 94 */ "!",
+ /* 95 */ "?",
+ /* 96~ */
+ null, null, null,
+ /* ~98 */
+ /* 99 */ "\u00A1",
+ /* 100 */ "\u00A1,!",
+ /* 101 */ "\u00BF",
+ /* 102 */ "\u00BF,?",
+ };
+
+ /* Language et: Estonian */
+ private static final String[] LANGUAGE_et = {
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ /* 0 */ "\u00E4,\u0101,\u00E0,\u00E1,\u00E2,\u00E3,\u00E5,\u00E6,\u0105",
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+ /* 1 */ "\u0113,\u00E8,\u0117,\u00E9,\u00EA,\u00EB,\u0119,\u011B",
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ /* 2 */ "\u012B,\u00EC,\u012F,\u00ED,\u00EE,\u00EF,\u0131",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 3 */ "\u00F6,\u00F5,\u00F2,\u00F3,\u00F4,\u0153,\u0151,\u00F8",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+ // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ /* 4 */ "\u00FC,\u016B,\u0173,\u00F9,\u00FA,\u00FB,\u016F,\u0171",
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ /* 5 */ "\u0161,\u00DF,\u015B,\u015F",
+ // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u0146,\u00F1,\u0144,\u0144",
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u010D,\u00E7,\u0107",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ /* 9 */ "\u010F",
+ // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+ /* 10 */ "\u0157,\u0159,\u0155",
+ // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ /* 11 */ "\u0163,\u0165",
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ /* 12 */ "\u017E,\u017C,\u017A",
+ // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+ /* 13 */ "\u0137",
+ // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+ // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+ /* 14 */ "\u013C,\u0142,\u013A,\u013E",
+ // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+ // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+ /* 15 */ "\u0123,\u011F",
+ /* 16~ */
+ null, null, null, null,
+ /* ~19 */
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ /* 20 */ "\u00FC",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 21 */ "\u00F6",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 22 */ "\u00E4",
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ /* 23 */ "\u00F5",
+ };
+
+ /* Language fa: Persian */
+ private static final String[] LANGUAGE_fa = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~41 */
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\",\'",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
+ /* 44~ */
+ null, null, null, null,
+ /* ~47 */
+ // U+061F: "؟" ARABIC QUESTION MARK
+ // U+060C: "،" ARABIC COMMA
+ // U+061B: "؛" ARABIC SEMICOLON
+ /* 48 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
+ // U+2605: "★" BLACK STAR
+ // U+066D: "٭" ARABIC FIVE POINTED STAR
+ /* 49 */ "\u2605,\u066D",
+ // U+266A: "♪" EIGHTH NOTE
+ /* 50 */ "\u266A",
+ /* 51 */ 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
+ /* 52 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 53 */ "!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
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 54 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>",
+ /* 55 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<",
+ // U+0655: "ٕ" ARABIC HAMZA BELOW
+ // U+0652: "ْ" ARABIC SUKUN
+ // U+0651: "ّ" ARABIC SHADDA
+ // U+064C: "ٌ" ARABIC DAMMATAN
+ // U+064D: "ٍ" ARABIC KASRATAN
+ // U+064B: "ً" ARABIC FATHATAN
+ // U+0654: "ٔ" ARABIC HAMZA ABOVE
+ // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF
+ // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF
+ // U+0653: "ٓ" ARABIC MADDAH ABOVE
+ // U+064F: "ُ" ARABIC DAMMA
+ // U+0650: "ِ" ARABIC KASRA
+ // U+064E: "َ" ARABIC FATHA
+ // U+0640: "ـ" ARABIC TATWEEL
+ // In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
+ /* 56 */ "!fixedColumnOrder!7,\u0655,\u0652,\u0651,\u064C,\u064D,\u064B,\u0654,\u0656,\u0670,\u0653,\u064F,\u0650,\u064E,\u0640\u0640\u0640|\u0640",
+ /* 57 */ "\u064B",
+ // U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE
+ /* 58 */ "\u06F1",
+ // U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO
+ /* 59 */ "\u06F2",
+ // U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE
+ /* 60 */ "\u06F3",
+ // U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR
+ /* 61 */ "\u06F4",
+ // U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE
+ /* 62 */ "\u06F5",
+ // U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX
+ /* 63 */ "\u06F6",
+ // U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN
+ /* 64 */ "\u06F7",
+ // U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT
+ /* 65 */ "\u06F8",
+ // U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE
+ /* 66 */ "\u06F9",
+ // U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO
+ /* 67 */ "\u06F0",
+ /* 68 */ "1",
+ /* 69 */ "2",
+ /* 70 */ "3",
+ /* 71 */ "4",
+ /* 72 */ "5",
+ /* 73 */ "6",
+ /* 74 */ "7",
+ /* 75 */ "8",
+ /* 76 */ "9",
+ // U+066B: "٫" ARABIC DECIMAL SEPARATOR
+ // U+066C: "٬" ARABIC THOUSANDS SEPARATOR
+ /* 77 */ "0,\u066B,\u066C",
+ /* 78~ */
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~87 */
+ // U+060C: "،" ARABIC COMMA
+ /* 88 */ "\u060C",
+ /* 89 */ "\\,",
+ /* 90 */ null,
+ /* 91 */ "\u061F",
+ /* 92 */ "\u061B",
+ // U+066A: "٪" ARABIC PERCENT SIGN
+ /* 93 */ "\u066A",
+ /* 94 */ null,
+ /* 95 */ "?",
+ /* 96 */ ";",
+ // U+2030: "‰" PER MILLE SIGN
+ /* 97 */ "\\%,\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
+ /* 98 */ "\u060C",
+ /* 99 */ "!",
+ /* 100 */ "!,\\,",
+ /* 101 */ "\u061F",
+ /* 102 */ "\u061F,?",
+ /* 103 */ "\u060C",
+ /* 104 */ "\u061F",
+ /* 105 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB",
+ };
+
+ /* Language fi: Finnish */
+ private static final String[] LANGUAGE_fi = {
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E6,\u00E0,\u00E1,\u00E2,\u00E3,\u0101",
+ /* 1 */ null,
+ /* 2 */ null,
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F8,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u014D",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ /* 4 */ "\u00FC",
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ /* 5 */ "\u0161,\u00DF,\u015B",
+ /* 6~ */
+ null, null, null, null, null, null,
+ /* ~11 */
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ /* 12 */ "\u017E,\u017A,\u017C",
+ /* 13~ */
+ null, null, null, null, null, null, null,
+ /* ~19 */
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ /* 20 */ "\u00E5",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 21 */ "\u00F6",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 22 */ "\u00E4",
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 23 */ "\u00F8",
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ /* 24 */ "\u00E6",
+ };
+
+ /* Language fr: French */
+ private static final String[] LANGUAGE_fr = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+ /* 0 */ "\u00E0,\u00E2,%,\u00E6,\u00E1,\u00E4,\u00E3,\u00E5,\u0101,\u00AA",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,%,\u0119,\u0117,\u0113",
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00EE,%,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+ /* 3 */ "\u00F4,\u0153,%,\u00F6,\u00F2,\u00F3,\u00F5,\u00F8,\u014D,\u00BA",
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00F9,\u00FB,%,\u00FC,\u00FA,\u016B",
+ /* 5 */ null,
+ /* 6 */ null,
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u00E7,\u0107,\u010D",
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "%,\u00FF",
+ };
+
+ /* Language hi: Hindi */
+ private static final String[] LANGUAGE_hi = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~57 */
+ // U+0967: "१" DEVANAGARI DIGIT ONE
+ /* 58 */ "\u0967",
+ // U+0968: "२" DEVANAGARI DIGIT TWO
+ /* 59 */ "\u0968",
+ // U+0969: "३" DEVANAGARI DIGIT THREE
+ /* 60 */ "\u0969",
+ // U+096A: "४" DEVANAGARI DIGIT FOUR
+ /* 61 */ "\u096A",
+ // U+096B: "५" DEVANAGARI DIGIT FIVE
+ /* 62 */ "\u096B",
+ // U+096C: "६" DEVANAGARI DIGIT SIX
+ /* 63 */ "\u096C",
+ // U+096D: "७" DEVANAGARI DIGIT SEVEN
+ /* 64 */ "\u096D",
+ // U+096E: "८" DEVANAGARI DIGIT EIGHT
+ /* 65 */ "\u096E",
+ // U+096F: "९" DEVANAGARI DIGIT NINE
+ /* 66 */ "\u096F",
+ // U+0966: "०" DEVANAGARI DIGIT ZERO
+ /* 67 */ "\u0966",
+ /* 68 */ "1",
+ /* 69 */ "2",
+ /* 70 */ "3",
+ /* 71 */ "4",
+ /* 72 */ "5",
+ /* 73 */ "6",
+ /* 74 */ "7",
+ /* 75 */ "8",
+ /* 76 */ "9",
+ /* 77 */ "0",
+ };
+
+ /* Language hr: Croatian */
+ private static final String[] LANGUAGE_hr = {
+ /* 0~ */
+ null, null, null, null, null,
+ /* ~4 */
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ /* 5 */ "\u0161,\u015B,\u00DF",
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u00F1,\u0144",
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ /* 7 */ "\u010D,\u0107,\u00E7",
+ /* 8 */ null,
+ // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+ /* 9 */ "\u0111",
+ /* 10 */ null,
+ /* 11 */ null,
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ /* 12 */ "\u017E,\u017A,\u017C",
+ };
+
+ /* Language hu: Hungarian */
+ private static final String[] LANGUAGE_hu = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E1,\u00E0,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00ED,\u00EE,\u00EF,\u00EC,\u012F,\u012B",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F3,\u00F6,\u0151,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u0171,\u00FB,\u00F9,\u016B",
+ };
+
+ /* Language is: Icelandic */
+ private static final String[] LANGUAGE_is = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E1,\u00E4,\u00E6,\u00E5,\u00E0,\u00E2,\u00E3,\u0101",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u00EB,\u00E8,\u00EA,\u0119,\u0117,\u0113",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00ED,\u00EF,\u00EE,\u00EC,\u012F,\u012B",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
+ /* 5~ */
+ null, null, null,
+ /* ~7 */
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+00F0: "ð" LATIN SMALL LETTER ETH
+ /* 9 */ "\u00F0",
+ /* 10 */ null,
+ // U+00FE: "þ" LATIN SMALL LETTER THORN
+ /* 11 */ "\u00FE",
+ /* 12~ */
+ null, null, null, null, null, null, null, null,
+ /* ~19 */
+ // U+00F0: "ð" LATIN SMALL LETTER ETH
+ /* 20 */ "\u00F0",
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ /* 21 */ "\u00E6",
+ // U+00FE: "þ" LATIN SMALL LETTER THORN
+ /* 22 */ "\u00FE",
+ };
+
+ /* Language it: Italian */
+ private static final String[] LANGUAGE_it = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+ /* 0 */ "\u00E0,\u00E1,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101,\u00AA",
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00EC,\u00ED,\u00EE,\u00EF,\u012F,\u012B",
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+ /* 3 */ "\u00F2,\u00F3,\u00F4,\u00F6,\u00F5,\u0153,\u00F8,\u014D,\u00BA",
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00F9,\u00FA,\u00FB,\u00FC,\u016B",
+ };
+
+ /* Language iw: Hebrew */
+ private static final String[] LANGUAGE_iw = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~41 */
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
+ /* 44~ */
+ null, null, null, null, null,
+ /* ~48 */
+ // U+2605: "★" BLACK STAR
+ /* 49 */ "\u2605",
+ /* 50 */ null,
+ // U+00B1: "±" PLUS-MINUS SIGN
+ // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
+ /* 51 */ "\u00B1,\uFB29",
+ // The all letters need to be mirrored are found at
+ // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
+ /* 52 */ "!fixedColumnOrder!3,<|>,{|},[|]",
+ /* 53 */ "!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
+ // The following characters don't need BIDI mirroring.
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ /* 54 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 55 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ };
+
+ /* Language ky: Kirghiz */
+ private static final String[] LANGUAGE_ky = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~24 */
+ // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA
+ /* 25 */ "\u0449",
+ // U+044B: "ы" CYRILLIC SMALL LETTER YERU
+ /* 26 */ "\u044B",
+ // U+0438: "и" CYRILLIC SMALL LETTER I
+ /* 27 */ "\u0438",
+ // U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U
+ /* 28 */ "\u04AF",
+ /* 29 */ null,
+ // U+04A3: "ң" CYRILLIC SMALL LETTER EN WITH DESCENDER
+ /* 30 */ "\u04A3",
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 31 */ "\u044A",
+ /* 32 */ null,
+ // U+04E9: "ө" CYRILLIC SMALL LETTER BARRED O
+ /* 33 */ "\u04E9",
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 34 */ "\u044A",
+ };
+
+ /* Language lt: Lithuanian */
+ private static final String[] LANGUAGE_lt = {
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ /* 0 */ "\u0105,\u00E4,\u0101,\u00E0,\u00E1,\u00E2,\u00E3,\u00E5,\u00E6",
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+ /* 1 */ "\u0117,\u0119,\u0113,\u00E8,\u00E9,\u00EA,\u00EB,\u011B",
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ /* 2 */ "\u012F,\u012B,\u00EC,\u00ED,\u00EE,\u00EF,\u0131",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 3 */ "\u00F6,\u00F5,\u00F2,\u00F3,\u00F4,\u0153,\u0151,\u00F8",
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+ // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ /* 4 */ "\u016B,\u0173,\u00FC,\u016B,\u00F9,\u00FA,\u00FB,\u016F,\u0171",
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ /* 5 */ "\u0161,\u00DF,\u015B,\u015F",
+ // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u0146,\u00F1,\u0144,\u0144",
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u010D,\u00E7,\u0107",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ /* 9 */ "\u010F",
+ // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+ /* 10 */ "\u0157,\u0159,\u0155",
+ // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ /* 11 */ "\u0163,\u0165",
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ /* 12 */ "\u017E,\u017C,\u017A",
+ // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+ /* 13 */ "\u0137",
+ // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+ // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+ /* 14 */ "\u013C,\u0142,\u013A,\u013E",
+ // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+ // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+ /* 15 */ "\u0123,\u011F",
+ };
+
+ /* Language lv: Latvian */
+ private static final String[] LANGUAGE_lv = {
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ /* 0 */ "\u0101,\u00E0,\u00E1,\u00E2,\u00E3,\u00E4,\u00E5,\u00E6,\u0105",
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+ /* 1 */ "\u0113,\u0117,\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u011B",
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ /* 2 */ "\u012B,\u012F,\u00EC,\u00ED,\u00EE,\u00EF,\u0131",
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 3 */ "\u00F2,\u00F3,\u00F4,\u00F5,\u00F6,\u0153,\u0151,\u00F8",
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+ // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ /* 4 */ "\u016B,\u0173,\u00F9,\u00FA,\u00FB,\u00FC,\u016F,\u0171",
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ /* 5 */ "\u0161,\u00DF,\u015B,\u015F",
+ // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u0146,\u00F1,\u0144,\u0144",
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u010D,\u00E7,\u0107",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ /* 9 */ "\u010F",
+ // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+ /* 10 */ "\u0157,\u0159,\u0155",
+ // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ /* 11 */ "\u0163,\u0165",
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ /* 12 */ "\u017E,\u017C,\u017A",
+ // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+ /* 13 */ "\u0137",
+ // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+ // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+ /* 14 */ "\u013C,\u0142,\u013A,\u013E",
+ // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+ // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+ /* 15 */ "\u0123,\u011F",
+ };
+
+ /* Language mk: Macedonian */
+ private static final String[] LANGUAGE_mk = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null,
+ /* ~34 */
+ // U+0455: "ѕ" CYRILLIC SMALL LETTER DZE
+ /* 35 */ "\u0455",
+ // U+045C: "ќ" CYRILLIC SMALL LETTER KJE
+ /* 36 */ "\u045C",
+ // U+0437: "з" CYRILLIC SMALL LETTER ZE
+ /* 37 */ "\u0437",
+ // U+0453: "ѓ" CYRILLIC SMALL LETTER GJE
+ /* 38 */ "\u0453",
+ // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE
+ /* 39 */ "\u0450",
+ // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
+ /* 40 */ "\u045D",
+ /* 41 */ null,
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
+ /* 42 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ /* 43 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
+ };
+
+ /* Language nb: Norwegian Bokmål */
+ private static final String[] LANGUAGE_nb = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E0,\u00E4,\u00E1,\u00E2,\u00E3,\u0101",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+ /* 2 */ null,
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F4,\u00F2,\u00F3,\u00F6,\u00F5,\u0153,\u014D",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+ /* 5~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~19 */
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ /* 20 */ "\u00E5",
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 21 */ "\u00F8",
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ /* 22 */ "\u00E6",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 23 */ "\u00F6",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 24 */ "\u00E4",
+ };
+
+ /* Language nl: Dutch */
+ private static final String[] LANGUAGE_nl = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E1,\u00E4,\u00E2,\u00E0,\u00E6,\u00E3,\u00E5,\u0101",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u00E9,\u00EB,\u00EA,\u00E8,\u0119,\u0117,\u0113",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+0133: "ij" LATIN SMALL LIGATURE IJ
+ /* 2 */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B,\u0133",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
+ /* 5 */ null,
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u00F1,\u0144",
+ /* 7 */ null,
+ // U+0133: "ij" LATIN SMALL LIGATURE IJ
+ /* 8 */ "\u0133",
+ };
+
+ /* Language pl: Polish */
+ private static final String[] LANGUAGE_pl = {
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u0105,\u00E1,\u00E0,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101",
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ /* 1 */ "\u0119,\u00E8,\u00E9,\u00EA,\u00EB,\u0117,\u0113",
+ /* 2 */ null,
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
+ /* 4 */ null,
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u015B,\u00DF,\u0161",
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ /* 6 */ "\u0144,\u00F1",
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u0107,\u00E7,\u010D",
+ /* 8~ */
+ null, null, null, null,
+ /* ~11 */
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ /* 12 */ "\u017C,\u017A,\u017E",
+ /* 13 */ null,
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ /* 14 */ "\u0142",
+ };
+
+ /* Language pt: Portuguese */
+ private static final String[] LANGUAGE_pt = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+ /* 0 */ "\u00E1,\u00E3,\u00E0,\u00E2,\u00E4,\u00E5,\u00E6,\u00AA",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ /* 1 */ "\u00E9,\u00EA,\u00E8,\u0119,\u0117,\u0113,\u00EB",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00ED,\u00EE,\u00EC,\u00EF,\u012F,\u012B",
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+ /* 3 */ "\u00F3,\u00F5,\u00F4,\u00F2,\u00F6,\u0153,\u00F8,\u014D,\u00BA",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+ /* 5 */ null,
+ /* 6 */ null,
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u00E7,\u010D,\u0107",
+ };
+
+ /* Language rm: Raeto-Romance */
+ private static final String[] LANGUAGE_rm = {
+ /* 0~ */
+ null, null, null,
+ /* ~2 */
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 3 */ "\u00F2,\u00F3,\u00F6,\u00F4,\u00F5,\u0153,\u00F8",
+ };
+
+ /* Language ro: Romanian */
+ private static final String[] LANGUAGE_ro = {
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ /* 0 */ "\u00E2,\u00E3,\u0103,\u00E0,\u00E1,\u00E4,\u00E6,\u00E5,\u0101",
+ /* 1 */ null,
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+ /* 3 */ null,
+ /* 4 */ null,
+ // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u0219,\u00DF,\u015B,\u0161",
+ /* 6~ */
+ null, null, null, null, null,
+ /* ~10 */
+ // U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW
+ /* 11 */ "\u021B",
+ };
+
+ /* Language ru: Russian */
+ private static final String[] LANGUAGE_ru = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~24 */
+ // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA
+ /* 25 */ "\u0449",
+ // U+044B: "ы" CYRILLIC SMALL LETTER YERU
+ /* 26 */ "\u044B",
+ // U+0438: "и" CYRILLIC SMALL LETTER I
+ /* 27 */ "\u0438",
+ /* 28 */ null,
+ // U+0451: "ё" CYRILLIC SMALL LETTER IO
+ /* 29 */ "\u0451",
+ /* 30 */ null,
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 31 */ "\u044A",
+ /* 32 */ null,
+ /* 33 */ null,
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 34 */ "\u044A",
+ };
+
+ /* Language sk: Slovak */
+ private static final String[] LANGUAGE_sk = {
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ /* 0 */ "\u00E1,\u00E4,\u0101,\u00E0,\u00E2,\u00E3,\u00E5,\u00E6,\u0105",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ /* 1 */ "\u00E9,\u011B,\u0113,\u0117,\u00E8,\u00EA,\u00EB,\u0119",
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ /* 2 */ "\u00ED,\u012B,\u012F,\u00EC,\u00EE,\u00EF,\u0131",
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 3 */ "\u00F4,\u00F3,\u00F6,\u00F2,\u00F5,\u0153,\u0151,\u00F8",
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ /* 4 */ "\u00FA,\u016F,\u00FC,\u016B,\u0173,\u00F9,\u00FB,\u0171",
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ /* 5 */ "\u0161,\u00DF,\u015B,\u015F",
+ // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+ // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ /* 6 */ "\u0148,\u0146,\u00F1,\u0144,\u0144",
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u010D,\u00E7,\u0107",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ /* 8 */ "\u00FD,\u00FF",
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ /* 9 */ "\u010F",
+ // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+ /* 10 */ "\u0155,\u0159,\u0157",
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+ /* 11 */ "\u0165,\u0163",
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ /* 12 */ "\u017E,\u017C,\u017A",
+ // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+ /* 13 */ "\u0137",
+ // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+ // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+ // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ /* 14 */ "\u013E,\u013A,\u013C,\u0142",
+ // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+ // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+ /* 15 */ "\u0123,\u011F",
+ };
+
+ /* Language sl: Slovenian */
+ private static final String[] LANGUAGE_sl = {
+ /* 0~ */
+ null, null, null, null, null,
+ /* ~4 */
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u0161",
+ /* 6 */ null,
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ /* 7 */ "\u010D,\u0107",
+ /* 8 */ null,
+ // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+ /* 9 */ "\u0111",
+ /* 10 */ null,
+ /* 11 */ null,
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ /* 12 */ "\u017E",
+ };
+
+ /* Language sr: Serbian */
+ private static final String[] LANGUAGE_sr = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null,
+ /* ~34 */
+ // U+0437: "з" CYRILLIC SMALL LETTER ZE
+ /* 35 */ "\u0437",
+ // U+045B: "ћ" CYRILLIC SMALL LETTER TSHE
+ /* 36 */ "\u045B",
+ // U+0455: "ѕ" CYRILLIC SMALL LETTER DZE
+ /* 37 */ "\u0455",
+ // U+0452: "ђ" CYRILLIC SMALL LETTER DJE
+ /* 38 */ "\u0452",
+ // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE
+ /* 39 */ "\u0450",
+ // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
+ /* 40 */ "\u045D",
+ /* 41 */ null,
+ // U+2018: "‘" LEFT SINGLE QUOTATION MARK
+ // U+2019: "’" RIGHT SINGLE QUOTATION MARK
+ // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ // U+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_double_quote">!fixedColumnOrder!6,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
+ /* 42 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB",
+ // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK.
+ // <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ /* 43 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
+ };
+
+ /* Language sv: Swedish */
+ private static final String[] LANGUAGE_sv = {
+ /* 0 */ null,
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119",
+ /* 2 */ null,
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u0153,\u00F4,\u00F2,\u00F3,\u00F5,\u014D",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u00DF,\u015B,\u0161",
+ /* 6~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~19 */
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ /* 20 */ "\u00E5",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 21 */ "\u00F6",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 22 */ "\u00E4",
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ /* 23 */ "\u00F8",
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ /* 24 */ "\u00E6",
+ };
+
+ /* Language tr: Turkish */
+ private static final String[] LANGUAGE_tr = {
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ /* 0 */ "\u00E2",
+ /* 1 */ null,
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ /* 2 */ "\u0131,\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ /* 3 */ "\u00F6,\u00F4,\u0153,\u00F2,\u00F3,\u00F5,\u00F8,\u014D",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ /* 5 */ "\u015F,\u00DF,\u015B,\u0161",
+ /* 6 */ null,
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u00E7,\u0107,\u010D",
+ /* 8~ */
+ null, null, null, null, null, null, null,
+ /* ~14 */
+ // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+ /* 15 */ "\u011F",
+ };
+
+ /* Language uk: Ukrainian */
+ private static final String[] LANGUAGE_uk = {
+ /* 0~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~24 */
+ // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA
+ /* 25 */ "\u0449",
+ // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+ /* 26 */ "\u0456",
+ // U+0438: "и" CYRILLIC SMALL LETTER I
+ /* 27 */ "\u0438",
+ /* 28~ */
+ null, null, null,
+ /* ~30 */
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 31 */ "\u044A",
+ // U+0457: "ї" CYRILLIC SMALL LETTER YI
+ /* 32 */ "\u0457",
+ /* 33 */ null,
+ // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
+ /* 34 */ "\u044A",
+ };
+
+ /* Language vi: Vietnamese */
+ private static final String[] LANGUAGE_vi = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+1EA3: "ả" LATIN SMALL LETTER A WITH HOOK ABOVE
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+1EA1: "ạ" LATIN SMALL LETTER A WITH DOT BELOW
+ // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
+ // U+1EB1: "ằ" LATIN SMALL LETTER A WITH BREVE AND GRAVE
+ // U+1EAF: "ắ" LATIN SMALL LETTER A WITH BREVE AND ACUTE
+ // U+1EB3: "ẳ" LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
+ // U+1EB5: "ẵ" LATIN SMALL LETTER A WITH BREVE AND TILDE
+ // U+1EB7: "ặ" LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+1EA7: "ầ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
+ // U+1EA5: "ấ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
+ // U+1EA9: "ẩ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+ // U+1EAB: "ẫ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
+ // U+1EAD: "ậ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+ /* 0 */ "\u00E0,\u00E1,\u1EA3,\u00E3,\u1EA1,\u0103,\u1EB1,\u1EAF,\u1EB3,\u1EB5,\u1EB7,\u00E2,\u1EA7,\u1EA5,\u1EA9,\u1EAB,\u1EAD",
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+1EBB: "ẻ" LATIN SMALL LETTER E WITH HOOK ABOVE
+ // U+1EBD: "ẽ" LATIN SMALL LETTER E WITH TILDE
+ // U+1EB9: "ẹ" LATIN SMALL LETTER E WITH DOT BELOW
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+1EC1: "ề" LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+ // U+1EBF: "ế" LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+ // U+1EC3: "ể" LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+ // U+1EC5: "ễ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+ // U+1EC7: "ệ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+ /* 1 */ "\u00E8,\u00E9,\u1EBB,\u1EBD,\u1EB9,\u00EA,\u1EC1,\u1EBF,\u1EC3,\u1EC5,\u1EC7",
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+1EC9: "ỉ" LATIN SMALL LETTER I WITH HOOK ABOVE
+ // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE
+ // U+1ECB: "ị" LATIN SMALL LETTER I WITH DOT BELOW
+ /* 2 */ "\u00EC,\u00ED,\u1EC9,\u0129,\u1ECB",
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+1ECF: "ỏ" LATIN SMALL LETTER O WITH HOOK ABOVE
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+1ECD: "ọ" LATIN SMALL LETTER O WITH DOT BELOW
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+1ED3: "ồ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
+ // U+1ED1: "ố" LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
+ // U+1ED5: "ổ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+ // U+1ED7: "ỗ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
+ // U+1ED9: "ộ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+ // U+01A1: "ơ" LATIN SMALL LETTER O WITH HORN
+ // U+1EDD: "ờ" LATIN SMALL LETTER O WITH HORN AND GRAVE
+ // U+1EDB: "ớ" LATIN SMALL LETTER O WITH HORN AND ACUTE
+ // U+1EDF: "ở" LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
+ // U+1EE1: "ỡ" LATIN SMALL LETTER O WITH HORN AND TILDE
+ // U+1EE3: "ợ" LATIN SMALL LETTER O WITH HORN AND DOT BELOW
+ /* 3 */ "\u00F2,\u00F3,\u1ECF,\u00F5,\u1ECD,\u00F4,\u1ED3,\u1ED1,\u1ED5,\u1ED7,\u1ED9,\u01A1,\u1EDD,\u1EDB,\u1EDF,\u1EE1,\u1EE3",
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+1EE7: "ủ" LATIN SMALL LETTER U WITH HOOK ABOVE
+ // U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE
+ // U+1EE5: "ụ" LATIN SMALL LETTER U WITH DOT BELOW
+ // U+01B0: "ư" LATIN SMALL LETTER U WITH HORN
+ // U+1EEB: "ừ" LATIN SMALL LETTER U WITH HORN AND GRAVE
+ // U+1EE9: "ứ" LATIN SMALL LETTER U WITH HORN AND ACUTE
+ // U+1EED: "ử" LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
+ // U+1EEF: "ữ" LATIN SMALL LETTER U WITH HORN AND TILDE
+ // U+1EF1: "ự" LATIN SMALL LETTER U WITH HORN AND DOT BELOW
+ /* 4 */ "\u00F9,\u00FA,\u1EE7,\u0169,\u1EE5,\u01B0,\u1EEB,\u1EE9,\u1EED,\u1EEF,\u1EF1",
+ /* 5~ */
+ null, null, null,
+ /* ~7 */
+ // U+1EF3: "ỳ" LATIN SMALL LETTER Y WITH GRAVE
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+1EF7: "ỷ" LATIN SMALL LETTER Y WITH HOOK ABOVE
+ // U+1EF9: "ỹ" LATIN SMALL LETTER Y WITH TILDE
+ // U+1EF5: "ỵ" LATIN SMALL LETTER Y WITH DOT BELOW
+ /* 8 */ "\u1EF3,\u00FD,\u1EF7,\u1EF9,\u1EF5",
+ // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+ /* 9 */ "\u0111",
+ };
+
+ /* Language zz: No language */
+ private static final String[] LANGUAGE_zz = {
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+ // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+ // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+ // U+00E6: "æ" LATIN SMALL LETTER AE
+ // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+ // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
+ // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+ // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+ /* 0 */ "\u00E0,\u00E1,\u00E2,\u00E3,\u00E4,\u00E5,\u00E6,\u00E3,\u00E5,\u0101,\u0103,\u0105,\u00AA",
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+ // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+ // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+ // U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE
+ // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+ // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+ // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+ /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113,\u0115,\u0117,\u0119,\u011B",
+ // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+ // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+ // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+ // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+ // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE
+ // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+ // U+012D: "ĭ" LATIN SMALL LETTER I WITH BREVE
+ // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+ // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+ // U+0133: "ij" LATIN SMALL LIGATURE IJ
+ /* 2 */ "\u00EC,\u00ED,\u00EE,\u00EF,\u0129,\u012B,\u012D,\u012F,\u0131,\u0133",
+ // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+ // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+ // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+ // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+ // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+ // U+014F: "ŏ" LATIN SMALL LETTER O WITH BREVE
+ // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+ // U+0153: "œ" LATIN SMALL LIGATURE OE
+ // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+ /* 3 */ "\u00F2,\u00F3,\u00F4,\u00F5,\u00F6,\u00F8,\u014D,\u014F,\u0151,\u0153,\u00BA",
+ // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+ // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+ // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ // U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE
+ // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+ // U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE
+ // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+ // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+ // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+ /* 4 */ "\u00F9,\u00FA,\u00FB,\u00FC,\u0169,\u016B,\u016D,\u016F,\u0171,\u0173",
+ // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+ // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+ // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
+ // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+ // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+ // U+017F: "ſ" LATIN SMALL LETTER LONG S
+ /* 5 */ "\u00DF,\u015B,\u015D,\u015F,\u0161,\u017F",
+ // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+ // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+ // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+ // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+ // U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+ // U+014B: "ŋ" LATIN SMALL LETTER ENG
+ /* 6 */ "\u00F1,\u0144,\u0146,\u0148,\u0149,\u014B",
+ // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+ // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+ // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
+ // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
+ // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+ /* 7 */ "\u00E7,\u0107,\u0109,\u010B,\u010D",
+ // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+ // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
+ // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+ // U+0133: "ij" LATIN SMALL LIGATURE IJ
+ /* 8 */ "\u00FD,\u0177,\u00FF,\u0133",
+ // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+ // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+ // U+00F0: "ð" LATIN SMALL LETTER ETH
+ /* 9 */ "\u010F,\u0111,\u00F0",
+ // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+ // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+ // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+ /* 10 */ "\u0155,\u0157,\u0159",
+ // U+00FE: "þ" LATIN SMALL LETTER THORN
+ // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+ // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+ // U+0167: "ŧ" LATIN SMALL LETTER T WITH STROKE
+ /* 11 */ "\u00FE,\u0163,\u0165,\u0167",
+ // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+ // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+ // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+ /* 12 */ "\u017A,\u017C,\u017E",
+ // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+ // U+0138: "ĸ" LATIN SMALL LETTER KRA
+ /* 13 */ "\u0137,\u0138",
+ // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+ // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+ // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+ // U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT
+ // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+ /* 14 */ "\u013A,\u013C,\u013E,\u0140,\u0142",
+ // U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX
+ // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+ // U+0121: "ġ" LATIN SMALL LETTER G WITH DOT ABOVE
+ // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+ /* 15 */ "\u011D,\u011F,\u0121,\u0123",
+ /* 16 */ null,
+ // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
+ /* 17 */ "\u0125",
+ // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
+ /* 18 */ "\u0135",
+ // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX
+ /* 19 */ "\u0175",
+ };
+
+ private static final Object[] LANGUAGES_AND_TEXTS = {
+ "DEFAULT", LANGUAGE_DEFAULT, /* default */
+ "ar", LANGUAGE_ar, /* Arabic */
+ "be", LANGUAGE_be, /* Belarusian */
+ "ca", LANGUAGE_ca, /* Catalan */
+ "cs", LANGUAGE_cs, /* Czech */
+ "da", LANGUAGE_da, /* Danish */
+ "de", LANGUAGE_de, /* German */
+ "en", LANGUAGE_en, /* English */
+ "es", LANGUAGE_es, /* Spanish */
+ "et", LANGUAGE_et, /* Estonian */
+ "fa", LANGUAGE_fa, /* Persian */
+ "fi", LANGUAGE_fi, /* Finnish */
+ "fr", LANGUAGE_fr, /* French */
+ "hi", LANGUAGE_hi, /* Hindi */
+ "hr", LANGUAGE_hr, /* Croatian */
+ "hu", LANGUAGE_hu, /* Hungarian */
+ "is", LANGUAGE_is, /* Icelandic */
+ "it", LANGUAGE_it, /* Italian */
+ "iw", LANGUAGE_iw, /* Hebrew */
+ "ky", LANGUAGE_ky, /* Kirghiz */
+ "lt", LANGUAGE_lt, /* Lithuanian */
+ "lv", LANGUAGE_lv, /* Latvian */
+ "mk", LANGUAGE_mk, /* Macedonian */
+ "nb", LANGUAGE_nb, /* Norwegian Bokmål */
+ "nl", LANGUAGE_nl, /* Dutch */
+ "pl", LANGUAGE_pl, /* Polish */
+ "pt", LANGUAGE_pt, /* Portuguese */
+ "rm", LANGUAGE_rm, /* Raeto-Romance */
+ "ro", LANGUAGE_ro, /* Romanian */
+ "ru", LANGUAGE_ru, /* Russian */
+ "sk", LANGUAGE_sk, /* Slovak */
+ "sl", LANGUAGE_sl, /* Slovenian */
+ "sr", LANGUAGE_sr, /* Serbian */
+ "sv", LANGUAGE_sv, /* Swedish */
+ "tr", LANGUAGE_tr, /* Turkish */
+ "uk", LANGUAGE_uk, /* Ukrainian */
+ "vi", LANGUAGE_vi, /* Vietnamese */
+ "zz", LANGUAGE_zz, /* No language */
+ };
+
+ static {
+ int id = 0;
+ for (final String name : NAMES) {
+ sNameToIdsMap.put(name, id++);
+ }
+
+ for (int i = 0; i < LANGUAGES_AND_TEXTS.length; i += 2) {
+ final String language = (String)LANGUAGES_AND_TEXTS[i];
+ final String[] texts = (String[])LANGUAGES_AND_TEXTS[i + 1];
+ sLocaleToTextsMap.put(language, texts);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
deleted file mode 100644
index 1e67eec70..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard.internal;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Paint;
-import android.graphics.Rect;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.MiniKeyboard;
-import com.android.inputmethod.latin.R;
-
-import java.util.List;
-
-public class MiniKeyboardBuilder {
- private final Resources mRes;
- private final MiniKeyboard mKeyboard;
- private final CharSequence[] mPopupCharacters;
- private final MiniKeyboardLayoutParams mParams;
-
- /* package */ static class MiniKeyboardLayoutParams {
- public final int mKeyWidth;
- public final int mRowHeight;
- /* package */ final int mTopRowAdjustment;
- public final int mNumRows;
- public final int mNumColumns;
- public final int mLeftKeys;
- public final int mRightKeys; // includes default key.
-
- /**
- * The object holding mini keyboard layout parameters.
- *
- * @param numKeys number of keys in this mini keyboard.
- * @param maxColumns number of maximum columns of this mini keyboard.
- * @param keyWidth mini keyboard key width in pixel, including horizontal gap.
- * @param rowHeight mini keyboard row height in pixel, including vertical gap.
- * @param coordXInParent coordinate x of the popup key in parent keyboard.
- * @param parentKeyboardWidth parent keyboard width in pixel.
- */
- public MiniKeyboardLayoutParams(int numKeys, int maxColumns, int keyWidth, int rowHeight,
- int coordXInParent, int parentKeyboardWidth) {
- if (parentKeyboardWidth / keyWidth < maxColumns)
- throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: "
- + parentKeyboardWidth + " " + keyWidth + " " + maxColumns);
- mKeyWidth = keyWidth;
- mRowHeight = rowHeight;
-
- final int numRows = (numKeys + maxColumns - 1) / maxColumns;
- mNumRows = numRows;
- final int numColumns = getOptimizedColumns(numKeys, maxColumns);
- mNumColumns = numColumns;
-
- final int numLeftKeys = (numColumns - 1) / 2;
- final int numRightKeys = numColumns - numLeftKeys; // including default key.
- final int maxLeftKeys = coordXInParent / keyWidth;
- final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth);
- int leftKeys, rightKeys;
- if (numLeftKeys > maxLeftKeys) {
- leftKeys = maxLeftKeys;
- rightKeys = numColumns - maxLeftKeys;
- } else if (numRightKeys > maxRightKeys) {
- leftKeys = numColumns - maxRightKeys;
- rightKeys = maxRightKeys;
- } else {
- leftKeys = numLeftKeys;
- rightKeys = numRightKeys;
- }
- // Shift right if the left edge of mini keyboard is on the edge of parent keyboard
- // unless the parent key is on the left edge.
- if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) {
- leftKeys--;
- rightKeys++;
- }
- // Shift left if the right edge of mini keyboard is on the edge of parent keyboard
- // unless the parent key is on the right edge.
- if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) {
- leftKeys++;
- rightKeys--;
- }
- mLeftKeys = leftKeys;
- mRightKeys = rightKeys;
-
- // Centering of the top row.
- final boolean onEdge = (leftKeys == 0 || rightKeys == 1);
- if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) {
- mTopRowAdjustment = 0;
- } else if (mLeftKeys < mRightKeys - 1) {
- mTopRowAdjustment = 1;
- } else {
- mTopRowAdjustment = -1;
- }
- }
-
- // Return key position according to column count (0 is default).
- /* package */ int getColumnPos(int n) {
- final int col = n % mNumColumns;
- if (col == 0) {
- // default position.
- return 0;
- }
- int pos = 0;
- int right = 1; // include default position key.
- int left = 0;
- int i = 0;
- while (true) {
- // Assign right key if available.
- if (right < mRightKeys) {
- pos = right;
- right++;
- i++;
- }
- if (i >= col)
- break;
- // Assign left key if available.
- if (left < mLeftKeys) {
- left++;
- pos = -left;
- i++;
- }
- if (i >= col)
- break;
- }
- return pos;
- }
-
- private static int getTopRowEmptySlots(int numKeys, int numColumns) {
- final int remainingKeys = numKeys % numColumns;
- if (remainingKeys == 0) {
- return 0;
- } else {
- return numColumns - remainingKeys;
- }
- }
-
- private int getOptimizedColumns(int numKeys, int maxColumns) {
- int numColumns = Math.min(numKeys, maxColumns);
- while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) {
- numColumns--;
- }
- return numColumns;
- }
-
- public int getDefaultKeyCoordX() {
- return mLeftKeys * mKeyWidth;
- }
-
- public int getX(int n, int row) {
- final int x = getColumnPos(n) * mKeyWidth + getDefaultKeyCoordX();
- if (isTopRow(row)) {
- return x + mTopRowAdjustment * (mKeyWidth / 2);
- }
- return x;
- }
-
- public int getY(int row) {
- return (mNumRows - 1 - row) * mRowHeight;
- }
-
- public int getRowFlags(int row) {
- int rowFlags = 0;
- if (row == 0) rowFlags |= Keyboard.EDGE_TOP;
- if (isTopRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
- return rowFlags;
- }
-
- private boolean isTopRow(int rowCount) {
- return rowCount == mNumRows - 1;
- }
- }
-
- public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key parentKey,
- Keyboard parentKeyboard) {
- final Context context = view.getContext();
- mRes = context.getResources();
- final MiniKeyboard keyboard = new MiniKeyboard(
- context, layoutTemplateResId, parentKeyboard);
- mKeyboard = keyboard;
- mPopupCharacters = parentKey.mPopupCharacters;
-
- final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, keyboard.getKeyWidth());
- final MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
- mPopupCharacters.length, parentKey.mMaxPopupColumn,
- keyWidth, parentKeyboard.getRowHeight(),
- parentKey.mX + (parentKey.mWidth + parentKey.mGap) / 2 - keyWidth / 2,
- view.getMeasuredWidth());
- mParams = params;
-
- keyboard.setRowHeight(params.mRowHeight);
- keyboard.setHeight(params.mNumRows * params.mRowHeight);
- keyboard.setMinWidth(params.mNumColumns * params.mKeyWidth);
- keyboard.setDefaultCoordX(params.getDefaultKeyCoordX() + params.mKeyWidth / 2);
- }
-
- private static int getMaxKeyWidth(KeyboardView view, CharSequence[] popupCharacters,
- int minKeyWidth) {
- Paint paint = null;
- Rect bounds = null;
- int maxWidth = 0;
- for (CharSequence popupSpec : popupCharacters) {
- final CharSequence label = PopupCharactersParser.getLabel(popupSpec.toString());
- // If the label is single letter, minKeyWidth is enough to hold the label.
- if (label != null && label.length() > 1) {
- if (paint == null) {
- paint = new Paint();
- paint.setAntiAlias(true);
- }
- final int labelSize = view.getDefaultLabelSizeAndSetPaint(paint);
- paint.setTextSize(labelSize);
- if (bounds == null) bounds = new Rect();
- paint.getTextBounds(label.toString(), 0, label.length(), bounds);
- if (maxWidth < bounds.width())
- maxWidth = bounds.width();
- }
- }
- final int horizontalPadding = (int)view.getContext().getResources().getDimension(
- R.dimen.mini_keyboard_key_horizontal_padding);
- return Math.max(minKeyWidth, maxWidth + horizontalPadding);
- }
-
- public MiniKeyboard build() {
- final MiniKeyboard keyboard = mKeyboard;
- final List<Key> keys = keyboard.getKeys();
- final MiniKeyboardLayoutParams params = mParams;
- for (int n = 0; n < mPopupCharacters.length; n++) {
- final CharSequence label = mPopupCharacters[n];
- final int row = n / params.mNumColumns;
- final Key key = new Key(mRes, keyboard, label, params.getX(n, row), params.getY(row),
- params.mKeyWidth, params.mRowHeight, params.getRowFlags(row));
- keys.add(key);
- }
- return keyboard;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java
index dae73c4e4..b39b97720 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java
@@ -18,15 +18,13 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-
-public class ModifierKeyState {
- protected static final String TAG = "ModifierKeyState";
- protected static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE;
+/* package */ class ModifierKeyState {
+ protected static final String TAG = ModifierKeyState.class.getSimpleName();
+ protected static final boolean DEBUG = false;
protected static final int RELEASING = 0;
protected static final int PRESSING = 1;
- protected static final int MOMENTARY = 2;
+ protected static final int CHORDING = 2;
protected final String mName;
protected int mState = RELEASING;
@@ -52,7 +50,7 @@ public class ModifierKeyState {
public void onOtherKeyPressed() {
final int oldState = mState;
if (oldState == PRESSING)
- mState = MOMENTARY;
+ mState = CHORDING;
if (DEBUG)
Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this);
}
@@ -65,8 +63,8 @@ public class ModifierKeyState {
return mState == RELEASING;
}
- public boolean isMomentary() {
- return mState == MOMENTARY;
+ public boolean isChording() {
+ return mState == CHORDING;
}
@Override
@@ -78,7 +76,7 @@ public class ModifierKeyState {
switch (state) {
case RELEASING: return "RELEASING";
case PRESSING: return "PRESSING";
- case MOMENTARY: return "MOMENTARY";
+ case CHORDING: return "CHORDING";
default: return "UNKNOWN";
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
deleted file mode 100644
index ddadb1338..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2010 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 com.android.inputmethod.keyboard.KeyDetector;
-import com.android.inputmethod.keyboard.PointerTracker;
-
-/**
- * This class keeps track of a key index and a position where {@link PointerTracker} is.
- */
-public class PointerTrackerKeyState {
- private final KeyDetector mKeyDetector;
-
- // The position and time at which first down event occurred.
- private long mDownTime;
- private long mUpTime;
-
- // The current key index where this pointer is.
- private int mKeyIndex = KeyDetector.NOT_A_KEY;
- // The position where mKeyIndex was recognized for the first time.
- private int mKeyX;
- private int mKeyY;
-
- // Last pointer position.
- private int mLastX;
- private int mLastY;
-
- public PointerTrackerKeyState(KeyDetector keyDetecor) {
- mKeyDetector = keyDetecor;
- }
-
- public int getKeyIndex() {
- return mKeyIndex;
- }
-
- public int getKeyX() {
- return mKeyX;
- }
-
- public int getKeyY() {
- return mKeyY;
- }
-
- public long getDownTime() {
- return mDownTime;
- }
-
- public long getUpTime() {
- return mUpTime;
- }
-
- public int getLastX() {
- return mLastX;
- }
-
- public int getLastY() {
- return mLastY;
- }
-
- public int onDownKey(int x, int y, long eventTime) {
- mDownTime = eventTime;
- return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
- }
-
- private int onMoveKeyInternal(int x, int y) {
- mLastX = x;
- mLastY = y;
- return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
- }
-
- public int onMoveKey(int x, int y) {
- return onMoveKeyInternal(x, y);
- }
-
- public int onMoveToNewKey(int keyIndex, int x, int y) {
- mKeyIndex = keyIndex;
- mKeyX = x;
- mKeyY = y;
- return keyIndex;
- }
-
- public int onUpKey(int x, int y, long eventTime) {
- mUpTime = eventTime;
- mKeyIndex = KeyDetector.NOT_A_KEY;
- return onMoveKeyInternal(x, y);
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
index f87cd869e..5db65c660 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
@@ -16,70 +16,89 @@
package com.android.inputmethod.keyboard.internal;
+import android.util.Log;
+
+import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.PointerTracker;
+import java.util.Iterator;
import java.util.LinkedList;
public class PointerTrackerQueue {
- private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
+ private static final String TAG = PointerTrackerQueue.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private final LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
- public void add(PointerTracker tracker) {
+ public synchronized void add(PointerTracker tracker) {
mQueue.add(tracker);
}
- public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) {
- if (mQueue.lastIndexOf(tracker) < 0) {
+ public synchronized void remove(PointerTracker tracker) {
+ mQueue.remove(tracker);
+ }
+
+ public synchronized void releaseAllPointersOlderThan(PointerTracker tracker,
+ long eventTime) {
+ if (DEBUG) {
+ Log.d(TAG, "releaseAllPoniterOlderThan: [" + tracker.mPointerId + "] " + this);
+ }
+ if (!mQueue.contains(tracker)) {
return;
}
- final LinkedList<PointerTracker> queue = mQueue;
- int oldestPos = 0;
- for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
- if (t.isModifier()) {
- oldestPos++;
- } else {
- t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime, true);
- queue.remove(oldestPos);
+ final Iterator<PointerTracker> it = mQueue.iterator();
+ while (it.hasNext()) {
+ final PointerTracker t = it.next();
+ if (t == tracker) {
+ break;
+ }
+ if (!t.isModifier()) {
+ t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime);
+ it.remove();
}
}
}
public void releaseAllPointers(long eventTime) {
- releaseAllPointersExcept(null, eventTime, true);
+ releaseAllPointersExcept(null, eventTime);
}
- public void releaseAllPointersExcept(PointerTracker tracker, long eventTime,
- boolean updateReleasedKeyGraphics) {
- for (PointerTracker t : mQueue) {
- if (t == tracker)
- continue;
- t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime, updateReleasedKeyGraphics);
+ public synchronized void releaseAllPointersExcept(PointerTracker tracker, long eventTime) {
+ if (DEBUG) {
+ if (tracker == null) {
+ Log.d(TAG, "releaseAllPoniters: " + this);
+ } else {
+ Log.d(TAG, "releaseAllPoniterExcept: [" + tracker.mPointerId + "] " + this);
+ }
+ }
+ final Iterator<PointerTracker> it = mQueue.iterator();
+ while (it.hasNext()) {
+ final PointerTracker t = it.next();
+ if (t != tracker) {
+ t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime);
+ it.remove();
+ }
}
- mQueue.clear();
- if (tracker != null)
- mQueue.add(tracker);
- }
-
- public void remove(PointerTracker tracker) {
- mQueue.remove(tracker);
}
- public boolean isInSlidingKeyInput() {
+ public synchronized boolean isAnyInSlidingKeyInput() {
for (final PointerTracker tracker : mQueue) {
- if (tracker.isInSlidingKeyInput())
+ if (tracker.isInSlidingKeyInput()) {
return true;
+ }
}
return false;
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("[");
- for (PointerTracker tracker : mQueue) {
- if (sb.length() > 1)
+ final StringBuilder sb = new StringBuilder();
+ for (final PointerTracker tracker : mQueue) {
+ if (sb.length() > 0)
sb.append(" ");
- sb.append(String.format("%d", tracker.mPointerId));
+ sb.append("[" + tracker.mPointerId + " "
+ + Keyboard.printableCode(tracker.getKey().mCode) + "]");
}
- sb.append("]");
return sb.toString();
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java b/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
deleted file mode 100644
index 8276f5d78..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/PopupCharactersParser.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2010 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.res.Resources;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.R;
-
-/**
- * String parser of popupCharacters attribute of Key.
- * The string is comma separated texts each of which represents one popup key.
- * Each popup key text is one of the following:
- * - A single letter (Letter)
- * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText).
- * - Icon followed by keyOutputText or code (@icon/icon_number|@integer/key_code)
- * Special character, comma ',' backslash '\', and bar '|' can be escaped by '\'
- * character.
- * Note that the character '@' and '\' are also parsed by XML parser and CSV parser as well.
- * See {@link KeyboardIconsSet} about icon_number.
- */
-public class PopupCharactersParser {
- private static final String TAG = PopupCharactersParser.class.getSimpleName();
-
- private static final char ESCAPE = '\\';
- private static final String LABEL_END = "|";
- private static final String PREFIX_AT = "@";
- private static final String PREFIX_ICON = PREFIX_AT + "icon/";
- private static final String PREFIX_CODE = PREFIX_AT + "integer/";
-
- private PopupCharactersParser() {
- // Intentional empty constructor for utility class.
- }
-
- private static boolean hasIcon(String popupSpec) {
- if (popupSpec.startsWith(PREFIX_ICON)) {
- final int end = indexOfLabelEnd(popupSpec, 0);
- if (end > 0)
- return true;
- throw new PopupCharactersParserError("outputText or code not specified: " + popupSpec);
- }
- return false;
- }
-
- private static boolean hasCode(String popupSpec) {
- final int end = indexOfLabelEnd(popupSpec, 0);
- if (end > 0 && end + 1 < popupSpec.length()
- && popupSpec.substring(end + 1).startsWith(PREFIX_CODE)) {
- return true;
- }
- return false;
- }
-
- private static String parseEscape(String text) {
- if (text.indexOf(ESCAPE) < 0)
- return text;
- final int length = text.length();
- final StringBuilder sb = new StringBuilder();
- for (int pos = 0; pos < length; pos++) {
- final char c = text.charAt(pos);
- if (c == ESCAPE && pos + 1 < length) {
- sb.append(text.charAt(++pos));
- } else {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- private static int indexOfLabelEnd(String popupSpec, int start) {
- if (popupSpec.indexOf(ESCAPE, start) < 0) {
- final int end = popupSpec.indexOf(LABEL_END, start);
- if (end == 0)
- throw new PopupCharactersParserError(LABEL_END + " at " + start + ": " + popupSpec);
- return end;
- }
- final int length = popupSpec.length();
- for (int pos = start; pos < length; pos++) {
- final char c = popupSpec.charAt(pos);
- if (c == ESCAPE && pos + 1 < length) {
- pos++;
- } else if (popupSpec.startsWith(LABEL_END, pos)) {
- return pos;
- }
- }
- return -1;
- }
-
- public static String getLabel(String popupSpec) {
- if (hasIcon(popupSpec))
- return null;
- final int end = indexOfLabelEnd(popupSpec, 0);
- final String label = (end > 0) ? parseEscape(popupSpec.substring(0, end))
- : parseEscape(popupSpec);
- if (TextUtils.isEmpty(label))
- throw new PopupCharactersParserError("Empty label: " + popupSpec);
- return label;
- }
-
- public static String getOutputText(String popupSpec) {
- if (hasCode(popupSpec))
- return null;
- final int end = indexOfLabelEnd(popupSpec, 0);
- if (end > 0) {
- if (indexOfLabelEnd(popupSpec, end + 1) >= 0)
- throw new PopupCharactersParserError("Multiple " + LABEL_END + ": "
- + popupSpec);
- final String outputText = parseEscape(popupSpec.substring(end + LABEL_END.length()));
- if (!TextUtils.isEmpty(outputText))
- return outputText;
- throw new PopupCharactersParserError("Empty outputText: " + popupSpec);
- }
- final String label = getLabel(popupSpec);
- if (label == null)
- throw new PopupCharactersParserError("Empty label: " + popupSpec);
- // Code is automatically generated for one letter label. See {@link getCode()}.
- if (label.length() == 1)
- return null;
- return label;
- }
-
- public static int getCode(Resources res, String popupSpec) {
- if (hasCode(popupSpec)) {
- final int end = indexOfLabelEnd(popupSpec, 0);
- if (indexOfLabelEnd(popupSpec, end + 1) >= 0)
- throw new PopupCharactersParserError("Multiple " + LABEL_END + ": " + popupSpec);
- final int resId = getResourceId(res,
- popupSpec.substring(end + LABEL_END.length() + PREFIX_AT.length()));
- final int code = res.getInteger(resId);
- return code;
- }
- if (indexOfLabelEnd(popupSpec, 0) > 0)
- return Keyboard.CODE_DUMMY;
- final String label = getLabel(popupSpec);
- // Code is automatically generated for one letter label.
- if (label != null && label.length() == 1)
- return label.charAt(0);
- return Keyboard.CODE_DUMMY;
- }
-
- public static int getIconId(String popupSpec) {
- if (hasIcon(popupSpec)) {
- int end = popupSpec.indexOf(LABEL_END, PREFIX_ICON.length() + 1);
- final String iconId = popupSpec.substring(PREFIX_ICON.length(), end);
- try {
- return Integer.valueOf(iconId);
- } catch (NumberFormatException e) {
- Log.w(TAG, "illegal icon id specified: " + iconId);
- return KeyboardIconsSet.ICON_UNDEFINED;
- }
- }
- return KeyboardIconsSet.ICON_UNDEFINED;
- }
-
- private static int getResourceId(Resources res, String name) {
- String packageName = res.getResourcePackageName(R.string.english_ime_name);
- int resId = res.getIdentifier(name, null, packageName);
- if (resId == 0)
- throw new PopupCharactersParserError("Unknown resource: " + name);
- return resId;
- }
-
- @SuppressWarnings("serial")
- public static class PopupCharactersParserError extends RuntimeException {
- public PopupCharactersParserError(String message) {
- super(message);
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/Row.java b/java/src/com/android/inputmethod/keyboard/internal/Row.java
deleted file mode 100644
index 06aadcc05..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/Row.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 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.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.util.Xml;
-
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.R;
-
-/**
- * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
- * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
- * defines.
- */
-public class Row {
- /** Default width of a key in this row. */
- public final int mDefaultWidth;
- /** Default height of a key in this row. */
- public final int mDefaultHeight;
- /** Default horizontal gap between keys in this row. */
- public final int mDefaultHorizontalGap;
- /** Vertical gap following this row. */
- public final int mVerticalGap;
- /**
- * Edge flags for this row of keys. Possible values that can be assigned are
- * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM}
- */
- public final int mRowEdgeFlags;
-
- private final Keyboard mKeyboard;
-
- public Row(Resources res, Keyboard keyboard, XmlResourceParser parser) {
- this.mKeyboard = keyboard;
- final int keyboardWidth = keyboard.getDisplayWidth();
- final int keyboardHeight = keyboard.getKeyboardHeight();
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard);
- mDefaultWidth = KeyboardParser.getDimensionOrFraction(a,
- R.styleable.Keyboard_keyWidth, keyboardWidth, keyboard.getKeyWidth());
- mDefaultHeight = KeyboardParser.getDimensionOrFraction(a,
- R.styleable.Keyboard_rowHeight, keyboardHeight, keyboard.getRowHeight());
- mDefaultHorizontalGap = KeyboardParser.getDimensionOrFraction(a,
- R.styleable.Keyboard_horizontalGap, keyboardWidth, keyboard.getHorizontalGap());
- mVerticalGap = KeyboardParser.getDimensionOrFraction(a,
- R.styleable.Keyboard_verticalGap, keyboardHeight, keyboard.getVerticalGap());
- a.recycle();
- a = res.obtainAttributes(Xml.asAttributeSet(parser),
- R.styleable.Keyboard_Row);
- mRowEdgeFlags = a.getInt(R.styleable.Keyboard_Row_rowEdgeFlags, 0);
- a.recycle();
- }
-
- public Keyboard getKeyboard() {
- return mKeyboard;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java
index 6617b917f..edb40c8e7 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java
@@ -18,7 +18,7 @@ package com.android.inputmethod.keyboard.internal;
import android.util.Log;
-public class ShiftKeyState extends ModifierKeyState {
+/* package */ class ShiftKeyState extends ModifierKeyState {
private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked
private static final int IGNORING = 4;
@@ -30,7 +30,7 @@ public class ShiftKeyState extends ModifierKeyState {
public void onOtherKeyPressed() {
int oldState = mState;
if (oldState == PRESSING) {
- mState = MOMENTARY;
+ mState = CHORDING;
} else if (oldState == PRESSING_ON_SHIFTED) {
mState = IGNORING;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java b/java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java
deleted file mode 100644
index 78a3a7e9d..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/SlidingLocaleDrawable.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.keyboard.internal;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-import android.text.TextPaint;
-import android.view.ViewConfiguration;
-
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.LatinKeyboard;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-
-/**
- * Animation to be displayed on the spacebar preview popup when switching languages by swiping the
- * spacebar. It draws the current, previous and next languages and moves them by the delta of touch
- * movement on the spacebar.
- */
-public class SlidingLocaleDrawable extends Drawable {
- private static final int SLIDE_SPEED_MULTIPLIER_RATIO = 150;
- private final int mWidth;
- private final int mHeight;
- private final Drawable mBackground;
- private final int mSpacebarTextColor;
- private final TextPaint mTextPaint;
- private final int mMiddleX;
- private final Drawable mLeftDrawable;
- private final Drawable mRightDrawable;
- private final int mThreshold;
-
- private int mDiff;
- private boolean mHitThreshold;
- private String mCurrentLanguage;
- private String mNextLanguage;
- private String mPrevLanguage;
-
- public SlidingLocaleDrawable(Context context, Drawable background, int width, int height) {
- mBackground = background;
- Keyboard.setDefaultBounds(background);
- mWidth = width;
- mHeight = height;
- final TextPaint textPaint = new TextPaint();
- textPaint.setTextSize(LatinKeyboard.getTextSizeFromTheme(
- context.getTheme(), android.R.style.TextAppearance_Medium, 18));
- textPaint.setColor(Color.TRANSPARENT);
- textPaint.setTextAlign(Align.CENTER);
- textPaint.setAntiAlias(true);
- mTextPaint = textPaint;
- mMiddleX = (background != null) ? (mWidth - mBackground.getIntrinsicWidth()) / 2 : 0;
-
- final TypedArray lka = context.obtainStyledAttributes(
- null, R.styleable.LatinKeyboard, R.attr.latinKeyboardStyle, R.style.LatinKeyboard);
- mLeftDrawable = lka.getDrawable(R.styleable.LatinKeyboard_spacebarArrowPreviewLeftIcon);
- mRightDrawable = lka.getDrawable(R.styleable.LatinKeyboard_spacebarArrowPreviewRightIcon);
- lka.recycle();
- final TypedArray kva = context.obtainStyledAttributes(
- null, R.styleable.KeyboardView, R.attr.keyboardViewStyle, R.style.KeyboardView);
- mSpacebarTextColor = kva.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0);
- kva.recycle();
-
- mThreshold = ViewConfiguration.get(context).getScaledTouchSlop();
- }
-
- public void setDiff(int diff) {
- if (diff == Integer.MAX_VALUE) {
- mHitThreshold = false;
- mCurrentLanguage = null;
- return;
- }
- mDiff = Math.max(diff, diff * SLIDE_SPEED_MULTIPLIER_RATIO / 100);
- if (mDiff > mWidth) mDiff = mWidth;
- if (mDiff < -mWidth) mDiff = -mWidth;
- if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
- invalidateSelf();
- }
-
-
- @Override
- public void draw(Canvas canvas) {
- canvas.save();
- if (mHitThreshold) {
- Paint paint = mTextPaint;
- final int width = mWidth;
- final int height = mHeight;
- final int diff = mDiff;
- final Drawable lArrow = mLeftDrawable;
- final Drawable rArrow = mRightDrawable;
- canvas.clipRect(0, 0, width, height);
- if (mCurrentLanguage == null) {
- SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
- mCurrentLanguage = subtypeSwitcher.getInputLanguageName();
- mNextLanguage = subtypeSwitcher.getNextInputLanguageName();
- mPrevLanguage = subtypeSwitcher.getPreviousInputLanguageName();
- }
- // Draw language text with shadow
- final float baseline = mHeight * LatinKeyboard.SPACEBAR_LANGUAGE_BASELINE
- - paint.descent();
- paint.setColor(mSpacebarTextColor);
- canvas.drawText(mCurrentLanguage, width / 2 + diff, baseline, paint);
- canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint);
- canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint);
-
- if (lArrow != null && rArrow != null) {
- Keyboard.setDefaultBounds(lArrow);
- rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width,
- rArrow.getIntrinsicHeight());
- lArrow.draw(canvas);
- rArrow.draw(canvas);
- }
- }
- if (mBackground != null) {
- canvas.translate(mMiddleX, 0);
- mBackground.draw(canvas);
- }
- canvas.restore();
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public void setAlpha(int alpha) {
- // Ignore
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- // Ignore
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mWidth;
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mHeight;
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java b/java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java
deleted file mode 100644
index 8d192c2f0..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2010 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.view.MotionEvent;
-
-public class SwipeTracker {
- private static final int NUM_PAST = 4;
- private static final int LONGEST_PAST_TIME = 200;
-
- final EventRingBuffer mBuffer = new EventRingBuffer(NUM_PAST);
-
- private float mYVelocity;
- private float mXVelocity;
-
- public void addMovement(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mBuffer.clear();
- return;
- }
- long time = ev.getEventTime();
- final int count = ev.getHistorySize();
- for (int i = 0; i < count; i++) {
- addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), ev.getHistoricalEventTime(i));
- }
- addPoint(ev.getX(), ev.getY(), time);
- }
-
- private void addPoint(float x, float y, long time) {
- final EventRingBuffer buffer = mBuffer;
- while (buffer.size() > 0) {
- long lastT = buffer.getTime(0);
- if (lastT >= time - LONGEST_PAST_TIME)
- break;
- buffer.dropOldest();
- }
- buffer.add(x, y, time);
- }
-
- public void computeCurrentVelocity(int units) {
- computeCurrentVelocity(units, Float.MAX_VALUE);
- }
-
- public void computeCurrentVelocity(int units, float maxVelocity) {
- final EventRingBuffer buffer = mBuffer;
- final float oldestX = buffer.getX(0);
- final float oldestY = buffer.getY(0);
- final long oldestTime = buffer.getTime(0);
-
- float accumX = 0;
- float accumY = 0;
- final int count = buffer.size();
- for (int pos = 1; pos < count; pos++) {
- final int dur = (int)(buffer.getTime(pos) - oldestTime);
- if (dur == 0) continue;
- float dist = buffer.getX(pos) - oldestX;
- float vel = (dist / dur) * units; // pixels/frame.
- if (accumX == 0) accumX = vel;
- else accumX = (accumX + vel) * .5f;
-
- dist = buffer.getY(pos) - oldestY;
- vel = (dist / dur) * units; // pixels/frame.
- if (accumY == 0) accumY = vel;
- else accumY = (accumY + vel) * .5f;
- }
- mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity)
- : Math.min(accumX, maxVelocity);
- mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity)
- : Math.min(accumY, maxVelocity);
- }
-
- public float getXVelocity() {
- return mXVelocity;
- }
-
- public float getYVelocity() {
- return mYVelocity;
- }
-
- public static class EventRingBuffer {
- private final int bufSize;
- private final float xBuf[];
- private final float yBuf[];
- private final long timeBuf[];
- private int top; // points new event
- private int end; // points oldest event
- private int count; // the number of valid data
-
- public EventRingBuffer(int max) {
- this.bufSize = max;
- xBuf = new float[max];
- yBuf = new float[max];
- timeBuf = new long[max];
- clear();
- }
-
- public void clear() {
- top = end = count = 0;
- }
-
- public int size() {
- return count;
- }
-
- // Position 0 points oldest event
- private int index(int pos) {
- return (end + pos) % bufSize;
- }
-
- private int advance(int index) {
- return (index + 1) % bufSize;
- }
-
- public void add(float x, float y, long time) {
- xBuf[top] = x;
- yBuf[top] = y;
- timeBuf[top] = time;
- top = advance(top);
- if (count < bufSize) {
- count++;
- } else {
- end = advance(end);
- }
- }
-
- public float getX(int pos) {
- return xBuf[index(pos)];
- }
-
- public float getY(int pos) {
- return yBuf[index(pos)];
- }
-
- public long getTime(int pos) {
- return timeBuf[index(pos)];
- }
-
- public void dropOldest() {
- count--;
- end = advance(end);
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
new file mode 100644
index 000000000..f8f1395b3
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
+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.view.inputmethod.InputMethodSubtype;
+
+import java.util.ArrayList;
+
+public class AdditionalSubtype {
+ private static final InputMethodSubtype[] EMPTY_SUBTYPE_ARRAY = new InputMethodSubtype[0];
+
+ private AdditionalSubtype() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static boolean isAdditionalSubtype(InputMethodSubtype subtype) {
+ return subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE);
+ }
+
+ private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":";
+ public static final String PREF_SUBTYPE_SEPARATOR = ";";
+
+ public static InputMethodSubtype createAdditionalSubtype(
+ String localeString, String keyboardLayoutSetName, String extraValue) {
+ final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
+ final String layoutDisplayNameExtraValue;
+ if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15
+ && SubtypeLocale.isExceptionalLocale(localeString)) {
+ final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName(
+ keyboardLayoutSetName);
+ layoutDisplayNameExtraValue = StringUtils.appendToCsvIfNotExists(
+ UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME + "=" + layoutDisplayName, extraValue);
+ } else {
+ layoutDisplayNameExtraValue = extraValue;
+ }
+ final String additionalSubtypeExtraValue = StringUtils.appendToCsvIfNotExists(
+ IS_ADDITIONAL_SUBTYPE, layoutDisplayNameExtraValue);
+ final int nameId = SubtypeLocale.getSubtypeNameId(localeString, keyboardLayoutSetName);
+ return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
+ localeString, KEYBOARD_MODE,
+ layoutExtraValue + "," + additionalSubtypeExtraValue, false, false);
+ }
+
+ public static String getPrefSubtype(InputMethodSubtype subtype) {
+ final String localeString = subtype.getLocale();
+ final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
+ final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName;
+ final String extraValue = StringUtils.removeFromCsvIfExists(layoutExtraValue,
+ StringUtils.removeFromCsvIfExists(IS_ADDITIONAL_SUBTYPE, subtype.getExtraValue()));
+ final String basePrefSubtype = localeString + LOCALE_AND_LAYOUT_SEPARATOR
+ + keyboardLayoutSetName;
+ return extraValue.isEmpty() ? basePrefSubtype
+ : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue;
+ }
+
+ public static InputMethodSubtype createAdditionalSubtype(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(String prefSubtypes) {
+ if (TextUtils.isEmpty(prefSubtypes)) {
+ return EMPTY_SUBTYPE_ARRAY;
+ }
+ final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR);
+ final ArrayList<InputMethodSubtype> subtypesList =
+ new ArrayList<InputMethodSubtype>(prefSubtypeArray.length);
+ for (final String prefSubtype : prefSubtypeArray) {
+ final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtype);
+ if (subtype.getNameResId() == SubtypeLocale.UNKNOWN_KEYBOARD_LAYOUT) {
+ // Skip unknown keyboard layout subtype. This may happen when predefined keyboard
+ // layout has been removed.
+ continue;
+ }
+ subtypesList.add(subtype);
+ }
+ return subtypesList.toArray(new InputMethodSubtype[subtypesList.size()]);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
new file mode 100644
index 000000000..779a38823
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -0,0 +1,599 @@
+/**
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceGroup;
+import android.util.Pair;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.SpinnerAdapter;
+import android.widget.Toast;
+
+import com.android.inputmethod.compat.CompatUtils;
+
+import java.util.ArrayList;
+import java.util.TreeSet;
+
+public class AdditionalSubtypeSettings extends PreferenceFragment {
+ private SharedPreferences mPrefs;
+ private SubtypeLocaleAdapter mSubtypeLocaleAdapter;
+ private KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;
+
+ private boolean mIsAddingNewSubtype;
+ private AlertDialog mSubtypeEnablerNotificationDialog;
+ private String mSubtypePreferenceKeyForSubtypeEnabler;
+
+ private static final int MENU_ADD_SUBTYPE = Menu.FIRST;
+ private static final String KEY_IS_ADDING_NEW_SUBTYPE = "is_adding_new_subtype";
+ private static final String KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN =
+ "is_subtype_enabler_notification_dialog_open";
+ private static final String KEY_SUBTYPE_FOR_SUBTYPE_ENABLER = "subtype_for_subtype_enabler";
+ static class SubtypeLocaleItem extends Pair<String, String>
+ implements Comparable<SubtypeLocaleItem> {
+ public SubtypeLocaleItem(String localeString, String displayName) {
+ super(localeString, displayName);
+ }
+
+ public SubtypeLocaleItem(String localeString) {
+ this(localeString, SubtypeLocale.getSubtypeLocaleDisplayName(localeString));
+ }
+
+ @Override
+ public String toString() {
+ return second;
+ }
+
+ @Override
+ public int compareTo(SubtypeLocaleItem o) {
+ return first.compareTo(o.first);
+ }
+ }
+
+ static class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
+ public SubtypeLocaleAdapter(Context context) {
+ super(context, android.R.layout.simple_spinner_item);
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+ final TreeSet<SubtypeLocaleItem> items = new TreeSet<SubtypeLocaleItem>();
+ final InputMethodInfo imi = ImfUtils.getInputMethodInfoOfThisIme(context);
+ final int count = imi.getSubtypeCount();
+ for (int i = 0; i < count; i++) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ if (subtype.containsExtraValueKey(ASCII_CAPABLE)) {
+ items.add(createItem(context, subtype.getLocale()));
+ }
+ }
+ // TODO: Should filter out already existing combinations of locale and layout.
+ addAll(items);
+ }
+
+ public static SubtypeLocaleItem createItem(Context context, String localeString) {
+ if (localeString.equals(SubtypeLocale.NO_LANGUAGE)) {
+ final String displayName = context.getString(R.string.subtype_no_language);
+ return new SubtypeLocaleItem(localeString, displayName);
+ } else {
+ return new SubtypeLocaleItem(localeString);
+ }
+ }
+ }
+
+ static class KeyboardLayoutSetItem extends Pair<String, String> {
+ public KeyboardLayoutSetItem(InputMethodSubtype subtype) {
+ super(SubtypeLocale.getKeyboardLayoutSetName(subtype),
+ SubtypeLocale.getKeyboardLayoutSetDisplayName(subtype));
+ }
+
+ @Override
+ public String toString() {
+ return second;
+ }
+ }
+
+ static class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
+ public KeyboardLayoutSetAdapter(Context context) {
+ super(context, android.R.layout.simple_spinner_item);
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+ // TODO: Should filter out already existing combinations of locale and layout.
+ for (final String layout : SubtypeLocale.getPredefinedKeyboardLayoutSet()) {
+ // This is a dummy subtype with NO_LANGUAGE, only for display.
+ final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
+ SubtypeLocale.NO_LANGUAGE, layout, null);
+ add(new KeyboardLayoutSetItem(subtype));
+ }
+ }
+ }
+
+ private interface SubtypeDialogProxy {
+ public void onRemovePressed(SubtypePreference subtypePref);
+ public void onSavePressed(SubtypePreference subtypePref);
+ public void onAddPressed(SubtypePreference subtypePref);
+ public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
+ public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
+ }
+
+ static class SubtypePreference extends DialogPreference
+ implements DialogInterface.OnCancelListener {
+ private static final String KEY_PREFIX = "subtype_pref_";
+ private static final String KEY_NEW_SUBTYPE = KEY_PREFIX + "new";
+
+ private InputMethodSubtype mSubtype;
+ private InputMethodSubtype mPreviousSubtype;
+
+ private final SubtypeDialogProxy mProxy;
+ private Spinner mSubtypeLocaleSpinner;
+ private Spinner mKeyboardLayoutSetSpinner;
+
+ public static SubtypePreference newIncompleteSubtypePreference(
+ Context context, SubtypeDialogProxy proxy) {
+ return new SubtypePreference(context, null, proxy);
+ }
+
+ public SubtypePreference(Context context, InputMethodSubtype subtype,
+ SubtypeDialogProxy proxy) {
+ super(context, null);
+ setDialogLayoutResource(R.layout.additional_subtype_dialog);
+ setPersistent(false);
+ mProxy = proxy;
+ setSubtype(subtype);
+ }
+
+ public void show() {
+ showDialog(null);
+ }
+
+ public final boolean isIncomplete() {
+ return mSubtype == null;
+ }
+
+ public InputMethodSubtype getSubtype() {
+ return mSubtype;
+ }
+
+ public void setSubtype(InputMethodSubtype subtype) {
+ mPreviousSubtype = mSubtype;
+ mSubtype = subtype;
+ if (isIncomplete()) {
+ setTitle(null);
+ setDialogTitle(R.string.add_style);
+ setKey(KEY_NEW_SUBTYPE);
+ } else {
+ final String displayName = SubtypeLocale.getSubtypeDisplayName(
+ subtype, getContext().getResources());
+ setTitle(displayName);
+ setDialogTitle(displayName);
+ setKey(KEY_PREFIX + subtype.getLocale() + "_"
+ + SubtypeLocale.getKeyboardLayoutSetName(subtype));
+ }
+ }
+
+ public void revert() {
+ setSubtype(mPreviousSubtype);
+ }
+
+ public boolean hasBeenModified() {
+ return mSubtype != null && !mSubtype.equals(mPreviousSubtype);
+ }
+
+ @Override
+ protected View onCreateDialogView() {
+ final View v = super.onCreateDialogView();
+ mSubtypeLocaleSpinner = (Spinner) v.findViewById(R.id.subtype_locale_spinner);
+ mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
+ mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
+ mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
+ return v;
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ final Context context = builder.getContext();
+ builder.setCancelable(true).setOnCancelListener(this);
+ if (isIncomplete()) {
+ builder.setPositiveButton(R.string.add, this)
+ .setNegativeButton(android.R.string.cancel, this);
+ } else {
+ builder.setPositiveButton(R.string.save, this)
+ .setNeutralButton(android.R.string.cancel, this)
+ .setNegativeButton(R.string.remove, this);
+ final SubtypeLocaleItem localeItem = SubtypeLocaleAdapter.createItem(
+ context, mSubtype.getLocale());
+ final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(mSubtype);
+ setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
+ setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
+ }
+ }
+
+ private static void setSpinnerPosition(Spinner spinner, Object itemToSelect) {
+ final SpinnerAdapter adapter = spinner.getAdapter();
+ final int count = adapter.getCount();
+ for (int i = 0; i < count; i++) {
+ final Object item = spinner.getItemAtPosition(i);
+ if (item.equals(itemToSelect)) {
+ spinner.setSelection(i);
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (isIncomplete()) {
+ mProxy.onRemovePressed(this);
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ super.onClick(dialog, which);
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ final boolean isEditing = !isIncomplete();
+ final SubtypeLocaleItem locale =
+ (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
+ final KeyboardLayoutSetItem layout =
+ (KeyboardLayoutSetItem) mKeyboardLayoutSetSpinner.getSelectedItem();
+ final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
+ locale.first, layout.first, ASCII_CAPABLE);
+ setSubtype(subtype);
+ notifyChanged();
+ if (isEditing) {
+ mProxy.onSavePressed(this);
+ } else {
+ mProxy.onAddPressed(this);
+ }
+ break;
+ case DialogInterface.BUTTON_NEUTRAL:
+ // Nothing to do
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ mProxy.onRemovePressed(this);
+ break;
+ }
+ }
+
+ private static int getSpinnerPosition(Spinner spinner) {
+ if (spinner == null) return -1;
+ return spinner.getSelectedItemPosition();
+ }
+
+ private static void setSpinnerPosition(Spinner spinner, int position) {
+ if (spinner == null || position < 0) return;
+ spinner.setSelection(position);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ final Dialog dialog = getDialog();
+ if (dialog == null || !dialog.isShowing()) {
+ return superState;
+ }
+
+ final SavedState myState = new SavedState(superState);
+ myState.mSubtype = mSubtype;
+ myState.mSubtypeLocaleSelectedPos = getSpinnerPosition(mSubtypeLocaleSpinner);
+ myState.mKeyboardLayoutSetSelectedPos = getSpinnerPosition(mKeyboardLayoutSetSpinner);
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (!(state instanceof SavedState)) {
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ final SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ setSpinnerPosition(mSubtypeLocaleSpinner, myState.mSubtypeLocaleSelectedPos);
+ setSpinnerPosition(mKeyboardLayoutSetSpinner, myState.mKeyboardLayoutSetSelectedPos);
+ setSubtype(myState.mSubtype);
+ }
+
+ static class SavedState extends Preference.BaseSavedState {
+ InputMethodSubtype mSubtype;
+ int mSubtypeLocaleSelectedPos;
+ int mKeyboardLayoutSetSelectedPos;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mSubtypeLocaleSelectedPos);
+ dest.writeInt(mKeyboardLayoutSetSelectedPos);
+ dest.writeParcelable(mSubtype, 0);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ mSubtypeLocaleSelectedPos = source.readInt();
+ mKeyboardLayoutSetSelectedPos = source.readInt();
+ mSubtype = (InputMethodSubtype)source.readParcelable(null);
+ }
+
+ @SuppressWarnings("hiding")
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ @Override
+ public SavedState createFromParcel(Parcel source) {
+ return new SavedState(source);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+ }
+
+ public AdditionalSubtypeSettings() {
+ // Empty constructor for fragment generation.
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.additional_subtype_settings);
+ setHasOptionsMenu(true);
+
+ mPrefs = getPreferenceManager().getSharedPreferences();
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ final Context context = getActivity();
+ mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
+ mKeyboardLayoutSetAdapter = new KeyboardLayoutSetAdapter(context);
+
+ final String prefSubtypes =
+ SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
+ setPrefSubtypes(prefSubtypes, context);
+
+ mIsAddingNewSubtype = (savedInstanceState != null)
+ && savedInstanceState.containsKey(KEY_IS_ADDING_NEW_SUBTYPE);
+ if (mIsAddingNewSubtype) {
+ getPreferenceScreen().addPreference(
+ SubtypePreference.newIncompleteSubtypePreference(context, mSubtypeProxy));
+ }
+
+ super.onActivityCreated(savedInstanceState);
+
+ if (savedInstanceState != null && savedInstanceState.containsKey(
+ KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN)) {
+ mSubtypePreferenceKeyForSubtypeEnabler = savedInstanceState.getString(
+ KEY_SUBTYPE_FOR_SUBTYPE_ENABLER);
+ final SubtypePreference subtypePref = (SubtypePreference)findPreference(
+ mSubtypePreferenceKeyForSubtypeEnabler);
+ mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
+ mSubtypeEnablerNotificationDialog.show();
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mIsAddingNewSubtype) {
+ outState.putBoolean(KEY_IS_ADDING_NEW_SUBTYPE, true);
+ }
+ if (mSubtypeEnablerNotificationDialog != null
+ && mSubtypeEnablerNotificationDialog.isShowing()) {
+ outState.putBoolean(KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN, true);
+ outState.putString(
+ KEY_SUBTYPE_FOR_SUBTYPE_ENABLER, mSubtypePreferenceKeyForSubtypeEnabler);
+ }
+ }
+
+ private final SubtypeDialogProxy mSubtypeProxy = new SubtypeDialogProxy() {
+ @Override
+ public void onRemovePressed(SubtypePreference subtypePref) {
+ mIsAddingNewSubtype = false;
+ final PreferenceGroup group = getPreferenceScreen();
+ group.removePreference(subtypePref);
+ ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes());
+ }
+
+ @Override
+ public void onSavePressed(SubtypePreference subtypePref) {
+ final InputMethodSubtype subtype = subtypePref.getSubtype();
+ if (!subtypePref.hasBeenModified()) {
+ return;
+ }
+ if (findDuplicatedSubtype(subtype) == null) {
+ ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes());
+ return;
+ }
+
+ // Saved subtype is duplicated.
+ final PreferenceGroup group = getPreferenceScreen();
+ group.removePreference(subtypePref);
+ subtypePref.revert();
+ group.addPreference(subtypePref);
+ showSubtypeAlreadyExistsToast(subtype);
+ }
+
+ @Override
+ public void onAddPressed(SubtypePreference subtypePref) {
+ mIsAddingNewSubtype = false;
+ final InputMethodSubtype subtype = subtypePref.getSubtype();
+ if (findDuplicatedSubtype(subtype) == null) {
+ ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), getSubtypes());
+ mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey();
+ mSubtypeEnablerNotificationDialog = createDialog(subtypePref);
+ mSubtypeEnablerNotificationDialog.show();
+ return;
+ }
+
+ // Newly added subtype is duplicated.
+ final PreferenceGroup group = getPreferenceScreen();
+ group.removePreference(subtypePref);
+ showSubtypeAlreadyExistsToast(subtype);
+ }
+
+ @Override
+ public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
+ return mSubtypeLocaleAdapter;
+ }
+
+ @Override
+ public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
+ return mKeyboardLayoutSetAdapter;
+ }
+ };
+
+ private void showSubtypeAlreadyExistsToast(InputMethodSubtype subtype) {
+ final Context context = getActivity();
+ final Resources res = context.getResources();
+ final String message = res.getString(R.string.custom_input_style_already_exists,
+ SubtypeLocale.getSubtypeDisplayName(subtype, res));
+ Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+ }
+
+ private InputMethodSubtype findDuplicatedSubtype(InputMethodSubtype subtype) {
+ final String localeString = subtype.getLocale();
+ final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
+ return ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+ getActivity(), localeString, keyboardLayoutSetName);
+ }
+
+ private AlertDialog createDialog(SubtypePreference subtypePref) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.custom_input_styles_title)
+ .setMessage(R.string.custom_input_style_note_message)
+ .setNegativeButton(R.string.not_now, null)
+ .setPositiveButton(R.string.enable, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final Intent intent = CompatUtils.getInputLanguageSelectionIntent(
+ ImfUtils.getInputMethodIdOfThisIme(getActivity()),
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ // TODO: Add newly adding subtype to extra value of the intent as a hint
+ // for the input language selection activity.
+ // intent.putExtra("newlyAddedSubtype", subtypePref.getSubtype());
+ startActivity(intent);
+ }
+ });
+
+ return builder.create();
+ }
+
+ private void setPrefSubtypes(String prefSubtypes, Context context) {
+ final PreferenceGroup group = getPreferenceScreen();
+ group.removeAll();
+ final InputMethodSubtype[] subtypesArray =
+ AdditionalSubtype.createAdditionalSubtypesArray(prefSubtypes);
+ for (final InputMethodSubtype subtype : subtypesArray) {
+ final SubtypePreference pref = new SubtypePreference(
+ context, subtype, mSubtypeProxy);
+ group.addPreference(pref);
+ }
+ }
+
+ private InputMethodSubtype[] getSubtypes() {
+ final PreferenceGroup group = getPreferenceScreen();
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ final int count = group.getPreferenceCount();
+ for (int i = 0; i < count; i++) {
+ final Preference pref = group.getPreference(i);
+ if (pref instanceof SubtypePreference) {
+ final SubtypePreference subtypePref = (SubtypePreference)pref;
+ // We should not save newly adding subtype to preference because it is incomplete.
+ if (subtypePref.isIncomplete()) continue;
+ subtypes.add(subtypePref.getSubtype());
+ }
+ }
+ return subtypes.toArray(new InputMethodSubtype[subtypes.size()]);
+ }
+
+ private String getPrefSubtypes(InputMethodSubtype[] subtypes) {
+ final StringBuilder sb = new StringBuilder();
+ for (final InputMethodSubtype subtype : subtypes) {
+ if (sb.length() > 0) {
+ sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR);
+ }
+ sb.append(AdditionalSubtype.getPrefSubtype(subtype));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ final String oldSubtypes = SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
+ final InputMethodSubtype[] subtypes = getSubtypes();
+ final String prefSubtypes = getPrefSubtypes(subtypes);
+ if (prefSubtypes.equals(oldSubtypes)) {
+ return;
+ }
+
+ final SharedPreferences.Editor editor = mPrefs.edit();
+ try {
+ editor.putString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes);
+ } finally {
+ editor.apply();
+ }
+ ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), subtypes);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ final MenuItem addSubtypeMenu = menu.add(0, MENU_ADD_SUBTYPE, 0, R.string.add_style);
+ addSubtypeMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == MENU_ADD_SUBTYPE) {
+ final SubtypePreference newSubtype =
+ SubtypePreference.newIncompleteSubtypePreference(getActivity(), mSubtypeProxy);
+ getPreferenceScreen().addPreference(newSubtype);
+ newSubtype.show();
+ mIsAddingNewSubtype = true;
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
index 074ecacc5..3549a1561 100644
--- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java
+++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
@@ -37,16 +37,16 @@ class AssetFileAddress {
public static AssetFileAddress makeFromFileName(final String filename) {
if (null == filename) return null;
- File f = new File(filename);
- if (null == f || !f.isFile()) return null;
+ final File f = new File(filename);
+ if (!f.isFile()) return null;
return new AssetFileAddress(filename, 0l, f.length());
}
public static AssetFileAddress makeFromFileNameAndOffset(final String filename,
final long offset, final long length) {
if (null == filename) return null;
- File f = new File(filename);
- if (null == f || !f.isFile()) return null;
+ final File f = new File(filename);
+ if (!f.isFile()) return null;
return new AssetFileAddress(filename, offset, length);
}
}
diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
new file mode 100644
index 000000000..55664d411
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.VibratorUtils;
+
+/**
+ * This class gathers audio feedback and haptic feedback functions.
+ *
+ * It offers a consistent and simple interface that allows LatinIME to forget about the
+ * complexity of settings and the like.
+ */
+public class AudioAndHapticFeedbackManager {
+ final private SettingsValues mSettingsValues;
+ final private AudioManager mAudioManager;
+ final private VibratorUtils mVibratorUtils;
+ private boolean mSoundOn;
+
+ public AudioAndHapticFeedbackManager(final LatinIME latinIme,
+ final SettingsValues settingsValues) {
+ mSettingsValues = settingsValues;
+ mVibratorUtils = VibratorUtils.getInstance(latinIme);
+ mAudioManager = (AudioManager) latinIme.getSystemService(Context.AUDIO_SERVICE);
+ mSoundOn = reevaluateIfSoundIsOn();
+ }
+
+ public void hapticAndAudioFeedback(final int primaryCode,
+ final View viewToPerformHapticFeedbackOn) {
+ vibrate(viewToPerformHapticFeedbackOn);
+ playKeyClick(primaryCode);
+ }
+
+ private boolean reevaluateIfSoundIsOn() {
+ if (!mSettingsValues.mSoundOn || mAudioManager == null) {
+ return false;
+ } else {
+ return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL;
+ }
+ }
+
+ private void playKeyClick(int primaryCode) {
+ // if mAudioManager is null, we can't play a sound anyway, so return
+ if (mAudioManager == null) return;
+ if (mSoundOn) {
+ final int sound;
+ switch (primaryCode) {
+ case Keyboard.CODE_DELETE:
+ sound = AudioManager.FX_KEYPRESS_DELETE;
+ break;
+ case Keyboard.CODE_ENTER:
+ sound = AudioManager.FX_KEYPRESS_RETURN;
+ break;
+ case Keyboard.CODE_SPACE:
+ sound = AudioManager.FX_KEYPRESS_SPACEBAR;
+ break;
+ default:
+ sound = AudioManager.FX_KEYPRESS_STANDARD;
+ break;
+ }
+ mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume);
+ }
+ }
+
+ // TODO: make this private when LatinIME does not call it any more
+ public void vibrate(final View viewToPerformHapticFeedbackOn) {
+ if (!mSettingsValues.mVibrateOn) {
+ return;
+ }
+ if (mSettingsValues.mKeypressVibrationDuration < 0) {
+ // Go ahead with the system default
+ if (viewToPerformHapticFeedbackOn != null) {
+ viewToPerformHapticFeedbackOn.performHapticFeedback(
+ HapticFeedbackConstants.KEYBOARD_TAP,
+ HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
+ }
+ } else if (mVibratorUtils != null) {
+ mVibratorUtils.vibrate(mSettingsValues.mKeypressVibrationDuration);
+ }
+ }
+
+ public void onRingerModeChanged() {
+ mSoundOn = reevaluateIfSoundIsOn();
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java
index d3119792c..e0452483c 100644
--- a/java/src/com/android/inputmethod/latin/AutoCorrection.java
+++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java
@@ -16,60 +16,41 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
-import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
public class AutoCorrection {
private static final boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = AutoCorrection.class.getSimpleName();
- private boolean mHasAutoCorrection;
- private CharSequence mAutoCorrectionWord;
- private double mNormalizedScore;
-
- public void init() {
- mHasAutoCorrection = false;
- mAutoCorrectionWord = null;
- mNormalizedScore = Integer.MIN_VALUE;
- }
-
- public boolean hasAutoCorrection() {
- return mHasAutoCorrection;
- }
- public CharSequence getAutoCorrectionWord() {
- return mAutoCorrectionWord;
+ private AutoCorrection() {
+ // Purely static class: can't instantiate.
}
- public double getNormalizedScore() {
- return mNormalizedScore;
- }
-
- public void updateAutoCorrectionStatus(Map<String, Dictionary> dictionaries,
- WordComposer wordComposer, ArrayList<CharSequence> suggestions, int[] sortedScores,
- CharSequence typedWord, double autoCorrectionThreshold, int correctionMode,
- CharSequence quickFixedWord, CharSequence whitelistedWord) {
+ public static CharSequence computeAutoCorrectionWord(
+ final ConcurrentHashMap<String, Dictionary> dictionaries,
+ final WordComposer wordComposer, final ArrayList<SuggestedWordInfo> suggestions,
+ final CharSequence consideredWord, final float autoCorrectionThreshold,
+ final CharSequence whitelistedWord) {
if (hasAutoCorrectionForWhitelistedWord(whitelistedWord)) {
- mHasAutoCorrection = true;
- mAutoCorrectionWord = whitelistedWord;
- } else if (hasAutoCorrectionForTypedWord(
- dictionaries, wordComposer, suggestions, typedWord, correctionMode)) {
- mHasAutoCorrection = true;
- mAutoCorrectionWord = typedWord;
- } else if (hasAutoCorrectionForQuickFix(quickFixedWord)) {
- mHasAutoCorrection = true;
- mAutoCorrectionWord = quickFixedWord;
- } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions, correctionMode,
- sortedScores, typedWord, autoCorrectionThreshold)) {
- mHasAutoCorrection = true;
- mAutoCorrectionWord = suggestions.get(0);
+ return whitelistedWord;
+ } else if (hasAutoCorrectionForConsideredWord(
+ dictionaries, wordComposer, suggestions, consideredWord)) {
+ return consideredWord;
+ } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions,
+ consideredWord, autoCorrectionThreshold)) {
+ return suggestions.get(0).mWord;
}
+ return null;
}
- public static boolean isValidWord(
- Map<String, Dictionary> dictionaries, CharSequence word, boolean ignoreCase) {
+ public static boolean isValidWord(final ConcurrentHashMap<String, Dictionary> dictionaries,
+ CharSequence word, boolean ignoreCase) {
if (TextUtils.isEmpty(word)) {
return false;
}
@@ -77,6 +58,14 @@ public class AutoCorrection {
for (final String key : dictionaries.keySet()) {
if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue;
final Dictionary dictionary = dictionaries.get(key);
+ // It's unclear how realistically 'dictionary' can be null, but the monkey is somehow
+ // managing to get null in here. Presumably the language is changing to a language with
+ // no main dictionary and the monkey manages to type a whole word before the thread
+ // that reads the dictionary is started or something?
+ // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
+ // would be immutable once it's finished initializing, but concretely a null test is
+ // probably good enough for the time being.
+ if (null == dictionary) continue;
if (dictionary.isValidWord(word)
|| (ignoreCase && dictionary.isValidWord(lowerCasedWord))) {
return true;
@@ -85,52 +74,68 @@ public class AutoCorrection {
return false;
}
- public static boolean isValidWordForAutoCorrection(
- Map<String, Dictionary> dictionaries, CharSequence word, boolean ignoreCase) {
- final Dictionary whiteList = dictionaries.get(Suggest.DICT_KEY_WHITELIST);
+ public static int getMaxFrequency(final ConcurrentHashMap<String, Dictionary> dictionaries,
+ CharSequence word) {
+ if (TextUtils.isEmpty(word)) {
+ return Dictionary.NOT_A_PROBABILITY;
+ }
+ int maxFreq = -1;
+ for (final String key : dictionaries.keySet()) {
+ if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue;
+ final Dictionary dictionary = dictionaries.get(key);
+ if (null == dictionary) continue;
+ final int tempFreq = dictionary.getFrequency(word);
+ if (tempFreq >= maxFreq) {
+ maxFreq = tempFreq;
+ }
+ }
+ return maxFreq;
+ }
+
+ public static boolean allowsToBeAutoCorrected(
+ final ConcurrentHashMap<String, Dictionary> dictionaries,
+ final CharSequence word, final boolean ignoreCase) {
+ final WhitelistDictionary whitelistDictionary =
+ (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST);
// If "word" is in the whitelist dictionary, it should not be auto corrected.
- if (whiteList != null && whiteList.isValidWord(word)) {
- return false;
+ if (whitelistDictionary != null
+ && whitelistDictionary.shouldForciblyAutoCorrectFrom(word)) {
+ return true;
}
- return isValidWord(dictionaries, word, ignoreCase);
+ return !isValidWord(dictionaries, word, ignoreCase);
}
private static boolean hasAutoCorrectionForWhitelistedWord(CharSequence whiteListedWord) {
return whiteListedWord != null;
}
- private boolean hasAutoCorrectionForTypedWord(Map<String, Dictionary> dictionaries,
- WordComposer wordComposer, ArrayList<CharSequence> suggestions, CharSequence typedWord,
- int correctionMode) {
- if (TextUtils.isEmpty(typedWord)) return false;
- boolean isValidWord = isValidWordForAutoCorrection(dictionaries, typedWord, false);
- return wordComposer.size() > 1 && suggestions.size() > 0 && isValidWord
- && (correctionMode == Suggest.CORRECTION_FULL
- || correctionMode == Suggest.CORRECTION_FULL_BIGRAM);
- }
-
- private static boolean hasAutoCorrectionForQuickFix(CharSequence quickFixedWord) {
- return quickFixedWord != null;
+ private static boolean hasAutoCorrectionForConsideredWord(
+ final ConcurrentHashMap<String, Dictionary> dictionaries,
+ final WordComposer wordComposer, final ArrayList<SuggestedWordInfo> suggestions,
+ final CharSequence consideredWord) {
+ if (TextUtils.isEmpty(consideredWord)) return false;
+ return wordComposer.size() > 1 && suggestions.size() > 0
+ && !allowsToBeAutoCorrected(dictionaries, consideredWord, false);
}
- private boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer,
- ArrayList<CharSequence> suggestions, int correctionMode, int[] sortedScores,
- CharSequence typedWord, double autoCorrectionThreshold) {
- if (wordComposer.size() > 1 && (correctionMode == Suggest.CORRECTION_FULL
- || correctionMode == Suggest.CORRECTION_FULL_BIGRAM)
- && typedWord != null && suggestions.size() > 0 && sortedScores.length > 0) {
- final CharSequence autoCorrectionCandidate = suggestions.get(0);
- final int autoCorrectionCandidateScore = sortedScores[0];
+ private static boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer,
+ ArrayList<SuggestedWordInfo> suggestions,
+ CharSequence consideredWord, float autoCorrectionThreshold) {
+ if (wordComposer.size() > 1 && suggestions.size() > 0) {
+ final SuggestedWordInfo autoCorrectionSuggestion = suggestions.get(0);
+ //final int autoCorrectionSuggestionScore = sortedScores[0];
+ final int autoCorrectionSuggestionScore = autoCorrectionSuggestion.mScore;
// TODO: when the normalized score of the first suggestion is nearly equals to
// the normalized score of the second suggestion, behave less aggressive.
- mNormalizedScore = Utils.calcNormalizedScore(
- typedWord,autoCorrectionCandidate, autoCorrectionCandidateScore);
+ final float normalizedScore = BinaryDictionary.calcNormalizedScore(
+ consideredWord.toString(), autoCorrectionSuggestion.mWord.toString(),
+ autoCorrectionSuggestionScore);
if (DBG) {
- Log.d(TAG, "Normalized " + typedWord + "," + autoCorrectionCandidate + ","
- + autoCorrectionCandidateScore + ", " + mNormalizedScore
+ Log.d(TAG, "Normalized " + consideredWord + "," + autoCorrectionSuggestion + ","
+ + autoCorrectionSuggestionScore + ", " + normalizedScore
+ "(" + autoCorrectionThreshold + ")");
}
- if (mNormalizedScore >= autoCorrectionThreshold) {
+ if (normalizedScore >= autoCorrectionThreshold) {
if (DBG) {
Log.d(TAG, "Auto corrected by S-threshold.");
}
diff --git a/java/src/com/android/inputmethod/latin/AutoDictionary.java b/java/src/com/android/inputmethod/latin/AutoDictionary.java
deleted file mode 100644
index 460930f16..000000000
--- a/java/src/com/android/inputmethod/latin/AutoDictionary.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.os.AsyncTask;
-import android.provider.BaseColumns;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * Stores new words temporarily until they are promoted to the user dictionary
- * for longevity. Words in the auto dictionary are used to determine if it's ok
- * to accept a word that's not in the main or user dictionary. Using a new word
- * repeatedly will promote it to the user dictionary.
- */
-public class AutoDictionary extends ExpandableDictionary {
- // Weight added to a user picking a new word from the suggestion strip
- static final int FREQUENCY_FOR_PICKED = 3;
- // Weight added to a user typing a new word that doesn't get corrected (or is reverted)
- static final int FREQUENCY_FOR_TYPED = 1;
- // If the user touches a typed word 2 times or more, it will become valid.
- private static final int VALIDITY_THRESHOLD = 2 * FREQUENCY_FOR_PICKED;
-
- private LatinIME mIme;
- // Locale for which this auto dictionary is storing words
- private String mLocale;
-
- private HashMap<String,Integer> mPendingWrites = new HashMap<String,Integer>();
- private final Object mPendingWritesLock = new Object();
-
- private static final String DATABASE_NAME = "auto_dict.db";
- private static final int DATABASE_VERSION = 1;
-
- // These are the columns in the dictionary
- // TODO: Consume less space by using a unique id for locale instead of the whole
- // 2-5 character string.
- private static final String COLUMN_ID = BaseColumns._ID;
- private static final String COLUMN_WORD = "word";
- private static final String COLUMN_FREQUENCY = "freq";
- private static final String COLUMN_LOCALE = "locale";
-
- /** Sort by descending order of frequency. */
- public static final String DEFAULT_SORT_ORDER = COLUMN_FREQUENCY + " DESC";
-
- /** Name of the words table in the auto_dict.db */
- private static final String AUTODICT_TABLE_NAME = "words";
-
- private static HashMap<String, String> sDictProjectionMap;
-
- static {
- sDictProjectionMap = new HashMap<String, String>();
- sDictProjectionMap.put(COLUMN_ID, COLUMN_ID);
- sDictProjectionMap.put(COLUMN_WORD, COLUMN_WORD);
- sDictProjectionMap.put(COLUMN_FREQUENCY, COLUMN_FREQUENCY);
- sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE);
- }
-
- private static DatabaseHelper sOpenHelper = null;
-
- public AutoDictionary(Context context, LatinIME ime, String locale, int dicTypeId) {
- super(context, dicTypeId);
- mIme = ime;
- mLocale = locale;
- if (sOpenHelper == null) {
- sOpenHelper = new DatabaseHelper(getContext());
- }
- if (mLocale != null && mLocale.length() > 1) {
- loadDictionary();
- }
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- final int frequency = getWordFrequency(word);
- return frequency >= VALIDITY_THRESHOLD;
- }
-
- @Override
- public void close() {
- flushPendingWrites();
- // Don't close the database as locale changes will require it to be reopened anyway
- // Also, the database is written to somewhat frequently, so it needs to be kept alive
- // throughout the life of the process.
- // mOpenHelper.close();
- super.close();
- }
-
- @Override
- public void loadDictionaryAsync() {
- // Load the words that correspond to the current input locale
- Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale });
- try {
- if (cursor.moveToFirst()) {
- int wordIndex = cursor.getColumnIndex(COLUMN_WORD);
- int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY);
- while (!cursor.isAfterLast()) {
- String word = cursor.getString(wordIndex);
- int frequency = cursor.getInt(frequencyIndex);
- // Safeguard against adding really long words. Stack may overflow due
- // to recursive lookup
- if (word.length() < getMaxWordLength()) {
- super.addWord(word, frequency);
- }
- cursor.moveToNext();
- }
- }
- } finally {
- cursor.close();
- }
- }
-
- @Override
- public void addWord(String newWord, int addFrequency) {
- String word = newWord;
- final int length = word.length();
- // Don't add very short or very long words.
- if (length < 2 || length > getMaxWordLength()) return;
- if (mIme.getCurrentWord().isAutoCapitalized()) {
- // Remove caps before adding
- word = Character.toLowerCase(word.charAt(0)) + word.substring(1);
- }
- int freq = getWordFrequency(word);
- freq = freq < 0 ? addFrequency : freq + addFrequency;
- super.addWord(word, freq);
-
- synchronized (mPendingWritesLock) {
- // Write a null frequency if it is to be deleted from the db
- mPendingWrites.put(word, freq == 0 ? null : new Integer(freq));
- }
- }
-
- /**
- * Schedules a background thread to write any pending words to the database.
- */
- public void flushPendingWrites() {
- synchronized (mPendingWritesLock) {
- // Nothing pending? Return
- if (mPendingWrites.isEmpty()) return;
- // Create a background thread to write the pending entries
- new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute();
- // Create a new map for writing new entries into while the old one is written to db
- mPendingWrites = new HashMap<String, Integer>();
- }
- }
-
- /**
- * This class helps open, create, and upgrade the database file.
- */
- private static class DatabaseHelper extends SQLiteOpenHelper {
-
- DatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + AUTODICT_TABLE_NAME + " ("
- + COLUMN_ID + " INTEGER PRIMARY KEY,"
- + COLUMN_WORD + " TEXT,"
- + COLUMN_FREQUENCY + " INTEGER,"
- + COLUMN_LOCALE + " TEXT"
- + ");");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- Log.w("AutoDictionary", "Upgrading database from version " + oldVersion + " to "
- + newVersion + ", which will destroy all old data");
- db.execSQL("DROP TABLE IF EXISTS " + AUTODICT_TABLE_NAME);
- onCreate(db);
- }
- }
-
- private Cursor query(String selection, String[] selectionArgs) {
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
- qb.setTables(AUTODICT_TABLE_NAME);
- qb.setProjectionMap(sDictProjectionMap);
-
- // Get the database and run the query
- SQLiteDatabase db = sOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db, null, selection, selectionArgs, null, null,
- DEFAULT_SORT_ORDER);
- return c;
- }
-
- /**
- * Async task to write pending words to the database so that it stays in sync with
- * the in-memory trie.
- */
- private static class UpdateDbTask extends AsyncTask<Void, Void, Void> {
- private final HashMap<String, Integer> mMap;
- private final DatabaseHelper mDbHelper;
- private final String mLocale;
-
- public UpdateDbTask(@SuppressWarnings("unused") Context context, DatabaseHelper openHelper,
- HashMap<String, Integer> pendingWrites, String locale) {
- mMap = pendingWrites;
- mLocale = locale;
- mDbHelper = openHelper;
- }
-
- @Override
- protected Void doInBackground(Void... v) {
- SQLiteDatabase db = mDbHelper.getWritableDatabase();
- // Write all the entries to the db
- Set<Entry<String,Integer>> mEntries = mMap.entrySet();
- for (Entry<String,Integer> entry : mEntries) {
- Integer freq = entry.getValue();
- db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?",
- new String[] { entry.getKey(), mLocale });
- if (freq != null) {
- db.insert(AUTODICT_TABLE_NAME, null,
- getContentValues(entry.getKey(), freq, mLocale));
- }
- }
- return null;
- }
-
- private ContentValues getContentValues(String word, int frequency, String locale) {
- ContentValues values = new ContentValues(4);
- values.put(COLUMN_WORD, word);
- values.put(COLUMN_FREQUENCY, frequency);
- values.put(COLUMN_LOCALE, locale);
- return values;
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 9748d6006..d0613bd72 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -16,13 +16,13 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.ProximityInfo;
-
import android.content.Context;
+import android.text.TextUtils;
+
+import com.android.inputmethod.keyboard.ProximityInfo;
import java.util.Arrays;
+import java.util.Locale;
/**
* Implements a static, compacted, binary dictionary of standard words.
@@ -41,38 +41,20 @@ public class BinaryDictionary extends Dictionary {
public static final int MAX_WORD_LENGTH = 48;
public static final int MAX_WORDS = 18;
- @SuppressWarnings("unused")
private static final String TAG = "BinaryDictionary";
- private static final int MAX_PROXIMITY_CHARS_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE;
private static final int MAX_BIGRAMS = 60;
private static final int TYPED_LETTER_MULTIPLIER = 2;
private int mDicTypeId;
- private int mNativeDict;
- private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE];
+ private long mNativeDict;
+ private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
private final int[] mScores = new int[MAX_WORDS];
private final int[] mBigramScores = new int[MAX_BIGRAMS];
- private final KeyboardSwitcher mKeyboardSwitcher = KeyboardSwitcher.getInstance();
-
- public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING =
- new Flag(R.bool.config_require_umlaut_processing, 0x1);
-
- // Can create a new flag from extravalue :
- // public static final Flag FLAG_MYFLAG =
- // new Flag("my_flag", 0x02);
-
- private static final Flag[] ALL_FLAGS = {
- // Here should reside all flags that trigger some special processing
- // These *must* match the definition in UnigramDictionary enum in
- // unigram_dictionary.h so please update both at the same time.
- FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING,
- };
-
- private int mFlags = 0;
+ private final boolean mUseFullEditDistance;
/**
* Constructor for the binary dictionary. This is supposed to be called from the
@@ -82,40 +64,42 @@ public class BinaryDictionary extends Dictionary {
* @param filename the name of the file to read through native code.
* @param offset the offset of the dictionary data within the file.
* @param length the length of the binary data.
- * @param flagArray the flags to limit the dictionary to, or null for default.
+ * @param useFullEditDistance whether to use the full edit distance in suggestions
*/
public BinaryDictionary(final Context context,
- final String filename, final long offset, final long length, Flag[] flagArray) {
+ final String filename, final long offset, final long length,
+ final boolean useFullEditDistance, final Locale locale) {
// Note: at the moment a binary dictionary is always of the "main" type.
// Initializing this here will help transitioning out of the scheme where
// the Suggest class knows everything about every single dictionary.
mDicTypeId = Suggest.DIC_MAIN;
- // TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter
- mFlags = Flag.initFlags(null == flagArray ? ALL_FLAGS : flagArray, context,
- SubtypeSwitcher.getInstance());
+ mUseFullEditDistance = useFullEditDistance;
loadDictionary(filename, offset, length);
}
static {
- Utils.loadNativeLibrary();
+ JniUtils.loadNativeLibrary();
}
- private native int openNative(String sourceDir, long dictOffset, long dictSize,
- int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength,
- int maxWords, int maxAlternatives);
- private native void closeNative(int dict);
- private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
- private native int getSuggestionsNative(int dict, int proximityInfo, int[] xCoordinates,
- int[] yCoordinates, int[] inputCodes, int codesSize, int flags, char[] outputChars,
- int[] scores);
- private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength,
+ private native long openNative(String sourceDir, long dictOffset, long dictSize,
+ int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords);
+ private native void closeNative(long dict);
+ private native int getFrequencyNative(long dict, int[] word, int wordLength);
+ private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
+ private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
+ int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams,
+ boolean useFullEditDistance, char[] outputChars, int[] scores);
+ private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength,
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
- int maxWordLength, int maxBigrams, int maxAlternatives);
+ int maxWordLength, int maxBigrams);
+ private static native float calcNormalizedScoreNative(
+ char[] before, int beforeLength, char[] after, int afterLength, int score);
+ private static native int editDistanceNative(
+ char[] before, int beforeLength, char[] after, int afterLength);
private final void loadDictionary(String path, long startOffset, long length) {
mNativeDict = openNative(path, startOffset, length,
- TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER,
- MAX_WORD_LENGTH, MAX_WORDS, MAX_PROXIMITY_CHARS_SIZE);
+ TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS);
}
@Override
@@ -123,27 +107,24 @@ public class BinaryDictionary extends Dictionary {
final WordCallback callback) {
if (mNativeDict == 0) return;
- char[] chars = previousWord.toString().toCharArray();
+ int[] codePoints = StringUtils.toCodePointArray(previousWord.toString());
Arrays.fill(mOutputChars_bigrams, (char) 0);
Arrays.fill(mBigramScores, 0);
int codesSize = codes.size();
- if (codesSize <= 0) {
- // Do not return bigrams from BinaryDictionary when nothing was typed.
- // Only use user-history bigrams (or whatever other bigram dictionaries decide).
- return;
- }
Arrays.fill(mInputCodes, -1);
- int[] alternatives = codes.getCodesAt(0);
- System.arraycopy(alternatives, 0, mInputCodes, 0,
- Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE));
+ if (codesSize > 0) {
+ mInputCodes[0] = codes.getCodeAt(0);
+ }
- int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize,
- mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS,
- MAX_PROXIMITY_CHARS_SIZE);
+ int count = getBigramsNative(mNativeDict, codePoints, codePoints.length, mInputCodes,
+ codesSize, mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS);
+ if (count > MAX_BIGRAMS) {
+ count = MAX_BIGRAMS;
+ }
for (int j = 0; j < count; ++j) {
- if (mBigramScores[j] < 1) break;
+ if (codesSize > 0 && mBigramScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH;
int len = 0;
while (len < MAX_WORD_LENGTH && mOutputChars_bigrams[start + len] != 0) {
@@ -151,15 +132,17 @@ public class BinaryDictionary extends Dictionary {
}
if (len > 0) {
callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j],
- mDicTypeId, DataType.BIGRAM);
+ mDicTypeId, Dictionary.BIGRAM);
}
}
}
+ // proximityInfo and/or prevWordForBigrams may not be null.
@Override
- public void getWords(final WordComposer codes, final WordCallback callback) {
- final int count = getSuggestions(codes, mKeyboardSwitcher.getLatinKeyboard(),
- mOutputChars, mScores);
+ public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
+ final WordCallback callback, final ProximityInfo proximityInfo) {
+ final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
+ mScores);
for (int j = 0; j < count; ++j) {
if (mScores[j] < 1) break;
@@ -170,7 +153,7 @@ public class BinaryDictionary extends Dictionary {
}
if (len > 0) {
callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId,
- DataType.UNIGRAM);
+ Dictionary.UNIGRAM);
}
}
}
@@ -179,7 +162,9 @@ public class BinaryDictionary extends Dictionary {
return mNativeDict != 0;
}
- /* package for test */ int getSuggestions(final WordComposer codes, final Keyboard keyboard,
+ // proximityInfo may not be null.
+ /* package for test */ int getSuggestions(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo,
char[] outputChars, int[] scores) {
if (!isValidDictionary()) return -1;
@@ -189,25 +174,50 @@ public class BinaryDictionary extends Dictionary {
Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE);
for (int i = 0; i < codesSize; i++) {
- int[] alternatives = codes.getCodesAt(i);
- System.arraycopy(alternatives, 0, mInputCodes, i * MAX_PROXIMITY_CHARS_SIZE,
- Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE));
+ mInputCodes[i] = codes.getCodeAt(i);
}
Arrays.fill(outputChars, (char) 0);
Arrays.fill(scores, 0);
- final int proximityInfo = keyboard == null ? 0 : keyboard.getProximityInfo();
+ final int[] prevWordCodePointArray = null == prevWordForBigrams
+ ? null : StringUtils.toCodePointArray(prevWordForBigrams.toString());
+
+ // TODO: pass the previous word to native code
return getSuggestionsNative(
- mNativeDict, proximityInfo,
+ mNativeDict, proximityInfo.getNativeProximityInfo(),
codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize,
- mFlags, outputChars, scores);
+ prevWordCodePointArray, mUseFullEditDistance, outputChars, scores);
+ }
+
+ public static float calcNormalizedScore(String before, String after, int score) {
+ return calcNormalizedScoreNative(before.toCharArray(), before.length(),
+ after.toCharArray(), after.length(), score);
+ }
+
+ public static int editDistance(String before, String after) {
+ return editDistanceNative(
+ before.toCharArray(), before.length(), after.toCharArray(), after.length());
}
@Override
public boolean isValidWord(CharSequence word) {
- if (word == null) return false;
- char[] chars = word.toString().toCharArray();
- return isValidWordNative(mNativeDict, chars, chars.length);
+ return getFrequency(word) >= 0;
+ }
+
+ @Override
+ public int getFrequency(CharSequence word) {
+ if (word == null) return -1;
+ int[] chars = StringUtils.toCodePointArray(word.toString());
+ return getFrequencyNative(mNativeDict, chars, chars.length);
+ }
+
+ // TODO: Add a batch process version (isValidBigramMultiple?) to avoid excessive numbers of jni
+ // calls when checking for changes in an entire dictionary.
+ public boolean isValidBigram(CharSequence word1, CharSequence word2) {
+ if (TextUtils.isEmpty(word1) || TextUtils.isEmpty(word2)) return false;
+ int[] chars1 = StringUtils.toCodePointArray(word1.toString());
+ int[] chars2 = StringUtils.toCodePointArray(word2.toString());
+ return isValidBigramNative(mNativeDict, chars1, chars2);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 76a230f82..37eced5d6 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -19,16 +19,20 @@ package com.android.inputmethod.latin;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
+import android.util.Log;
+import java.io.BufferedInputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
@@ -37,115 +41,262 @@ import java.util.Locale;
* file from the dictionary provider
*/
public class BinaryDictionaryFileDumper {
+ private static final String TAG = BinaryDictionaryFileDumper.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
/**
* The size of the temporary buffer to copy files.
*/
- static final int FILE_READ_BUFFER_SIZE = 1024;
+ private static final int FILE_READ_BUFFER_SIZE = 1024;
+ // TODO: make the following data common with the native code
+ private static final byte[] MAGIC_NUMBER_VERSION_1 =
+ new byte[] { (byte)0x78, (byte)0xB1, (byte)0x00, (byte)0x00 };
+ private static final byte[] MAGIC_NUMBER_VERSION_2 =
+ new byte[] { (byte)0x9B, (byte)0xC1, (byte)0x3A, (byte)0xFE };
+
+ private static final String DICTIONARY_PROJECTION[] = { "id" };
+
+ public static final String QUERY_PARAMETER_MAY_PROMPT_USER = "mayPrompt";
+ public static final String QUERY_PARAMETER_TRUE = "true";
+ public static final String QUERY_PARAMETER_DELETE_RESULT = "result";
+ public static final String QUERY_PARAMETER_SUCCESS = "success";
+ public static final String QUERY_PARAMETER_FAILURE = "failure";
// Prevents this class to be accidentally instantiated.
private BinaryDictionaryFileDumper() {
}
/**
- * Generates a file name that matches the locale passed as an argument.
- * The file name is basically the result of the .toString() method, except we replace
- * any @File.separator with an underscore to avoid generating a file name that may not
- * be created.
- * @param locale the locale for which to get the file name
- * @param context the context to use for getting the directory
- * @return the name of the file to be created
+ * Returns a URI builder pointing to the dictionary pack.
+ *
+ * This creates a URI builder able to build a URI pointing to the dictionary
+ * pack content provider for a specific dictionary id.
*/
- private static String getCacheFileNameForLocale(Locale locale, Context context) {
- // The following assumes two things :
- // 1. That File.separator is not the same character as "_"
- // I don't think any android system will ever use "_" as a path separator
- // 2. That no two locales differ by only a File.separator versus a "_"
- // Since "_" can't be part of locale components this should be safe.
- // Examples:
- // en -> en
- // en_US_POSIX -> en_US_POSIX
- // en__foo/bar -> en__foo_bar
- final String[] separator = { File.separator };
- final String[] empty = { "_" };
- final CharSequence basename = TextUtils.replace(locale.toString(), separator, empty);
- return context.getFilesDir() + File.separator + basename;
+ private static Uri.Builder getProviderUriBuilder(final String path) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
+ path);
}
/**
- * Return for a given locale the provider URI to query to get the dictionary.
+ * Queries a content provider for the list of word lists for a specific locale
+ * available to copy into Latin IME.
*/
- public static Uri getProviderUri(Locale locale) {
- return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
- .authority(BinaryDictionary.DICTIONARY_PACK_AUTHORITY).appendPath(
- locale.toString()).build();
+ private static List<WordListInfo> getWordListWordListInfos(final Locale locale,
+ final Context context, final boolean hasDefaultWordList) {
+ final ContentResolver resolver = context.getContentResolver();
+ final Uri.Builder builder = getProviderUriBuilder(locale.toString());
+ if (!hasDefaultWordList) {
+ builder.appendQueryParameter(QUERY_PARAMETER_MAY_PROMPT_USER, QUERY_PARAMETER_TRUE);
+ }
+ final Uri dictionaryPackUri = builder.build();
+
+ final Cursor c = resolver.query(dictionaryPackUri, DICTIONARY_PROJECTION, null, null, null);
+ if (null == c) return Collections.<WordListInfo>emptyList();
+ if (c.getCount() <= 0 || !c.moveToFirst()) {
+ c.close();
+ return Collections.<WordListInfo>emptyList();
+ }
+
+ try {
+ final List<WordListInfo> list = new ArrayList<WordListInfo>();
+ do {
+ final String wordListId = c.getString(0);
+ final String wordListLocale = c.getString(1);
+ if (TextUtils.isEmpty(wordListId)) continue;
+ list.add(new WordListInfo(wordListId, wordListLocale));
+ } while (c.moveToNext());
+ c.close();
+ return list;
+ } catch (Exception e) {
+ // Just in case we hit a problem in communication with the dictionary pack.
+ // We don't want to die.
+ Log.e(TAG, "Exception communicating with the dictionary pack : " + e);
+ return Collections.<WordListInfo>emptyList();
+ }
}
+
/**
- * Queries a content provider for dictionary data for some locale and returns the file addresses
- *
- * This will query a content provider for dictionary data for a given locale, and return
- * the addresses of a file set the members of which are suitable to be mmap'ed. It will copy
- * them to local storage if needed.
- * It should also check the dictionary versions to avoid unnecessary copies but this is
- * still in TODO state.
- * This will make the data from the content provider the cached dictionary for this locale,
- * overwriting any previous cached data.
- * @returns the addresses of the files, or null if no data could be obtained.
- * @throw FileNotFoundException if the provider returns non-existent data.
- * @throw IOException if the provider-returned data could not be read.
+ * Helper method to encapsulate exception handling.
*/
- public static List<AssetFileAddress> getDictSetFromContentProvider(Locale locale,
- Context context) throws FileNotFoundException, IOException {
- // TODO: check whether the dictionary is the same or not and if it is, return the cached
- // file.
- // TODO: This should be able to read a number of files from the dictionary pack, copy
- // them all and return them.
- final ContentResolver resolver = context.getContentResolver();
- final Uri dictionaryPackUri = getProviderUri(locale);
- final AssetFileDescriptor afd = resolver.openAssetFileDescriptor(dictionaryPackUri, "r");
- if (null == afd) return null;
- final String fileName =
- copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context));
- return Arrays.asList(AssetFileAddress.makeFromFileName(fileName));
+ private static AssetFileDescriptor openAssetFileDescriptor(final ContentResolver resolver,
+ final Uri uri) {
+ try {
+ return resolver.openAssetFileDescriptor(uri, "r");
+ } catch (FileNotFoundException e) {
+ // I don't want to log the word list URI here for security concerns
+ Log.e(TAG, "Could not find a word list from the dictionary provider.");
+ return null;
+ }
}
/**
- * Accepts a file as dictionary data for some locale and returns the name of a file.
- *
- * This will make the data in the input file the cached dictionary for this locale, overwriting
- * any previous cached data.
+ * Caches a word list the id of which is passed as an argument. This will write the file
+ * to the cache file name designated by its id and locale, overwriting it if already present
+ * and creating it (and its containing directory) if necessary.
*/
- public static String getDictionaryFileFromFile(String fileName, Locale locale,
- Context context) throws FileNotFoundException, IOException {
- return copyFileTo(new FileInputStream(fileName), getCacheFileNameForLocale(locale,
- context));
+ private static AssetFileAddress cacheWordList(final String id, final String locale,
+ final ContentResolver resolver, final Context context) {
+
+ final int COMPRESSED_CRYPTED_COMPRESSED = 0;
+ final int CRYPTED_COMPRESSED = 1;
+ final int COMPRESSED_CRYPTED = 2;
+ final int COMPRESSED_ONLY = 3;
+ final int CRYPTED_ONLY = 4;
+ final int NONE = 5;
+ final int MODE_MIN = COMPRESSED_CRYPTED_COMPRESSED;
+ final int MODE_MAX = NONE;
+
+ final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id);
+ final String outputFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context);
+
+ for (int mode = MODE_MIN; mode <= MODE_MAX; ++mode) {
+ InputStream originalSourceStream = null;
+ InputStream inputStream = null;
+ File outputFile = null;
+ FileOutputStream outputStream = null;
+ AssetFileDescriptor afd = null;
+ final Uri wordListUri = wordListUriBuilder.build();
+ try {
+ // Open input.
+ afd = openAssetFileDescriptor(resolver, wordListUri);
+ // If we can't open it at all, don't even try a number of times.
+ if (null == afd) return null;
+ originalSourceStream = afd.createInputStream();
+ // Open output.
+ outputFile = new File(outputFileName);
+ outputStream = new FileOutputStream(outputFile);
+ // Get the appropriate decryption method for this try
+ switch (mode) {
+ case COMPRESSED_CRYPTED_COMPRESSED:
+ inputStream = FileTransforms.getUncompressedStream(
+ FileTransforms.getDecryptedStream(
+ FileTransforms.getUncompressedStream(
+ originalSourceStream)));
+ break;
+ case CRYPTED_COMPRESSED:
+ inputStream = FileTransforms.getUncompressedStream(
+ FileTransforms.getDecryptedStream(originalSourceStream));
+ break;
+ case COMPRESSED_CRYPTED:
+ inputStream = FileTransforms.getDecryptedStream(
+ FileTransforms.getUncompressedStream(originalSourceStream));
+ break;
+ case COMPRESSED_ONLY:
+ inputStream = FileTransforms.getUncompressedStream(originalSourceStream);
+ break;
+ case CRYPTED_ONLY:
+ inputStream = FileTransforms.getDecryptedStream(originalSourceStream);
+ break;
+ case NONE:
+ inputStream = originalSourceStream;
+ break;
+ }
+ checkMagicAndCopyFileTo(new BufferedInputStream(inputStream), outputStream);
+ wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
+ QUERY_PARAMETER_SUCCESS);
+ if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) {
+ Log.e(TAG, "Could not have the dictionary pack delete a word list");
+ }
+ BinaryDictionaryGetter.removeFilesWithIdExcept(context, id, outputFile);
+ // Success! Close files (through the finally{} clause) and return.
+ return AssetFileAddress.makeFromFileName(outputFileName);
+ } catch (Exception e) {
+ if (DEBUG) {
+ Log.i(TAG, "Can't open word list in mode " + mode + " : " + e);
+ }
+ if (null != outputFile) {
+ // This may or may not fail. The file may not have been created if the
+ // exception was thrown before it could be. Hence, both failure and
+ // success are expected outcomes, so we don't check the return value.
+ outputFile.delete();
+ }
+ // Try the next method.
+ } finally {
+ // Ignore exceptions while closing files.
+ try {
+ // inputStream.close() will close afd, we should not call afd.close().
+ if (null != inputStream) inputStream.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while closing a cross-process file descriptor : " + e);
+ }
+ try {
+ if (null != outputStream) outputStream.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while closing a file : " + e);
+ }
+ }
+ }
+
+ // We could not copy the file at all. This is very unexpected.
+ // I'd rather not print the word list ID to the log out of security concerns
+ Log.e(TAG, "Could not copy a word list. Will not be able to use it.");
+ // If we can't copy it we should warn the dictionary provider so that it can mark it
+ // as invalid.
+ wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
+ QUERY_PARAMETER_FAILURE);
+ if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) {
+ Log.e(TAG, "In addition, we were unable to delete it.");
+ }
+ return null;
}
/**
- * Accepts a resource number as dictionary data for some locale and returns the name of a file.
+ * Queries a content provider for word list data for some locale and cache the returned files
*
- * This will make the resource the cached dictionary for this locale, overwriting any previous
- * cached data.
+ * This will query a content provider for word list data for a given locale, and copy the
+ * files locally so that they can be mmap'ed. This may overwrite previously cached word lists
+ * with newer versions if a newer version is made available by the content provider.
+ * @returns the addresses of the word list files, or null if no data could be obtained.
+ * @throw FileNotFoundException if the provider returns non-existent data.
+ * @throw IOException if the provider-returned data could not be read.
*/
- public static String getDictionaryFileFromResource(int resource, Locale locale,
- Context context) throws FileNotFoundException, IOException {
- return copyFileTo(context.getResources().openRawResource(resource),
- getCacheFileNameForLocale(locale, context));
+ public static List<AssetFileAddress> cacheWordListsFromContentProvider(final Locale locale,
+ final Context context, final boolean hasDefaultWordList) {
+ final ContentResolver resolver = context.getContentResolver();
+ final List<WordListInfo> idList = getWordListWordListInfos(locale, context,
+ hasDefaultWordList);
+ final List<AssetFileAddress> fileAddressList = new ArrayList<AssetFileAddress>();
+ for (WordListInfo id : idList) {
+ final AssetFileAddress afd = cacheWordList(id.mId, id.mLocale, resolver, context);
+ if (null != afd) {
+ fileAddressList.add(afd);
+ }
+ }
+ return fileAddressList;
}
/**
- * Copies the data in an input stream to a target file, creating the file if necessary and
- * overwriting it if it already exists.
+ * Copies the data in an input stream to a target file if the magic number matches.
+ *
+ * If the magic number does not match the expected value, this method throws an
+ * IOException. Other usual conditions for IOException or FileNotFoundException
+ * also apply.
+ *
* @param input the stream to be copied.
- * @param outputFileName the name of a file to copy the data to. It is created if necessary.
+ * @param output an output stream to copy the data to.
*/
- private static String copyFileTo(final InputStream input, final String outputFileName)
- throws FileNotFoundException, IOException {
+ private static void checkMagicAndCopyFileTo(final BufferedInputStream input,
+ final FileOutputStream output) throws FileNotFoundException, IOException {
+ // Check the magic number
+ final int length = MAGIC_NUMBER_VERSION_2.length;
+ final byte[] magicNumberBuffer = new byte[length];
+ final int readMagicNumberSize = input.read(magicNumberBuffer, 0, length);
+ if (readMagicNumberSize < length) {
+ throw new IOException("Less bytes to read than the magic number length");
+ }
+ if (!Arrays.equals(MAGIC_NUMBER_VERSION_2, magicNumberBuffer)) {
+ if (!Arrays.equals(MAGIC_NUMBER_VERSION_1, magicNumberBuffer)) {
+ throw new IOException("Wrong magic number for downloaded file");
+ }
+ }
+ output.write(magicNumberBuffer);
+
+ // Actually copy the file
final byte[] buffer = new byte[FILE_READ_BUFFER_SIZE];
- final FileOutputStream output = new FileOutputStream(outputFileName);
for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer))
output.write(buffer, 0, readBytes);
input.close();
- return outputFileName;
}
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 7ce92920d..063243e1b 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -17,13 +17,14 @@
package com.android.inputmethod.latin;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.util.Log;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Locale;
/**
@@ -36,13 +37,127 @@ class BinaryDictionaryGetter {
*/
private static final String TAG = BinaryDictionaryGetter.class.getSimpleName();
+ /**
+ * Used to return empty lists
+ */
+ private static final File[] EMPTY_FILE_ARRAY = new File[0];
+
+ /**
+ * Name of the common preferences name to know which word list are on and which are off.
+ */
+ private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs";
+
+ // Name of the category for the main dictionary
+ private static final String MAIN_DICTIONARY_CATEGORY = "main";
+ public static final String ID_CATEGORY_SEPARATOR = ":";
+
// Prevents this from being instantiated
private BinaryDictionaryGetter() {}
/**
+ * Returns whether we may want to use this character as part of a file name.
+ *
+ * This basically only accepts ascii letters and numbers, and rejects everything else.
+ */
+ private static boolean isFileNameCharacter(int codePoint) {
+ if (codePoint >= 0x30 && codePoint <= 0x39) return true; // Digit
+ if (codePoint >= 0x41 && codePoint <= 0x5A) return true; // Uppercase
+ if (codePoint >= 0x61 && codePoint <= 0x7A) return true; // Lowercase
+ return codePoint == '_'; // Underscore
+ }
+
+ /**
+ * Escapes a string for any characters that may be suspicious for a file or directory name.
+ *
+ * Concretely this does a sort of URL-encoding except it will encode everything that's not
+ * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which
+ * we cannot allow here)
+ */
+ // TODO: create a unit test for this method
+ private static String replaceFileNameDangerousCharacters(final String name) {
+ // This assumes '%' is fully available as a non-separator, normal
+ // character in a file name. This is probably true for all file systems.
+ final StringBuilder sb = new StringBuilder();
+ final int nameLength = name.length();
+ for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
+ final int codePoint = name.codePointAt(i);
+ if (isFileNameCharacter(codePoint)) {
+ sb.appendCodePoint(codePoint);
+ } else {
+ // 6 digits - unicode is limited to 21 bits
+ sb.append(String.format((Locale)null, "%%%1$06x", codePoint));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Reverse escaping done by replaceFileNameDangerousCharacters.
+ */
+ private static String getWordListIdFromFileName(final String fname) {
+ final StringBuilder sb = new StringBuilder();
+ final int fnameLength = fname.length();
+ for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
+ final int codePoint = fname.codePointAt(i);
+ if ('%' != codePoint) {
+ sb.appendCodePoint(codePoint);
+ } else {
+ final int encodedCodePoint = Integer.parseInt(fname.substring(i + 1, i + 7), 16);
+ i += 6;
+ sb.appendCodePoint(encodedCodePoint);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Helper method to get the top level cache directory.
+ */
+ private static String getWordListCacheDirectory(final Context context) {
+ return context.getFilesDir() + File.separator + "dicts";
+ }
+
+ /**
+ * Find out the cache directory associated with a specific locale.
+ */
+ private static String getCacheDirectoryForLocale(final String locale, final Context context) {
+ final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale);
+ final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator
+ + relativeDirectoryName;
+ final File directory = new File(absoluteDirectoryName);
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ Log.e(TAG, "Could not create the directory for locale" + locale);
+ }
+ }
+ return absoluteDirectoryName;
+ }
+
+ /**
+ * Generates a file name for the id and locale passed as an argument.
+ *
+ * In the current implementation the file name returned will always be unique for
+ * any id/locale pair, but please do not expect that the id can be the same for
+ * different dictionaries with different locales. An id should be unique for any
+ * dictionary.
+ * The file name is pretty much an URL-encoded version of the id inside a directory
+ * named like the locale, except it will also escape characters that look dangerous
+ * to some file systems.
+ * @param id the id of the dictionary for which to get a file name
+ * @param locale the locale for which to get the file name as a string
+ * @param context the context to use for getting the directory
+ * @return the name of the file to be created
+ */
+ public static String getCacheFileName(String id, String locale, Context context) {
+ final String fileName = replaceFileNameDangerousCharacters(id);
+ return getCacheDirectoryForLocale(locale, context) + File.separator + fileName;
+ }
+
+ /**
* Returns a file address from a resource, or null if it cannot be opened.
*/
- private static AssetFileAddress loadFallbackResource(Context context, int fallbackResId) {
+ private static AssetFileAddress loadFallbackResource(final Context context,
+ final int fallbackResId) {
final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId);
if (afd == null) {
Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId="
@@ -53,45 +168,224 @@ class BinaryDictionaryGetter {
context.getApplicationInfo().sourceDir, afd.getStartOffset(), afd.getLength());
}
+ static private class DictPackSettings {
+ final SharedPreferences mDictPreferences;
+ public DictPackSettings(final Context context) {
+ Context dictPackContext = null;
+ try {
+ final String dictPackName =
+ context.getString(R.string.dictionary_pack_package_name);
+ dictPackContext = context.createPackageContext(dictPackName, 0);
+ } catch (NameNotFoundException e) {
+ // The dictionary pack is not installed...
+ // TODO: fallback on the built-in dict, see the TODO above
+ Log.e(TAG, "Could not find a dictionary pack");
+ }
+ mDictPreferences = null == dictPackContext ? null
+ : dictPackContext.getSharedPreferences(COMMON_PREFERENCES_NAME,
+ Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
+ }
+ public boolean isWordListActive(final String dictId) {
+ if (null == mDictPreferences) {
+ // If we don't have preferences it basically means we can't find the dictionary
+ // pack - either it's not installed, or it's disabled, or there is some strange
+ // bug. Either way, a word list with no settings should be on by default: default
+ // dictionaries in LatinIME are on if there is no settings at all, and if for some
+ // reason some dictionaries have been installed BUT the dictionary pack can't be
+ // found anymore it's safer to actually supply installed dictionaries.
+ return true;
+ } else {
+ // The default is true here for the same reasons as above. We got the dictionary
+ // pack but if we don't have any settings for it it means the user has never been
+ // to the settings yet. So by default, the main dictionaries should be on.
+ return mDictPreferences.getBoolean(dictId, true);
+ }
+ }
+ }
+
+ /**
+ * Helper method to the list of cache directories, one for each distinct locale.
+ */
+ private static File[] getCachedDirectoryList(final Context context) {
+ return new File(getWordListCacheDirectory(context)).listFiles();
+ }
+
+ /**
+ * Returns the category for a given file name.
+ *
+ * This parses the file name, extracts the category, and returns it. See
+ * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
+ * @return The category as a string or null if it can't be found in the file name.
+ */
+ private static String getCategoryFromFileName(final String fileName) {
+ final String id = getWordListIdFromFileName(fileName);
+ final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
+ if (2 != idArray.length) return null;
+ return idArray[0];
+ }
+
+ /**
+ * Utility class for the {@link #getCachedWordLists} method
+ */
+ private static class FileAndMatchLevel {
+ final File mFile;
+ final int mMatchLevel;
+ public FileAndMatchLevel(final File file, final int matchLevel) {
+ mFile = file;
+ mMatchLevel = matchLevel;
+ }
+ }
+
+ /**
+ * Returns the list of cached files for a specific locale, one for each category.
+ *
+ * This will return exactly one file for each word list category that matches
+ * the passed locale. If several files match the locale for any given category,
+ * this returns the file with the closest match to the locale. For example, if
+ * the passed word list is en_US, and for a category we have an en and an en_US
+ * word list available, we'll return only the en_US one.
+ * Thus, the list will contain as many files as there are categories.
+ *
+ * @param locale the locale to find the dictionary files for, as a string.
+ * @param context the context on which to open the files upon.
+ * @return an array of binary dictionary files, which may be empty but may not be null.
+ */
+ private static File[] getCachedWordLists(final String locale,
+ final Context context) {
+ final File[] directoryList = getCachedDirectoryList(context);
+ if (null == directoryList) return EMPTY_FILE_ARRAY;
+ final HashMap<String, FileAndMatchLevel> cacheFiles =
+ new HashMap<String, FileAndMatchLevel>();
+ for (File directory : directoryList) {
+ if (!directory.isDirectory()) continue;
+ final String dirLocale = getWordListIdFromFileName(directory.getName());
+ final int matchLevel = LocaleUtils.getMatchLevel(dirLocale, locale);
+ if (LocaleUtils.isMatch(matchLevel)) {
+ final File[] wordLists = directory.listFiles();
+ if (null != wordLists) {
+ for (File wordList : wordLists) {
+ final String category = getCategoryFromFileName(wordList.getName());
+ final FileAndMatchLevel currentBestMatch = cacheFiles.get(category);
+ if (null == currentBestMatch || currentBestMatch.mMatchLevel < matchLevel) {
+ cacheFiles.put(category, new FileAndMatchLevel(wordList, matchLevel));
+ }
+ }
+ }
+ }
+ }
+ if (cacheFiles.isEmpty()) return EMPTY_FILE_ARRAY;
+ final File[] result = new File[cacheFiles.size()];
+ int index = 0;
+ for (final FileAndMatchLevel entry : cacheFiles.values()) {
+ result[index++] = entry.mFile;
+ }
+ return result;
+ }
+
+ /**
+ * Remove all files with the passed id, except the passed file.
+ *
+ * If a dictionary with a given ID has a metadata change that causes it to change
+ * path, we need to remove the old version. The only way to do this is to check all
+ * installed files for a matching ID in a different directory.
+ */
+ public static void removeFilesWithIdExcept(final Context context, final String id,
+ final File fileToKeep) {
+ try {
+ final File canonicalFileToKeep = fileToKeep.getCanonicalFile();
+ final File[] directoryList = getCachedDirectoryList(context);
+ if (null == directoryList) return;
+ for (File directory : directoryList) {
+ // There is one directory per locale. See #getCachedDirectoryList
+ if (!directory.isDirectory()) continue;
+ final File[] wordLists = directory.listFiles();
+ if (null == wordLists) continue;
+ for (File wordList : wordLists) {
+ final String fileId = getWordListIdFromFileName(wordList.getName());
+ if (fileId.equals(id)) {
+ if (!canonicalFileToKeep.equals(wordList.getCanonicalFile())) {
+ wordList.delete();
+ }
+ }
+ }
+ }
+ } catch (java.io.IOException e) {
+ Log.e(TAG, "IOException trying to cleanup files : " + e);
+ }
+ }
+
+
+ /**
+ * Returns the id associated with the main word list for a specified locale.
+ *
+ * Word lists stored in Android Keyboard's resources are referred to as the "main"
+ * word lists. Since they can be updated like any other list, we need to assign a
+ * unique ID to them. This ID is just the name of the language (locale-wise) they
+ * are for, and this method returns this ID.
+ */
+ private static String getMainDictId(final Locale locale) {
+ // This works because we don't include by default different dictionaries for
+ // different countries. This actually needs to return the id that we would
+ // like to use for word lists included in resources, and the following is okay.
+ return MAIN_DICTIONARY_CATEGORY + ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
+ }
+
+ private static boolean isMainWordListId(final String id) {
+ final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
+ if (2 != idArray.length) return false;
+ return MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
+ }
+
/**
* Returns a list of file addresses for a given locale, trying relevant methods in order.
*
* Tries to get binary dictionaries from various sources, in order:
- * - Uses a private method of getting a private dictionaries, as implemented by the
- * PrivateBinaryDictionaryGetter class.
- * If that fails:
* - Uses a content provider to get a public dictionary set, as per the protocol described
* in BinaryDictionaryFileDumper.
* If that fails:
- * - Gets a file name from the fallback resource passed as an argument.
+ * - Gets a file name from the built-in dictionary for this locale, if any.
* If that fails:
* - Returns null.
- * @return The address of a valid file, or null.
- */
- public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context,
- int fallbackResId) {
- // Try first to query a private package signed the same way for private files.
- final List<AssetFileAddress> privateFiles =
- PrivateBinaryDictionaryGetter.getDictionaryFiles(locale, context);
- if (null != privateFiles) {
- return privateFiles;
- } else {
- try {
- // If that was no-go, try to find a publicly exported dictionary.
- List<AssetFileAddress> listFromContentProvider =
- BinaryDictionaryFileDumper.getDictSetFromContentProvider(locale, context);
- if (null != listFromContentProvider) {
- return listFromContentProvider;
- }
- // If the list is null, fall through and return the fallback
- } catch (FileNotFoundException e) {
- Log.e(TAG, "Unable to create dictionary file from provider for locale "
- + locale.toString() + ": falling back to internal dictionary");
- } catch (IOException e) {
- Log.e(TAG, "Unable to read source data for locale "
- + locale.toString() + ": falling back to internal dictionary");
+ * @return The list of addresses of valid dictionary files, or null.
+ */
+ public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale,
+ final Context context) {
+
+ final boolean hasDefaultWordList = DictionaryFactory.isDictionaryAvailable(context, locale);
+ // cacheWordListsFromContentProvider returns the list of files it copied to local
+ // storage, but we don't really care about what was copied NOW: what we want is the
+ // list of everything we ever cached, so we ignore the return value.
+ BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context,
+ hasDefaultWordList);
+ final File[] cachedWordLists = getCachedWordLists(locale.toString(), context);
+ final String mainDictId = getMainDictId(locale);
+ final DictPackSettings dictPackSettings = new DictPackSettings(context);
+
+ boolean foundMainDict = false;
+ final ArrayList<AssetFileAddress> fileList = new ArrayList<AssetFileAddress>();
+ // cachedWordLists may not be null, see doc for getCachedDictionaryList
+ for (final File f : cachedWordLists) {
+ final String wordListId = getWordListIdFromFileName(f.getName());
+ if (isMainWordListId(wordListId)) {
+ foundMainDict = true;
+ }
+ if (!dictPackSettings.isWordListActive(wordListId)) continue;
+ if (f.canRead()) {
+ fileList.add(AssetFileAddress.makeFromFileName(f.getPath()));
+ } else {
+ Log.e(TAG, "Found a cached dictionary file but cannot read it");
+ }
+ }
+
+ if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) {
+ final int fallbackResId =
+ DictionaryFactory.getMainDictionaryResourceId(context.getResources(), locale);
+ final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId);
+ if (null != fallbackAsset) {
+ fileList.add(fallbackAsset);
}
- return Arrays.asList(loadFallbackResource(context, fallbackResId));
}
+
+ return fileList;
}
}
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
deleted file mode 100644
index a5bfea0f8..000000000
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.Typeface;
-import android.os.Message;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.UnderlineSpan;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-
-import com.android.inputmethod.compat.FrameLayoutCompatUtils;
-import com.android.inputmethod.compat.LinearLayoutCompatUtils;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
-
- public interface Listener {
- public boolean addWordToDictionary(String word);
- public void pickSuggestionManually(int index, CharSequence word);
- }
-
- private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
- // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
- private static final int MAX_SUGGESTIONS = 18;
- private static final int MATCH_PARENT = MeasureSpec.makeMeasureSpec(
- -1, MeasureSpec.UNSPECIFIED);
-
- private static final boolean DBG = LatinImeLogger.sDBG;
-
- private final View mCandidatesStrip;
- private static final int NUM_CANDIDATES_IN_STRIP = 3;
- private final ImageView mExpandCandidatesPane;
- private final ImageView mCloseCandidatesPane;
- private ViewGroup mCandidatesPane;
- private ViewGroup mCandidatesPaneContainer;
- private View mKeyboardView;
- private final ArrayList<TextView> mWords = new ArrayList<TextView>();
- private final ArrayList<TextView> mInfos = new ArrayList<TextView>();
- private final ArrayList<View> mDividers = new ArrayList<View>();
- private final int mCandidateStripHeight;
- private final CharacterStyle mInvertedForegroundColorSpan;
- private final CharacterStyle mInvertedBackgroundColorSpan;
- private final int mAutoCorrectHighlight;
- private static final int AUTO_CORRECT_BOLD = 0x01;
- private static final int AUTO_CORRECT_UNDERLINE = 0x02;
- private static final int AUTO_CORRECT_INVERT = 0x04;
- private final int mColorTypedWord;
- private final int mColorAutoCorrect;
- private final int mColorSuggestedCandidate;
- private final PopupWindow mPreviewPopup;
- private final TextView mPreviewText;
-
- private final View mTouchToSave;
- private final TextView mWordToSave;
-
- private Listener mListener;
- private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
- private boolean mShowingAutoCorrectionInverted;
- private boolean mShowingAddToDictionary;
-
- private static final float MIN_TEXT_XSCALE = 0.4f;
- private static final String ELLIPSIS = "\u2026";
-
- private final UiHandler mHandler = new UiHandler(this);
-
- private static class UiHandler extends StaticInnerHandlerWrapper<CandidateView> {
- private static final int MSG_HIDE_PREVIEW = 0;
- private static final int MSG_UPDATE_SUGGESTION = 1;
-
- private static final long DELAY_HIDE_PREVIEW = 1000;
- private static final long DELAY_UPDATE_SUGGESTION = 300;
-
- public UiHandler(CandidateView outerInstance) {
- super(outerInstance);
- }
-
- @Override
- public void dispatchMessage(Message msg) {
- final CandidateView candidateView = getOuterInstance();
- switch (msg.what) {
- case MSG_HIDE_PREVIEW:
- candidateView.hidePreview();
- break;
- case MSG_UPDATE_SUGGESTION:
- candidateView.updateSuggestions();
- break;
- }
- }
-
- public void postHidePreview() {
- cancelHidePreview();
- sendMessageDelayed(obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW);
- }
-
- public void cancelHidePreview() {
- removeMessages(MSG_HIDE_PREVIEW);
- }
-
- public void postUpdateSuggestions() {
- cancelUpdateSuggestions();
- sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION),
- DELAY_UPDATE_SUGGESTION);
- }
-
- public void cancelUpdateSuggestions() {
- removeMessages(MSG_UPDATE_SUGGESTION);
- }
-
- public void cancelAllMessages() {
- cancelHidePreview();
- cancelUpdateSuggestions();
- }
- }
-
- /**
- * Construct a CandidateView for showing suggested words for completion.
- * @param context
- * @param attrs
- */
- public CandidateView(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.candidateViewStyle);
- }
-
- public CandidateView(Context context, AttributeSet attrs, int defStyle) {
- // Note: Up to version 10 (Gingerbread) of the API, LinearLayout doesn't have 3-argument
- // constructor.
- // TODO: Call 3-argument constructor, super(context, attrs, defStyle), when we abandon
- // backward compatibility with the version 10 or earlier of the API.
- super(context, attrs);
- if (defStyle != R.attr.candidateViewStyle) {
- throw new IllegalArgumentException(
- "can't accept defStyle other than R.attr.candidayeViewStyle: defStyle="
- + defStyle);
- }
- setBackgroundDrawable(LinearLayoutCompatUtils.getBackgroundDrawable(
- context, attrs, defStyle, R.style.CandidateViewStyle));
-
- Resources res = context.getResources();
- LayoutInflater inflater = LayoutInflater.from(context);
- inflater.inflate(R.layout.candidates_strip, this);
-
- mPreviewPopup = new PopupWindow(context);
- mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null);
- mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- mPreviewPopup.setContentView(mPreviewText);
- mPreviewPopup.setBackgroundDrawable(null);
-
- mCandidatesStrip = findViewById(R.id.candidates_strip);
- mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height);
- for (int i = 0; i < MAX_SUGGESTIONS; i++) {
- final TextView word, info;
- switch (i) {
- case 0:
- word = (TextView)findViewById(R.id.word_left);
- info = (TextView)findViewById(R.id.info_left);
- break;
- case 1:
- word = (TextView)findViewById(R.id.word_center);
- info = (TextView)findViewById(R.id.info_center);
- break;
- case 2:
- word = (TextView)findViewById(R.id.word_right);
- info = (TextView)findViewById(R.id.info_right);
- break;
- default:
- word = (TextView)inflater.inflate(R.layout.candidate_word, null);
- info = (TextView)inflater.inflate(R.layout.candidate_info, null);
- break;
- }
- word.setTag(i);
- word.setOnClickListener(this);
- if (i == 0)
- word.setOnLongClickListener(this);
- mWords.add(word);
- mInfos.add(info);
- if (i > 0) {
- final View divider = inflater.inflate(R.layout.candidate_divider, null);
- divider.measure(MATCH_PARENT, MATCH_PARENT);
- mDividers.add(divider);
- }
- }
-
- mTouchToSave = findViewById(R.id.touch_to_save);
- mWordToSave = (TextView)findViewById(R.id.word_to_save);
- mWordToSave.setOnClickListener(this);
-
- final TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle);
- mAutoCorrectHighlight = a.getInt(R.styleable.CandidateView_autoCorrectHighlight, 0);
- mColorTypedWord = a.getColor(R.styleable.CandidateView_colorTypedWord, 0);
- mColorAutoCorrect = a.getColor(R.styleable.CandidateView_colorAutoCorrect, 0);
- mColorSuggestedCandidate = a.getColor(R.styleable.CandidateView_colorSuggested, 0);
- mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorTypedWord ^ 0x00ffffff);
- mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord);
-
- mExpandCandidatesPane = (ImageView)findViewById(R.id.expand_candidates_pane);
- mExpandCandidatesPane.setImageDrawable(
- a.getDrawable(R.styleable.CandidateView_iconExpandPane));
- mExpandCandidatesPane.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- expandCandidatesPane();
- }
- });
- mCloseCandidatesPane = (ImageView)findViewById(R.id.close_candidates_pane);
- mCloseCandidatesPane.setImageDrawable(
- a.getDrawable(R.styleable.CandidateView_iconClosePane));
- mCloseCandidatesPane.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- closeCandidatesPane();
- }
- });
-
- a.recycle();
- }
-
- /**
- * A connection back to the input method.
- * @param listener
- */
- public void setListener(Listener listener, View inputView) {
- mListener = listener;
- mKeyboardView = inputView.findViewById(R.id.keyboard_view);
- mCandidatesPane = FrameLayoutCompatUtils.getPlacer(
- (ViewGroup)inputView.findViewById(R.id.candidates_pane));
- mCandidatesPane.setOnClickListener(this);
- mCandidatesPaneContainer = (ViewGroup)inputView.findViewById(
- R.id.candidates_pane_container);
- }
-
- public void setSuggestions(SuggestedWords suggestions) {
- if (suggestions == null)
- return;
- mSuggestions = suggestions;
- if (mShowingAutoCorrectionInverted) {
- mHandler.postUpdateSuggestions();
- } else {
- updateSuggestions();
- }
- }
-
- private CharSequence getStyledCandidateWord(CharSequence word, TextView v,
- boolean isAutoCorrect) {
- v.setTypeface(Typeface.DEFAULT);
- if (!isAutoCorrect)
- return word;
- final Spannable spannedWord = new SpannableString(word);
- if ((mAutoCorrectHighlight & AUTO_CORRECT_BOLD) != 0)
- v.setTypeface(Typeface.DEFAULT_BOLD);
- if ((mAutoCorrectHighlight & AUTO_CORRECT_UNDERLINE) != 0)
- spannedWord.setSpan(UNDERLINE_SPAN, 0, word.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- return spannedWord;
- }
-
- private int getCandidateTextColor(boolean isAutoCorrect, boolean isSuggestedCandidate,
- SuggestedWordInfo info) {
- final int color;
- if (isAutoCorrect) {
- color = mColorAutoCorrect;
- } else if (isSuggestedCandidate) {
- color = mColorSuggestedCandidate;
- } else {
- color = mColorTypedWord;
- }
- if (info != null && info.isPreviousSuggestedWord()) {
- final int newAlpha = (int)(Color.alpha(color) * 0.5f);
- return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
- } else {
- return color;
- }
- }
-
- private void updateSuggestions() {
- final SuggestedWords suggestions = mSuggestions;
- final List<SuggestedWordInfo> suggestedWordInfoList = suggestions.mSuggestedWordInfoList;
-
- clear();
- final int paneWidth = getWidth();
- final int dividerWidth = mDividers.get(0).getMeasuredWidth();
- final int dividerHeight = mDividers.get(0).getMeasuredHeight();
- int x = 0;
- int y = 0;
- int fromIndex = NUM_CANDIDATES_IN_STRIP;
- final int count = Math.min(mWords.size(), suggestions.size());
- closeCandidatesPane();
- mExpandCandidatesPane.setVisibility(count > NUM_CANDIDATES_IN_STRIP ? VISIBLE : GONE);
- for (int i = 0; i < count; i++) {
- final CharSequence suggestion = suggestions.getWord(i);
- if (suggestion == null) continue;
-
- final SuggestedWordInfo suggestionInfo = (suggestedWordInfoList != null)
- ? suggestedWordInfoList.get(i) : null;
- final boolean isAutoCorrect = suggestions.mHasMinimalSuggestion
- && ((i == 1 && !suggestions.mTypedWordValid)
- || (i == 0 && suggestions.mTypedWordValid));
- // HACK: even if i == 0, we use mColorOther when this suggestion's length is 1
- // and there are multiple suggestions, such as the default punctuation list.
- // TODO: Need to revisit this logic with bigram suggestions
- final boolean isSuggestedCandidate = (i != 0);
- final boolean isPunctuationSuggestions = (suggestion.length() == 1 && count > 1);
-
- final TextView word = mWords.get(i);
- // TODO: Reorder candidates in strip as appropriate. The center candidate should hold
- // the word when space is typed (valid typed word or auto corrected word).
- word.setTextColor(getCandidateTextColor(isAutoCorrect,
- isSuggestedCandidate || isPunctuationSuggestions, suggestionInfo));
- final CharSequence text = getStyledCandidateWord(suggestion, word, isAutoCorrect);
- if (i < NUM_CANDIDATES_IN_STRIP) {
- final View parent = (View)word.getParent();
- final int width = parent.getWidth() - word.getPaddingLeft()
- - word.getPaddingRight();
- setTextWithAutoScaleAndEllipsis(text, width, word);
- } else {
- setTextWithAutoScaleAndEllipsis(text, paneWidth, word);
- }
-
- final TextView info;
- if (DBG && suggestionInfo != null
- && !TextUtils.isEmpty(suggestionInfo.getDebugString())) {
- info = mInfos.get(i);
- info.setText(suggestionInfo.getDebugString());
- info.setVisibility(View.VISIBLE);
- } else {
- info = null;
- }
-
- if (i < NUM_CANDIDATES_IN_STRIP) {
- if (info != null) {
- word.measure(MATCH_PARENT, MATCH_PARENT);
- info.measure(MATCH_PARENT, MATCH_PARENT);
- final int width = word.getMeasuredWidth();
- final int infoWidth = info.getMeasuredWidth();
- FrameLayoutCompatUtils.placeViewAt(
- info, width - infoWidth, 0, infoWidth, info.getMeasuredHeight());
- }
- } else {
- word.measure(MATCH_PARENT, MATCH_PARENT);
- final int width = word.getMeasuredWidth();
- final int height = word.getMeasuredHeight();
- // TODO: Handle overflow case.
- if (dividerWidth + x + width >= paneWidth) {
- centeringCandidates(fromIndex, i - 1, x, paneWidth);
- x = 0;
- y += mCandidateStripHeight;
- fromIndex = i;
- }
- if (x != 0) {
- final View divider = mDividers.get(i - NUM_CANDIDATES_IN_STRIP);
- mCandidatesPane.addView(divider);
- FrameLayoutCompatUtils.placeViewAt(
- divider, x, y + (mCandidateStripHeight - dividerHeight) / 2,
- dividerWidth, dividerHeight);
- x += dividerWidth;
- }
- mCandidatesPane.addView(word);
- FrameLayoutCompatUtils.placeViewAt(
- word, x, y + (mCandidateStripHeight - height) / 2, width, height);
- if (info != null) {
- mCandidatesPane.addView(info);
- info.measure(MATCH_PARENT, MATCH_PARENT);
- final int infoWidth = info.getMeasuredWidth();
- FrameLayoutCompatUtils.placeViewAt(
- info, x + width - infoWidth, y, infoWidth, info.getMeasuredHeight());
- }
- x += width;
- }
- }
- if (x != 0) {
- // Centering last candidates row.
- centeringCandidates(fromIndex, count - 1, x, paneWidth);
- }
- }
-
- private void centeringCandidates(int from, int to, int width, int paneWidth) {
- final ViewGroup pane = mCandidatesPane;
- final int fromIndex = pane.indexOfChild(mWords.get(from));
- final int toIndex;
- if (mInfos.get(to).getParent() != null) {
- toIndex = pane.indexOfChild(mInfos.get(to));
- } else {
- toIndex = pane.indexOfChild(mWords.get(to));
- }
- final int offset = (paneWidth - width) / 2;
- for (int index = fromIndex; index <= toIndex; index++) {
- offsetMargin(pane.getChildAt(index), offset, 0);
- }
- }
-
- private static void offsetMargin(View v, int dx, int dy) {
- if (v == null)
- return;
- final ViewGroup.LayoutParams lp = v.getLayoutParams();
- if (lp instanceof ViewGroup.MarginLayoutParams) {
- final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp;
- mlp.setMargins(mlp.leftMargin + dx, mlp.topMargin + dy, 0, 0);
- }
- }
-
- private static void setTextWithAutoScaleAndEllipsis(CharSequence text, int w, TextView v) {
- // To prevent partially rendered character at the end of text, subtract few extra pixels
- // from the width.
- final int width = w - 4;
-
- final TextPaint paint = v.getPaint();
- final int textWidth = getTextWidth(text, paint, 1.0f);
- if (textWidth < width || textWidth == 0 || width <= 0) {
- v.setTextScaleX(1.0f);
- v.setText(text);
- return;
- }
-
- final float scaleX = Math.min((float)width / textWidth, 1.0f);
- if (scaleX >= MIN_TEXT_XSCALE) {
- v.setTextScaleX(scaleX);
- v.setText(text);
- return;
- }
-
- final int truncatedWidth = width - getTextWidth(ELLIPSIS, paint, MIN_TEXT_XSCALE);
- final CharSequence ellipsized = getTextEllipsizedAtStart(text, paint, truncatedWidth);
- v.setTextScaleX(MIN_TEXT_XSCALE);
- v.setText(ELLIPSIS);
- v.append(ellipsized);
- }
-
- private static int getTextWidth(CharSequence text, TextPaint paint, float scaleX) {
- if (TextUtils.isEmpty(text)) return 0;
- final int len = text.length();
- final float[] widths = new float[len];
- paint.setTextScaleX(scaleX);
- final int count = paint.getTextWidths(text, 0, len, widths);
- float width = 0;
- for (int i = 0; i < count; i++) {
- width += widths[i];
- }
- return (int)Math.round(width + 0.5);
- }
-
- private static CharSequence getTextEllipsizedAtStart(CharSequence text, TextPaint paint,
- int maxWidth) {
- final int len = text.length();
- final float[] widths = new float[len];
- final int count = paint.getTextWidths(text, 0, len, widths);
- float width = 0;
- for (int i = count - 1; i >= 0; i--) {
- width += widths[i];
- if (width > maxWidth)
- return text.subSequence(i + 1, len);
- }
- return text;
- }
-
- private void expandCandidatesPane() {
- mExpandCandidatesPane.setVisibility(View.GONE);
- mCloseCandidatesPane.setVisibility(View.VISIBLE);
- mCandidatesPaneContainer.setMinimumHeight(mKeyboardView.getMeasuredHeight());
- mCandidatesPaneContainer.setVisibility(View.VISIBLE);
- mKeyboardView.setVisibility(View.GONE);
- }
-
- private void closeCandidatesPane() {
- mExpandCandidatesPane.setVisibility(View.VISIBLE);
- mCloseCandidatesPane.setVisibility(View.GONE);
- mCandidatesPaneContainer.setVisibility(View.GONE);
- mKeyboardView.setVisibility(View.VISIBLE);
- }
-
- public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) {
- if ((mAutoCorrectHighlight & AUTO_CORRECT_INVERT) == 0)
- return;
- final TextView tv = mWords.get(1);
- final Spannable word = new SpannableString(autoCorrectedWord);
- final int wordLength = word.length();
- word.setSpan(mInvertedBackgroundColorSpan, 0, wordLength,
- Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- word.setSpan(mInvertedForegroundColorSpan, 0, wordLength,
- Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- tv.setText(word);
- mShowingAutoCorrectionInverted = true;
- }
-
- public boolean isShowingAddToDictionaryHint() {
- return mShowingAddToDictionary;
- }
-
- public void showAddToDictionaryHint(CharSequence word) {
- mWordToSave.setText(word);
- mShowingAddToDictionary = true;
- mCandidatesStrip.setVisibility(View.GONE);
- mTouchToSave.setVisibility(View.VISIBLE);
- }
-
- public boolean dismissAddToDictionaryHint() {
- if (!mShowingAddToDictionary) return false;
- clear();
- return true;
- }
-
- public SuggestedWords getSuggestions() {
- return mSuggestions;
- }
-
- public void clear() {
- mShowingAddToDictionary = false;
- mShowingAutoCorrectionInverted = false;
- for (int i = 0; i < NUM_CANDIDATES_IN_STRIP; i++) {
- mWords.get(i).setText(null);
- mInfos.get(i).setVisibility(View.GONE);
- }
- mTouchToSave.setVisibility(View.GONE);
- mCandidatesStrip.setVisibility(View.VISIBLE);
- mCandidatesPane.removeAllViews();
- }
-
- private void hidePreview() {
- mPreviewPopup.dismiss();
- }
-
- private void showPreview(int index, CharSequence word) {
- if (TextUtils.isEmpty(word))
- return;
-
- final TextView previewText = mPreviewText;
- previewText.setTextColor(mColorTypedWord);
- previewText.setText(word);
- previewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- View v = mWords.get(index);
- final int[] offsetInWindow = new int[2];
- v.getLocationInWindow(offsetInWindow);
- final int posX = offsetInWindow[0];
- final int posY = offsetInWindow[1] - previewText.getMeasuredHeight();
- final PopupWindow previewPopup = mPreviewPopup;
- if (previewPopup.isShowing()) {
- previewPopup.update(posX, posY, previewPopup.getWidth(), previewPopup.getHeight());
- } else {
- previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY);
- }
- previewText.setVisibility(VISIBLE);
- mHandler.postHidePreview();
- }
-
- private void addToDictionary(CharSequence word) {
- if (mListener.addWordToDictionary(word.toString())) {
- showPreview(0, getContext().getString(R.string.added_word, word));
- }
- }
-
- @Override
- public boolean onLongClick(View view) {
- final Object tag = view.getTag();
- if (!(tag instanceof Integer))
- return true;
- final int index = (Integer) tag;
- if (index >= mSuggestions.size())
- return true;
-
- final CharSequence word = mSuggestions.getWord(index);
- if (word.length() < 2)
- return false;
- addToDictionary(word);
- return true;
- }
-
- @Override
- public void onClick(View view) {
- if (view == mWordToSave) {
- addToDictionary(((TextView)view).getText());
- clear();
- return;
- }
-
- final Object tag = view.getTag();
- if (!(tag instanceof Integer))
- return;
- final int index = (Integer) tag;
- if (index >= mSuggestions.size())
- return;
-
- final CharSequence word = mSuggestions.getWord(index);
- mListener.pickSuggestionManually(index, word);
- // Because some punctuation letters are not treated as word separator depending on locale,
- // {@link #setSuggestions} might not be called and candidates pane left opened.
- closeCandidatesPane();
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mHandler.cancelAllMessages();
- hidePreview();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
new file mode 100644
index 000000000..e79db367c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.view.inputmethod.EditorInfo;
+
+public final class Constants {
+ public static final class ImeOption {
+ /**
+ * The private IME option used to indicate that no microphone should be shown for a given
+ * text field. For instance, this is specified by the search dialog when the dialog is
+ * already showing a voice search button.
+ *
+ * @deprecated Use {@link ImeOption#NO_MICROPHONE} with package name prefixed.
+ */
+ @SuppressWarnings("dep-ann")
+ public static final String NO_MICROPHONE_COMPAT = "nm";
+
+ /**
+ * The private IME option used to indicate that no microphone should be shown for a given
+ * text field. For instance, this is specified by the search dialog when the dialog is
+ * already showing a voice search button.
+ */
+ public static final String NO_MICROPHONE = "noMicrophoneKey";
+
+ /**
+ * The private IME option used to indicate that no settings key should be shown for a given
+ * text field.
+ */
+ public static final String NO_SETTINGS_KEY = "noSettingsKey";
+
+ /**
+ * The private IME option used to indicate that the given text field needs ASCII code points
+ * input.
+ *
+ * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}.
+ */
+ @SuppressWarnings("dep-ann")
+ public static final String FORCE_ASCII = "forceAscii";
+
+ private ImeOption() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
+ public static final class Subtype {
+ /**
+ * The subtype mode used to indicate that the subtype is a keyboard.
+ */
+ public static final String KEYBOARD_MODE = "keyboard";
+
+ public static final class ExtraValue {
+ /**
+ * The subtype extra value used to indicate that the subtype keyboard layout is capable
+ * for typing ASCII characters.
+ */
+ public static final String ASCII_CAPABLE = "AsciiCapable";
+
+ /**
+ * The subtype extra value used to indicate that the subtype require network connection
+ * to work.
+ */
+ public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity";
+
+ /**
+ * The subtype extra value used to indicate that the subtype display name contains "%s"
+ * for replacement mark and it should be replaced by this extra value.
+ * This extra value is supported on JellyBean and later.
+ */
+ public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
+ "UntranslatableReplacementStringInSubtypeName";
+
+ /**
+ * The subtype extra value used to indicate that the subtype keyboard layout set name.
+ * This extra value is private to LatinIME.
+ */
+ public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
+
+ /**
+ * The subtype extra value used to indicate that the subtype is additional subtype
+ * that the user defined. This extra value is private to LatinIME.
+ */
+ public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
+
+ private ExtraValue() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
+ private Subtype() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
+ public static class TextUtils {
+ /**
+ * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
+ * characters. This value may be used with
+ * {@link android.text.TextUtils#CAP_MODE_CHARACTERS},
+ * {@link android.text.TextUtils#CAP_MODE_WORDS}, and
+ * {@link android.text.TextUtils#CAP_MODE_SENTENCES}.
+ */
+ public static final int CAP_MODE_OFF = 0;
+
+ private TextUtils() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
+ private Constants() {
+ // This utility class is not publicly instantiable.
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
new file mode 100644
index 000000000..10e511eaf
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.os.SystemClock;
+import android.provider.BaseColumns;
+import android.provider.ContactsContract.Contacts;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.inputmethod.keyboard.Keyboard;
+
+import java.util.Locale;
+
+public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
+
+ private static final String[] PROJECTION = {BaseColumns._ID, Contacts.DISPLAY_NAME,};
+ private static final String[] PROJECTION_ID_ONLY = {BaseColumns._ID};
+
+ private static final String TAG = ContactsBinaryDictionary.class.getSimpleName();
+ private static final String NAME = "contacts";
+
+ private static boolean DEBUG = false;
+
+ /**
+ * Frequency for contacts information into the dictionary
+ */
+ private static final int FREQUENCY_FOR_CONTACTS = 40;
+ private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
+
+ /** The maximum number of contacts that this dictionary supports. */
+ private static final int MAX_CONTACT_COUNT = 10000;
+
+ private static final int INDEX_NAME = 1;
+
+ /** The number of contacts in the most recent dictionary rebuild. */
+ static private int sContactCountAtLastRebuild = 0;
+
+ /** The locale for this contacts dictionary. Controls name bigram predictions. */
+ public final Locale mLocale;
+
+ private ContentObserver mObserver;
+
+ /**
+ * Whether to use "firstname lastname" in bigram predictions.
+ */
+ private final boolean mUseFirstLastBigrams;
+
+ public ContactsBinaryDictionary(final Context context, final int dicTypeId, Locale locale) {
+ super(context, getFilenameWithLocale(NAME, locale.toString()), dicTypeId);
+ mLocale = locale;
+ mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
+ registerObserver(context);
+
+ // Load the current binary dictionary from internal storage. If no binary dictionary exists,
+ // loadDictionary will start a new thread to generate one asynchronously.
+ loadDictionary();
+ }
+
+ private synchronized void registerObserver(final Context context) {
+ // Perform a managed query. The Activity will handle closing and requerying the cursor
+ // when needed.
+ if (mObserver != null) return;
+ ContentResolver cres = context.getContentResolver();
+ cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver =
+ new ContentObserver(null) {
+ @Override
+ public void onChange(boolean self) {
+ setRequiresReload(true);
+ }
+ });
+ }
+
+ public void reopen(final Context context) {
+ registerObserver(context);
+ }
+
+ @Override
+ public synchronized void close() {
+ if (mObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ mObserver = null;
+ }
+ super.close();
+ }
+
+ @Override
+ public void loadDictionaryAsync() {
+ try {
+ Cursor cursor = mContext.getContentResolver()
+ .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ sContactCountAtLastRebuild = getContactCount();
+ addWords(cursor);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Contacts DB is having problems");
+ }
+ }
+
+ @Override
+ public void getBigrams(final WordComposer codes, final CharSequence previousWord,
+ final WordCallback callback) {
+ super.getBigrams(codes, previousWord, callback);
+ }
+
+ private boolean useFirstLastBigramsForLocale(Locale locale) {
+ // TODO: Add firstname/lastname bigram rules for other languages.
+ if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
+ return true;
+ }
+ return false;
+ }
+
+ private void addWords(Cursor cursor) {
+ clearFusionDictionary();
+ int count = 0;
+ while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) {
+ String name = cursor.getString(INDEX_NAME);
+ if (isValidName(name)) {
+ addName(name);
+ ++count;
+ }
+ cursor.moveToNext();
+ }
+ }
+
+ private int getContactCount() {
+ // TODO: consider switching to a rawQuery("select count(*)...") on the database if
+ // performance is a bottleneck.
+ final Cursor cursor = mContext.getContentResolver().query(
+ Contacts.CONTENT_URI, PROJECTION_ID_ONLY, null, null, null);
+ if (cursor != null) {
+ try {
+ return cursor.getCount();
+ } finally {
+ cursor.close();
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Adds the words in a name (e.g., firstname/lastname) to the binary dictionary along with their
+ * bigrams depending on locale.
+ */
+ private void addName(String name) {
+ int len = name.codePointCount(0, name.length());
+ String prevWord = null;
+ // TODO: Better tokenization for non-Latin writing systems
+ for (int i = 0; i < len; i++) {
+ if (Character.isLetter(name.codePointAt(i))) {
+ int end = getWordEndPosition(name, len, i);
+ String word = name.substring(i, end);
+ i = end - 1;
+ // Don't add single letter words, possibly confuses
+ // capitalization of i.
+ final int wordLen = word.codePointCount(0, word.length());
+ if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
+ super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS);
+ if (!TextUtils.isEmpty(prevWord)) {
+ if (mUseFirstLastBigrams) {
+ super.setBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM);
+ }
+ }
+ prevWord = word;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the index of the last letter in the word, starting from position startIndex.
+ */
+ private static int getWordEndPosition(String string, int len, int startIndex) {
+ int end;
+ int cp = 0;
+ for (end = startIndex + 1; end < len; end += Character.charCount(cp)) {
+ cp = string.codePointAt(end);
+ if (!(cp == Keyboard.CODE_DASH || cp == Keyboard.CODE_SINGLE_QUOTE
+ || Character.isLetter(cp))) {
+ break;
+ }
+ }
+ return end;
+ }
+
+ @Override
+ protected boolean hasContentChanged() {
+ final long startTime = SystemClock.uptimeMillis();
+ final int contactCount = getContactCount();
+ if (contactCount > MAX_CONTACT_COUNT) {
+ // If there are too many contacts then return false. In this rare case it is impossible
+ // to include all of them anyways and the cost of rebuilding the dictionary is too high.
+ // TODO: Sort and check only the MAX_CONTACT_COUNT most recent contacts?
+ return false;
+ }
+ if (contactCount != sContactCountAtLastRebuild) {
+ if (DEBUG) {
+ Log.d(TAG, "Contact count changed: " + sContactCountAtLastRebuild + " to "
+ + contactCount);
+ }
+ return true;
+ }
+ // Check all contacts since it's not possible to find out which names have changed.
+ // This is needed because it's possible to receive extraneous onChange events even when no
+ // name has changed.
+ Cursor cursor = mContext.getContentResolver().query(
+ Contacts.CONTENT_URI, PROJECTION, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ while (!cursor.isAfterLast()) {
+ String name = cursor.getString(INDEX_NAME);
+ if (isValidName(name) && !isNameInDictionary(name)) {
+ if (DEBUG) {
+ Log.d(TAG, "Contact name missing: " + name + " (runtime = "
+ + (SystemClock.uptimeMillis() - startTime) + " ms)");
+ }
+ return true;
+ }
+ cursor.moveToNext();
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ if (DEBUG) {
+ Log.d(TAG, "No contacts changed. (runtime = " + (SystemClock.uptimeMillis() - startTime)
+ + " ms)");
+ }
+ return false;
+ }
+
+ private static boolean isValidName(String name) {
+ if (name != null && -1 == name.indexOf('@')) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the words in a name are in the current binary dictionary.
+ */
+ private boolean isNameInDictionary(String name) {
+ int len = name.codePointCount(0, name.length());
+ String prevWord = null;
+ for (int i = 0; i < len; i++) {
+ if (Character.isLetter(name.codePointAt(i))) {
+ int end = getWordEndPosition(name, len, i);
+ String word = name.substring(i, end);
+ i = end - 1;
+ final int wordLen = word.codePointCount(0, word.length());
+ if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
+ if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
+ if (!super.isValidBigramLocked(prevWord, word)) {
+ return false;
+ }
+ } else {
+ if (!super.isValidWordLocked(word)) {
+ return false;
+ }
+ }
+ prevWord = word;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
deleted file mode 100644
index 66a041508..000000000
--- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.os.SystemClock;
-import android.provider.BaseColumns;
-import android.provider.ContactsContract.Contacts;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.inputmethod.keyboard.Keyboard;
-
-public class ContactsDictionary extends ExpandableDictionary {
-
- private static final String[] PROJECTION = {
- BaseColumns._ID,
- Contacts.DISPLAY_NAME,
- };
-
- private static final String TAG = "ContactsDictionary";
-
- /**
- * Frequency for contacts information into the dictionary
- */
- private static final int FREQUENCY_FOR_CONTACTS = 40;
- private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
-
- private static final int INDEX_NAME = 1;
-
- private ContentObserver mObserver;
-
- private long mLastLoadedContacts;
-
- public ContactsDictionary(Context context, int dicTypeId) {
- super(context, dicTypeId);
- // Perform a managed query. The Activity will handle closing and requerying the cursor
- // when needed.
- ContentResolver cres = context.getContentResolver();
-
- cres.registerContentObserver(
- Contacts.CONTENT_URI, true,mObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean self) {
- setRequiresReload(true);
- }
- });
- loadDictionary();
- }
-
- @Override
- public synchronized void close() {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- super.close();
- }
-
- @Override
- public void startDictionaryLoadingTaskLocked() {
- long now = SystemClock.uptimeMillis();
- if (mLastLoadedContacts == 0
- || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) {
- super.startDictionaryLoadingTaskLocked();
- }
- }
-
- @Override
- public void loadDictionaryAsync() {
- try {
- Cursor cursor = getContext().getContentResolver()
- .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
- if (cursor != null) {
- addWords(cursor);
- }
- } catch(IllegalStateException e) {
- Log.e(TAG, "Contacts DB is having problems");
- }
- mLastLoadedContacts = SystemClock.uptimeMillis();
- }
-
- @Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
- // Do not return bigrams from Contacts when nothing was typed.
- if (codes.size() <= 0) return;
- super.getBigrams(codes, previousWord, callback);
- }
-
- private void addWords(Cursor cursor) {
- clearDictionary();
-
- final int maxWordLength = getMaxWordLength();
- try {
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- String name = cursor.getString(INDEX_NAME);
-
- if (name != null && -1 == name.indexOf('@')) {
- int len = name.length();
- String prevWord = null;
-
- // TODO: Better tokenization for non-Latin writing systems
- for (int i = 0; i < len; i++) {
- if (Character.isLetter(name.charAt(i))) {
- int j;
- for (j = i + 1; j < len; j++) {
- char c = name.charAt(j);
-
- if (!(c == Keyboard.CODE_DASH
- || c == Keyboard.CODE_SINGLE_QUOTE
- || Character.isLetter(c))) {
- break;
- }
- }
-
- String word = name.substring(i, j);
- i = j - 1;
-
- // Safeguard against adding really long words. Stack
- // may overflow due to recursion
- // Also don't add single letter words, possibly confuses
- // capitalization of i.
- final int wordLen = word.length();
- if (wordLen < maxWordLength && wordLen > 1) {
- super.addWord(word, FREQUENCY_FOR_CONTACTS);
- if (!TextUtils.isEmpty(prevWord)) {
- super.setBigram(prevWord, word,
- FREQUENCY_FOR_CONTACTS_BIGRAM);
- }
- prevWord = word;
- }
- }
- }
- }
- cursor.moveToNext();
- }
- }
- cursor.close();
- } catch(IllegalStateException e) {
- Log.e(TAG, "Contacts DB is having problems");
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java
index fd62d61c3..af7649863 100644
--- a/java/src/com/android/inputmethod/latin/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/DebugSettings.java
@@ -16,27 +16,30 @@
package com.android.inputmethod.latin;
+import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Process;
import android.preference.CheckBoxPreference;
-import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
import android.util.Log;
-public class DebugSettings extends PreferenceActivity
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
+
+public class DebugSettings extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
- private static final String TAG = "DebugSettings";
+ private static final String TAG = DebugSettings.class.getSimpleName();
private static final String DEBUG_MODE_KEY = "debug_mode";
+ public static final String FORCE_NON_DISTINCT_MULTITOUCH_KEY = "force_non_distinct_multitouch";
private boolean mServiceNeedsRestart = false;
private CheckBoxPreference mDebugMode;
- private CheckBoxPreference mUseSpacebarLanguageSwitch;
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.prefs_for_debug);
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
@@ -48,7 +51,7 @@ public class DebugSettings extends PreferenceActivity
}
@Override
- protected void onStop() {
+ public void onStop() {
super.onStop();
if (mServiceNeedsRestart) Process.killProcess(Process.myPid());
}
@@ -61,13 +64,9 @@ public class DebugSettings extends PreferenceActivity
updateDebugMode();
mServiceNeedsRestart = true;
}
- } else if (key.equals(SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCH_KEY)) {
- if (mUseSpacebarLanguageSwitch != null) {
- mUseSpacebarLanguageSwitch.setChecked(
- prefs.getBoolean(SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCH_KEY,
- getResources().getBoolean(
- R.bool.config_use_spacebar_language_switcher)));
- }
+ } else if (key.equals(FORCE_NON_DISTINCT_MULTITOUCH_KEY)
+ || key.equals(KeyboardSwitcher.PREF_KEYBOARD_LAYOUT)) {
+ mServiceNeedsRestart = true;
}
}
@@ -78,7 +77,9 @@ public class DebugSettings extends PreferenceActivity
boolean isDebugMode = mDebugMode.isChecked();
String version = "";
try {
- PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
+ final Context context = getActivity();
+ final String packageName = context.getPackageName();
+ PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
version = "Version " + info.versionName;
} catch (NameNotFoundException e) {
Log.e(TAG, "Could not find version info.");
diff --git a/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java b/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java
new file mode 100644
index 000000000..cde20606a
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DebugSettingsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class DebugSettingsActivity extends PreferenceActivity {
+ @Override
+ public Intent getIntent() {
+ final Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, DebugSettings.class.getName());
+ return modIntent;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setTitle(R.string.english_ime_debug_settings);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index c7737b9a2..9c3d46e70 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,28 +16,25 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.ProximityInfo;
+
/**
* Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
* strokes.
*/
public abstract class Dictionary {
/**
- * Whether or not to replicate the typed word in the suggested list, even if it's valid.
- */
- protected static final boolean INCLUDE_TYPED_WORD_IF_VALID = false;
-
- /**
* The weight to give to a word if it's length is the same as the number of typed characters.
*/
protected static final int FULL_WORD_SCORE_MULTIPLIER = 2;
- public static enum DataType {
- UNIGRAM, BIGRAM
- }
+ public static final int UNIGRAM = 0;
+ public static final int BIGRAM = 1;
+ public static final int NOT_A_PROBABILITY = -1;
/**
* Interface to be implemented by classes requesting words to be fetched from the dictionary.
- * @see #getWords(WordComposer, WordCallback)
+ * @see #getWords(WordComposer, CharSequence, WordCallback, ProximityInfo)
*/
public interface WordCallback {
/**
@@ -49,21 +46,25 @@ public abstract class Dictionary {
* @param score the score of occurrence. This is normalized between 1 and 255, but
* can exceed those limits
* @param dicTypeId of the dictionary where word was from
- * @param dataType tells type of this data
+ * @param dataType tells type of this data, either UNIGRAM or BIGRAM
* @return true if the word was added, false if no more words are required
*/
boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId,
- DataType dataType);
+ int dataType);
}
/**
- * Searches for words in the dictionary that match the characters in the composer. Matched
+ * Searches for words in the dictionary that match the characters in the composer. Matched
* words are added through the callback object.
* @param composer the key sequence to match
+ * @param prevWordForBigrams the previous word, or null if none
* @param callback the callback object to send matched words to as possible candidates
- * @see WordCallback#addWord(char[], int, int, int, int, DataType)
+ * @param proximityInfo the object for key proximity. May be ignored by some implementations.
+ * @see WordCallback#addWord(char[], int, int, int, int, int)
*/
- abstract public void getWords(final WordComposer composer, final WordCallback callback);
+ abstract public void getWords(final WordComposer composer,
+ final CharSequence prevWordForBigrams, final WordCallback callback,
+ final ProximityInfo proximityInfo);
/**
* Searches for pairs in the bigram dictionary that matches the previous word and all the
@@ -83,7 +84,11 @@ public abstract class Dictionary {
* @return true if the word exists, false otherwise
*/
abstract public boolean isValidWord(CharSequence word);
-
+
+ public int getFrequency(CharSequence word) {
+ return NOT_A_PROBABILITY;
+ }
+
/**
* Compares the contents of the character array with the typed word and returns true if they
* are the same.
@@ -110,4 +115,12 @@ public abstract class Dictionary {
public void close() {
// empty base implementation
}
+
+ /**
+ * Subclasses may override to indicate that this Dictionary is not yet properly initialized.
+ */
+
+ public boolean isInitialized() {
+ return true;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 5e7de3e6b..26c2e637e 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -16,33 +16,44 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+import android.util.Log;
+
import java.util.Collection;
-import java.util.List;
+import java.util.Collections;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Class for a collection of dictionaries that behave like one dictionary.
*/
public class DictionaryCollection extends Dictionary {
-
- protected final List<Dictionary> mDictionaries;
+ private final String TAG = DictionaryCollection.class.getSimpleName();
+ protected final CopyOnWriteArrayList<Dictionary> mDictionaries;
public DictionaryCollection() {
mDictionaries = new CopyOnWriteArrayList<Dictionary>();
}
public DictionaryCollection(Dictionary... dictionaries) {
- mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
+ if (null == dictionaries) {
+ mDictionaries = new CopyOnWriteArrayList<Dictionary>();
+ } else {
+ mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
+ mDictionaries.removeAll(Collections.singleton(null));
+ }
}
public DictionaryCollection(Collection<Dictionary> dictionaries) {
mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
+ mDictionaries.removeAll(Collections.singleton(null));
}
@Override
- public void getWords(final WordComposer composer, final WordCallback callback) {
+ public void getWords(final WordComposer composer, final CharSequence prevWordForBigrams,
+ final WordCallback callback, final ProximityInfo proximityInfo) {
for (final Dictionary dict : mDictionaries)
- dict.getWords(composer, callback);
+ dict.getWords(composer, prevWordForBigrams, callback, proximityInfo);
}
@Override
@@ -60,12 +71,43 @@ public class DictionaryCollection extends Dictionary {
}
@Override
+ public int getFrequency(CharSequence word) {
+ int maxFreq = -1;
+ for (int i = mDictionaries.size() - 1; i >= 0; --i) {
+ final int tempFreq = mDictionaries.get(i).getFrequency(word);
+ if (tempFreq >= maxFreq) {
+ maxFreq = tempFreq;
+ }
+ }
+ return maxFreq;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return !mDictionaries.isEmpty();
+ }
+
+ @Override
public void close() {
for (final Dictionary dict : mDictionaries)
dict.close();
}
- public void addDictionary(Dictionary newDict) {
+ // Warning: this is not thread-safe. Take necessary precaution when calling.
+ public void addDictionary(final Dictionary newDict) {
+ if (null == newDict) return;
+ if (mDictionaries.contains(newDict)) {
+ Log.w(TAG, "This collection already contains this dictionary: " + newDict);
+ }
mDictionaries.add(newDict);
}
+
+ // Warning: this is not thread-safe. Take necessary precaution when calling.
+ public void removeDictionary(final Dictionary dict) {
+ if (mDictionaries.contains(dict)) {
+ mDictionaries.remove(dict);
+ } else {
+ Log.w(TAG, "This collection does not contain this dictionary: " + dict);
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index bba331868..a22d73af7 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -22,60 +22,88 @@ import android.content.res.Resources;
import android.util.Log;
import java.io.File;
+import java.util.ArrayList;
import java.util.LinkedList;
-import java.util.List;
import java.util.Locale;
/**
* Factory for dictionary instances.
*/
public class DictionaryFactory {
-
- private static String TAG = DictionaryFactory.class.getSimpleName();
+ private static final String TAG = DictionaryFactory.class.getSimpleName();
+ // This class must be located in the same package as LatinIME.java.
+ private static final String RESOURCE_PACKAGE_NAME =
+ DictionaryFactory.class.getPackage().getName();
/**
- * Initializes a dictionary from a dictionary pack.
+ * Initializes a main dictionary collection from a dictionary pack, with explicit flags.
*
* This searches for a content provider providing a dictionary pack for the specified
- * locale. If none is found, it falls back to using the resource passed as fallBackResId
- * as a dictionary.
+ * locale. If none is found, it falls back to the built-in dictionary - if any.
* @param context application context for reading resources
* @param locale the locale for which to create the dictionary
- * @param fallbackResId the id of the resource to use as a fallback if no pack is found
- * @return an initialized instance of Dictionary
+ * @param useFullEditDistance whether to use the full edit distance in suggestions
+ * @return an initialized instance of DictionaryCollection
*/
- public static Dictionary createDictionaryFromManager(Context context, Locale locale,
- int fallbackResId) {
+ public static DictionaryCollection createMainDictionaryFromManager(final Context context,
+ final Locale locale, final boolean useFullEditDistance) {
if (null == locale) {
Log.e(TAG, "No locale defined for dictionary");
- return new DictionaryCollection(createBinaryDictionary(context, fallbackResId));
+ return new DictionaryCollection(createBinaryDictionary(context, locale));
}
- final List<Dictionary> dictList = new LinkedList<Dictionary>();
- for (final AssetFileAddress f : BinaryDictionaryGetter.getDictionaryFiles(locale,
- context, fallbackResId)) {
- dictList.add(new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null));
+ final LinkedList<Dictionary> dictList = new LinkedList<Dictionary>();
+ final ArrayList<AssetFileAddress> assetFileList =
+ BinaryDictionaryGetter.getDictionaryFiles(locale, context);
+ if (null != assetFileList) {
+ for (final AssetFileAddress f : assetFileList) {
+ final BinaryDictionary binaryDictionary =
+ new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength,
+ useFullEditDistance, locale);
+ if (binaryDictionary.isValidDictionary()) {
+ dictList.add(binaryDictionary);
+ }
+ }
}
- if (null == dictList) return null;
+ // If the list is empty, that means we should not use any dictionary (for example, the user
+ // explicitly disabled the main dictionary), so the following is okay. dictList is never
+ // null, but if for some reason it is, DictionaryCollection handles it gracefully.
return new DictionaryCollection(dictList);
}
/**
+ * Initializes a main dictionary collection from a dictionary pack, with default flags.
+ *
+ * This searches for a content provider providing a dictionary pack for the specified
+ * locale. If none is found, it falls back to the built-in dictionary, if any.
+ * @param context application context for reading resources
+ * @param locale the locale for which to create the dictionary
+ * @return an initialized instance of DictionaryCollection
+ */
+ public static DictionaryCollection createMainDictionaryFromManager(final Context context,
+ final Locale locale) {
+ return createMainDictionaryFromManager(context, locale, false /* useFullEditDistance */);
+ }
+
+ /**
* Initializes a dictionary from a raw resource file
* @param context application context for reading resources
- * @param resId the resource containing the raw binary dictionary
+ * @param locale the locale to use for the resource
* @return an initialized instance of BinaryDictionary
*/
- protected static BinaryDictionary createBinaryDictionary(Context context, int resId) {
+ protected static BinaryDictionary createBinaryDictionary(final Context context,
+ final Locale locale) {
AssetFileDescriptor afd = null;
try {
+ final int resId =
+ getMainDictionaryResourceIdIfAvailableForLocale(context.getResources(), locale);
+ if (0 == resId) return null;
afd = context.getResources().openRawResourceFd(resId);
if (afd == null) {
Log.e(TAG, "Found the resource but it is compressed. resId=" + resId);
return null;
}
- if (!isFullDictionary(afd)) return null;
final String sourceDir = context.getApplicationInfo().sourceDir;
final File packagePath = new File(sourceDir);
// TODO: Come up with a way to handle a directory.
@@ -83,10 +111,10 @@ public class DictionaryFactory {
Log.e(TAG, "sourceDir is not a file: " + sourceDir);
return null;
}
- return new BinaryDictionary(context,
- sourceDir, afd.getStartOffset(), afd.getLength(), null);
+ return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(),
+ false /* useFullEditDistance */, locale);
} catch (android.content.res.Resources.NotFoundException e) {
- Log.e(TAG, "Could not find the resource. resId=" + resId);
+ Log.e(TAG, "Could not find the resource");
return null;
} finally {
if (null != afd) {
@@ -105,14 +133,14 @@ public class DictionaryFactory {
* @param dictionary the file to read
* @param startOffset the offset in the file where the data starts
* @param length the length of the data
- * @param flagArray the flags to use with this data for testing
+ * @param useFullEditDistance whether to use the full edit distance in suggestions
* @return the created dictionary, or null.
*/
public static Dictionary createDictionaryForTest(Context context, File dictionary,
- long startOffset, long length, Flag[] flagArray) {
+ long startOffset, long length, final boolean useFullEditDistance, Locale locale) {
if (dictionary.isFile()) {
return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length,
- flagArray);
+ useFullEditDistance, locale);
} else {
Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath());
return null;
@@ -127,51 +155,47 @@ public class DictionaryFactory {
*/
public static boolean isDictionaryAvailable(Context context, Locale locale) {
final Resources res = context.getResources();
- final Locale saveLocale = Utils.setSystemLocale(res, locale);
-
- final int resourceId = Utils.getMainDictionaryResourceId(res);
- final AssetFileDescriptor afd = res.openRawResourceFd(resourceId);
- final boolean hasDictionary = isFullDictionary(afd);
- try {
- if (null != afd) afd.close();
- } catch (java.io.IOException e) {
- /* Um, what can we do here exactly? */
- }
-
- Utils.setSystemLocale(res, saveLocale);
- return hasDictionary;
+ return 0 != getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
}
- // TODO: Do not use the size of the dictionary as an unique dictionary ID.
- public static Long getDictionaryId(Context context, Locale locale) {
- final Resources res = context.getResources();
- final Locale saveLocale = Utils.setSystemLocale(res, locale);
+ private static final String DEFAULT_MAIN_DICT = "main";
+ private static final String MAIN_DICT_PREFIX = "main_";
- final int resourceId = Utils.getMainDictionaryResourceId(res);
- final AssetFileDescriptor afd = res.openRawResourceFd(resourceId);
- final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH)
- ? afd.getLength()
- : null;
- try {
- if (null != afd) afd.close();
- } catch (java.io.IOException e) {
+ /**
+ * Helper method to return a dictionary res id for a locale, or 0 if none.
+ * @param locale dictionary locale
+ * @return main dictionary resource id
+ */
+ private static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res,
+ final Locale locale) {
+ int resId;
+ // Try to find main_language_country dictionary.
+ if (!locale.getCountry().isEmpty()) {
+ final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase();
+ if ((resId = res.getIdentifier(
+ dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
+ return resId;
+ }
+ }
+
+ // Try to find main_language dictionary.
+ final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
+ if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
+ return resId;
}
- Utils.setSystemLocale(res, saveLocale);
- return size;
+ // Not found, return 0
+ return 0;
}
- // TODO: Find the Right Way to find out whether the resource is a placeholder or not.
- // Suggestion : strip the locale, open the placeholder file and store its offset.
- // Upon opening the file, if it's the same offset, then it's the placeholder.
- private static final long PLACEHOLDER_LENGTH = 34;
/**
- * Finds out whether the data pointed out by an AssetFileDescriptor is a full
- * dictionary (as opposed to null, or to a place holder).
- * @param afd the file descriptor to test, or null
- * @return true if the dictionary is a real full dictionary, false if it's null or a placeholder
+ * Returns a main dictionary resource id
+ * @param locale dictionary locale
+ * @return main dictionary resource id
*/
- protected static boolean isFullDictionary(final AssetFileDescriptor afd) {
- return (afd != null && afd.getLength() > PLACEHOLDER_LENGTH);
+ public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
+ int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
+ if (0 != resourceId) return resourceId;
+ return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
}
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
index 9d30af84b..9c37d7673 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
@@ -51,6 +51,8 @@ public class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
if (null == packageUri) return; // No package name : we can't do anything
final String packageName = packageUri.getSchemeSpecificPart();
if (null == packageName) return;
+ // TODO: do this in a more appropriate place
+ TargetApplicationGetter.removeApplicationInfoCache(packageName);
final PackageInfo packageInfo;
try {
packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java
deleted file mode 100644
index e56aa695d..000000000
--- a/java/src/com/android/inputmethod/latin/EditingUtils.java
+++ /dev/null
@@ -1,293 +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 com.android.inputmethod.compat.InputConnectionCompatUtils;
-
-import android.text.TextUtils;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-import java.util.regex.Pattern;
-
-/**
- * Utility methods to deal with editing text through an InputConnection.
- */
-public class EditingUtils {
- /**
- * Number of characters we want to look back in order to identify the previous word
- */
- private static final int LOOKBACK_CHARACTER_NUM = 15;
-
- private EditingUtils() {
- // Unintentional empty constructor for singleton.
- }
-
- /**
- * Append newText to the text field represented by connection.
- * The new text becomes selected.
- */
- public static void appendText(InputConnection connection, String newText) {
- if (connection == null) {
- return;
- }
-
- // Commit the composing text
- connection.finishComposingText();
-
- // Add a space if the field already has text.
- String text = newText;
- CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0);
- if (charBeforeCursor != null
- && !charBeforeCursor.equals(" ")
- && (charBeforeCursor.length() > 0)) {
- text = " " + text;
- }
-
- connection.setComposingText(text, 1);
- }
-
- private static int getCursorPosition(InputConnection connection) {
- ExtractedText extracted = connection.getExtractedText(
- new ExtractedTextRequest(), 0);
- if (extracted == null) {
- return -1;
- }
- return extracted.startOffset + extracted.selectionStart;
- }
-
- /**
- * @param connection connection to the current text field.
- * @param separators characters which may separate words
- * @return the word that surrounds the cursor, including up to one trailing
- * separator. For example, if the field contains "he|llo world", where |
- * represents the cursor, then "hello " will be returned.
- */
- public static String getWordAtCursor(InputConnection connection, String separators) {
- Range r = getWordRangeAtCursor(connection, separators);
- return (r == null) ? null : r.mWord;
- }
-
- /**
- * Removes the word surrounding the cursor. Parameters are identical to
- * getWordAtCursor.
- */
- public static void deleteWordAtCursor(InputConnection connection, String separators) {
- Range range = getWordRangeAtCursor(connection, separators);
- if (range == null) return;
-
- connection.finishComposingText();
- // Move cursor to beginning of word, to avoid crash when cursor is outside
- // of valid range after deleting text.
- int newCursor = getCursorPosition(connection) - range.mCharsBefore;
- connection.setSelection(newCursor, newCursor);
- connection.deleteSurroundingText(0, range.mCharsBefore + range.mCharsAfter);
- }
-
- /**
- * Represents a range of text, relative to the current cursor position.
- */
- public static class Range {
- /** Characters before selection start */
- public final int mCharsBefore;
-
- /**
- * Characters after selection start, including one trailing word
- * separator.
- */
- public final int mCharsAfter;
-
- /** The actual characters that make up a word */
- public final String mWord;
-
- public Range(int charsBefore, int charsAfter, String word) {
- if (charsBefore < 0 || charsAfter < 0) {
- throw new IndexOutOfBoundsException();
- }
- this.mCharsBefore = charsBefore;
- this.mCharsAfter = charsAfter;
- this.mWord = word;
- }
- }
-
- private static Range getWordRangeAtCursor(InputConnection connection, String sep) {
- if (connection == null || sep == null) {
- return null;
- }
- CharSequence before = connection.getTextBeforeCursor(1000, 0);
- CharSequence after = connection.getTextAfterCursor(1000, 0);
- if (before == null || after == null) {
- return null;
- }
-
- // Find first word separator before the cursor
- int start = before.length();
- while (start > 0 && !isWhitespace(before.charAt(start - 1), sep)) start--;
-
- // Find last word separator after the cursor
- int end = -1;
- while (++end < after.length() && !isWhitespace(after.charAt(end), sep)) {
- // Nothing to do here.
- }
-
- int cursor = getCursorPosition(connection);
- if (start >= 0 && cursor + end <= after.length() + before.length()) {
- String word = before.toString().substring(start, before.length())
- + after.toString().substring(0, end);
- return new Range(before.length() - start, end, word);
- }
-
- return null;
- }
-
- private static boolean isWhitespace(int code, String whitespace) {
- return whitespace.contains(String.valueOf((char) code));
- }
-
- private static final Pattern spaceRegex = Pattern.compile("\\s+");
-
-
- public static CharSequence getPreviousWord(InputConnection connection,
- String sentenceSeperators) {
- //TODO: Should fix this. This could be slow!
- CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
- return getPreviousWord(prev, sentenceSeperators);
- }
-
- // Get the word before the whitespace preceding the non-whitespace preceding the cursor.
- // Also, it won't return words that end in a separator.
- // Example :
- // "abc def|" -> abc
- // "abc def |" -> abc
- // "abc def. |" -> abc
- // "abc def . |" -> def
- // "abc|" -> null
- // "abc |" -> null
- // "abc. def|" -> null
- public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) {
- if (prev == null) return null;
- String[] w = spaceRegex.split(prev);
-
- // If we can't find two words, or we found an empty word, return null.
- if (w.length < 2 || w[w.length - 2].length() <= 0) return null;
-
- // If ends in a separator, return null
- char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1);
- if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
-
- return w[w.length - 2];
- }
-
- public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) {
- final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
- return getThisWord(prev, sentenceSeperators);
- }
-
- // Get the word immediately before the cursor, even if there is whitespace between it and
- // the cursor - but not if there is punctuation.
- // Example :
- // "abc def|" -> def
- // "abc def |" -> def
- // "abc def. |" -> null
- // "abc def . |" -> null
- public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) {
- if (prev == null) return null;
- String[] w = spaceRegex.split(prev);
-
- // No word : return null
- if (w.length < 1 || w[w.length - 1].length() <= 0) return null;
-
- // If ends in a separator, return null
- char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1);
- if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
-
- return w[w.length - 1];
- }
-
- public static class SelectedWord {
- public final int mStart;
- public final int mEnd;
- public final CharSequence mWord;
-
- public SelectedWord(int start, int end, CharSequence word) {
- mStart = start;
- mEnd = end;
- mWord = word;
- }
- }
-
- /**
- * Takes a character sequence with a single character and checks if the character occurs
- * in a list of word separators or is empty.
- * @param singleChar A CharSequence with null, zero or one character
- * @param wordSeparators A String containing the word separators
- * @return true if the character is at a word boundary, false otherwise
- */
- private static boolean isWordBoundary(CharSequence singleChar, String wordSeparators) {
- return TextUtils.isEmpty(singleChar) || wordSeparators.contains(singleChar);
- }
-
- /**
- * Checks if the cursor is inside a word or the current selection is a whole word.
- * @param ic the InputConnection for accessing the text field
- * @param selStart the start position of the selection within the text field
- * @param selEnd the end position of the selection within the text field. This could be
- * the same as selStart, if there's no selection.
- * @param wordSeparators the word separator characters for the current language
- * @return an object containing the text and coordinates of the selected/touching word,
- * null if the selection/cursor is not marking a whole word.
- */
- public static SelectedWord getWordAtCursorOrSelection(final InputConnection ic,
- int selStart, int selEnd, String wordSeparators) {
- if (selStart == selEnd) {
- // There is just a cursor, so get the word at the cursor
- EditingUtils.Range range = getWordRangeAtCursor(ic, wordSeparators);
- if (range != null && !TextUtils.isEmpty(range.mWord)) {
- return new SelectedWord(selStart - range.mCharsBefore, selEnd + range.mCharsAfter,
- range.mWord);
- }
- } else {
- // Is the previous character empty or a word separator? If not, return null.
- CharSequence charsBefore = ic.getTextBeforeCursor(1, 0);
- if (!isWordBoundary(charsBefore, wordSeparators)) {
- return null;
- }
-
- // Is the next character empty or a word separator? If not, return null.
- CharSequence charsAfter = ic.getTextAfterCursor(1, 0);
- if (!isWordBoundary(charsAfter, wordSeparators)) {
- return null;
- }
-
- // Extract the selection alone
- CharSequence touching = InputConnectionCompatUtils.getSelectedText(
- ic, selStart, selEnd);
- if (TextUtils.isEmpty(touching)) return null;
- // Is any part of the selection a separator? If so, return null.
- final int length = touching.length();
- for (int i = 0; i < length; i++) {
- if (wordSeparators.contains(touching.subSequence(i, i + 1))) {
- return null;
- }
- }
- // Prepare the selected word
- return new SelectedWord(selStart, selEnd, touching);
- }
- return null;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
new file mode 100644
index 000000000..c65404cbc
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;
+import com.android.inputmethod.latin.makedict.FusionDictionary;
+import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
+import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Abstract base class for an expandable dictionary that can be created and updated dynamically
+ * during runtime. When updated it automatically generates a new binary dictionary to handle future
+ * queries in native code. This binary dictionary is written to internal storage, and potentially
+ * shared across multiple ExpandableBinaryDictionary instances. Updates to each dictionary filename
+ * are controlled across multiple instances to ensure that only one instance can update the same
+ * dictionary at the same time.
+ */
+abstract public class ExpandableBinaryDictionary extends Dictionary {
+
+ /** Used for Log actions from this class */
+ private static final String TAG = ExpandableBinaryDictionary.class.getSimpleName();
+
+ /** Whether to print debug output to log */
+ private static boolean DEBUG = false;
+
+ /**
+ * The maximum length of a word in this dictionary. This is the same value as the binary
+ * dictionary.
+ */
+ protected static final int MAX_WORD_LENGTH = BinaryDictionary.MAX_WORD_LENGTH;
+
+ /**
+ * A static map of locks, each of which controls access to a single binary dictionary file. They
+ * ensure that only one instance can update the same dictionary at the same time. The key for
+ * this map is the filename and the value is the shared dictionary controller associated with
+ * that filename.
+ */
+ private static final HashMap<String, DictionaryController> sSharedDictionaryControllers =
+ new HashMap<String, DictionaryController>();
+
+ /** The application context. */
+ protected final Context mContext;
+
+ /**
+ * The binary dictionary generated dynamically from the fusion dictionary. This is used to
+ * answer unigram and bigram queries.
+ */
+ private BinaryDictionary mBinaryDictionary;
+
+ /** The expandable fusion dictionary used to generate the binary dictionary. */
+ private FusionDictionary mFusionDictionary;
+
+ /** The dictionary type id. */
+ public final int mDicTypeId;
+
+ /**
+ * The name of this dictionary, used as the filename for storing the binary dictionary. Multiple
+ * dictionary instances with the same filename is supported, with access controlled by
+ * DictionaryController.
+ */
+ private final String mFilename;
+
+ /** Controls access to the shared binary dictionary file across multiple instances. */
+ private final DictionaryController mSharedDictionaryController;
+
+ /** Controls access to the local binary dictionary for this instance. */
+ private final DictionaryController mLocalDictionaryController = new DictionaryController();
+
+ /**
+ * Abstract method for loading the unigrams and bigrams of a given dictionary in a background
+ * thread.
+ */
+ protected abstract void loadDictionaryAsync();
+
+ /**
+ * Indicates that the source dictionary content has changed and a rebuild of the binary file is
+ * required. If it returns false, the next reload will only read the current binary dictionary
+ * from file. Note that the shared binary dictionary is locked when this is called.
+ */
+ protected abstract boolean hasContentChanged();
+
+ /**
+ * Gets the shared dictionary controller for the given filename.
+ */
+ private static synchronized DictionaryController getSharedDictionaryController(
+ String filename) {
+ DictionaryController controller = sSharedDictionaryControllers.get(filename);
+ if (controller == null) {
+ controller = new DictionaryController();
+ sSharedDictionaryControllers.put(filename, controller);
+ }
+ return controller;
+ }
+
+ /**
+ * Creates a new expandable binary dictionary.
+ *
+ * @param context The application context of the parent.
+ * @param filename The filename for this binary dictionary. Multiple dictionaries with the same
+ * filename is supported.
+ * @param dictType The type of this dictionary.
+ */
+ public ExpandableBinaryDictionary(
+ final Context context, final String filename, final int dictType) {
+ mDicTypeId = dictType;
+ mFilename = filename;
+ mContext = context;
+ mBinaryDictionary = null;
+ mSharedDictionaryController = getSharedDictionaryController(filename);
+ clearFusionDictionary();
+ }
+
+ protected static String getFilenameWithLocale(final String name, final String localeStr) {
+ return name + "." + localeStr + ".dict";
+ }
+
+ /**
+ * Closes and cleans up the binary dictionary.
+ */
+ @Override
+ public void close() {
+ // Ensure that no other threads are accessing the local binary dictionary.
+ mLocalDictionaryController.lock();
+ try {
+ if (mBinaryDictionary != null) {
+ mBinaryDictionary.close();
+ mBinaryDictionary = null;
+ }
+ } finally {
+ mLocalDictionaryController.unlock();
+ }
+ }
+
+ /**
+ * Clears the fusion dictionary on the Java side. Note: Does not modify the binary dictionary on
+ * the native side.
+ */
+ public void clearFusionDictionary() {
+ mFusionDictionary = new FusionDictionary(new Node(),
+ new FusionDictionary.DictionaryOptions(new HashMap<String, String>(), false,
+ false));
+ }
+
+ /**
+ * Adds a word unigram to the fusion dictionary. Call updateBinaryDictionary when all changes
+ * are done to update the binary dictionary.
+ */
+ // TODO: Create "cache dictionary" to cache fresh words for frequently updated dictionaries,
+ // considering performance regression.
+ protected void addWord(final String word, final String shortcutTarget, final int frequency) {
+ if (shortcutTarget == null) {
+ mFusionDictionary.add(word, frequency, null);
+ } else {
+ // TODO: Do this in the subclass, with this class taking an arraylist.
+ final ArrayList<WeightedString> shortcutTargets = new ArrayList<WeightedString>();
+ shortcutTargets.add(new WeightedString(shortcutTarget, frequency));
+ mFusionDictionary.add(word, frequency, shortcutTargets);
+ }
+ }
+
+ /**
+ * Sets a word bigram in the fusion dictionary. Call updateBinaryDictionary when all changes are
+ * done to update the binary dictionary.
+ */
+ // TODO: Create "cache dictionary" to cache fresh bigrams for frequently updated dictionaries,
+ // considering performance regression.
+ protected void setBigram(final String prevWord, final String word, final int frequency) {
+ mFusionDictionary.setBigram(prevWord, word, frequency);
+ }
+
+ @Override
+ public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
+ final WordCallback callback, final ProximityInfo proximityInfo) {
+ asyncReloadDictionaryIfRequired();
+ getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ }
+
+ protected final void getWordsInner(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final WordCallback callback,
+ final ProximityInfo proximityInfo) {
+ // Ensure that there are no concurrent calls to getWords. If there are, do nothing and
+ // return.
+ if (mLocalDictionaryController.tryLock()) {
+ try {
+ if (mBinaryDictionary != null) {
+ mBinaryDictionary.getWords(codes, prevWordForBigrams, callback, proximityInfo);
+ }
+ } finally {
+ mLocalDictionaryController.unlock();
+ }
+ }
+ }
+
+ @Override
+ public void getBigrams(final WordComposer codes, final CharSequence previousWord,
+ final WordCallback callback) {
+ asyncReloadDictionaryIfRequired();
+ getBigramsInner(codes, previousWord, callback);
+ }
+
+ protected void getBigramsInner(final WordComposer codes, final CharSequence previousWord,
+ final WordCallback callback) {
+ if (mLocalDictionaryController.tryLock()) {
+ try {
+ if (mBinaryDictionary != null) {
+ mBinaryDictionary.getBigrams(codes, previousWord, callback);
+ }
+ } finally {
+ mLocalDictionaryController.unlock();
+ }
+ }
+ }
+
+ @Override
+ public boolean isValidWord(final CharSequence word) {
+ asyncReloadDictionaryIfRequired();
+ return isValidWordInner(word);
+ }
+
+ protected boolean isValidWordInner(final CharSequence word) {
+ if (mLocalDictionaryController.tryLock()) {
+ try {
+ return isValidWordLocked(word);
+ } finally {
+ mLocalDictionaryController.unlock();
+ }
+ }
+ return false;
+ }
+
+ protected boolean isValidWordLocked(final CharSequence word) {
+ if (mBinaryDictionary == null) return false;
+ return mBinaryDictionary.isValidWord(word);
+ }
+
+ protected boolean isValidBigram(final CharSequence word1, final CharSequence word2) {
+ if (mBinaryDictionary == null) return false;
+ return mBinaryDictionary.isValidBigram(word1, word2);
+ }
+
+ protected boolean isValidBigramInner(final CharSequence word1, final CharSequence word2) {
+ if (mLocalDictionaryController.tryLock()) {
+ try {
+ return isValidBigramLocked(word1, word2);
+ } finally {
+ mLocalDictionaryController.unlock();
+ }
+ }
+ return false;
+ }
+
+ protected boolean isValidBigramLocked(final CharSequence word1, final CharSequence word2) {
+ if (mBinaryDictionary == null) return false;
+ return mBinaryDictionary.isValidBigram(word1, word2);
+ }
+
+ /**
+ * Load the current binary dictionary from internal storage in a background thread. If no binary
+ * dictionary exists, this method will generate one.
+ */
+ protected void loadDictionary() {
+ mLocalDictionaryController.mLastUpdateRequestTime = SystemClock.uptimeMillis();
+ asyncReloadDictionaryIfRequired();
+ }
+
+ /**
+ * Loads the current binary dictionary from internal storage. Assumes the dictionary file
+ * exists.
+ */
+ protected void loadBinaryDictionary() {
+ if (DEBUG) {
+ Log.d(TAG, "Loading binary dictionary: " + mFilename + " request="
+ + mSharedDictionaryController.mLastUpdateRequestTime + " update="
+ + mSharedDictionaryController.mLastUpdateTime);
+ }
+
+ final File file = new File(mContext.getFilesDir(), mFilename);
+ final String filename = file.getAbsolutePath();
+ final long length = file.length();
+
+ // Build the new binary dictionary
+ final BinaryDictionary newBinaryDictionary =
+ new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */,
+ null);
+
+ if (mBinaryDictionary != null) {
+ // Ensure all threads accessing the current dictionary have finished before swapping in
+ // the new one.
+ final BinaryDictionary oldBinaryDictionary = mBinaryDictionary;
+ mLocalDictionaryController.lock();
+ mBinaryDictionary = newBinaryDictionary;
+ mLocalDictionaryController.unlock();
+ oldBinaryDictionary.close();
+ } else {
+ mBinaryDictionary = newBinaryDictionary;
+ }
+ }
+
+ /**
+ * Generates and writes a new binary dictionary based on the contents of the fusion dictionary.
+ */
+ private void generateBinaryDictionary() {
+ if (DEBUG) {
+ Log.d(TAG, "Generating binary dictionary: " + mFilename + " request="
+ + mSharedDictionaryController.mLastUpdateRequestTime + " update="
+ + mSharedDictionaryController.mLastUpdateTime);
+ }
+
+ loadDictionaryAsync();
+
+ final String tempFileName = mFilename + ".temp";
+ final File file = new File(mContext.getFilesDir(), mFilename);
+ final File tempFile = new File(mContext.getFilesDir(), tempFileName);
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(tempFile);
+ BinaryDictInputOutput.writeDictionaryBinary(out, mFusionDictionary, 1);
+ out.flush();
+ out.close();
+ tempFile.renameTo(file);
+ clearFusionDictionary();
+ } catch (IOException e) {
+ Log.e(TAG, "IO exception while writing file: " + e);
+ } catch (UnsupportedFormatException e) {
+ Log.e(TAG, "Unsupported format: " + e);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * Marks that the dictionary is out of date and requires a reload.
+ *
+ * @param requiresRebuild Indicates that the source dictionary content has changed and a rebuild
+ * of the binary file is required. If not true, the next reload process will only read
+ * the current binary dictionary from file.
+ */
+ protected void setRequiresReload(final boolean requiresRebuild) {
+ final long time = SystemClock.uptimeMillis();
+ mLocalDictionaryController.mLastUpdateRequestTime = time;
+ mSharedDictionaryController.mLastUpdateRequestTime = time;
+ if (DEBUG) {
+ Log.d(TAG, "Reload request: " + mFilename + ": request=" + time + " update="
+ + mSharedDictionaryController.mLastUpdateTime);
+ }
+ }
+
+ /**
+ * Reloads the dictionary if required. Reload will occur asynchronously in a separate thread.
+ */
+ void asyncReloadDictionaryIfRequired() {
+ if (!isReloadRequired()) return;
+ if (DEBUG) {
+ Log.d(TAG, "Starting AsyncReloadDictionaryTask: " + mFilename);
+ }
+ new AsyncReloadDictionaryTask().start();
+ }
+
+ /**
+ * Reloads the dictionary if required.
+ */
+ protected final void syncReloadDictionaryIfRequired() {
+ if (!isReloadRequired()) return;
+ syncReloadDictionaryInternal();
+ }
+
+ /**
+ * Returns whether a dictionary reload is required.
+ */
+ private boolean isReloadRequired() {
+ return mBinaryDictionary == null || mLocalDictionaryController.isOutOfDate();
+ }
+
+ /**
+ * Reloads the dictionary. Access is controlled on a per dictionary file basis and supports
+ * concurrent calls from multiple instances that share the same dictionary file.
+ */
+ private final void syncReloadDictionaryInternal() {
+ // Ensure that only one thread attempts to read or write to the shared binary dictionary
+ // file at the same time.
+ mSharedDictionaryController.lock();
+ try {
+ final long time = SystemClock.uptimeMillis();
+ final boolean dictionaryFileExists = dictionaryFileExists();
+ if (mSharedDictionaryController.isOutOfDate() || !dictionaryFileExists) {
+ // If the shared dictionary file does not exist or is out of date, the first
+ // instance that acquires the lock will generate a new one.
+ if (hasContentChanged() || !dictionaryFileExists) {
+ // If the source content has changed or the dictionary does not exist, rebuild
+ // the binary dictionary. Empty dictionaries are supported (in the case where
+ // loadDictionaryAsync() adds nothing) in order to provide a uniform framework.
+ mSharedDictionaryController.mLastUpdateTime = time;
+ generateBinaryDictionary();
+ loadBinaryDictionary();
+ } else {
+ // If not, the reload request was unnecessary so revert LastUpdateRequestTime
+ // to LastUpdateTime.
+ mSharedDictionaryController.mLastUpdateRequestTime =
+ mSharedDictionaryController.mLastUpdateTime;
+ }
+ } else if (mBinaryDictionary == null || mLocalDictionaryController.mLastUpdateTime
+ < mSharedDictionaryController.mLastUpdateTime) {
+ // Otherwise, if the local dictionary is older than the shared dictionary, load the
+ // shared dictionary.
+ loadBinaryDictionary();
+ }
+ mLocalDictionaryController.mLastUpdateTime = time;
+ } finally {
+ mSharedDictionaryController.unlock();
+ }
+ }
+
+ // TODO: cache the file's existence so that we avoid doing a disk access each time.
+ private boolean dictionaryFileExists() {
+ final File file = new File(mContext.getFilesDir(), mFilename);
+ return file.exists();
+ }
+
+ /**
+ * Thread class for asynchronously reloading and rewriting the binary dictionary.
+ */
+ private class AsyncReloadDictionaryTask extends Thread {
+ @Override
+ public void run() {
+ syncReloadDictionaryInternal();
+ }
+ }
+
+ /**
+ * Lock for controlling access to a given binary dictionary and for tracking whether the
+ * dictionary is out of date. Can be shared across multiple dictionary instances that access the
+ * same filename.
+ */
+ private static class DictionaryController extends ReentrantLock {
+ private volatile long mLastUpdateTime = 0;
+ private volatile long mLastUpdateRequestTime = 0;
+
+ private boolean isOutOfDate() {
+ return (mLastUpdateRequestTime > mLastUpdateTime);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index 97a4a1816..f5886aa12 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -17,10 +17,14 @@
package com.android.inputmethod.latin;
import android.content.Context;
-import android.os.AsyncTask;
+import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.UserHistoryForgettingCurveUtils.ForgettingCurveParams;
+import java.util.ArrayList;
import java.util.LinkedList;
/**
@@ -28,17 +32,12 @@ import java.util.LinkedList;
* be searched for suggestions and valid words.
*/
public class ExpandableDictionary extends Dictionary {
- /**
- * There is difference between what java and native code can handle.
- * It uses 32 because Java stack overflows when greater value is used.
- */
- protected static final int MAX_WORD_LENGTH = 32;
// Bigram frequency is a fixed point number with 1 meaning 1.2 and 255 meaning 1.8.
protected static final int BIGRAM_MAX_FREQUENCY = 255;
private Context mContext;
- private char[] mWordBuilder = new char[MAX_WORD_LENGTH];
+ private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH];
private int mDicTypeId;
private int mMaxDepth;
private int mInputLength;
@@ -51,11 +50,14 @@ public class ExpandableDictionary extends Dictionary {
private Object mUpdatingLock = new Object();
private static class Node {
+ Node() {}
char mCode;
int mFrequency;
boolean mTerminal;
Node mParent;
NodeArray mChildren;
+ ArrayList<char[]> mShortcutTargets;
+ boolean mShortcutOnly;
LinkedList<NextWord> mNGrams; // Supports ngram
}
@@ -80,31 +82,72 @@ public class ExpandableDictionary extends Dictionary {
}
}
- private static class NextWord {
- public final Node mWord;
- private int mFrequency;
+ protected interface NextWord {
+ public Node getWordNode();
+ public int getFrequency();
+ public ForgettingCurveParams getFcParams();
+ public int notifyTypedAgainAndGetFrequency();
+ }
- public NextWord(Node word, int frequency) {
+ private static 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;
}
- public int setFrequency(int freq) {
- mFrequency = freq;
- return mFrequency;
+ @Override
+ public ForgettingCurveParams getFcParams() {
+ return null;
}
- public int addFrequency(int add) {
- mFrequency += add;
- if (mFrequency > BIGRAM_MAX_FREQUENCY) mFrequency = BIGRAM_MAX_FREQUENCY;
+ @Override
+ public int notifyTypedAgainAndGetFrequency() {
return mFrequency;
}
}
+ private static 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;
@@ -112,7 +155,7 @@ public class ExpandableDictionary extends Dictionary {
public ExpandableDictionary(Context context, int dicTypeId) {
mContext = context;
clearDictionary();
- mCodes = new int[MAX_WORD_LENGTH][];
+ mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][];
mDicTypeId = dicTypeId;
}
@@ -126,7 +169,7 @@ public class ExpandableDictionary extends Dictionary {
if (!mUpdatingDictionary) {
mUpdatingDictionary = true;
mRequiresReload = false;
- new LoadDictionaryTask().execute();
+ new LoadDictionaryTask().start();
}
}
@@ -150,38 +193,50 @@ public class ExpandableDictionary extends Dictionary {
}
public int getMaxWordLength() {
- return MAX_WORD_LENGTH;
+ return BinaryDictionary.MAX_WORD_LENGTH;
}
- public void addWord(String word, int frequency) {
- addWordRec(mRoots, word, 0, frequency, null);
+ public void addWord(final String word, final String shortcutTarget, final int frequency) {
+ if (word.length() >= BinaryDictionary.MAX_WORD_LENGTH) {
+ return;
+ }
+ addWordRec(mRoots, word, 0, shortcutTarget, frequency, null);
}
private void addWordRec(NodeArray children, final String word, final int depth,
- final int frequency, Node parentNode) {
+ final String shortcutTarget, final int frequency, 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;
- boolean found = false;
for (int i = 0; i < childrenLength; i++) {
- childNode = children.mData[i];
- if (childNode.mCode == c) {
- found = true;
+ final Node node = children.mData[i];
+ if (node.mCode == c) {
+ childNode = node;
break;
}
}
- if (!found) {
+ 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) {
+ if (wordLength == depth + 1 && shortcutTarget != null) {
// Terminate this word
childNode.mTerminal = true;
+ if (isShortcutOnly) {
+ if (null == childNode.mShortcutTargets) {
+ childNode.mShortcutTargets = new ArrayList<char[]>();
+ }
+ childNode.mShortcutTargets.add(shortcutTarget.toCharArray());
+ } else {
+ childNode.mShortcutOnly = false;
+ }
childNode.mFrequency = Math.max(frequency, childNode.mFrequency);
if (childNode.mFrequency > 255) childNode.mFrequency = 255;
return;
@@ -189,29 +244,51 @@ public class ExpandableDictionary extends Dictionary {
if (childNode.mChildren == null) {
childNode.mChildren = new NodeArray();
}
- addWordRec(childNode.mChildren, word, depth + 1, frequency, childNode);
+ addWordRec(childNode.mChildren, word, depth + 1, shortcutTarget, frequency, childNode);
}
@Override
- public void getWords(final WordComposer codes, final WordCallback callback) {
+ public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
+ final WordCallback callback, final ProximityInfo proximityInfo) {
synchronized (mUpdatingLock) {
// If we need to update, start off a background task
if (mRequiresReload) startDictionaryLoadingTaskLocked();
// Currently updating contacts, don't return any results.
if (mUpdatingDictionary) return;
}
+ if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) {
+ return;
+ }
+ final ArrayList<SuggestedWordInfo> suggestions =
+ getWordsInner(codes, prevWordForBigrams, proximityInfo);
+ Utils.addAllSuggestions(mDicTypeId, Dictionary.UNIGRAM, suggestions, callback);
+ }
+ protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
mInputLength = codes.size();
if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
+ final int[] xCoordinates = codes.getXCoordinates();
+ final int[] yCoordinates = codes.getYCoordinates();
// Cache the codes so that we don't have to lookup an array list
for (int i = 0; i < mInputLength; i++) {
- mCodes[i] = codes.getCodesAt(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] : WordComposer.NOT_A_COORDINATE;
+ final int y = xCoordinates != null && i < yCoordinates.length ?
+ yCoordinates[i] : WordComposer.NOT_A_COORDINATE;
+ proximityInfo.fillArrayWithNearestKeyCodes(x, y, codes.getCodeAt(i), mCodes[i]);
}
mMaxDepth = mInputLength * 3;
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback);
+ getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, suggestions);
for (int i = 0; i < mInputLength; i++) {
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, callback);
+ getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, suggestions);
}
+ return suggestions;
}
@Override
@@ -221,8 +298,35 @@ public class ExpandableDictionary extends Dictionary {
if (mRequiresReload) startDictionaryLoadingTaskLocked();
if (mUpdatingDictionary) return false;
}
- final int freq = getWordFrequency(word);
- return freq > -1;
+ 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;
+ }
+
+ protected boolean removeBigram(String word1, String word2) {
+ // Refer to addOrSetBigram() about word1.toLowerCase()
+ final Node firstWord = searchWord(mRoots, word1.toLowerCase(), 0, null);
+ final Node secondWord = searchWord(mRoots, word2, 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);
}
/**
@@ -230,10 +334,27 @@ public class ExpandableDictionary extends Dictionary {
*/
protected int getWordFrequency(CharSequence word) {
// Case-sensitive search
- Node node = searchNode(mRoots, word, 0, word.length());
+ final Node node = searchNode(mRoots, word, 0, word.length());
return (node == null) ? -1 : node.mFrequency;
}
+ protected NextWord getBigramWord(String word1, String word2) {
+ // Refer to addOrSetBigram() about word1.toLowerCase()
+ final Node firstWord = searchWord(mRoots, word1.toLowerCase(), 0, null);
+ final Node secondWord = searchWord(mRoots, word2, 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(int freq, int snr, 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
@@ -245,6 +366,39 @@ public class ExpandableDictionary extends Dictionary {
}
/**
+ * 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));
+ 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));
+ 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
@@ -261,21 +415,21 @@ public class ExpandableDictionary extends Dictionary {
* case we skip over some punctuations such as apostrophe in the traversal. That is, if you type
* "wouldve", it could be matching "would've", so the depth will be one more than the
* inputIndex
- * @param callback the callback class for adding a word
+ * @param suggestions the list in which to add suggestions
*/
// TODO: Share this routine with the native code for BinaryDictionary
protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word,
- final int depth, boolean completion, int snr, int inputIndex, int skipPos,
- WordCallback callback) {
+ final int depth, final boolean completion, int snr, int inputIndex, 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;
}
- int[] currentChars = null;
+ final int[] currentChars;
if (codeSize <= inputIndex) {
- completion = true;
+ currentChars = null;
} else {
currentChars = mCodes[inputIndex];
}
@@ -287,7 +441,7 @@ public class ExpandableDictionary extends Dictionary {
final boolean terminal = node.mTerminal;
final NodeArray children = node.mChildren;
final int freq = node.mFrequency;
- if (completion) {
+ if (completion || currentChars == null) {
word[depth] = c;
if (terminal) {
final int finalFreq;
@@ -296,14 +450,14 @@ public class ExpandableDictionary extends Dictionary {
} else {
finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength);
}
- if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId,
- DataType.UNIGRAM)) {
+ 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, completion, snr, inputIndex,
- skipPos, callback);
+ getWordsRec(children, codes, word, depth + 1, true, snr, inputIndex,
+ skipPos, suggestions);
}
} else if ((c == Keyboard.CODE_SINGLE_QUOTE
&& currentChars[0] != Keyboard.CODE_SINGLE_QUOTE) || depth == skipPos) {
@@ -311,15 +465,15 @@ public class ExpandableDictionary extends Dictionary {
word[depth] = c;
if (children != null) {
getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
- skipPos, callback);
+ skipPos, suggestions);
}
} else {
// Don't use alternatives if we're looking for missing characters
- final int alternativesSize = skipPos >= 0? 1 : currentChars.length;
+ 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 == -1) {
+ if (currentChar == KeyDetector.NOT_A_CODE) {
break;
}
if (currentChar == lowerC || currentChar == c) {
@@ -327,29 +481,29 @@ public class ExpandableDictionary extends Dictionary {
if (codeSize == inputIndex + 1) {
if (terminal) {
- if (INCLUDE_TYPED_WORD_IF_VALID
- || !same(word, depth + 1, codes.getTypedWord())) {
- final int finalFreq;
- if (skipPos < 0) {
- finalFreq = freq * snr * addedAttenuation
- * FULL_WORD_SCORE_MULTIPLIER;
- } else {
- finalFreq = computeSkippedWordFinalFreq(freq,
- snr * addedAttenuation, mInputLength);
- }
- callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId,
- DataType.UNIGRAM);
+ 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, callback);
+ skipPos, suggestions);
}
} else if (children != null) {
getWordsRec(children, codes, word, depth + 1,
false, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
+ skipPos, suggestions);
}
}
}
@@ -357,43 +511,47 @@ public class ExpandableDictionary extends Dictionary {
}
}
- protected int setBigram(String word1, String word2, int frequency) {
- return addOrSetBigram(word1, word2, frequency, false);
+ public int setBigramAndGetFrequency(String word1, String word2, int frequency) {
+ return setBigramAndGetFrequency(word1, word2, frequency, null /* unused */);
}
- protected int addBigram(String word1, String word2, int frequency) {
- return addOrSetBigram(word1, word2, frequency, true);
+ public int setBigramAndGetFrequency(String word1, String word2, ForgettingCurveParams fcp) {
+ return setBigramAndGetFrequency(word1, word2, 0 /* unused */, fcp);
}
/**
* Adds bigrams to the in-memory trie structure that is being used to retrieve any word
+ * @param word1 the first word of this bigram
+ * @param word2 the second word of this bigram
* @param frequency frequency for this bigram
- * @param addFrequency if true, it adds to current frequency, else it overwrites the old value
- * @return returns the final frequency
+ * @param fcp an instance of ForgettingCurveParams to use for decay policy
+ * @return returns the final bigram frequency
*/
- private int addOrSetBigram(String word1, String word2, int frequency, boolean addFrequency) {
+ private int setBigramAndGetFrequency(
+ String word1, String word2, int frequency, ForgettingCurveParams fcp) {
// 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.
Node firstWord = searchWord(mRoots, word1.toLowerCase(), 0, null);
Node secondWord = searchWord(mRoots, word2, 0, null);
- LinkedList<NextWord> bigram = firstWord.mNGrams;
- if (bigram == null || bigram.size() == 0) {
+ LinkedList<NextWord> bigrams = firstWord.mNGrams;
+ if (bigrams == null || bigrams.size() == 0) {
firstWord.mNGrams = new LinkedList<NextWord>();
- bigram = firstWord.mNGrams;
+ bigrams = firstWord.mNGrams;
} else {
- for (NextWord nw : bigram) {
- if (nw.mWord == secondWord) {
- if (addFrequency) {
- return nw.addFrequency(frequency);
- } else {
- return nw.setFrequency(frequency);
- }
+ for (NextWord nw : bigrams) {
+ if (nw.getWordNode() == secondWord) {
+ return nw.notifyTypedAgainAndGetFrequency();
}
}
}
- firstWord.mNGrams.add(new NextWord(secondWord, frequency));
+ if (fcp != null) {
+ // history
+ firstWord.mNGrams.add(new NextHistoryWord(secondWord, fcp));
+ } else {
+ firstWord.mNGrams.add(new NextStaticWord(secondWord, frequency));
+ }
return frequency;
}
@@ -407,15 +565,14 @@ public class ExpandableDictionary extends Dictionary {
// Does children have the current character?
final int childrenLength = children.mLength;
Node childNode = null;
- boolean found = false;
for (int i = 0; i < childrenLength; i++) {
- childNode = children.mData[i];
- if (childNode.mCode == c) {
- found = true;
+ final Node node = children.mData[i];
+ if (node.mCode == c) {
+ childNode = node;
break;
}
}
- if (!found) {
+ if (childNode == null) {
childNode = new Node();
childNode.mCode = c;
childNode.mParent = parentNode;
@@ -462,7 +619,7 @@ public class ExpandableDictionary extends Dictionary {
}
/**
- * Used only for testing purposes
+ * Used for testing purposes and in the spell checker
* This function will wait for loading from database to be done
*/
void waitForDictionaryLoading() {
@@ -475,8 +632,13 @@ public class ExpandableDictionary extends Dictionary {
}
}
+ protected final void blockingReloadDictionaryIfRequired() {
+ reloadDictionaryIfRequired();
+ waitForDictionaryLoading();
+ }
+
// Local to reverseLookUp, but do not allocate each time.
- private final char[] mLookedUpString = new char[MAX_WORD_LENGTH];
+ private final char[] mLookedUpString = new char[BinaryDictionary.MAX_WORD_LENGTH];
/**
* reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
@@ -488,17 +650,19 @@ public class ExpandableDictionary extends Dictionary {
Node node;
int freq;
for (NextWord nextWord : terminalNodes) {
- node = nextWord.mWord;
+ node = nextWord.getWordNode();
freq = nextWord.getFrequency();
- int index = MAX_WORD_LENGTH;
+ int index = BinaryDictionary.MAX_WORD_LENGTH;
do {
--index;
mLookedUpString[index] = node.mCode;
node = node.mParent;
} while (node != null);
- callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId,
- DataType.BIGRAM);
+ if (freq >= 0) {
+ callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index,
+ freq, mDicTypeId, Dictionary.BIGRAM);
+ }
}
}
@@ -539,14 +703,14 @@ public class ExpandableDictionary extends Dictionary {
mRoots = new NodeArray();
}
- private class LoadDictionaryTask extends AsyncTask<Void, Void, Void> {
+ private class LoadDictionaryTask extends Thread {
+ LoadDictionaryTask() {}
@Override
- protected Void doInBackground(Void... v) {
+ public void run() {
loadDictionaryAsync();
synchronized (mUpdatingLock) {
mUpdatingDictionary = false;
}
- return null;
}
}
@@ -570,167 +734,167 @@ public class ExpandableDictionary extends Dictionary {
* is combined.
*/
private static final char BASE_CHARS[] = {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
- 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
- 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
- 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
- 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
- 0x0020, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
- 0x0020, 0x00a9, 0x0061, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0020,
- 0x00b0, 0x00b1, 0x0032, 0x0033, 0x0020, 0x03bc, 0x00b6, 0x00b7,
- 0x0020, 0x0031, 0x006f, 0x00bb, 0x0031, 0x0031, 0x0033, 0x00bf,
- 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00c6, 0x0043,
- 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049,
- 0x00d0, 0x004e, 0x004f, 0x004f, 0x004f, 0x004f, 0x004f, 0x00d7,
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x0020, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x0020, 0x00a9, 0x0061, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0020,
+ 0x00b0, 0x00b1, 0x0032, 0x0033, 0x0020, 0x03bc, 0x00b6, 0x00b7,
+ 0x0020, 0x0031, 0x006f, 0x00bb, 0x0031, 0x0031, 0x0033, 0x00bf,
+ 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00c6, 0x0043,
+ 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049,
+ 0x00d0, 0x004e, 0x004f, 0x004f, 0x004f, 0x004f, 0x004f, 0x00d7,
0x004f, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00de, 0x0073, // Manually changed d8 to 4f
// Manually changed df to 73
- 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00e6, 0x0063,
- 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069,
- 0x00f0, 0x006e, 0x006f, 0x006f, 0x006f, 0x006f, 0x006f, 0x00f7,
+ 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00e6, 0x0063,
+ 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069,
+ 0x00f0, 0x006e, 0x006f, 0x006f, 0x006f, 0x006f, 0x006f, 0x00f7,
0x006f, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0x00fe, 0x0079, // Manually changed f8 to 6f
- 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063,
- 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064,
- 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065,
- 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067,
- 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127,
- 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069,
- 0x0049, 0x0131, 0x0049, 0x0069, 0x004a, 0x006a, 0x004b, 0x006b,
- 0x0138, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c,
- 0x006c, 0x0141, 0x0142, 0x004e, 0x006e, 0x004e, 0x006e, 0x004e,
- 0x006e, 0x02bc, 0x014a, 0x014b, 0x004f, 0x006f, 0x004f, 0x006f,
- 0x004f, 0x006f, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072,
- 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073,
- 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167,
- 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075,
- 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079,
- 0x0059, 0x005a, 0x007a, 0x005a, 0x007a, 0x005a, 0x007a, 0x0073,
- 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187,
- 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d, 0x018e, 0x018f,
- 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,
- 0x0198, 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, 0x019f,
- 0x004f, 0x006f, 0x01a2, 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7,
- 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x0055,
- 0x0075, 0x01b1, 0x01b2, 0x01b3, 0x01b4, 0x01b5, 0x01b6, 0x01b7,
- 0x01b8, 0x01b9, 0x01ba, 0x01bb, 0x01bc, 0x01bd, 0x01be, 0x01bf,
- 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x0044, 0x0044, 0x0064, 0x004c,
- 0x004c, 0x006c, 0x004e, 0x004e, 0x006e, 0x0041, 0x0061, 0x0049,
- 0x0069, 0x004f, 0x006f, 0x0055, 0x0075, 0x00dc, 0x00fc, 0x00dc,
- 0x00fc, 0x00dc, 0x00fc, 0x00dc, 0x00fc, 0x01dd, 0x00c4, 0x00e4,
- 0x0226, 0x0227, 0x00c6, 0x00e6, 0x01e4, 0x01e5, 0x0047, 0x0067,
- 0x004b, 0x006b, 0x004f, 0x006f, 0x01ea, 0x01eb, 0x01b7, 0x0292,
- 0x006a, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01f6, 0x01f7,
- 0x004e, 0x006e, 0x00c5, 0x00e5, 0x00c6, 0x00e6, 0x00d8, 0x00f8,
- 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065,
- 0x0049, 0x0069, 0x0049, 0x0069, 0x004f, 0x006f, 0x004f, 0x006f,
- 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075,
- 0x0053, 0x0073, 0x0054, 0x0074, 0x021c, 0x021d, 0x0048, 0x0068,
- 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061,
- 0x0045, 0x0065, 0x00d6, 0x00f6, 0x00d5, 0x00f5, 0x004f, 0x006f,
- 0x022e, 0x022f, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237,
- 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f,
- 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,
- 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f,
- 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257,
- 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f,
- 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267,
- 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f,
- 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277,
- 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f,
- 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287,
- 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f,
- 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
- 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
- 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
- 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af,
- 0x0068, 0x0266, 0x006a, 0x0072, 0x0279, 0x027b, 0x0281, 0x0077,
- 0x0079, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf,
- 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7,
- 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf,
- 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7,
- 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02de, 0x02df,
- 0x0263, 0x006c, 0x0073, 0x0078, 0x0295, 0x02e5, 0x02e6, 0x02e7,
- 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef,
- 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7,
- 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff,
- 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
- 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f,
- 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
- 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f,
- 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
- 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f,
- 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
- 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f,
- 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347,
- 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f,
- 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
- 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f,
- 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
- 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
- 0x0370, 0x0371, 0x0372, 0x0373, 0x02b9, 0x0375, 0x0376, 0x0377,
- 0x0378, 0x0379, 0x0020, 0x037b, 0x037c, 0x037d, 0x003b, 0x037f,
- 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00a8, 0x0391, 0x00b7,
- 0x0395, 0x0397, 0x0399, 0x038b, 0x039f, 0x038d, 0x03a5, 0x03a9,
- 0x03ca, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
- 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
- 0x03a8, 0x03a9, 0x0399, 0x03a5, 0x03b1, 0x03b5, 0x03b7, 0x03b9,
- 0x03cb, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
- 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
- 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
- 0x03c8, 0x03c9, 0x03b9, 0x03c5, 0x03bf, 0x03c5, 0x03c9, 0x03cf,
- 0x03b2, 0x03b8, 0x03a5, 0x03d2, 0x03d2, 0x03c6, 0x03c0, 0x03d7,
- 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df,
- 0x03e0, 0x03e1, 0x03e2, 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x03e7,
- 0x03e8, 0x03e9, 0x03ea, 0x03eb, 0x03ec, 0x03ed, 0x03ee, 0x03ef,
- 0x03ba, 0x03c1, 0x03c2, 0x03f3, 0x0398, 0x03b5, 0x03f6, 0x03f7,
- 0x03f8, 0x03a3, 0x03fa, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff,
- 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406,
- 0x0408, 0x0409, 0x040a, 0x040b, 0x041a, 0x0418, 0x0423, 0x040f,
- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
- 0x0418, 0x0418, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
- 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
- 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
- 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
- 0x0438, 0x0438, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
- 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
- 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
- 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456,
- 0x0458, 0x0459, 0x045a, 0x045b, 0x043a, 0x0438, 0x0443, 0x045f,
- 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467,
- 0x0468, 0x0469, 0x046a, 0x046b, 0x046c, 0x046d, 0x046e, 0x046f,
- 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475,
- 0x0478, 0x0479, 0x047a, 0x047b, 0x047c, 0x047d, 0x047e, 0x047f,
- 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
- 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
- 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497,
- 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x049f,
- 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7,
- 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
- 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7,
- 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x04be, 0x04bf,
- 0x04c0, 0x0416, 0x0436, 0x04c3, 0x04c4, 0x04c5, 0x04c6, 0x04c7,
- 0x04c8, 0x04c9, 0x04ca, 0x04cb, 0x04cc, 0x04cd, 0x04ce, 0x04cf,
- 0x0410, 0x0430, 0x0410, 0x0430, 0x04d4, 0x04d5, 0x0415, 0x0435,
- 0x04d8, 0x04d9, 0x04d8, 0x04d9, 0x0416, 0x0436, 0x0417, 0x0437,
- 0x04e0, 0x04e1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041e, 0x043e,
- 0x04e8, 0x04e9, 0x04e8, 0x04e9, 0x042d, 0x044d, 0x0423, 0x0443,
- 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04f6, 0x04f7,
- 0x042b, 0x044b, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff,
+ 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063,
+ 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064,
+ 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065,
+ 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067,
+ 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127,
+ 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069,
+ 0x0049, 0x0131, 0x0049, 0x0069, 0x004a, 0x006a, 0x004b, 0x006b,
+ 0x0138, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c,
+ 0x006c, 0x0141, 0x0142, 0x004e, 0x006e, 0x004e, 0x006e, 0x004e,
+ 0x006e, 0x02bc, 0x014a, 0x014b, 0x004f, 0x006f, 0x004f, 0x006f,
+ 0x004f, 0x006f, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072,
+ 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073,
+ 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167,
+ 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075,
+ 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079,
+ 0x0059, 0x005a, 0x007a, 0x005a, 0x007a, 0x005a, 0x007a, 0x0073,
+ 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187,
+ 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d, 0x018e, 0x018f,
+ 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,
+ 0x0198, 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, 0x019f,
+ 0x004f, 0x006f, 0x01a2, 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7,
+ 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x0055,
+ 0x0075, 0x01b1, 0x01b2, 0x01b3, 0x01b4, 0x01b5, 0x01b6, 0x01b7,
+ 0x01b8, 0x01b9, 0x01ba, 0x01bb, 0x01bc, 0x01bd, 0x01be, 0x01bf,
+ 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x0044, 0x0044, 0x0064, 0x004c,
+ 0x004c, 0x006c, 0x004e, 0x004e, 0x006e, 0x0041, 0x0061, 0x0049,
+ 0x0069, 0x004f, 0x006f, 0x0055, 0x0075, 0x00dc, 0x00fc, 0x00dc,
+ 0x00fc, 0x00dc, 0x00fc, 0x00dc, 0x00fc, 0x01dd, 0x00c4, 0x00e4,
+ 0x0226, 0x0227, 0x00c6, 0x00e6, 0x01e4, 0x01e5, 0x0047, 0x0067,
+ 0x004b, 0x006b, 0x004f, 0x006f, 0x01ea, 0x01eb, 0x01b7, 0x0292,
+ 0x006a, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01f6, 0x01f7,
+ 0x004e, 0x006e, 0x00c5, 0x00e5, 0x00c6, 0x00e6, 0x00d8, 0x00f8,
+ 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065,
+ 0x0049, 0x0069, 0x0049, 0x0069, 0x004f, 0x006f, 0x004f, 0x006f,
+ 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075,
+ 0x0053, 0x0073, 0x0054, 0x0074, 0x021c, 0x021d, 0x0048, 0x0068,
+ 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061,
+ 0x0045, 0x0065, 0x00d6, 0x00f6, 0x00d5, 0x00f5, 0x004f, 0x006f,
+ 0x022e, 0x022f, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237,
+ 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f,
+ 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,
+ 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f,
+ 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257,
+ 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f,
+ 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267,
+ 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f,
+ 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277,
+ 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f,
+ 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287,
+ 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f,
+ 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
+ 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f,
+ 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
+ 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af,
+ 0x0068, 0x0266, 0x006a, 0x0072, 0x0279, 0x027b, 0x0281, 0x0077,
+ 0x0079, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf,
+ 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7,
+ 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf,
+ 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02de, 0x02df,
+ 0x0263, 0x006c, 0x0073, 0x0078, 0x0295, 0x02e5, 0x02e6, 0x02e7,
+ 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef,
+ 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7,
+ 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff,
+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+ 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f,
+ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+ 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f,
+ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+ 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f,
+ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+ 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f,
+ 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347,
+ 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f,
+ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+ 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f,
+ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+ 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
+ 0x0370, 0x0371, 0x0372, 0x0373, 0x02b9, 0x0375, 0x0376, 0x0377,
+ 0x0378, 0x0379, 0x0020, 0x037b, 0x037c, 0x037d, 0x003b, 0x037f,
+ 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00a8, 0x0391, 0x00b7,
+ 0x0395, 0x0397, 0x0399, 0x038b, 0x039f, 0x038d, 0x03a5, 0x03a9,
+ 0x03ca, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x0399, 0x03a5, 0x03b1, 0x03b5, 0x03b7, 0x03b9,
+ 0x03cb, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
+ 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
+ 0x03c8, 0x03c9, 0x03b9, 0x03c5, 0x03bf, 0x03c5, 0x03c9, 0x03cf,
+ 0x03b2, 0x03b8, 0x03a5, 0x03d2, 0x03d2, 0x03c6, 0x03c0, 0x03d7,
+ 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df,
+ 0x03e0, 0x03e1, 0x03e2, 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x03e7,
+ 0x03e8, 0x03e9, 0x03ea, 0x03eb, 0x03ec, 0x03ed, 0x03ee, 0x03ef,
+ 0x03ba, 0x03c1, 0x03c2, 0x03f3, 0x0398, 0x03b5, 0x03f6, 0x03f7,
+ 0x03f8, 0x03a3, 0x03fa, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff,
+ 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406,
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x041a, 0x0418, 0x0423, 0x040f,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0418, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0438, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
+ 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456,
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x043a, 0x0438, 0x0443, 0x045f,
+ 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467,
+ 0x0468, 0x0469, 0x046a, 0x046b, 0x046c, 0x046d, 0x046e, 0x046f,
+ 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475,
+ 0x0478, 0x0479, 0x047a, 0x047b, 0x047c, 0x047d, 0x047e, 0x047f,
+ 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+ 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
+ 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497,
+ 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x049f,
+ 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7,
+ 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
+ 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7,
+ 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x04be, 0x04bf,
+ 0x04c0, 0x0416, 0x0436, 0x04c3, 0x04c4, 0x04c5, 0x04c6, 0x04c7,
+ 0x04c8, 0x04c9, 0x04ca, 0x04cb, 0x04cc, 0x04cd, 0x04ce, 0x04cf,
+ 0x0410, 0x0430, 0x0410, 0x0430, 0x04d4, 0x04d5, 0x0415, 0x0435,
+ 0x04d8, 0x04d9, 0x04d8, 0x04d9, 0x0416, 0x0436, 0x0417, 0x0437,
+ 0x04e0, 0x04e1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041e, 0x043e,
+ 0x04e8, 0x04e9, 0x04e8, 0x04e9, 0x042d, 0x044d, 0x0423, 0x0443,
+ 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04f6, 0x04f7,
+ 0x042b, 0x044b, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff,
};
// generated with:
diff --git a/java/src/com/android/inputmethod/latin/FileTransforms.java b/java/src/com/android/inputmethod/latin/FileTransforms.java
new file mode 100644
index 000000000..80159521c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/FileTransforms.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPInputStream;
+
+public class FileTransforms {
+ public static OutputStream getCryptedStream(OutputStream out) {
+ // Crypt the stream.
+ return out;
+ }
+
+ public static InputStream getDecryptedStream(InputStream in) {
+ // Decrypt the stream.
+ return in;
+ }
+
+ public static InputStream getUncompressedStream(InputStream in) throws IOException {
+ return new GZIPInputStream(in);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Flag.java b/java/src/com/android/inputmethod/latin/Flag.java
deleted file mode 100644
index 3cb8f7e17..000000000
--- a/java/src/com/android/inputmethod/latin/Flag.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-public class Flag {
- public final String mName;
- public final int mResource;
- public final int mMask;
- public final int mSource;
-
- static private final int SOURCE_CONFIG = 1;
- static private final int SOURCE_EXTRAVALUE = 2;
-
- public Flag(int resourceId, int mask) {
- mName = null;
- mResource = resourceId;
- mSource = SOURCE_CONFIG;
- mMask = mask;
- }
-
- public Flag(String name, int mask) {
- mName = name;
- mResource = 0;
- mSource = SOURCE_EXTRAVALUE;
- mMask = mask;
- }
-
- // If context/switcher are null, set all related flags in flagArray to on.
- public static int initFlags(Flag[] flagArray, Context context, SubtypeSwitcher switcher) {
- int flags = 0;
- final Resources res = null == context ? null : context.getResources();
- for (Flag entry : flagArray) {
- switch (entry.mSource) {
- case Flag.SOURCE_CONFIG:
- if (res == null || res.getBoolean(entry.mResource))
- flags |= entry.mMask;
- break;
- case Flag.SOURCE_EXTRAVALUE:
- if (switcher == null ||
- switcher.currentSubtypeContainsExtraValueKey(entry.mName))
- flags |= entry.mMask;
- break;
- }
- }
- return flags;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/ImfUtils.java b/java/src/com/android/inputmethod/latin/ImfUtils.java
new file mode 100644
index 000000000..b882a4860
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ImfUtils.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
+
+import android.content.Context;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Utility class for Input Method Framework
+ */
+public class ImfUtils {
+ private ImfUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ private static InputMethodManager sInputMethodManager;
+
+ public static InputMethodManager getInputMethodManager(Context context) {
+ if (sInputMethodManager == null) {
+ sInputMethodManager = (InputMethodManager)context.getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ }
+ return sInputMethodManager;
+ }
+
+ private static InputMethodInfo sInputMethodInfoOfThisIme;
+
+ public static InputMethodInfo getInputMethodInfoOfThisIme(Context context) {
+ if (sInputMethodInfoOfThisIme == null) {
+ final InputMethodManager imm = getInputMethodManager(context);
+ final String packageName = context.getPackageName();
+ for (final InputMethodInfo imi : imm.getInputMethodList()) {
+ if (imi.getPackageName().equals(packageName))
+ return imi;
+ }
+ throw new RuntimeException("Can not find input method id for " + packageName);
+ }
+ return sInputMethodInfoOfThisIme;
+ }
+
+ public static String getInputMethodIdOfThisIme(Context context) {
+ return getInputMethodInfoOfThisIme(context).getId();
+ }
+
+ public static boolean checkIfSubtypeBelongsToThisImeAndEnabled(Context context,
+ InputMethodSubtype ims) {
+ final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
+ final InputMethodManager imm = getInputMethodManager(context);
+ // TODO: Cache all subtypes of this IME for optimization
+ final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(myImi, true);
+ for (final InputMethodSubtype subtype : subtypes) {
+ if (subtype.equals(ims)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean checkIfSubtypeBelongsToThisIme(Context context,
+ InputMethodSubtype ims) {
+ final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
+ final int count = myImi.getSubtypeCount();
+ for (int i = 0; i < count; i++) {
+ final InputMethodSubtype subtype = myImi.getSubtypeAt(i);
+ if (subtype.equals(ims)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean hasMultipleEnabledIMEsOrSubtypes(Context context,
+ final boolean shouldIncludeAuxiliarySubtypes) {
+ final InputMethodManager imm = getInputMethodManager(context);
+ final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
+ return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, enabledImis);
+ }
+
+ public static boolean hasMultipleEnabledSubtypesInThisIme(Context context,
+ final boolean shouldIncludeAuxiliarySubtypes) {
+ final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
+ final List<InputMethodInfo> imiList = Collections.singletonList(myImi);
+ return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, imiList);
+ }
+
+ private static boolean hasMultipleEnabledSubtypes(Context context,
+ final boolean shouldIncludeAuxiliarySubtypes, List<InputMethodInfo> imiList) {
+ final InputMethodManager imm = getInputMethodManager(context);
+
+ // Number of the filtered IMEs
+ int filteredImisCount = 0;
+
+ for (InputMethodInfo imi : imiList) {
+ // We can return true immediately after we find two or more filtered IMEs.
+ if (filteredImisCount > 1) return true;
+ final List<InputMethodSubtype> subtypes =
+ imm.getEnabledInputMethodSubtypeList(imi, true);
+ // IMEs that have no subtypes should be counted.
+ if (subtypes.isEmpty()) {
+ ++filteredImisCount;
+ continue;
+ }
+
+ int auxCount = 0;
+ for (InputMethodSubtype subtype : subtypes) {
+ if (subtype.isAuxiliary()) {
+ ++auxCount;
+ }
+ }
+ final int nonAuxCount = subtypes.size() - auxCount;
+
+ // IMEs that have one or more non-auxiliary subtypes should be counted.
+ // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
+ // subtypes should be counted as well.
+ if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
+ ++filteredImisCount;
+ continue;
+ }
+ }
+
+ if (filteredImisCount > 1) {
+ return true;
+ }
+ final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(null, true);
+ int keyboardCount = 0;
+ // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's
+ // both explicitly and implicitly enabled input method subtype.
+ // (The current IME should be LatinIME.)
+ for (InputMethodSubtype subtype : subtypes) {
+ if (KEYBOARD_MODE.equals(subtype.getMode())) {
+ ++keyboardCount;
+ }
+ }
+ return keyboardCount > 1;
+ }
+
+ public static InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(
+ Context context, String localeString, String keyboardLayoutSetName) {
+ final InputMethodInfo imi = getInputMethodInfoOfThisIme(context);
+ final int count = imi.getSubtypeCount();
+ for (int i = 0; i < count; i++) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ final String layoutName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
+ if (localeString.equals(subtype.getLocale())
+ && keyboardLayoutSetName.equals(layoutName)) {
+ return subtype;
+ }
+ }
+ return null;
+ }
+
+ public static void setAdditionalInputMethodSubtypes(Context context,
+ InputMethodSubtype[] subtypes) {
+ final InputMethodManager imm = getInputMethodManager(context);
+ final String imiId = getInputMethodIdOfThisIme(context);
+ imm.setAdditionalInputMethodSubtypes(imiId, subtypes);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
new file mode 100644
index 000000000..229ae2f3c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.InputType;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+
+/**
+ * Class to hold attributes of the input field.
+ */
+public class InputAttributes {
+ private final String TAG = InputAttributes.class.getSimpleName();
+
+ final public boolean mInputTypeNoAutoCorrect;
+ final public boolean mIsSettingsSuggestionStripOn;
+ final public boolean mApplicationSpecifiedCompletionOn;
+ final public int mEditorAction;
+
+ public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
+ final int inputType = null != editorInfo ? editorInfo.inputType : 0;
+ final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
+ if (inputClass != InputType.TYPE_CLASS_TEXT) {
+ // If we are not looking at a TYPE_CLASS_TEXT field, the following strange
+ // cases may arise, so we do a couple sanity checks for them. If it's a
+ // TYPE_CLASS_TEXT field, these special cases cannot happen, by construction
+ // of the flags.
+ if (null == editorInfo) {
+ Log.w(TAG, "No editor info for this field. Bug?");
+ } else if (InputType.TYPE_NULL == inputType) {
+ // TODO: We should honor TYPE_NULL specification.
+ Log.i(TAG, "InputType.TYPE_NULL is specified");
+ } 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));
+ }
+ mIsSettingsSuggestionStripOn = false;
+ mInputTypeNoAutoCorrect = false;
+ mApplicationSpecifiedCompletionOn = false;
+ } else {
+ final int variation = inputType & InputType.TYPE_MASK_VARIATION;
+ final boolean flagNoSuggestions =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ final boolean flagMultiLine =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE);
+ final boolean flagAutoCorrect =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
+ final boolean flagAutoComplete =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+
+ // Make sure that passwords are not displayed in {@link SuggestionsView}.
+ if (InputTypeUtils.isPasswordInputType(inputType)
+ || InputTypeUtils.isVisiblePasswordInputType(inputType)
+ || InputTypeUtils.isEmailVariation(variation)
+ || InputType.TYPE_TEXT_VARIATION_URI == variation
+ || InputType.TYPE_TEXT_VARIATION_FILTER == variation
+ || flagNoSuggestions
+ || flagAutoComplete) {
+ mIsSettingsSuggestionStripOn = false;
+ } else {
+ mIsSettingsSuggestionStripOn = true;
+ }
+
+ // If it's a browser edit field and auto correct is not ON explicitly, then
+ // disable auto correction, but keep suggestions on.
+ // If NO_SUGGESTIONS is set, don't do prediction.
+ // If it's not multiline and the autoCorrect flag is not set, then don't correct
+ if ((variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
+ && !flagAutoCorrect)
+ || flagNoSuggestions
+ || (!flagAutoCorrect && !flagMultiLine)) {
+ mInputTypeNoAutoCorrect = true;
+ } else {
+ mInputTypeNoAutoCorrect = false;
+ }
+
+ mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
+ }
+ mEditorAction = (editorInfo == null) ? EditorInfo.IME_ACTION_UNSPECIFIED
+ : editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
+ }
+
+ @SuppressWarnings("unused")
+ private void dumpFlags(final int inputType) {
+ Log.i(TAG, "Input class:");
+ final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
+ if (inputClass == InputType.TYPE_CLASS_TEXT)
+ Log.i(TAG, " TYPE_CLASS_TEXT");
+ if (inputClass == InputType.TYPE_CLASS_PHONE)
+ Log.i(TAG, " TYPE_CLASS_PHONE");
+ if (inputClass == InputType.TYPE_CLASS_NUMBER)
+ Log.i(TAG, " TYPE_CLASS_NUMBER");
+ if (inputClass == InputType.TYPE_CLASS_DATETIME)
+ Log.i(TAG, " TYPE_CLASS_DATETIME");
+ Log.i(TAG, "Variation:");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_EMAIL_ADDRESS");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_EMAIL_SUBJECT");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_FILTER))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_FILTER");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_LONG_MESSAGE");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_NORMAL))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_NORMAL");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_PASSWORD))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_PASSWORD");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_PERSON_NAME))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_PERSON_NAME");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_PHONETIC))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_PHONETIC");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_POSTAL_ADDRESS");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_SHORT_MESSAGE");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_URI))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_URI");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_VISIBLE_PASSWORD");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_EDIT_TEXT");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS");
+ if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD))
+ Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_PASSWORD");
+ Log.i(TAG, "Flags:");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS))
+ Log.i(TAG, " TYPE_TEXT_FLAG_NO_SUGGESTIONS");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE))
+ Log.i(TAG, " TYPE_TEXT_FLAG_MULTI_LINE");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE))
+ Log.i(TAG, " TYPE_TEXT_FLAG_IME_MULTI_LINE");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS))
+ Log.i(TAG, " TYPE_TEXT_FLAG_CAP_WORDS");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES))
+ Log.i(TAG, " TYPE_TEXT_FLAG_CAP_SENTENCES");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS))
+ Log.i(TAG, " TYPE_TEXT_FLAG_CAP_CHARACTERS");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT))
+ Log.i(TAG, " TYPE_TEXT_FLAG_AUTO_CORRECT");
+ if (0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE))
+ Log.i(TAG, " TYPE_TEXT_FLAG_AUTO_COMPLETE");
+ }
+
+ // Pretty print
+ @Override
+ public String toString() {
+ return "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect
+ + "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn
+ + "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn;
+ }
+
+ public static boolean inPrivateImeOptions(String packageName, String key,
+ EditorInfo editorInfo) {
+ if (editorInfo == null) return false;
+ final String findingKey = (packageName != null) ? packageName + "." + key
+ : key;
+ return StringUtils.containsInCsv(findingKey, editorInfo.privateImeOptions);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/InputTypeUtils.java b/java/src/com/android/inputmethod/latin/InputTypeUtils.java
new file mode 100644
index 000000000..40c3b765e
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputTypeUtils.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.InputType;
+
+public class InputTypeUtils implements InputType {
+ private static final int WEB_TEXT_PASSWORD_INPUT_TYPE =
+ TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_PASSWORD;
+ private static final int WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE =
+ TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
+ private static final int NUMBER_PASSWORD_INPUT_TYPE =
+ TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_PASSWORD;
+ private static final int TEXT_PASSWORD_INPUT_TYPE =
+ TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD;
+ private static final int TEXT_VISIBLE_PASSWORD_INPUT_TYPE =
+ TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
+
+ private InputTypeUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ private static boolean isWebEditTextInputType(int inputType) {
+ return inputType == (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
+ }
+
+ private static boolean isWebPasswordInputType(int inputType) {
+ return WEB_TEXT_PASSWORD_INPUT_TYPE != 0
+ && inputType == WEB_TEXT_PASSWORD_INPUT_TYPE;
+ }
+
+ private static boolean isWebEmailAddressInputType(int inputType) {
+ return WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE != 0
+ && inputType == WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE;
+ }
+
+ private static boolean isNumberPasswordInputType(int inputType) {
+ return NUMBER_PASSWORD_INPUT_TYPE != 0
+ && inputType == NUMBER_PASSWORD_INPUT_TYPE;
+ }
+
+ private static boolean isTextPasswordInputType(int inputType) {
+ return inputType == TEXT_PASSWORD_INPUT_TYPE;
+ }
+
+ private static boolean isWebEmailAddressVariation(int variation) {
+ return variation == TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
+ }
+
+ public static boolean isEmailVariation(int variation) {
+ return variation == TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+ || isWebEmailAddressVariation(variation);
+ }
+
+ public static boolean isWebInputType(int inputType) {
+ final int maskedInputType =
+ inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
+ return isWebEditTextInputType(maskedInputType) || isWebPasswordInputType(maskedInputType)
+ || isWebEmailAddressInputType(maskedInputType);
+ }
+
+ // Please refer to TextView.isPasswordInputType
+ public static boolean isPasswordInputType(int inputType) {
+ final int maskedInputType =
+ inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
+ return isTextPasswordInputType(maskedInputType) || isWebPasswordInputType(maskedInputType)
+ || isNumberPasswordInputType(maskedInputType);
+ }
+
+ // Please refer to TextView.isVisiblePasswordInputType
+ public static boolean isVisiblePasswordInputType(int inputType) {
+ final int maskedInputType =
+ inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
+ return maskedInputType == TEXT_VISIBLE_PASSWORD_INPUT_TYPE;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/InputView.java b/java/src/com/android/inputmethod/latin/InputView.java
new file mode 100644
index 000000000..0dcb811b5
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputView.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+
+public class InputView extends LinearLayout {
+ private View mSuggestionsContainer;
+ private View mKeyboardView;
+ private int mKeyboardTopPadding;
+
+ private boolean mIsForwardingEvent;
+ private final Rect mInputViewRect = new Rect();
+ private final Rect mEventForwardingRect = new Rect();
+ private final Rect mEventReceivingRect = new Rect();
+
+ public InputView(Context context, AttributeSet attrs) {
+ super(context, attrs, 0);
+ }
+
+ public void setKeyboardGeometry(int keyboardTopPadding) {
+ mKeyboardTopPadding = keyboardTopPadding;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mSuggestionsContainer = findViewById(R.id.suggestions_container);
+ mKeyboardView = findViewById(R.id.keyboard_view);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent me) {
+ if (mSuggestionsContainer.getVisibility() == VISIBLE
+ && mKeyboardView.getVisibility() == VISIBLE
+ && forwardTouchEvent(me)) {
+ return true;
+ }
+ return super.dispatchTouchEvent(me);
+ }
+
+ // The touch events that hit the top padding of keyboard should be forwarded to SuggestionsView.
+ private boolean forwardTouchEvent(MotionEvent me) {
+ final Rect rect = mInputViewRect;
+ this.getGlobalVisibleRect(rect);
+ final int x = (int)me.getX() + rect.left;
+ final int y = (int)me.getY() + rect.top;
+
+ final Rect forwardingRect = mEventForwardingRect;
+ mKeyboardView.getGlobalVisibleRect(forwardingRect);
+ if (!mIsForwardingEvent && !forwardingRect.contains(x, y)) {
+ return false;
+ }
+
+ final int forwardingLimitY = forwardingRect.top + mKeyboardTopPadding;
+ boolean sendToTarget = false;
+
+ switch (me.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ if (y < forwardingLimitY) {
+ // This down event and further move and up events should be forwarded to the target.
+ mIsForwardingEvent = true;
+ sendToTarget = true;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ sendToTarget = mIsForwardingEvent;
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ sendToTarget = mIsForwardingEvent;
+ mIsForwardingEvent = false;
+ break;
+ }
+
+ if (!sendToTarget) {
+ return false;
+ }
+
+ final Rect receivingRect = mEventReceivingRect;
+ mSuggestionsContainer.getGlobalVisibleRect(receivingRect);
+ final int translatedX = x - receivingRect.left;
+ final int translatedY;
+ if (y < forwardingLimitY) {
+ // The forwarded event should have coordinates that are inside of the target.
+ translatedY = Math.min(y - receivingRect.top, receivingRect.height() - 1);
+ } else {
+ translatedY = y - receivingRect.top;
+ }
+ me.setLocation(translatedX, translatedY);
+ mSuggestionsContainer.dispatchTouchEvent(me);
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/JniUtils.java b/java/src/com/android/inputmethod/latin/JniUtils.java
new file mode 100644
index 000000000..4808b867a
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/JniUtils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.util.Log;
+
+import com.android.inputmethod.latin.define.JniLibName;
+
+public class JniUtils {
+ private static final String TAG = JniUtils.class.getSimpleName();
+
+ private JniUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static void loadNativeLibrary() {
+ try {
+ System.loadLibrary(JniLibName.JNI_LIB_NAME);
+ } catch (UnsatisfiedLinkError ule) {
+ Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME);
+ if (LatinImeLogger.sDBG) {
+ throw new RuntimeException(
+ "Could not load native library " + JniLibName.JNI_LIB_NAME);
+ }
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
new file mode 100644
index 000000000..4e1f5fe92
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.TextUtils;
+
+/**
+ * This class encapsulates data about a word previously composed, but that has been
+ * committed already. This is used for resuming suggestion, and cancel auto-correction.
+ */
+public class LastComposedWord {
+ // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with
+ // no hinting from the IME. It happens when some external event happens (rotating the device,
+ // for example) or when auto-correction is off by settings or editor attributes.
+ public static final int COMMIT_TYPE_USER_TYPED_WORD = 0;
+ // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip.
+ public static final int COMMIT_TYPE_MANUAL_PICK = 1;
+ // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best
+ // for the current user input. It may be different from what the user typed (true auto-correct)
+ // or it may be exactly what the user typed if it's in the dictionary or the IME does not have
+ // enough confidence in any suggestion to auto-correct (auto-correct to typed word).
+ public static final int COMMIT_TYPE_DECIDED_WORD = 2;
+ // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling
+ // an auto-correction.
+ public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3;
+
+ public static final int NOT_A_SEPARATOR = -1;
+
+ public final int[] mPrimaryKeyCodes;
+ public final int[] mXCoordinates;
+ public final int[] mYCoordinates;
+ public final String mTypedWord;
+ public final String mCommittedWord;
+ public final int mSeparatorCode;
+ public final CharSequence mPrevWord;
+
+ private boolean mActive;
+
+ public static final LastComposedWord NOT_A_COMPOSED_WORD =
+ new LastComposedWord(null, null, null, "", "", NOT_A_SEPARATOR, null);
+
+ // Warning: this is using the passed objects as is and fully expects them to be
+ // immutable. Do not fiddle with their contents after you passed them to this constructor.
+ public LastComposedWord(final int[] primaryKeyCodes, final int[] xCoordinates,
+ final int[] yCoordinates, final String typedWord, final String committedWord,
+ final int separatorCode, final CharSequence prevWord) {
+ mPrimaryKeyCodes = primaryKeyCodes;
+ mXCoordinates = xCoordinates;
+ mYCoordinates = yCoordinates;
+ mTypedWord = typedWord;
+ mCommittedWord = committedWord;
+ mSeparatorCode = separatorCode;
+ mActive = true;
+ mPrevWord = prevWord;
+ }
+
+ public void deactivate() {
+ mActive = false;
+ }
+
+ public boolean canRevertCommit() {
+ return mActive && !TextUtils.isEmpty(mCommittedWord);
+ }
+
+ public boolean didCommitTypedWord() {
+ return TextUtils.equals(mTypedWord, mCommittedWord);
+ }
+
+ public static int getSeparatorLength(final int separatorCode) {
+ return NOT_A_SEPARATOR == separatorCode ? 0 : 1;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 874d77f19..8a5fc495e 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,6 +16,10 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -23,8 +27,10 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.net.ConnectivityManager;
@@ -36,77 +42,51 @@ import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.text.TextUtils;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
-import android.view.HapticFeedbackConstants;
+import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.accessibility.AccessibilityUtils;
+import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.compat.CompatUtils;
-import com.android.inputmethod.compat.EditorInfoCompatUtils;
-import com.android.inputmethod.compat.InputConnectionCompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
import com.android.inputmethod.compat.SuggestionSpanUtils;
-import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
-import com.android.inputmethod.deprecated.VoiceProxy;
-import com.android.inputmethod.deprecated.recorrection.Recorrection;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
+import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.KeyboardView;
-import com.android.inputmethod.keyboard.LatinKeyboard;
import com.android.inputmethod.keyboard.LatinKeyboardView;
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
+import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethod.latin.suggestions.SuggestionsView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Locale;
/**
* Input method implementation for Qwerty'ish keyboard.
*/
-public class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener,
- CandidateView.Listener {
+public class LatinIME extends InputMethodService implements KeyboardActionListener,
+ SuggestionsView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener {
private static final String TAG = LatinIME.class.getSimpleName();
- private static final boolean PERF_DEBUG = false;
private static final boolean TRACE = false;
private static boolean DEBUG;
- /**
- * The private IME option used to indicate that no microphone should be
- * shown for a given text field. For instance, this is specified by the
- * search dialog when the dialog is already showing a voice search button.
- *
- * @deprecated Use {@link LatinIME#IME_OPTION_NO_MICROPHONE} with package name prefixed.
- */
- @SuppressWarnings("dep-ann")
- public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm";
-
- /**
- * The private IME option used to indicate that no microphone should be
- * shown for a given text field. For instance, this is specified by the
- * search dialog when the dialog is already showing a voice search button.
- */
- public static final String IME_OPTION_NO_MICROPHONE = "noMicrophoneKey";
-
- /**
- * The private IME option used to indicate that no settings key should be
- * shown for a given text field.
- */
- public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey";
-
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
// How many continuous deletes at which to start deleting at a higher speed.
@@ -114,74 +94,63 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Key events coming any faster than this are long-presses.
private static final int QUICK_PRESS = 200;
+ private static final int PENDING_IMS_CALLBACK_DURATION = 800;
+
/**
* The name of the scheme used by the Package Manager to warn of a new package installation,
* replacement or removal.
*/
private static final String SCHEME_PACKAGE = "package";
- private int mSuggestionVisibility;
- private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE
- = R.string.prefs_suggestion_visibility_show_value;
- private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE
- = R.string.prefs_suggestion_visibility_show_only_portrait_value;
- private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE
- = R.string.prefs_suggestion_visibility_hide_value;
-
- private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] {
- SUGGESTION_VISIBILILTY_SHOW_VALUE,
- SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE,
- SUGGESTION_VISIBILILTY_HIDE_VALUE
- };
-
- private Settings.Values mSettingsValues;
-
- private View mCandidateViewContainer;
- private int mCandidateStripHeight;
- private CandidateView mCandidateView;
- private Suggest mSuggest;
+ private static final int SPACE_STATE_NONE = 0;
+ // Double space: the state where the user pressed space twice quickly, which LatinIME
+ // resolved as period-space. Undoing this converts the period to a space.
+ private static final int SPACE_STATE_DOUBLE = 1;
+ // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip
+ // have just been swapped. Undoing this swaps them back; the space is still considered weak.
+ private static final int SPACE_STATE_SWAP_PUNCTUATION = 2;
+ // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak
+ // spaces happen when the user presses space, accepting the current suggestion (whether
+ // it's an auto-correction or not).
+ private static final int SPACE_STATE_WEAK = 3;
+ // Phantom space: a not-yet-inserted space that should get inserted on the next input,
+ // character provided it's not a separator. If it's a separator, the phantom space is dropped.
+ // Phantom spaces happen when a user chooses a word from the suggestion strip.
+ private static final int SPACE_STATE_PHANTOM = 4;
+
+ // Current space state of the input method. This can be any of the above constants.
+ private int mSpaceState;
+
+ private SettingsValues mCurrentSettings;
+
+ private View mExtractArea;
+ private View mKeyPreviewBackingView;
+ private View mSuggestionsContainer;
+ private SuggestionsView mSuggestionsView;
+ /* package for tests */ Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions;
-
- private AlertDialog mOptionsDialog;
+ private ApplicationInfo mTargetApplicationInfo;
private InputMethodManagerCompatWrapper mImm;
private Resources mResources;
private SharedPreferences mPrefs;
- private String mInputMethodId;
- private KeyboardSwitcher mKeyboardSwitcher;
- private SubtypeSwitcher mSubtypeSwitcher;
- private VoiceProxy mVoiceProxy;
- private Recorrection mRecorrection;
-
- private UserDictionary mUserDictionary;
- private UserBigramDictionary mUserBigramDictionary;
- private AutoDictionary mAutoDictionary;
-
- // TODO: Create an inner class to group options and pseudo-options to improve readability.
- // These variables are initialized according to the {@link EditorInfo#inputType}.
- private boolean mShouldInsertMagicSpace;
- private boolean mInputTypeNoAutoCorrect;
- private boolean mIsSettingsSuggestionStripOn;
- private boolean mApplicationSpecifiedCompletionOn;
-
- private final StringBuilder mComposing = new StringBuilder();
- private WordComposer mWord = new WordComposer();
- private CharSequence mBestWord;
- private boolean mHasUncommittedTypedChars;
- private boolean mHasDictionary;
- // Magic space: a space that should disappear on space/apostrophe insertion, move after the
- // punctuation on punctuation insertion, and become a real space on alpha char insertion.
- private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space.
- // This indicates whether the last keypress resulted in processing of double space replacement
- // with period-space.
- private boolean mJustReplacedDoubleSpace;
-
- private int mCorrectionMode;
- private int mCommittedLength;
- private int mOrientation;
+ /* package for tests */ final KeyboardSwitcher mKeyboardSwitcher;
+ private final SubtypeSwitcher mSubtypeSwitcher;
+ private boolean mShouldSwitchToLastSubtype = true;
+
+ private boolean mIsMainDictionaryAvailable;
+ private UserBinaryDictionary mUserDictionary;
+ private UserHistoryDictionary mUserHistoryDictionary;
+ private boolean mIsUserDictionaryAvailable;
+
+ private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
+ private WordComposer mWordComposer = new WordComposer();
+ private RichInputConnection mConnection = new RichInputConnection();
+
// Keep track of the last selection range to decide if we need to show word alternatives
- private int mLastSelectionStart;
- private int mLastSelectionEnd;
+ private static final int NOT_A_CURSOR_POSITION = -1;
+ 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.
@@ -189,13 +158,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private int mDeleteCount;
private long mLastKeyTime;
- private AudioManager mAudioManager;
- // Align sound effect volume on music volume
- private static final float FX_VOLUME = -1.0f;
- private boolean mSilentModeOn; // System-wide current configuration
+ private AudioAndHapticFeedbackManager mFeedbackManager;
- // TODO: Move this flag to VoiceProxy
- private boolean mConfigurationChanging;
+ // Member variables for remembering the current device orientation.
+ private int mDisplayOrientation;
// Object for reacting to adding/removing a dictionary pack.
private BroadcastReceiver mDictionaryPackInstallReceiver =
@@ -204,73 +170,57 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Keeps track of most recently inserted text (multi-character key) for reverting
private CharSequence mEnteredText;
+ private boolean mIsAutoCorrectionIndicatorOn;
+
+ private AlertDialog mOptionsDialog;
public final UIHandler mHandler = new UIHandler(this);
public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
- private static final int MSG_UPDATE_SUGGESTIONS = 0;
- private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1;
- private static final int MSG_UPDATE_SHIFT_STATE = 2;
- private static final int MSG_VOICE_RESULTS = 3;
- private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4;
- private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5;
- private static final int MSG_SPACE_TYPED = 6;
- private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
+ private static final int MSG_UPDATE_SHIFT_STATE = 1;
+ private static final int MSG_SET_BIGRAM_PREDICTIONS = 5;
+ private static final int MSG_PENDING_IMS_CALLBACK = 6;
+ private static final int MSG_UPDATE_SUGGESTIONS = 7;
+
+ private int mDelayUpdateSuggestions;
+ private int mDelayUpdateShiftState;
+ private long mDoubleSpacesTurnIntoPeriodTimeout;
+ private long mDoubleSpaceTimerStart;
public UIHandler(LatinIME outerInstance) {
super(outerInstance);
}
+ public void onCreate() {
+ final Resources res = getOuterInstance().getResources();
+ mDelayUpdateSuggestions =
+ res.getInteger(R.integer.config_delay_update_suggestions);
+ mDelayUpdateShiftState =
+ res.getInteger(R.integer.config_delay_update_shift_state);
+ mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger(
+ R.integer.config_double_spaces_turn_into_period_timeout);
+ }
+
@Override
public void handleMessage(Message msg) {
final LatinIME latinIme = getOuterInstance();
final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher;
- final LatinKeyboardView inputView = switcher.getKeyboardView();
switch (msg.what) {
case MSG_UPDATE_SUGGESTIONS:
latinIme.updateSuggestions();
break;
- case MSG_UPDATE_OLD_SUGGESTIONS:
- latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions(
- latinIme.mVoiceProxy, latinIme.mCandidateView,
- latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWord,
- latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart,
- latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators);
- break;
case MSG_UPDATE_SHIFT_STATE:
switcher.updateShiftState();
break;
case MSG_SET_BIGRAM_PREDICTIONS:
latinIme.updateBigramPredictions();
break;
- case MSG_VOICE_RESULTS:
- latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization()
- || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
- break;
- case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
- if (inputView != null) {
- inputView.setSpacebarTextFadeFactor(
- (1.0f + latinIme.mSettingsValues.
- mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
- (LatinKeyboard)msg.obj);
- }
- sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
- latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar);
- break;
- case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
- if (inputView != null) {
- inputView.setSpacebarTextFadeFactor(
- latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
- (LatinKeyboard)msg.obj);
- }
- break;
}
}
public void postUpdateSuggestions() {
removeMessages(MSG_UPDATE_SUGGESTIONS);
- sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS),
- getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
+ sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions);
}
public void cancelUpdateSuggestions() {
@@ -281,20 +231,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return hasMessages(MSG_UPDATE_SUGGESTIONS);
}
- public void postUpdateOldSuggestions() {
- removeMessages(MSG_UPDATE_OLD_SUGGESTIONS);
- sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS),
- getOuterInstance().mSettingsValues.mDelayUpdateOldSuggestions);
- }
-
- public void cancelUpdateOldSuggestions() {
- removeMessages(MSG_UPDATE_OLD_SUGGESTIONS);
- }
-
- public void postUpdateShiftKeyState() {
+ public void postUpdateShiftState() {
removeMessages(MSG_UPDATE_SHIFT_STATE);
- sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE),
- getOuterInstance().mSettingsValues.mDelayUpdateShiftState);
+ sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState);
}
public void cancelUpdateShiftState() {
@@ -303,85 +242,156 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void postUpdateBigramPredictions() {
removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
- sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS),
- getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
+ sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions);
}
public void cancelUpdateBigramPredictions() {
removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
}
- public void updateVoiceResults() {
- sendMessage(obtainMessage(MSG_VOICE_RESULTS));
+ public void startDoubleSpacesTimer() {
+ mDoubleSpaceTimerStart = SystemClock.uptimeMillis();
}
- public void startDisplayLanguageOnSpacebar(boolean localeChanged) {
+ public void cancelDoubleSpacesTimer() {
+ mDoubleSpaceTimerStart = 0;
+ }
+
+ public boolean isAcceptingDoubleSpaces() {
+ return SystemClock.uptimeMillis() - mDoubleSpaceTimerStart
+ < mDoubleSpacesTurnIntoPeriodTimeout;
+ }
+
+ // Working variables for the following methods.
+ private boolean mIsOrientationChanging;
+ private boolean mPendingSuccessiveImsCallback;
+ private boolean mHasPendingStartInput;
+ private boolean mHasPendingFinishInputView;
+ private boolean mHasPendingFinishInput;
+ private EditorInfo mAppliedEditorInfo;
+
+ public void startOrientationChanging() {
+ removeMessages(MSG_PENDING_IMS_CALLBACK);
+ resetPendingImsCallback();
+ mIsOrientationChanging = true;
final LatinIME latinIme = getOuterInstance();
- removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR);
- removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR);
- final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView();
- if (inputView != null) {
- final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard();
- // The language is always displayed when the delay is negative.
- final boolean needsToDisplayLanguage = localeChanged
- || latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0;
- // The language is never displayed when the delay is zero.
- if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
- inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f
- : latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
- keyboard);
- }
- // The fadeout animation will start when the delay is positive.
- if (localeChanged
- && latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
- sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard),
- latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar);
+ if (latinIme.isInputViewShown()) {
+ latinIme.mKeyboardSwitcher.saveKeyboardState();
+ }
+ }
+
+ private void resetPendingImsCallback() {
+ mHasPendingFinishInputView = false;
+ mHasPendingFinishInput = false;
+ mHasPendingStartInput = false;
+ }
+
+ private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo,
+ boolean restarting) {
+ if (mHasPendingFinishInputView)
+ latinIme.onFinishInputViewInternal(mHasPendingFinishInput);
+ if (mHasPendingFinishInput)
+ latinIme.onFinishInputInternal();
+ if (mHasPendingStartInput)
+ latinIme.onStartInputInternal(editorInfo, restarting);
+ resetPendingImsCallback();
+ }
+
+ public void onStartInput(EditorInfo editorInfo, boolean restarting) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the second onStartInput after orientation changed.
+ mHasPendingStartInput = true;
+ } else {
+ if (mIsOrientationChanging && restarting) {
+ // This is the first onStartInput after orientation changed.
+ mIsOrientationChanging = false;
+ mPendingSuccessiveImsCallback = true;
}
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, editorInfo, restarting);
+ latinIme.onStartInputInternal(editorInfo, restarting);
}
}
- public void startDoubleSpacesTimer() {
- removeMessages(MSG_SPACE_TYPED);
- sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED),
- getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout);
+ public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)
+ && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) {
+ // Typically this is the second onStartInputView after orientation changed.
+ resetPendingImsCallback();
+ } else {
+ if (mPendingSuccessiveImsCallback) {
+ // This is the first onStartInputView after orientation changed.
+ mPendingSuccessiveImsCallback = false;
+ resetPendingImsCallback();
+ sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
+ PENDING_IMS_CALLBACK_DURATION);
+ }
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, editorInfo, restarting);
+ latinIme.onStartInputViewInternal(editorInfo, restarting);
+ mAppliedEditorInfo = editorInfo;
+ }
}
- public void cancelDoubleSpacesTimer() {
- removeMessages(MSG_SPACE_TYPED);
+ public void onFinishInputView(boolean finishingInput) {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the first onFinishInputView after orientation changed.
+ mHasPendingFinishInputView = true;
+ } else {
+ final LatinIME latinIme = getOuterInstance();
+ latinIme.onFinishInputViewInternal(finishingInput);
+ mAppliedEditorInfo = null;
+ }
}
- public boolean isAcceptingDoubleSpaces() {
- return hasMessages(MSG_SPACE_TYPED);
+ public void onFinishInput() {
+ if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
+ // Typically this is the first onFinishInput after orientation changed.
+ mHasPendingFinishInput = true;
+ } else {
+ final LatinIME latinIme = getOuterInstance();
+ executePendingImsCallback(latinIme, null, false);
+ latinIme.onFinishInputInternal();
+ }
}
}
+ public LatinIME() {
+ super();
+ mSubtypeSwitcher = SubtypeSwitcher.getInstance();
+ mKeyboardSwitcher = KeyboardSwitcher.getInstance();
+ }
+
@Override
public void onCreate() {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mPrefs = prefs;
LatinImeLogger.init(this, prefs);
- LanguageSwitcherProxy.init(this, prefs);
- SubtypeSwitcher.init(this, prefs);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().init(this, prefs);
+ }
+ InputMethodManagerCompatWrapper.init(this);
+ SubtypeSwitcher.init(this);
KeyboardSwitcher.init(this, prefs);
- Recorrection.init(this, prefs);
- AccessibilityUtils.init(this, prefs);
+ AccessibilityUtils.init(this);
super.onCreate();
- mImm = InputMethodManagerCompatWrapper.getInstance(this);
- mInputMethodId = Utils.getInputMethodId(mImm, getPackageName());
- mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- mKeyboardSwitcher = KeyboardSwitcher.getInstance();
- mRecorrection = Recorrection.getInstance();
+ mImm = InputMethodManagerCompatWrapper.getInstance();
+ mHandler.onCreate();
DEBUG = LatinImeLogger.sDBG;
- loadSettings();
-
final Resources res = getResources();
mResources = res;
+ loadSettings();
+
+ ImfUtils.setAdditionalInputMethodSubtypes(this, mCurrentSettings.getAdditionalSubtypes());
+
Utils.GCUtils.getInstance().reset();
boolean tryGC = true;
+ // Shouldn't this be removed? I think that from Honeycomb on, the GC is now actually working
+ // as expected and this code is useless.
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
try {
initSuggest();
@@ -391,15 +401,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
- mOrientation = res.getConfiguration().orientation;
+ mDisplayOrientation = res.getConfiguration().orientation;
// Register to receive ringer mode change and network state change.
// Also receive installation and removal of a dictionary pack.
final IntentFilter filter = new IntentFilter();
- filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
registerReceiver(mReceiver, filter);
- mVoiceProxy = VoiceProxy.init(this, prefs, mHandler);
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -415,57 +424,103 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Has to be package-visible for unit tests
/* package */ void loadSettings() {
+ // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
+ // is not guaranteed. It may even be called at the same time on a different thread.
if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance();
- mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr());
- resetContactsDictionary();
+ final InputAttributes inputAttributes =
+ new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
+ final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
+ @Override
+ protected SettingsValues job(Resources res) {
+ return new SettingsValues(mPrefs, inputAttributes, LatinIME.this);
+ }
+ };
+ mCurrentSettings = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale());
+ mFeedbackManager = new AudioAndHapticFeedbackManager(this, mCurrentSettings);
+ resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
private void initSuggest() {
- final String localeStr = mSubtypeSwitcher.getInputLocaleStr();
- final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr);
+ final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ final String localeStr = subtypeLocale.toString();
- final Resources res = mResources;
- final Locale savedLocale = Utils.setSystemLocale(res, keyboardLocale);
+ final ContactsBinaryDictionary oldContactsDictionary;
if (mSuggest != null) {
+ oldContactsDictionary = mSuggest.getContactsDictionary();
mSuggest.close();
+ } else {
+ oldContactsDictionary = null;
+ }
+ mSuggest = new Suggest(this, subtypeLocale);
+ if (mCurrentSettings.mCorrectionEnabled) {
+ mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
}
- int mainDicResId = Utils.getMainDictionaryResourceId(res);
- mSuggest = new Suggest(this, mainDicResId, keyboardLocale);
- if (mSettingsValues.mAutoCorrectEnabled) {
- mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
+ mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().initSuggest(mSuggest);
}
- updateAutoTextEnabled();
- mUserDictionary = new UserDictionary(this, localeStr);
+ mUserDictionary = new UserBinaryDictionary(this, localeStr);
+ mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
mSuggest.setUserDictionary(mUserDictionary);
- resetContactsDictionary();
-
- mAutoDictionary = new AutoDictionary(this, this, localeStr, Suggest.DIC_AUTO);
- mSuggest.setAutoDictionary(mAutoDictionary);
+ resetContactsDictionary(oldContactsDictionary);
- mUserBigramDictionary = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER);
- mSuggest.setUserBigramDictionary(mUserBigramDictionary);
-
- updateCorrectionMode();
-
- Utils.setSystemLocale(res, savedLocale);
+ // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
+ // is not guaranteed. It may even be called at the same time on a different thread.
+ if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ mUserHistoryDictionary = UserHistoryDictionary.getInstance(
+ this, localeStr, Suggest.DIC_USER_HISTORY, mPrefs);
+ mSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
}
- private void resetContactsDictionary() {
- if (null == mSuggest) return;
- ContactsDictionary contactsDictionary = mSettingsValues.mUseContactsDict
- ? new ContactsDictionary(this, Suggest.DIC_CONTACTS) : null;
- mSuggest.setContactsDictionary(contactsDictionary);
+ /**
+ * Resets the contacts dictionary in mSuggest according to the user settings.
+ *
+ * This method takes an optional contacts dictionary to use when the locale hasn't changed
+ * since the contacts dictionary can be opened or closed as necessary depending on the settings.
+ *
+ * @param oldContactsDictionary an optional dictionary to use, or null
+ */
+ private void resetContactsDictionary(final ContactsBinaryDictionary oldContactsDictionary) {
+ final boolean shouldSetDictionary = (null != mSuggest && mCurrentSettings.mUseContactsDict);
+
+ final ContactsBinaryDictionary dictionaryToUse;
+ if (!shouldSetDictionary) {
+ // Make sure the dictionary is closed. If it is already closed, this is a no-op,
+ // so it's safe to call it anyways.
+ if (null != oldContactsDictionary) oldContactsDictionary.close();
+ dictionaryToUse = null;
+ } else {
+ final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ if (null != oldContactsDictionary) {
+ if (!oldContactsDictionary.mLocale.equals(locale)) {
+ // If the locale has changed then recreate the contacts dictionary. This
+ // allows locale dependent rules for handling bigram name predictions.
+ oldContactsDictionary.close();
+ dictionaryToUse = new ContactsBinaryDictionary(
+ this, Suggest.DIC_CONTACTS, locale);
+ } else {
+ // Make sure the old contacts dictionary is opened. If it is already open,
+ // this is a no-op, so it's safe to call it anyways.
+ oldContactsDictionary.reopen(this);
+ dictionaryToUse = oldContactsDictionary;
+ }
+ } else {
+ dictionaryToUse = new ContactsBinaryDictionary(this, Suggest.DIC_CONTACTS, locale);
+ }
+ }
+
+ if (null != mSuggest) {
+ mSuggest.setContactsDictionary(dictionaryToUse);
+ }
}
/* package private */ void resetSuggestMainDict() {
- final String localeStr = mSubtypeSwitcher.getInputLocaleStr();
- final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr);
- int mainDicResId = Utils.getMainDictionaryResourceId(mResources);
- mSuggest.resetMainDict(this, mainDicResId, keyboardLocale);
+ final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ mSuggest.resetMainDict(this, subtypeLocale);
+ mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
}
@Override
@@ -476,7 +531,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
unregisterReceiver(mReceiver);
unregisterReceiver(mDictionaryPackInstallReceiver);
- mVoiceProxy.destroy();
LatinImeLogger.commit();
LatinImeLogger.onDestroy();
super.onDestroy();
@@ -486,22 +540,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
public void onConfigurationChanged(Configuration conf) {
mSubtypeSwitcher.onConfigurationChanged(conf);
// If orientation changed while predicting, commit the change
- if (conf.orientation != mOrientation) {
- InputConnection ic = getCurrentInputConnection();
- commitTyped(ic);
- if (ic != null) ic.finishComposingText(); // For voice input
- mOrientation = conf.orientation;
+ if (mDisplayOrientation != conf.orientation) {
+ mDisplayOrientation = conf.orientation;
+ mHandler.startOrientationChanging();
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+ commitTyped(LastComposedWord.NOT_A_SEPARATOR);
+ mConnection.finishComposingText();
+ mConnection.endBatchEdit();
if (isShowingOptionDialog())
mOptionsDialog.dismiss();
}
-
- mConfigurationChanging = true;
super.onConfigurationChanged(conf);
- mVoiceProxy.onConfigurationChanged(conf);
- mConfigurationChanging = false;
-
- // This will work only when the subtype is not supported.
- LanguageSwitcherProxy.onConfigurationChanged(conf);
}
@Override
@@ -512,11 +561,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void setInputView(View view) {
super.setInputView(view);
- mCandidateViewContainer = view.findViewById(R.id.candidates_container);
- mCandidateView = (CandidateView) view.findViewById(R.id.candidates);
- if (mCandidateView != null)
- mCandidateView.setListener(this, view);
- mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height);
+ mExtractArea = getWindow().getWindow().getDecorView()
+ .findViewById(android.R.id.extractArea);
+ mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing);
+ mSuggestionsContainer = view.findViewById(R.id.suggestions_container);
+ mSuggestionsView = (SuggestionsView) view.findViewById(R.id.suggestions_view);
+ if (mSuggestionsView != null)
+ mSuggestionsView.setListener(this, view);
+ if (LatinImeLogger.sVISUALDEBUG) {
+ mKeyPreviewBackingView.setBackgroundColor(0x10FF0000);
+ }
}
@Override
@@ -526,177 +580,175 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
@Override
- public void onStartInputView(EditorInfo attribute, boolean restarting) {
+ public void onStartInput(EditorInfo editorInfo, boolean restarting) {
+ mHandler.onStartInput(editorInfo, restarting);
+ }
+
+ @Override
+ public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
+ mHandler.onStartInputView(editorInfo, restarting);
+ }
+
+ @Override
+ public void onFinishInputView(boolean finishingInput) {
+ mHandler.onFinishInputView(finishingInput);
+ }
+
+ @Override
+ public void onFinishInput() {
+ mHandler.onFinishInput();
+ }
+
+ @Override
+ public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
+ // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
+ // is not guaranteed. It may even be called at the same time on a different thread.
+ mSubtypeSwitcher.updateSubtype(subtype);
+ }
+
+ private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) {
+ super.onStartInput(editorInfo, restarting);
+ }
+
+ @SuppressWarnings("deprecation")
+ private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+ super.onStartInputView(editorInfo, restarting);
final KeyboardSwitcher switcher = mKeyboardSwitcher;
LatinKeyboardView inputView = switcher.getKeyboardView();
- if (DEBUG) {
- Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none"
- : String.format("inputType=0x%08x imeOptions=0x%08x",
- attribute.inputType, attribute.imeOptions)));
+ if (editorInfo == null) {
+ Log.e(TAG, "Null EditorInfo in onStartInputView()");
+ if (LatinImeLogger.sDBG) {
+ throw new NullPointerException("Null EditorInfo in onStartInputView()");
+ }
+ return;
}
+ if (DEBUG) {
+ Log.d(TAG, "onStartInputView: editorInfo:"
+ + String.format("inputType=0x%08x imeOptions=0x%08x",
+ editorInfo.inputType, editorInfo.imeOptions));
+ Log.d(TAG, "All caps = "
+ + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0)
+ + ", sentence caps = "
+ + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0)
+ + ", word caps = "
+ + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0));
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().start();
+ ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs);
+ }
+ if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
+ Log.w(TAG, "Deprecated private IME option specified: "
+ + editorInfo.privateImeOptions);
+ Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead");
+ }
+ if (InputAttributes.inPrivateImeOptions(getPackageName(), FORCE_ASCII, editorInfo)) {
+ Log.w(TAG, "Deprecated private IME option specified: "
+ + editorInfo.privateImeOptions);
+ Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
+ }
+
+ mTargetApplicationInfo =
+ TargetApplicationGetter.getCachedApplicationInfo(editorInfo.packageName);
+ if (null == mTargetApplicationInfo) {
+ new TargetApplicationGetter(this /* context */, this /* listener */)
+ .execute(editorInfo.packageName);
+ }
+
+ LatinImeLogger.onStartInputView(editorInfo);
// In landscape mode, this method gets called without the input view being created.
if (inputView == null) {
return;
}
- mSubtypeSwitcher.updateParametersOnStartInputView();
-
- TextEntryState.reset();
+ // Forward this event to the accessibility utilities, if enabled.
+ final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
+ if (accessUtils.isTouchExplorationEnabled()) {
+ accessUtils.onStartInputViewInternal(editorInfo, restarting);
+ }
- // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to
- // know now whether this is a password text field, because we need to know now whether we
- // want to enable the voice button.
- final VoiceProxy voiceIme = mVoiceProxy;
- voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(attribute.inputType)
- || InputTypeCompatUtils.isVisiblePasswordInputType(attribute.inputType));
+ mSubtypeSwitcher.updateParametersOnStartInputView();
- initializeInputAttributes(attribute);
+ // The EditorInfo might have a flag that affects fullscreen mode.
+ // Note: This call should be done by InputMethodService?
+ updateFullscreenMode();
+ mLastSelectionStart = editorInfo.initialSelStart;
+ mLastSelectionEnd = editorInfo.initialSelEnd;
+ mApplicationSpecifiedCompletions = null;
inputView.closing();
mEnteredText = null;
- mComposing.setLength(0);
- mHasUncommittedTypedChars = false;
+ resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0;
- mJustAddedMagicSpace = false;
- mJustReplacedDoubleSpace = false;
+ mSpaceState = SPACE_STATE_NONE;
loadSettings();
- updateCorrectionMode();
- updateAutoTextEnabled();
- updateSuggestionVisibility(mPrefs, mResources);
- if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) {
- mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
- }
- mVoiceProxy.loadSettings(attribute, mPrefs);
- // This will work only when the subtype is not supported.
- LanguageSwitcherProxy.loadSettings();
-
- if (mSubtypeSwitcher.isKeyboardMode()) {
- switcher.loadKeyboard(attribute,
- mSubtypeSwitcher.isShortcutImeEnabled() && voiceIme.isVoiceButtonEnabled(),
- voiceIme.isVoiceButtonOnPrimary());
- switcher.updateShiftState();
+ if (mSuggest != null && mCurrentSettings.mCorrectionEnabled) {
+ mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
}
- setSuggestionStripShownInternal(isCandidateStripVisible(), /* needsInputViewShown */ false);
+ switcher.loadKeyboard(editorInfo, mCurrentSettings);
+
+ if (mSuggestionsView != null)
+ mSuggestionsView.clear();
+ setSuggestionStripShownInternal(
+ isSuggestionsStripVisible(), /* needsInputViewShown */ false);
// Delay updating suggestions because keyboard input view may not be shown at this point.
mHandler.postUpdateSuggestions();
+ mHandler.cancelDoubleSpacesTimer();
- updateCorrectionMode();
-
- inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn,
- mSettingsValues.mKeyPreviewPopupDismissDelay);
+ inputView.setKeyPreviewPopupEnabled(mCurrentSettings.mKeyPreviewPopupOn,
+ mCurrentSettings.mKeyPreviewPopupDismissDelay);
inputView.setProximityCorrectionEnabled(true);
- // If we just entered a text field, maybe it has some old text that requires correction
- mRecorrection.checkRecorrectionOnStart();
-
- voiceIme.onStartInputView(inputView.getWindowToken());
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
- private void initializeInputAttributes(EditorInfo attribute) {
- if (attribute == null)
- return;
- final int inputType = attribute.inputType;
- final int variation = inputType & InputType.TYPE_MASK_VARIATION;
- mShouldInsertMagicSpace = false;
- mInputTypeNoAutoCorrect = false;
- mIsSettingsSuggestionStripOn = false;
- mApplicationSpecifiedCompletionOn = false;
- mApplicationSpecifiedCompletions = null;
-
- if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) {
- mIsSettingsSuggestionStripOn = true;
- // Make sure that passwords are not displayed in candidate view
- if (InputTypeCompatUtils.isPasswordInputType(inputType)
- || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) {
- mIsSettingsSuggestionStripOn = false;
- }
- if (InputTypeCompatUtils.isEmailVariation(variation)
- || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) {
- mShouldInsertMagicSpace = false;
- } else {
- mShouldInsertMagicSpace = true;
- }
- if (InputTypeCompatUtils.isEmailVariation(variation)) {
- mIsSettingsSuggestionStripOn = false;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
- mIsSettingsSuggestionStripOn = false;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
- mIsSettingsSuggestionStripOn = false;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
- // If it's a browser edit field and auto correct is not ON explicitly, then
- // disable auto correction, but keep suggestions on.
- if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
- mInputTypeNoAutoCorrect = true;
- }
- }
-
- // If NO_SUGGESTIONS is set, don't do prediction.
- if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
- mIsSettingsSuggestionStripOn = false;
- mInputTypeNoAutoCorrect = true;
- }
- // If it's not multiline and the autoCorrect flag is not set, then don't correct
- if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0
- && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
- mInputTypeNoAutoCorrect = true;
- }
- if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
- mIsSettingsSuggestionStripOn = false;
- mApplicationSpecifiedCompletionOn = isFullscreenMode();
- }
- }
+ @Override
+ public void onTargetApplicationKnown(final ApplicationInfo info) {
+ mTargetApplicationInfo = info;
}
@Override
public void onWindowHidden() {
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_onWindowHidden(mLastSelectionStart, mLastSelectionEnd,
+ getCurrentInputConnection());
+ }
super.onWindowHidden();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.closing();
}
- @Override
- public void onFinishInput() {
+ private void onFinishInputInternal() {
super.onFinishInput();
LatinImeLogger.commit();
- mKeyboardSwitcher.onAutoCorrectionStateChanged(false);
-
- mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().stop();
+ }
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.closing();
- if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
- if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites();
}
- @Override
- public void onFinishInputView(boolean finishingInput) {
+ private void onFinishInputViewInternal(boolean finishingInput) {
super.onFinishInputView(finishingInput);
+ mKeyboardSwitcher.onFinishInputView();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
- if (inputView != null) inputView.cancelAllMessage();
+ if (inputView != null) inputView.cancelAllMessages();
// Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestions();
- mHandler.cancelUpdateOldSuggestions();
- }
-
- @Override
- public void onUpdateExtractedText(int token, ExtractedText text) {
- super.onUpdateExtractedText(token, text);
- mVoiceProxy.showPunctuationHintIfNecessary();
}
@Override
public void onUpdateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd) {
+ int composingSpanStart, int composingSpanEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
- candidatesStart, candidatesEnd);
-
+ composingSpanStart, composingSpanEnd);
if (DEBUG) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
@@ -704,79 +756,79 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
+ ", lse=" + mLastSelectionEnd
+ ", nss=" + newSelStart
+ ", nse=" + newSelEnd
- + ", cs=" + candidatesStart
- + ", ce=" + candidatesEnd);
- }
-
- mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart);
-
- // If the current selection in the text view changes, we should
- // clear whatever candidate text we have.
- final boolean selectionChanged = (newSelStart != candidatesEnd
- || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart;
- final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1;
- if (((mComposing.length() > 0 && mHasUncommittedTypedChars)
- || mVoiceProxy.isVoiceInputHighlighted())
- && (selectionChanged || candidatesCleared)) {
- if (candidatesCleared) {
- // If the composing span has been cleared, save the typed word in the history for
- // recorrection before we reset the candidate strip. Then, we'll be able to show
- // suggestions for recorrection right away.
- mRecorrection.saveRecorrectionSuggestion(mWord, mComposing);
- }
- mComposing.setLength(0);
- mHasUncommittedTypedChars = false;
- if (isCursorTouchingWord()) {
- mHandler.cancelUpdateBigramPredictions();
- mHandler.postUpdateSuggestions();
- } else {
- setPunctuationSuggestions();
- }
- TextEntryState.reset();
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
- mVoiceProxy.setVoiceInputHighlighted(false);
- } else if (!mHasUncommittedTypedChars && !mExpectingUpdateSelection) {
- if (TextEntryState.isAcceptedDefault() || TextEntryState.isSpaceAfterPicked()) {
- if (TextEntryState.isAcceptedDefault())
- TextEntryState.reset();
+ + ", cs=" + composingSpanStart
+ + ", ce=" + composingSpanEnd);
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ 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;
}
}
+
+ // TODO: refactor the following code to be less contrived.
+ // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means
+ // that the cursor is not at the end of the composing span, or there is a selection.
+ // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place
+ // as last time we were called (if there is a selection, it means the start hasn't
+ // changed, so it's the end that did).
+ final boolean selectionChanged = (newSelStart != composingSpanEnd
+ || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart;
+ // if composingSpanStart and composingSpanEnd are -1, it means there is no composing
+ // span in the view - we can use that to narrow down whether the cursor was moved
+ // by us or not. If we are composing a word but there is no composing span, then
+ // we know for sure the cursor moved while we were composing and we should reset
+ // the state.
+ final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1;
if (!mExpectingUpdateSelection) {
- mJustAddedMagicSpace = false; // The user moved the cursor.
- mJustReplacedDoubleSpace = false;
+ // 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.
+
+ // 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
+ // the call to postUpdateShiftState.
+ // We set this to NONE because after a cursor move, we don't want the space
+ // state-related special processing to kick in.
+ mSpaceState = SPACE_STATE_NONE;
+
+ if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) {
+ resetEntireInputState();
+ }
+
+ mHandler.postUpdateShiftState();
}
mExpectingUpdateSelection = false;
- mHandler.postUpdateShiftKeyState();
+ // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not
+ // here. It would probably be too expensive to call directly here but we may want to post a
+ // message to delay it. The point would be to unify behavior between backspace to the
+ // end of a word and manually put the pointer at the end of the word.
// Make a note of the cursor position
mLastSelectionStart = newSelStart;
mLastSelectionEnd = newSelEnd;
-
- mRecorrection.updateRecorrectionSelection(mKeyboardSwitcher,
- mCandidateView, candidatesStart, candidatesEnd, newSelStart,
- newSelEnd, oldSelStart, mLastSelectionStart,
- mLastSelectionEnd, mHasUncommittedTypedChars);
- }
-
- public void setLastSelection(int start, int end) {
- mLastSelectionStart = start;
- mLastSelectionEnd = end;
}
/**
* This is called when the user has clicked on the extracted text view,
* when running in fullscreen mode. The default implementation hides
- * the candidates view when this happens, but only if the extracted text
+ * the suggestions view when this happens, but only if the extracted text
* editor has a vertical scroll bar because its text doesn't fit.
* Here we override the behavior due to the possibility that a re-correction could
- * cause the candidate strip to disappear and re-appear.
+ * cause the suggestions strip to disappear and re-appear.
*/
@Override
public void onExtractedTextClicked() {
- if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return;
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) return;
super.onExtractedTextClicked();
}
@@ -784,15 +836,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
/**
* This is called when the user has performed a cursor movement in the
* extracted text view, when it is running in fullscreen mode. The default
- * implementation hides the candidates view when a vertical movement
+ * implementation hides the suggestions view when a vertical movement
* happens, but only if the extracted text editor has a vertical scroll bar
* because its text doesn't fit.
* Here we override the behavior due to the possibility that a re-correction could
- * cause the candidate strip to disappear and re-appear.
+ * cause the suggestions strip to disappear and re-appear.
*/
@Override
public void onExtractedCursorMovement(int dx, int dy) {
- if (mRecorrection.isRecorrectionEnabled() && isSuggestionsRequested()) return;
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) return;
super.onExtractedCursorMovement(dx, dy);
}
@@ -800,15 +852,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void hideWindow() {
LatinImeLogger.commit();
- mKeyboardSwitcher.onAutoCorrectionStateChanged(false);
+ mKeyboardSwitcher.onHideWindow();
if (TRACE) Debug.stopMethodTracing();
if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
mOptionsDialog.dismiss();
mOptionsDialog = null;
}
- mVoiceProxy.hideVoiceWindow(mConfigurationChanging);
- mRecorrection.clearWordsInHistory();
super.hideWindow();
}
@@ -822,39 +872,50 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
}
- if (mApplicationSpecifiedCompletionOn) {
- mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
- if (applicationSpecifiedCompletions == null) {
- clearSuggestions();
- return;
- }
-
- SuggestedWords.Builder builder = new SuggestedWords.Builder()
- .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions)
- .setTypedWordValid(true)
- .setHasMinimalSuggestion(true);
- // When in fullscreen mode, show completions generated by the application
- setSuggestions(builder.build());
- mBestWord = null;
- setSuggestionStripShown(true);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
+ if (!mCurrentSettings.isApplicationSpecifiedCompletionsOn()) return;
+ mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
+ if (applicationSpecifiedCompletions == null) {
+ clearSuggestions();
+ return;
+ }
+
+ final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords =
+ SuggestedWords.getFromApplicationSpecifiedCompletions(
+ applicationSpecifiedCompletions);
+ final SuggestedWords suggestedWords = new SuggestedWords(
+ applicationSuggestedWords,
+ false /* typedWordValid */,
+ false /* hasAutoCorrectionCandidate */,
+ false /* allowsToBeAutoCorrected */,
+ false /* isPunctuationSuggestions */,
+ false /* isObsoleteSuggestions */,
+ false /* isPrediction */);
+ // When in fullscreen mode, show completions generated by the application
+ final boolean isAutoCorrection = false;
+ setSuggestions(suggestedWords, isAutoCorrection);
+ setAutoCorrectionIndicator(isAutoCorrection);
+ // TODO: is this the right thing to do? What should we auto-correct to in
+ // this case? This says to keep whatever the user typed.
+ mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
+ setSuggestionStripShown(true);
}
private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) {
- // TODO: Modify this if we support candidates with hard keyboard
- if (onEvaluateInputViewShown() && mCandidateViewContainer != null) {
- final boolean shouldShowCandidates = shown
- && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true);
- if (isExtractViewShown()) {
- // No need to have extra space to show the key preview.
- mCandidateViewContainer.setMinimumHeight(0);
- mCandidateViewContainer.setVisibility(
- shouldShowCandidates ? View.VISIBLE : View.GONE);
+ // TODO: Modify this if we support suggestions with hard keyboard
+ if (onEvaluateInputViewShown() && mSuggestionsContainer != null) {
+ final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView();
+ final boolean inputViewShown = (keyboardView != null) ? keyboardView.isShown() : false;
+ final boolean shouldShowSuggestions = shown
+ && (needsInputViewShown ? inputViewShown : true);
+ if (isFullscreenMode()) {
+ mSuggestionsContainer.setVisibility(
+ shouldShowSuggestions ? View.VISIBLE : View.GONE);
} else {
- // We must control the visibility of the suggestion strip in order to avoid clipped
- // key previews, even when we don't show the suggestion strip.
- mCandidateViewContainer.setVisibility(
- shouldShowCandidates ? View.VISIBLE : View.INVISIBLE);
+ mSuggestionsContainer.setVisibility(
+ shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE);
}
}
}
@@ -863,28 +924,60 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
setSuggestionStripShownInternal(shown, /* needsInputViewShown */true);
}
+ private int getAdjustedBackingViewHeight() {
+ final int currentHeight = mKeyPreviewBackingView.getHeight();
+ if (currentHeight > 0) {
+ return currentHeight;
+ }
+
+ final KeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView();
+ if (keyboardView == null) {
+ return 0;
+ }
+ final int keyboardHeight = keyboardView.getHeight();
+ final int suggestionsHeight = mSuggestionsContainer.getHeight();
+ final int displayHeight = mResources.getDisplayMetrics().heightPixels;
+ final Rect rect = new Rect();
+ mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect);
+ final int notificationBarHeight = rect.top;
+ final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight
+ - keyboardHeight;
+
+ final LayoutParams params = mKeyPreviewBackingView.getLayoutParams();
+ params.height = mSuggestionsView.setMoreSuggestionsHeight(remainingHeight);
+ mKeyPreviewBackingView.setLayoutParams(params);
+ return params.height;
+ }
+
@Override
public void onComputeInsets(InputMethodService.Insets outInsets) {
super.onComputeInsets(outInsets);
final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
- if (inputView == null || mCandidateViewContainer == null)
+ if (inputView == null || mSuggestionsContainer == null)
return;
- final int containerHeight = mCandidateViewContainer.getHeight();
- int touchY = containerHeight;
+ final int adjustedBackingHeight = getAdjustedBackingViewHeight();
+ final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE);
+ final int backingHeight = backingGone ? 0 : adjustedBackingHeight;
+ // In fullscreen mode, the height of the extract area managed by InputMethodService should
+ // be considered.
+ // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}.
+ final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0;
+ final int suggestionsHeight = (mSuggestionsContainer.getVisibility() == View.GONE) ? 0
+ : mSuggestionsContainer.getHeight();
+ final int extraHeight = extractHeight + backingHeight + suggestionsHeight;
+ int touchY = extraHeight;
// Need to set touchable region only if input view is being shown
- if (mKeyboardSwitcher.isInputViewShown()) {
- if (mCandidateViewContainer.getVisibility() == View.VISIBLE) {
- touchY -= mCandidateStripHeight;
+ final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView();
+ if (keyboardView != null && keyboardView.isShown()) {
+ if (mSuggestionsContainer.getVisibility() == View.VISIBLE) {
+ touchY -= suggestionsHeight;
}
final int touchWidth = inputView.getWidth();
- final int touchHeight = inputView.getHeight() + containerHeight
+ final int touchHeight = inputView.getHeight() + extraHeight
// Extend touchable region below the keyboard.
+ EXTENDED_TOUCHABLE_REGION_HEIGHT;
- if (DEBUG) {
- Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth
- + " height=" + touchHeight);
- }
- setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight);
+ outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION;
+ outInsets.touchableRegion.set(0, touchY, touchWidth, touchHeight);
}
outInsets.contentTopInsets = touchY;
outInsets.visibleTopInsets = touchY;
@@ -892,278 +985,364 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public boolean onEvaluateFullscreenMode() {
- final Resources res = mResources;
- DisplayMetrics dm = res.getDisplayMetrics();
- float displayHeight = dm.heightPixels;
- // If the display is more than X inches high, don't go to fullscreen mode
- float dimen = res.getDimension(R.dimen.max_height_for_fullscreen);
- if (displayHeight > dimen) {
- return false;
- } else {
- return super.onEvaluateFullscreenMode();
- }
+ // Reread resource value here, because this method is called by framework anytime as needed.
+ final boolean isFullscreenModeAllowed =
+ mCurrentSettings.isFullscreenModeAllowed(getResources());
+ return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed;
}
@Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_BACK:
- if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getKeyboardView() != null) {
- if (mKeyboardSwitcher.getKeyboardView().handleBack()) {
- return true;
- }
- }
- break;
- }
- return super.onKeyDown(keyCode, event);
+ public void updateFullscreenMode() {
+ super.updateFullscreenMode();
+
+ if (mKeyPreviewBackingView == null) return;
+ // In fullscreen mode, no need to have extra space to show the key preview.
+ // If not, we should have extra space above the keyboard to show the key preview.
+ mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE);
}
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- // Enable shift key and DPAD to do selections
- if (mKeyboardSwitcher.isInputViewShown()
- && mKeyboardSwitcher.isShiftedOrShiftLocked()) {
- KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(),
- event.getAction(), event.getKeyCode(), event.getRepeatCount(),
- event.getDeviceId(), event.getScanCode(),
- KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
- InputConnection ic = getCurrentInputConnection();
- if (ic != null)
- ic.sendKeyEvent(newEvent);
- return true;
- }
- break;
- }
- return super.onKeyUp(keyCode, event);
+ // 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() {
+ resetComposingState(true /* alsoResetLastComposedWord */);
+ updateSuggestions();
+ mConnection.finishComposingText();
}
- public void commitTyped(InputConnection inputConnection) {
- if (mHasUncommittedTypedChars) {
- mHasUncommittedTypedChars = false;
- if (mComposing.length() > 0) {
- if (inputConnection != null) {
- inputConnection.commitText(mComposing, 1);
- }
- mCommittedLength = mComposing.length();
- TextEntryState.acceptedTyped(mComposing);
- addToAutoAndUserBigramDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED);
+ private void resetComposingState(final boolean alsoResetLastComposedWord) {
+ mWordComposer.reset();
+ if (alsoResetLastComposedWord)
+ mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
+ }
+
+ public void commitTyped(final int separatorCode) {
+ if (!mWordComposer.isComposingWord()) return;
+ final CharSequence typedWord = mWordComposer.getTypedWord();
+ if (typedWord.length() > 0) {
+ mConnection.commitText(typedWord, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_commitText(typedWord);
}
- updateSuggestions();
+ final CharSequence prevWord = addToUserHistoryDictionary(typedWord);
+ mLastComposedWord = mWordComposer.commitWord(
+ LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
+ separatorCode, prevWord);
}
+ updateSuggestions();
}
- public boolean getCurrentAutoCapsState() {
- InputConnection ic = getCurrentInputConnection();
- EditorInfo ei = getCurrentInputEditorInfo();
- if (mSettingsValues.mAutoCap && ic != null && ei != null
- && ei.inputType != InputType.TYPE_NULL) {
- return ic.getCursorCapsMode(ei.inputType) != 0;
+ public int getCurrentAutoCapsState() {
+ if (!mCurrentSettings.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
+
+ final EditorInfo ei = getCurrentInputEditorInfo();
+ if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
+
+ final int inputType = ei.inputType;
+ if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
+ return TextUtils.CAP_MODE_CHARACTERS;
}
- return false;
+
+ final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
+ | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0;
+ if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF;
+
+ // Avoid making heavy round-trip IPC calls of {@link InputConnection#getCursorCapsMode}
+ // unless needed.
+ if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF;
+
+ // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
+ // Note: getCursorCapsMode() returns the current capitalization mode that is any
+ // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none
+ // of them.
+ return mConnection.getCursorCapsMode(inputType);
}
private void swapSwapperAndSpace() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- CharSequence lastTwo = ic.getTextBeforeCursor(2, 0);
+ CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
// It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
if (lastTwo != null && lastTwo.length() == 2
&& lastTwo.charAt(0) == Keyboard.CODE_SPACE) {
- ic.beginBatchEdit();
- ic.deleteSurroundingText(2, 0);
- ic.commitText(lastTwo.charAt(1) + " ", 1);
- ic.endBatchEdit();
+ mConnection.deleteSurroundingText(2, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(2);
+ }
+ mConnection.commitText(lastTwo.charAt(1) + " ", 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_swapSwapperAndSpaceWhileInBatchEdit();
+ }
mKeyboardSwitcher.updateShiftState();
}
}
- private void maybeDoubleSpace() {
- if (mCorrectionMode == Suggest.CORRECTION_NONE) return;
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
+ private boolean maybeDoubleSpace() {
+ if (!mCurrentSettings.mCorrectionEnabled) return false;
+ if (!mHandler.isAcceptingDoubleSpaces()) return false;
+ final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3
- && Character.isLetterOrDigit(lastThree.charAt(0))
+ && canBeFollowedByPeriod(lastThree.charAt(0))
&& lastThree.charAt(1) == Keyboard.CODE_SPACE
- && lastThree.charAt(2) == Keyboard.CODE_SPACE
- && mHandler.isAcceptingDoubleSpaces()) {
+ && lastThree.charAt(2) == Keyboard.CODE_SPACE) {
mHandler.cancelDoubleSpacesTimer();
- ic.beginBatchEdit();
- ic.deleteSurroundingText(2, 0);
- ic.commitText(". ", 1);
- ic.endBatchEdit();
+ mConnection.deleteSurroundingText(2, 0);
+ mConnection.commitText(". ", 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_doubleSpaceAutoPeriod();
+ }
mKeyboardSwitcher.updateShiftState();
- mJustReplacedDoubleSpace = true;
- } else {
- mHandler.startDoubleSpacesTimer();
+ return true;
}
+ return false;
}
- private void maybeRemovePreviousPeriod(CharSequence text) {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
-
- // When the text's first character is '.', remove the previous period
- // if there is one.
- CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
- if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == Keyboard.CODE_PERIOD
- && text.charAt(0) == Keyboard.CODE_PERIOD) {
- ic.deleteSurroundingText(1, 0);
- }
- }
-
- private void removeTrailingSpace() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
-
- CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
- if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == Keyboard.CODE_SPACE) {
- ic.deleteSurroundingText(1, 0);
- }
+ private static boolean canBeFollowedByPeriod(final int codePoint) {
+ // TODO: Check again whether there really ain't a better way to check this.
+ // TODO: This should probably be language-dependant...
+ return Character.isLetterOrDigit(codePoint)
+ || codePoint == Keyboard.CODE_SINGLE_QUOTE
+ || codePoint == Keyboard.CODE_DOUBLE_QUOTE
+ || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS
+ || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET
+ || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET
+ || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
}
@Override
public boolean addWordToDictionary(String word) {
- mUserDictionary.addWord(word, 128);
+ mUserDictionary.addWordToUserDictionary(word, 128);
// Suggestion strip should be updated after the operation of adding word to the
// user dictionary
mHandler.postUpdateSuggestions();
return true;
}
- private boolean isAlphabet(int code) {
- if (Character.isLetter(code)) {
- return true;
- } else {
- return false;
- }
+ private static boolean isAlphabet(int code) {
+ return Character.isLetter(code);
}
private void onSettingsKeyPressed() {
- if (isShowingOptionDialog())
- return;
- if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
- showSubtypeSelectorAndSettings();
- } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) {
- showOptionsMenu();
- } else {
- launchSettings();
- }
+ if (isShowingOptionDialog()) return;
+ showSubtypeSelectorAndSettings();
}
- private void onSettingsKeyLongPressed() {
- if (!isShowingOptionDialog()) {
- if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm)) {
+ // Virtual codes representing custom requests. These are used in onCustomRequest() below.
+ public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1;
+
+ @Override
+ public boolean onCustomRequest(int requestCode) {
+ if (isShowingOptionDialog()) return false;
+ switch (requestCode) {
+ case CODE_SHOW_INPUT_METHOD_PICKER:
+ if (ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
+ this, true /* include aux subtypes */)) {
mImm.showInputMethodPicker();
- } else {
- launchSettings();
+ return true;
}
+ return false;
}
+ return false;
}
private boolean isShowingOptionDialog() {
return mOptionsDialog != null && mOptionsDialog.isShowing();
}
+ private static int getActionId(Keyboard keyboard) {
+ return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE;
+ }
+
+ private void performEditorAction(int actionId) {
+ mConnection.performEditorAction(actionId);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_performEditorAction(actionId);
+ }
+ }
+
+ private void handleLanguageSwitchKey() {
+ final boolean includesOtherImes = mCurrentSettings.mIncludesOtherImesInLanguageSwitchList;
+ final IBinder token = getWindow().getWindow().getAttributes().token;
+ if (mShouldSwitchToLastSubtype) {
+ final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype();
+ final boolean lastSubtypeBelongsToThisIme =
+ ImfUtils.checkIfSubtypeBelongsToThisImeAndEnabled(this, lastSubtype);
+ if ((includesOtherImes || lastSubtypeBelongsToThisIme)
+ && mImm.switchToLastInputMethod(token)) {
+ mShouldSwitchToLastSubtype = false;
+ } else {
+ mImm.switchToNextInputMethod(token, !includesOtherImes);
+ mShouldSwitchToLastSubtype = true;
+ }
+ } else {
+ mImm.switchToNextInputMethod(token, !includesOtherImes);
+ }
+ }
+
+ private void sendUpDownEnterOrBackspace(final int code) {
+ final long eventTime = SystemClock.uptimeMillis();
+ mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime,
+ KeyEvent.ACTION_DOWN, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
+ mConnection.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+ KeyEvent.ACTION_UP, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
+ }
+
+ private void sendKeyCodePoint(int code) {
+ // TODO: Remove this special handling of digit letters.
+ // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
+ if (code >= '0' && code <= '9') {
+ super.sendKeyChar((char)code);
+ return;
+ }
+
+ // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
+ // we want to be able to compile against the Ice Cream Sandwich SDK.
+ if (Keyboard.CODE_ENTER == code && mTargetApplicationInfo != null
+ && mTargetApplicationInfo.targetSdkVersion < 16) {
+ // Backward compatibility mode. Before Jelly bean, the keyboard would simulate
+ // a hardware keyboard event on pressing enter or delete. This is bad for many
+ // reasons (there are race conditions with commits) but some applications are
+ // relying on this behavior so we continue to support it for older apps.
+ sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_ENTER);
+ } else {
+ final String text = new String(new int[] { code }, 0, 1);
+ mConnection.commitText(text, text.length());
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_sendKeyCodePoint(code);
+ }
+ }
+
// Implementation of {@link KeyboardActionListener}.
@Override
- public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
- long when = SystemClock.uptimeMillis();
+ public void onCodeInput(int primaryCode, int x, int y) {
+ final long when = SystemClock.uptimeMillis();
if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
mDeleteCount = 0;
}
mLastKeyTime = when;
- KeyboardSwitcher switcher = mKeyboardSwitcher;
- final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
- final boolean lastStateOfJustReplacedDoubleSpace = mJustReplacedDoubleSpace;
- mJustReplacedDoubleSpace = false;
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
+ }
+
+ final KeyboardSwitcher switcher = mKeyboardSwitcher;
+ // The space state depends only on the last character pressed and its own previous
+ // state. Here, we revert the space state to neutral if the key is actually modifying
+ // the input contents (any non-shift key), which is what we should do for
+ // all inputs that do not result in a special state. Each character handling is then
+ // free to override the state as they see fit.
+ final int spaceState = mSpaceState;
+ if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false;
+
+ // TODO: Consolidate the double space timer, mLastKeyTime, and the space state.
+ if (primaryCode != Keyboard.CODE_SPACE) {
+ mHandler.cancelDoubleSpacesTimer();
+ }
+
+ boolean didAutoCorrect = false;
switch (primaryCode) {
case Keyboard.CODE_DELETE:
- handleBackspace(lastStateOfJustReplacedDoubleSpace);
+ mSpaceState = SPACE_STATE_NONE;
+ handleBackspace(spaceState);
mDeleteCount++;
mExpectingUpdateSelection = true;
- LatinImeLogger.logOnDelete();
+ mShouldSwitchToLastSubtype = true;
+ LatinImeLogger.logOnDelete(x, y);
break;
case Keyboard.CODE_SHIFT:
- // Shift key is handled in onPress() when device has distinct multi-touch panel.
- if (!distinctMultiTouch)
- switcher.toggleShift();
- break;
case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
- // Symbol key is handled in onPress() when device has distinct multi-touch panel.
- if (!distinctMultiTouch)
- switcher.changeKeyboardMode();
- break;
- case Keyboard.CODE_CANCEL:
- if (!isShowingOptionDialog()) {
- handleClose();
- }
+ // Shift and symbol key is handled in onPressKey() and onReleaseKey().
break;
case Keyboard.CODE_SETTINGS:
onSettingsKeyPressed();
break;
- case Keyboard.CODE_SETTINGS_LONGPRESS:
- onSettingsKeyLongPressed();
+ case Keyboard.CODE_SHORTCUT:
+ mSubtypeSwitcher.switchToShortcutIME();
break;
- case LatinKeyboard.CODE_NEXT_LANGUAGE:
- toggleLanguage(true);
+ case Keyboard.CODE_ACTION_ENTER:
+ performEditorAction(getActionId(switcher.getKeyboard()));
break;
- case LatinKeyboard.CODE_PREV_LANGUAGE:
- toggleLanguage(false);
+ case Keyboard.CODE_ACTION_NEXT:
+ performEditorAction(EditorInfo.IME_ACTION_NEXT);
break;
- case Keyboard.CODE_CAPSLOCK:
- switcher.toggleCapsLock();
+ case Keyboard.CODE_ACTION_PREVIOUS:
+ performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
break;
- case Keyboard.CODE_SHORTCUT:
- mSubtypeSwitcher.switchToShortcutIME();
+ case Keyboard.CODE_LANGUAGE_SWITCH:
+ handleLanguageSwitchKey();
break;
- case Keyboard.CODE_TAB:
- handleTab();
- // There are two cases for tab. Either we send a "next" event, that may change the
- // focus but will never move the cursor. Or, we send a real tab keycode, which some
- // applications may accept or ignore, and we don't know whether this will move the
- // cursor or not. So actually, we don't really know.
- // So to go with the safer option, we'd rather behave as if the user moved the
- // cursor when they didn't than the opposite. We also expect that most applications
- // will actually use tab only for focus movement.
- // To sum it up: do not update mExpectingUpdateSelection here.
+ case Keyboard.CODE_RESEARCH:
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().presentResearchDialog(this);
+ }
break;
default:
- if (mSettingsValues.isWordSeparator(primaryCode)) {
- handleSeparator(primaryCode, x, y);
+ if (primaryCode == Keyboard.CODE_TAB && mCurrentSettings.isEditorActionNext()) {
+ performEditorAction(EditorInfo.IME_ACTION_NEXT);
+ break;
+ }
+ mSpaceState = SPACE_STATE_NONE;
+ if (mCurrentSettings.isWordSeparator(primaryCode)) {
+ didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
} else {
- handleCharacter(primaryCode, keyCodes, x, y);
+ final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
+ if (keyboard != null && keyboard.hasProximityCharsCorrection(primaryCode)) {
+ handleCharacter(primaryCode, x, y, spaceState);
+ } else {
+ handleCharacter(primaryCode, NOT_A_TOUCH_COORDINATE, NOT_A_TOUCH_COORDINATE,
+ spaceState);
+ }
}
mExpectingUpdateSelection = true;
+ mShouldSwitchToLastSubtype = true;
break;
}
- switcher.onKey(primaryCode);
- // Reset after any single keystroke
+ switcher.onCodeInput(primaryCode);
+ // Reset after any single keystroke, except shift and symbol-shift
+ if (!didAutoCorrect && primaryCode != Keyboard.CODE_SHIFT
+ && primaryCode != Keyboard.CODE_SWITCH_ALPHA_SYMBOL)
+ mLastComposedWord.deactivate();
mEnteredText = null;
+ mConnection.endBatchEdit();
}
@Override
public void onTextInput(CharSequence text) {
- mVoiceProxy.commitVoiceInput();
- InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- mRecorrection.abortRecorrection(false);
- ic.beginBatchEdit();
- commitTyped(ic);
- maybeRemovePreviousPeriod(text);
- ic.commitText(text, 1);
- ic.endBatchEdit();
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+ commitTyped(LastComposedWord.NOT_A_SEPARATOR);
+ text = specificTldProcessingOnTextInput(text);
+ if (SPACE_STATE_PHANTOM == mSpaceState) {
+ sendKeyCodePoint(Keyboard.CODE_SPACE);
+ }
+ mConnection.commitText(text, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_commitText(text);
+ }
+ mConnection.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
- mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY);
- mJustAddedMagicSpace = false;
+ mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT);
+ mSpaceState = SPACE_STATE_NONE;
mEnteredText = text;
+ resetComposingState(true /* alsoResetLastComposedWord */);
+ }
+
+ private CharSequence specificTldProcessingOnTextInput(final CharSequence text) {
+ if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD
+ || !Character.isLetter(text.charAt(1))) {
+ // Not a tld: do nothing.
+ return text;
+ }
+ // We have a TLD (or something that looks like this): make sure we don't add
+ // a space even if currently in phantom mode.
+ mSpaceState = SPACE_STATE_NONE;
+ final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0);
+ if (lastOne != null && lastOne.length() == 1
+ && lastOne.charAt(0) == Keyboard.CODE_PERIOD) {
+ return text.subSequence(1, text.length());
+ } else {
+ return text;
+ }
}
@Override
@@ -1172,288 +1351,304 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mKeyboardSwitcher.onCancelInput();
}
- private void handleBackspace(boolean justReplacedDoubleSpace) {
- if (mVoiceProxy.logAndRevertVoiceInput()) return;
+ private void handleBackspace(final int spaceState) {
+ // In many cases, we may have to put the keyboard in auto-shift state again.
+ mHandler.postUpdateShiftState();
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- ic.beginBatchEdit();
-
- mVoiceProxy.handleBackspace();
+ if (mEnteredText != null && mConnection.sameAsTextBeforeCursor(mEnteredText)) {
+ // Cancel multi-character input: remove the text we just entered.
+ // This is triggered on backspace after a key that inputs multiple characters,
+ // like the smiley key or the .com key.
+ final int length = mEnteredText.length();
+ mConnection.deleteSurroundingText(length, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(length);
+ }
+ // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
+ // In addition we know that spaceState is false, and that we should not be
+ // reverting any autocorrect at this point. So we can safely return.
+ return;
+ }
- boolean deleteChar = false;
- if (mHasUncommittedTypedChars) {
- final int length = mComposing.length();
+ if (mWordComposer.isComposingWord()) {
+ final int length = mWordComposer.size();
if (length > 0) {
- mComposing.delete(length - 1, length);
- mWord.deleteLast();
- ic.setComposingText(mComposing, 1);
- if (mComposing.length() == 0) {
- mHasUncommittedTypedChars = false;
- }
- if (1 == length) {
- // 1 == length means we are about to erase the last character of the word,
- // so we can show bigrams.
+ mWordComposer.deleteLast();
+ mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+ // If we have deleted the last remaining character of a word, then we are not
+ // isComposingWord() any more.
+ if (!mWordComposer.isComposingWord()) {
+ // Not composing word any more, so we can show bigrams.
mHandler.postUpdateBigramPredictions();
} else {
- // length > 1, so we still have letters to deduce a suggestion from.
+ // Still composing a word, so we still have letters to deduce a suggestion from.
mHandler.postUpdateSuggestions();
}
} else {
- ic.deleteSurroundingText(1, 0);
+ mConnection.deleteSurroundingText(1, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(1);
+ }
}
} else {
- deleteChar = true;
- }
- mHandler.postUpdateShiftKeyState();
-
- TextEntryState.backspace();
- if (TextEntryState.isUndoCommit()) {
- revertLastWord(deleteChar);
- ic.endBatchEdit();
- return;
- }
- if (justReplacedDoubleSpace) {
- if (revertDoubleSpace()) {
- ic.endBatchEdit();
- return;
+ if (mLastComposedWord.canRevertCommit()) {
+ Utils.Stats.onAutoCorrectionCancellation();
+ revertCommit();
+ return;
+ }
+ if (SPACE_STATE_DOUBLE == spaceState) {
+ mHandler.cancelDoubleSpacesTimer();
+ if (mConnection.revertDoubleSpace()) {
+ // No need to reset mSpaceState, it has already be done (that's why we
+ // receive it as a parameter)
+ return;
+ }
+ } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
+ if (mConnection.revertSwapPunctuation()) {
+ // Likewise
+ return;
+ }
}
- }
- if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
- ic.deleteSurroundingText(mEnteredText.length(), 0);
- } else if (deleteChar) {
- if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) {
- // Go back to the suggestion mode if the user canceled the
- // "Touch again to save".
- // NOTE: In gerenal, we don't revert the word when backspacing
- // from a manual suggestion pick. We deliberately chose a
- // different behavior only in the case of picking the first
- // suggestion (typed word). It's intentional to have made this
- // inconsistent with backspacing after selecting other suggestions.
- revertLastWord(deleteChar);
+ // No cancelling of commit/double space/swap: we have a regular backspace.
+ // We should backspace one char and restart suggestion if at the end of a word.
+ if (mLastSelectionStart != mLastSelectionEnd) {
+ // If there is a selection, remove it.
+ final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart;
+ mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
+ mConnection.deleteSurroundingText(lengthToDelete, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(lengthToDelete);
+ }
} else {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+ // There is no selection, just delete one character.
+ if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
+ // This should never happen.
+ Log.e(TAG, "Backspace when we don't know the selection position");
+ }
+ // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
+ // we want to be able to compile against the Ice Cream Sandwich SDK.
+ if (mTargetApplicationInfo != null
+ && mTargetApplicationInfo.targetSdkVersion < 16) {
+ // Backward compatibility mode. Before Jelly bean, the keyboard would simulate
+ // a hardware keyboard event on pressing enter or delete. This is bad for many
+ // reasons (there are race conditions with commits) but some applications are
+ // relying on this behavior so we continue to support it for older apps.
+ sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_DEL);
+ } else {
+ mConnection.deleteSurroundingText(1, 0);
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(1);
+ }
if (mDeleteCount > DELETE_ACCELERATE_AT) {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+ mConnection.deleteSurroundingText(1, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(1);
+ }
}
}
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
+ }
}
- ic.endBatchEdit();
}
- private void handleTab() {
- final int imeOptions = getCurrentInputEditorInfo().imeOptions;
- if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
- && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
- return;
- }
-
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null)
- return;
-
- // True if keyboard is in either chording shift or manual temporary upper case mode.
- final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase();
- if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
- && !isManualTemporaryUpperCase) {
- EditorInfoCompatUtils.performEditorActionNext(ic);
- } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)
- && isManualTemporaryUpperCase) {
- EditorInfoCompatUtils.performEditorActionPrevious(ic);
+ private boolean maybeStripSpace(final int code,
+ final int spaceState, final boolean isFromSuggestionStrip) {
+ if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
+ mConnection.removeTrailingSpace();
+ return false;
+ } else if ((SPACE_STATE_WEAK == spaceState
+ || SPACE_STATE_SWAP_PUNCTUATION == spaceState)
+ && isFromSuggestionStrip) {
+ if (mCurrentSettings.isWeakSpaceSwapper(code)) {
+ return true;
+ } else {
+ if (mCurrentSettings.isWeakSpaceStripper(code)) {
+ mConnection.removeTrailingSpace();
+ }
+ return false;
+ }
+ } else {
+ return false;
}
}
- private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) {
- mVoiceProxy.handleCharacter();
+ private void handleCharacter(final int primaryCode, final int x,
+ final int y, final int spaceState) {
+ boolean isComposingWord = mWordComposer.isComposingWord();
- if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) {
- removeTrailingSpace();
- }
-
- if (mLastSelectionStart == mLastSelectionEnd) {
- mRecorrection.abortRecorrection(false);
- }
-
- int code = primaryCode;
- if (isAlphabet(code) && isSuggestionsRequested() && !isCursorTouchingWord()) {
- if (!mHasUncommittedTypedChars) {
- mHasUncommittedTypedChars = true;
- mComposing.setLength(0);
- mRecorrection.saveRecorrectionSuggestion(mWord, mBestWord);
- mWord.reset();
- clearSuggestions();
- }
- }
- final KeyboardSwitcher switcher = mKeyboardSwitcher;
- if (switcher.isShiftedOrShiftLocked()) {
- if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
- || keyCodes[0] > Character.MAX_CODE_POINT) {
- return;
+ if (SPACE_STATE_PHANTOM == spaceState &&
+ !mCurrentSettings.isSymbolExcludedFromWordSeparators(primaryCode)) {
+ if (isComposingWord) {
+ // Sanity check
+ throw new RuntimeException("Should not be composing here");
}
- code = keyCodes[0];
- if (switcher.isAlphabetMode() && Character.isLowerCase(code)) {
- // In some locales, such as Turkish, Character.toUpperCase() may return a wrong
- // character because it doesn't take care of locale.
- final String upperCaseString = new String(new int[] {code}, 0, 1)
- .toUpperCase(mSubtypeSwitcher.getInputLocale());
- if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) {
- code = upperCaseString.codePointAt(0);
- } else {
- // Some keys, such as [eszett], have upper case as multi-characters.
- onTextInput(upperCaseString);
- return;
- }
- }
- }
- if (mHasUncommittedTypedChars) {
- if (mComposing.length() == 0 && switcher.isAlphabetMode()
- && switcher.isShiftedOrShiftLocked()) {
- mWord.setFirstCharCapitalized(true);
- }
- mComposing.append((char) code);
- mWord.add(code, keyCodes, x, y);
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- // If it's the first letter, make note of auto-caps state
- if (mWord.size() == 1) {
- mWord.setAutoCapitalized(getCurrentAutoCapsState());
- }
- ic.setComposingText(mComposing, 1);
+ sendKeyCodePoint(Keyboard.CODE_SPACE);
+ }
+
+ // NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several
+ // dozen milliseconds. Avoid calling it as much as possible, since we are on the UI
+ // thread here.
+ if (!isComposingWord && (isAlphabet(primaryCode)
+ || mCurrentSettings.isSymbolExcludedFromWordSeparators(primaryCode))
+ && mCurrentSettings.isSuggestionsRequested(mDisplayOrientation) &&
+ !mConnection.isCursorTouchingWord(mCurrentSettings)) {
+ // Reset entirely the composing state anyway, then start composing a new word unless
+ // the character is a single quote. The idea here is, single quote is not a
+ // separator and it should be treated as a normal character, except in the first
+ // position where it should not start composing a word.
+ isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode);
+ // Here we don't need to reset the last composed word. It will be reset
+ // when we commit this one, if we ever do; if on the other hand we backspace
+ // it entirely and resume suggestions on the previous word, we'd like to still
+ // have touch coordinates for it.
+ resetComposingState(false /* alsoResetLastComposedWord */);
+ clearSuggestions();
+ }
+ if (isComposingWord) {
+ mWordComposer.add(
+ primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector());
+ // If it's the first letter, make note of auto-caps state
+ if (mWordComposer.size() == 1) {
+ mWordComposer.setAutoCapitalized(
+ getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF);
}
+ mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
mHandler.postUpdateSuggestions();
} else {
- sendKeyChar((char)code);
- }
- if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
- swapSwapperAndSpace();
- } else {
- mJustAddedMagicSpace = false;
- }
+ final boolean swapWeakSpace = maybeStripSpace(primaryCode,
+ spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x);
- switcher.updateShiftState();
- if (LatinIME.PERF_DEBUG) measureCps();
- TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y);
- }
+ sendKeyCodePoint(primaryCode);
- private void handleSeparator(int primaryCode, int x, int y) {
- mVoiceProxy.handleSeparator();
+ if (swapWeakSpace) {
+ swapSwapperAndSpace();
+ mSpaceState = SPACE_STATE_WEAK;
+ }
+ // Some characters are not word separators, yet they don't start a new
+ // composing span. For these, we haven't changed the suggestion strip, and
+ // if the "add to dictionary" hint is shown, we should do so now. Examples of
+ // such characters include single quote, dollar, and others; the exact list is
+ // the list of characters for which we enter handleCharacterWhileInBatchEdit
+ // that don't match the test if ((isAlphabet...)) at the top of this method.
+ if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) {
+ mHandler.postUpdateBigramPredictions();
+ }
+ }
+ Utils.Stats.onNonSeparator((char)primaryCode, x, y);
+ }
+ // Returns true if we did an autocorrection, false otherwise.
+ private boolean handleSeparator(final int primaryCode, final int x, final int y,
+ final int spaceState) {
// Should dismiss the "Touch again to save" message when handling separator
- if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) {
+ if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) {
mHandler.cancelUpdateBigramPredictions();
mHandler.postUpdateSuggestions();
}
- boolean pickedDefault = false;
+ boolean didAutoCorrect = false;
// Handle separator
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.beginBatchEdit();
- mRecorrection.abortRecorrection(false);
- }
- if (mHasUncommittedTypedChars) {
+ if (mWordComposer.isComposingWord()) {
// In certain languages where single quote is a separator, it's better
// not to auto correct, but accept the typed word. For instance,
// in Italian dov' should not be expanded to dove' because the elision
// requires the last vowel to be removed.
- final boolean shouldAutoCorrect =
- (mSettingsValues.mAutoCorrectEnabled || mSettingsValues.mQuickFixes)
- && !mInputTypeNoAutoCorrect && mHasDictionary;
- if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
- pickedDefault = pickDefaultSuggestion(primaryCode);
+ if (mCurrentSettings.mCorrectionEnabled && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
+ commitCurrentAutoCorrection(primaryCode);
+ didAutoCorrect = true;
} else {
- commitTyped(ic);
+ commitTyped(primaryCode);
}
}
- if (mJustAddedMagicSpace) {
- if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) {
- sendKeyChar((char)primaryCode);
- swapSwapperAndSpace();
- } else {
- if (mSettingsValues.isMagicSpaceStripper(primaryCode)) removeTrailingSpace();
- sendKeyChar((char)primaryCode);
- mJustAddedMagicSpace = false;
- }
- } else {
- sendKeyChar((char)primaryCode);
- }
+ final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
+ KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x);
- if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) {
- maybeDoubleSpace();
+ if (SPACE_STATE_PHANTOM == spaceState &&
+ mCurrentSettings.isPhantomSpacePromotingSymbol(primaryCode)) {
+ sendKeyCodePoint(Keyboard.CODE_SPACE);
}
+ sendKeyCodePoint(primaryCode);
- TextEntryState.typedCharacter((char) primaryCode, true, x, y);
-
- if (pickedDefault) {
- CharSequence typedWord = mWord.getTypedWord();
- TextEntryState.backToAcceptedDefault(typedWord);
- if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
- InputConnectionCompatUtils.commitCorrection(
- ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord);
- if (mCandidateView != null)
- mCandidateView.onAutoCorrectionInverted(mBestWord);
- }
- }
if (Keyboard.CODE_SPACE == primaryCode) {
- if (!isCursorTouchingWord()) {
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ if (maybeDoubleSpace()) {
+ mSpaceState = SPACE_STATE_DOUBLE;
+ } else if (!isShowingPunctuationList()) {
+ mSpaceState = SPACE_STATE_WEAK;
+ }
+ }
+
+ mHandler.startDoubleSpacesTimer();
+ if (!mConnection.isCursorTouchingWord(mCurrentSettings)) {
mHandler.cancelUpdateSuggestions();
- mHandler.cancelUpdateOldSuggestions();
mHandler.postUpdateBigramPredictions();
}
} else {
+ if (swapWeakSpace) {
+ swapSwapperAndSpace();
+ mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
+ } else if (SPACE_STATE_PHANTOM == spaceState) {
+ // If we are in phantom space state, and the user presses a separator, we want to
+ // stay in phantom space state so that the next keypress has a chance to add the
+ // space. For example, if I type "Good dat", pick "day" from the suggestion strip
+ // then insert a comma and go on to typing the next word, I want the space to be
+ // inserted automatically before the next word, the same way it is when I don't
+ // input the comma.
+ mSpaceState = SPACE_STATE_PHANTOM;
+ }
+
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
// already displayed or not, so it's okay.
setPunctuationSuggestions();
}
- mKeyboardSwitcher.updateShiftState();
- if (ic != null) {
- ic.endBatchEdit();
- }
+
+ Utils.Stats.onSeparator((char)primaryCode, x, y);
+
+ return didAutoCorrect;
+ }
+
+ private CharSequence getTextWithUnderline(final CharSequence text) {
+ return mIsAutoCorrectionIndicatorOn
+ ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text)
+ : text;
}
private void handleClose() {
- commitTyped(getCurrentInputConnection());
- mVoiceProxy.handleClose();
+ commitTyped(LastComposedWord.NOT_A_SEPARATOR);
requestHideSelf(0);
LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null)
inputView.closing();
}
- public boolean isSuggestionsRequested() {
- return mIsSettingsSuggestionStripOn
- && (mCorrectionMode > 0 || isShowingSuggestionsStrip());
- }
-
public boolean isShowingPunctuationList() {
- return mSettingsValues.mSuggestPuncList == mCandidateView.getSuggestions();
+ if (mSuggestionsView == null) return false;
+ return mCurrentSettings.mSuggestPuncList == mSuggestionsView.getSuggestions();
}
- public boolean isShowingSuggestionsStrip() {
- return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE)
- || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE
- && mOrientation == Configuration.ORIENTATION_PORTRAIT);
- }
-
- public boolean isCandidateStripVisible() {
- if (mCandidateView == null)
+ public boolean isSuggestionsStripVisible() {
+ if (mSuggestionsView == null)
return false;
- if (mCandidateView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting())
+ if (mSuggestionsView.isShowingAddToDictionaryHint())
return true;
- if (!isShowingSuggestionsStrip())
+ if (!mCurrentSettings.isSuggestionStripVisibleInOrientation(mDisplayOrientation))
return false;
- if (mApplicationSpecifiedCompletionOn)
+ if (mCurrentSettings.isApplicationSpecifiedCompletionsOn())
return true;
- return isSuggestionsRequested();
+ return mCurrentSettings.isSuggestionsRequested(mDisplayOrientation);
}
public void switchToKeyboardView() {
if (DEBUG) {
Log.d(TAG, "Switch to keyboard view.");
}
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_switchToKeyboardView();
+ }
View v = mKeyboardSwitcher.getKeyboardView();
if (v != null) {
// Confirms that the keyboard view doesn't have parent view.
@@ -1463,56 +1658,59 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
setInputView(v);
}
- setSuggestionStripShown(isCandidateStripVisible());
+ setSuggestionStripShown(isSuggestionsStripVisible());
updateInputViewShown();
mHandler.postUpdateSuggestions();
}
public void clearSuggestions() {
- setSuggestions(SuggestedWords.EMPTY);
+ setSuggestions(SuggestedWords.EMPTY, false);
+ setAutoCorrectionIndicator(false);
}
- public void setSuggestions(SuggestedWords words) {
- if (mCandidateView != null) {
- mCandidateView.setSuggestions(words);
- mKeyboardSwitcher.onAutoCorrectionStateChanged(
- words.hasWordAboveAutoCorrectionScoreThreshold());
+ private void setSuggestions(final SuggestedWords words, final boolean isAutoCorrection) {
+ if (mSuggestionsView != null) {
+ mSuggestionsView.setSuggestions(words);
+ mKeyboardSwitcher.onAutoCorrectionStateChanged(isAutoCorrection);
+ }
+ }
+
+ private void setAutoCorrectionIndicator(final boolean newAutoCorrectionIndicator) {
+ // Put a blue underline to a word in TextView which will be auto-corrected.
+ if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator
+ && mWordComposer.isComposingWord()) {
+ mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
+ final CharSequence textWithUnderline =
+ getTextWithUnderline(mWordComposer.getTypedWord());
+ mConnection.setComposingText(textWithUnderline, 1);
}
}
public void updateSuggestions() {
// Check if we have a suggestion engine attached.
- if ((mSuggest == null || !isSuggestionsRequested())
- && !mVoiceProxy.isVoiceInputHighlighted()) {
+ if ((mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))) {
+ if (mWordComposer.isComposingWord()) {
+ Log.w(TAG, "Called updateSuggestions but suggestions were not requested!");
+ mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
+ }
return;
}
- if (!mHasUncommittedTypedChars) {
+ mHandler.cancelUpdateSuggestions();
+ mHandler.cancelUpdateBigramPredictions();
+
+ if (!mWordComposer.isComposingWord()) {
setPunctuationSuggestions();
return;
}
- showSuggestions(mWord);
- }
- private void showSuggestions(WordComposer word) {
// TODO: May need a better way of retrieving previous word
- CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
- mSettingsValues.mWordSeparators);
- SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
- mKeyboardSwitcher.getKeyboardView(), word, prevWord);
-
- boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
- final CharSequence typedWord = word.getTypedWord();
- // Here, we want to promote a whitelisted word if exists.
- final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection(
- mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization());
- if (mCorrectionMode == Suggest.CORRECTION_FULL
- || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) {
- correctionAvailable |= typedWordValid;
- }
- // Don't auto-correct words with multiple capital letter
- correctionAvailable &= !word.isMostlyCaps();
- correctionAvailable &= !TextEntryState.isRecorrecting();
+ final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators);
+ final CharSequence typedWord = mWordComposer.getTypedWord();
+ // getSuggestedWords handles gracefully a null value of prevWord
+ final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
+ prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
+ mCurrentSettings.mCorrectionEnabled);
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1520,151 +1718,159 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// in most cases, suggestion count is 1 when typed word's length is 1, but we do always
// need to clear the previous state when the user starts typing a word (i.e. typed word's
// length == 1).
- if (typedWord != null) {
- if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid
- || mCandidateView.isShowingAddToDictionaryHint()) {
- builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(
- correctionAvailable);
- } else {
- final SuggestedWords previousSuggestions = mCandidateView.getSuggestions();
- if (previousSuggestions == mSettingsValues.mSuggestPuncList)
- return;
- builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions);
+ if (suggestedWords.size() > 1 || typedWord.length() == 1
+ || !suggestedWords.mAllowsToBeAutoCorrected
+ || mSuggestionsView.isShowingAddToDictionaryHint()) {
+ showSuggestions(suggestedWords, typedWord);
+ } else {
+ SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions();
+ if (previousSuggestions == mCurrentSettings.mSuggestPuncList) {
+ previousSuggestions = SuggestedWords.EMPTY;
}
- }
- showSuggestions(builder.build(), typedWord);
- }
-
- public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) {
- setSuggestions(suggestedWords);
+ final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
+ SuggestedWords.getTypedWordAndPreviousSuggestions(
+ typedWord, previousSuggestions);
+ final SuggestedWords obsoleteSuggestedWords =
+ new SuggestedWords(typedWordAndPreviousSuggestions,
+ false /* typedWordValid */,
+ false /* hasAutoCorrectionCandidate */,
+ false /* allowsToBeAutoCorrected */,
+ false /* isPunctuationSuggestions */,
+ true /* isObsoleteSuggestions */,
+ false /* isPrediction */);
+ showSuggestions(obsoleteSuggestedWords, typedWord);
+ }
+ }
+
+ public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) {
+ final CharSequence autoCorrection;
if (suggestedWords.size() > 0) {
- if (Utils.shouldBlockedBySafetyNetForAutoCorrection(suggestedWords, mSuggest)) {
- mBestWord = typedWord;
- } else if (suggestedWords.hasAutoCorrectionWord()) {
- mBestWord = suggestedWords.getWord(1);
+ if (suggestedWords.hasAutoCorrectionWord()) {
+ autoCorrection = suggestedWords.getWord(1);
} else {
- mBestWord = typedWord;
+ autoCorrection = typedWord;
}
} else {
- mBestWord = null;
+ autoCorrection = null;
}
- setSuggestionStripShown(isCandidateStripVisible());
+ mWordComposer.setAutoCorrection(autoCorrection);
+ final boolean isAutoCorrection = suggestedWords.willAutoCorrect();
+ setSuggestions(suggestedWords, isAutoCorrection);
+ setAutoCorrectionIndicator(isAutoCorrection);
+ setSuggestionStripShown(isSuggestionsStripVisible());
}
- private boolean pickDefaultSuggestion(int separatorCode) {
- // Complete any pending candidate query first
+ private void commitCurrentAutoCorrection(final int separatorCodePoint) {
+ // Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) {
mHandler.cancelUpdateSuggestions();
updateSuggestions();
}
- if (mBestWord != null && mBestWord.length() > 0) {
- TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord, separatorCode);
+ final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
+ if (autoCorrection != null) {
+ final String typedWord = mWordComposer.getTypedWord();
+ if (TextUtils.isEmpty(typedWord)) {
+ throw new RuntimeException("We have an auto-correction but the typed word "
+ + "is empty? Impossible! I must commit suicide.");
+ }
+ Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_commitCurrentAutoCorrection(typedWord,
+ autoCorrection.toString());
+ }
mExpectingUpdateSelection = true;
- commitBestWord(mBestWord);
- // Add the word to the auto dictionary if it's not a known word
- addToAutoAndUserBigramDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED);
- return true;
+ commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
+ separatorCodePoint);
+ if (!typedWord.equals(autoCorrection)) {
+ // This will make the correction flash for a short while as a visual clue
+ // to the user that auto-correction happened.
+ mConnection.commitCorrection(
+ new CorrectionInfo(mLastSelectionEnd - typedWord.length(),
+ typedWord, autoCorrection));
+ }
}
- return false;
}
@Override
- public void pickSuggestionManually(int index, CharSequence suggestion) {
- SuggestedWords suggestions = mCandidateView.getSuggestions();
- mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion,
- mSettingsValues.mWordSeparators);
+ public void pickSuggestionManually(final int index, final CharSequence suggestion,
+ final int x, final int y) {
+ final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
+ // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
+ if (suggestion.length() == 1 && isShowingPunctuationList()) {
+ // Word separators are suggested before the user inputs something.
+ // So, LatinImeLogger logs "" as a user's input.
+ LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords);
+ // Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y);
+ }
+ final int primaryCode = suggestion.charAt(0);
+ onCodeInput(primaryCode,
+ KeyboardActionListener.SUGGESTION_STRIP_COORDINATE,
+ KeyboardActionListener.SUGGESTION_STRIP_COORDINATE);
+ return;
+ }
- final boolean recorrecting = TextEntryState.isRecorrecting();
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.beginBatchEdit();
+ if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) {
+ int firstChar = Character.codePointAt(suggestion, 0);
+ if ((!mCurrentSettings.isWeakSpaceStripper(firstChar))
+ && (!mCurrentSettings.isWeakSpaceSwapper(firstChar))) {
+ sendKeyCodePoint(Keyboard.CODE_SPACE);
+ }
}
- if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null
+
+ if (mCurrentSettings.isApplicationSpecifiedCompletionsOn()
+ && mApplicationSpecifiedCompletions != null
&& index >= 0 && index < mApplicationSpecifiedCompletions.length) {
- CompletionInfo ci = mApplicationSpecifiedCompletions[index];
- if (ic != null) {
- ic.commitCompletion(ci);
- }
- mCommittedLength = suggestion.length();
- if (mCandidateView != null) {
- mCandidateView.clear();
+ if (mSuggestionsView != null) {
+ mSuggestionsView.clear();
}
mKeyboardSwitcher.updateShiftState();
- if (ic != null) {
- ic.endBatchEdit();
+ resetComposingState(true /* alsoResetLastComposedWord */);
+ final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+ mConnection.commitCompletion(completionInfo);
+ mConnection.endBatchEdit();
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index,
+ completionInfo.getText(), x, y);
}
return;
}
- // If this is a punctuation, apply it through the normal key press
- if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0))
- || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) {
- // Word separators are suggested before the user inputs something.
- // So, LatinImeLogger logs "" as a user's input.
- LatinImeLogger.logOnManualSuggestion(
- "", suggestion.toString(), index, suggestions.mWords);
- // Find out whether the previous character is a space. If it is, as a special case
- // for punctuation entered through the suggestion strip, it should be considered
- // a magic space even if it was a normal space. This is meant to help in case the user
- // pressed space on purpose of displaying the suggestion strip punctuation.
- final char primaryCode = suggestion.charAt(0);
- final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : "";
- final int toLeft = (ic == null || TextUtils.isEmpty(beforeText))
- ? 0 : beforeText.charAt(0);
- final boolean oldMagicSpace = mJustAddedMagicSpace;
- if (Keyboard.CODE_SPACE == toLeft) mJustAddedMagicSpace = true;
- onCodeInput(primaryCode, new int[] { primaryCode },
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
- KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
- mJustAddedMagicSpace = oldMagicSpace;
- if (ic != null) {
- ic.endBatchEdit();
- }
- return;
- }
- if (!mHasUncommittedTypedChars) {
- // If we are not composing a word, then it was a suggestion inferred from
- // context - no user input. We should reset the word composer.
- mWord.reset();
+ // We need to log before we commit, because the word composer will store away the user
+ // typed word.
+ final String replacedWord = mWordComposer.getTypedWord().toString();
+ LatinImeLogger.logOnManualSuggestion(replacedWord,
+ suggestion.toString(), index, suggestedWords);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_pickSuggestionManually(replacedWord, index, suggestion, x, y);
}
mExpectingUpdateSelection = true;
- commitBestWord(suggestion);
- // Add the word to the auto dictionary if it's not a known word
- if (index == 0) {
- addToAutoAndUserBigramDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED);
- } else {
- addToOnlyBigramDictionary(suggestion, 1);
- }
- LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(),
- index, suggestions.mWords);
- TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
- // Follow it with a space
- if (mShouldInsertMagicSpace && !recorrecting) {
- sendMagicSpace();
- }
+ commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
+ LastComposedWord.NOT_A_SEPARATOR);
+ // Don't allow cancellation of manual pick
+ mLastComposedWord.deactivate();
+ mSpaceState = SPACE_STATE_PHANTOM;
+ // TODO: is this necessary?
+ mKeyboardSwitcher.updateShiftState();
- // We should show the hint if the user pressed the first entry AND either:
+ // We should show the "Touch again to save" hint if the user pressed the first entry
+ // AND either:
// - There is no dictionary (we know that because we tried to load it => null != mSuggest
- // AND mHasDictionary is false)
+ // AND mSuggest.hasMainDictionary() is false)
// - There is a dictionary and the word is not in it
// Please note that if mSuggest is null, it means that everything is off: suggestion
// and correction, so we shouldn't try to show the hint
- // We used to look at mCorrectionMode here, but showing the hint should have nothing
- // to do with the autocorrection setting.
final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null
// If there is no dictionary the hint should be shown.
- && (!mHasDictionary
+ && (!mSuggest.hasMainDictionary()
// If "suggestion" is not in the dictionary, the hint should be shown.
|| !AutoCorrection.isValidWord(
mSuggest.getUnigramDictionaries(), suggestion, true));
- if (!recorrecting) {
- // Fool the state watcher so that a subsequent backspace will not do a revert, unless
- // we just did a correction, in which case we need to stay in
- // TextEntryState.State.PICKED_SUGGESTION state.
- TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true,
- WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
- }
+ Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE,
+ WordComposer.NOT_A_COORDINATE);
if (!showingAddToDictionaryHint) {
// If we're not showing the "Touch again to save", then show corrections again.
// In case the cursor position doesn't change, make sure we show the suggestions again.
@@ -1672,377 +1878,271 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Updating the predictions right away may be slow and feel unresponsive on slower
// terminals. On the other hand if we just postUpdateBigramPredictions() it will
// take a noticeable delay to update them which may feel uneasy.
- }
- if (showingAddToDictionaryHint) {
- mCandidateView.showAddToDictionaryHint(suggestion);
- }
- if (ic != null) {
- ic.endBatchEdit();
+ } else {
+ if (mIsUserDictionaryAvailable) {
+ mSuggestionsView.showAddToDictionaryHint(
+ suggestion, mCurrentSettings.mHintToSaveText);
+ } else {
+ mHandler.postUpdateSuggestions();
+ }
}
}
/**
- * Commits the chosen word to the text field and saves it for later
- * retrieval.
+ * Commits the chosen word to the text field and saves it for later retrieval.
*/
- private void commitBestWord(CharSequence bestWord) {
- KeyboardSwitcher switcher = mKeyboardSwitcher;
- if (!switcher.isKeyboardAvailable())
- return;
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators);
- SuggestedWords suggestedWords = mCandidateView.getSuggestions();
- ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
- this, bestWord, suggestedWords), 1);
- }
- mRecorrection.saveRecorrectionSuggestion(mWord, bestWord);
- mHasUncommittedTypedChars = false;
- mCommittedLength = bestWord.length();
+ private void commitChosenWord(final CharSequence chosenWord, final int commitType,
+ final int separatorCode) {
+ final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
+ mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
+ this, chosenWord, suggestedWords, mIsMainDictionaryAvailable), 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_commitText(chosenWord);
+ }
+ // Add the word to the user history dictionary
+ final CharSequence prevWord = addToUserHistoryDictionary(chosenWord);
+ // TODO: figure out here if this is an auto-correct or if the best word is actually
+ // what user typed. Note: currently this is done much later in
+ // LastComposedWord#didCommitTypedWord by string equality of the remembered
+ // strings.
+ mLastComposedWord = mWordComposer.commitWord(commitType, chosenWord.toString(),
+ separatorCode, prevWord);
}
- private static final WordComposer sEmptyWordComposer = new WordComposer();
public void updateBigramPredictions() {
- if (mSuggest == null || !isSuggestionsRequested())
+ if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))
return;
- if (!mSettingsValues.mBigramPredictionEnabled) {
+ if (!mCurrentSettings.mBigramPredictionEnabled) {
setPunctuationSuggestions();
return;
}
- final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(),
- mSettingsValues.mWordSeparators);
- SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
- mKeyboardSwitcher.getKeyboardView(), sEmptyWordComposer, prevWord);
+ final SuggestedWords suggestedWords;
+ if (mCurrentSettings.mCorrectionEnabled) {
+ final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
+ if (!TextUtils.isEmpty(prevWord)) {
+ suggestedWords = mSuggest.getBigramPredictions(prevWord);
+ } else {
+ suggestedWords = null;
+ }
+ } else {
+ suggestedWords = null;
+ }
- if (builder.size() > 0) {
+ if (null != suggestedWords && suggestedWords.size() > 0) {
// Explicitly supply an empty typed word (the no-second-arg version of
// showSuggestions will retrieve the word near the cursor, we don't want that here)
- showSuggestions(builder.build(), "");
+ showSuggestions(suggestedWords, "");
} else {
- if (!isShowingPunctuationList()) setPunctuationSuggestions();
+ clearSuggestions();
}
}
public void setPunctuationSuggestions() {
- setSuggestions(mSettingsValues.mSuggestPuncList);
- setSuggestionStripShown(isCandidateStripVisible());
- }
-
- private void addToAutoAndUserBigramDictionaries(CharSequence suggestion, int frequencyDelta) {
- checkAddToDictionary(suggestion, frequencyDelta, false);
- }
-
- private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) {
- checkAddToDictionary(suggestion, frequencyDelta, true);
+ if (mCurrentSettings.mBigramPredictionEnabled) {
+ clearSuggestions();
+ } else {
+ setSuggestions(mCurrentSettings.mSuggestPuncList, false);
+ }
+ setAutoCorrectionIndicator(false);
+ setSuggestionStripShown(isSuggestionsStripVisible());
}
- /**
- * Adds to the UserBigramDictionary and/or AutoDictionary
- * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible
- */
- private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta,
- boolean selectedANotTypedWord) {
- if (suggestion == null || suggestion.length() < 1) return;
-
- // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be
- // adding words in situations where the user or application really didn't
- // want corrections enabled or learned.
- if (!(mCorrectionMode == Suggest.CORRECTION_FULL
- || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) {
- return;
- }
+ private CharSequence addToUserHistoryDictionary(final CharSequence suggestion) {
+ if (TextUtils.isEmpty(suggestion)) return null;
- final boolean selectedATypedWordAndItsInAutoDic =
- !selectedANotTypedWord && mAutoDictionary.isValidWord(suggestion);
- final boolean isValidWord = AutoCorrection.isValidWord(
- mSuggest.getUnigramDictionaries(), suggestion, true);
- final boolean needsToAddToAutoDictionary = selectedATypedWordAndItsInAutoDic
- || !isValidWord;
- if (needsToAddToAutoDictionary) {
- mAutoDictionary.addWord(suggestion.toString(), frequencyDelta);
- }
+ // If correction is not enabled, we don't add words to the user history dictionary.
+ // That's to avoid unintended additions in some sensitive fields, or fields that
+ // expect to receive non-words.
+ if (!mCurrentSettings.mCorrectionEnabled) return null;
- if (mUserBigramDictionary != null) {
- // We don't want to register as bigrams words separated by a separator.
- // For example "I will, and you too" : we don't want the pair ("will" "and") to be
- // a bigram.
- CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
- mSettingsValues.mWordSeparators);
- if (!TextUtils.isEmpty(prevWord)) {
- mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString());
+ final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary;
+ if (userHistoryDictionary != null) {
+ final CharSequence prevWord
+ = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators);
+ final String secondWord;
+ if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
+ secondWord = suggestion.toString().toLowerCase(
+ mSubtypeSwitcher.getCurrentSubtypeLocale());
+ } else {
+ secondWord = suggestion.toString();
}
+ // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
+ // We don't add words with 0-frequency (assuming they would be profanity etc.).
+ final int maxFreq = AutoCorrection.getMaxFrequency(
+ mSuggest.getUnigramDictionaries(), suggestion);
+ if (maxFreq == 0) return null;
+ userHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(),
+ secondWord, maxFreq > 0);
+ return prevWord;
}
+ return null;
}
- public boolean isCursorTouchingWord() {
- InputConnection ic = getCurrentInputConnection();
- if (ic == null) return false;
- CharSequence toLeft = ic.getTextBeforeCursor(1, 0);
- CharSequence toRight = ic.getTextAfterCursor(1, 0);
- if (!TextUtils.isEmpty(toLeft)
- && !mSettingsValues.isWordSeparator(toLeft.charAt(0))
- && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) {
- return true;
- }
- if (!TextUtils.isEmpty(toRight)
- && !mSettingsValues.isWordSeparator(toRight.charAt(0))
- && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) {
- return true;
+ /**
+ * Check if the cursor is actually at the end of a word. If so, restart suggestions on this
+ * word, else do nothing.
+ */
+ private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
+ final CharSequence word = mConnection.getWordBeforeCursorIfAtEndOfWord(mCurrentSettings);
+ if (null != word) {
+ restartSuggestionsOnWordBeforeCursor(word);
}
- return false;
}
- private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) {
- CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0);
- return TextUtils.equals(text, beforeText);
+ private void restartSuggestionsOnWordBeforeCursor(final CharSequence word) {
+ mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard());
+ final int length = word.length();
+ mConnection.deleteSurroundingText(length, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(length);
+ }
+ mConnection.setComposingText(word, 1);
+ mHandler.postUpdateSuggestions();
}
- public void revertLastWord(boolean deleteChar) {
- final int length = mComposing.length();
- if (!mHasUncommittedTypedChars && length > 0) {
- final InputConnection ic = getCurrentInputConnection();
- final CharSequence punctuation = ic.getTextBeforeCursor(1, 0);
- if (deleteChar) ic.deleteSurroundingText(1, 0);
- int toDelete = mCommittedLength;
- final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
- if (!TextUtils.isEmpty(toTheLeft)
- && mSettingsValues.isWordSeparator(toTheLeft.charAt(0))) {
- toDelete--;
+ private void revertCommit() {
+ final CharSequence previousWord = mLastComposedWord.mPrevWord;
+ final String originallyTypedWord = mLastComposedWord.mTypedWord;
+ final CharSequence committedWord = mLastComposedWord.mCommittedWord;
+ final int cancelLength = committedWord.length();
+ final int separatorLength = LastComposedWord.getSeparatorLength(
+ mLastComposedWord.mSeparatorCode);
+ // TODO: should we check our saved separator against the actual contents of the text view?
+ final int deleteLength = cancelLength + separatorLength;
+ if (DEBUG) {
+ if (mWordComposer.isComposingWord()) {
+ throw new RuntimeException("revertCommit, but we are composing a word");
}
- ic.deleteSurroundingText(toDelete, 0);
- // Re-insert punctuation only when the deleted character was word separator and the
- // composing text wasn't equal to the auto-corrected text.
- if (deleteChar
- && !TextUtils.isEmpty(punctuation)
- && mSettingsValues.isWordSeparator(punctuation.charAt(0))
- && !TextUtils.equals(mComposing, toTheLeft)) {
- ic.commitText(mComposing, 1);
- TextEntryState.acceptedTyped(mComposing);
- ic.commitText(punctuation, 1);
- TextEntryState.typedCharacter(punctuation.charAt(0), true,
- WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
- // Clear composing text
- mComposing.setLength(0);
- } else {
- mHasUncommittedTypedChars = true;
- ic.setComposingText(mComposing, 1);
- TextEntryState.backspace();
+ final String wordBeforeCursor =
+ mConnection.getTextBeforeCursor(deleteLength, 0)
+ .subSequence(0, cancelLength).toString();
+ if (!TextUtils.equals(committedWord, wordBeforeCursor)) {
+ throw new RuntimeException("revertCommit check failed: we thought we were "
+ + "reverting \"" + committedWord
+ + "\", but before the cursor we found \"" + wordBeforeCursor + "\"");
}
- mHandler.cancelUpdateBigramPredictions();
- mHandler.postUpdateSuggestions();
+ }
+ mConnection.deleteSurroundingText(deleteLength, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(deleteLength);
+ }
+ if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
+ mUserHistoryDictionary.cancelAddingUserHistory(
+ previousWord.toString(), committedWord.toString());
+ }
+ if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) {
+ // This is the case when we cancel a manual pick.
+ // We should restart suggestion on the word right away.
+ mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord);
+ mConnection.setComposingText(originallyTypedWord, 1);
} else {
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+ mConnection.commitText(originallyTypedWord, 1);
+ // Re-insert the separator
+ sendKeyCodePoint(mLastComposedWord.mSeparatorCode);
+ Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE,
+ WordComposer.NOT_A_COORDINATE);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_revertCommit(originallyTypedWord);
+ }
+ // Don't restart suggestion yet. We'll restart if the user deletes the
+ // separator.
}
- }
-
- public boolean revertDoubleSpace() {
- mHandler.cancelDoubleSpacesTimer();
- final InputConnection ic = getCurrentInputConnection();
- // Here we test whether we indeed have a period and a space before us. This should not
- // be needed, but it's there just in case something went wrong.
- final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
- if (!". ".equals(textBeforeCursor))
- return false;
- ic.beginBatchEdit();
- ic.deleteSurroundingText(2, 0);
- ic.commitText(" ", 1);
- ic.endBatchEdit();
- return true;
+ mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
+ mHandler.cancelUpdateBigramPredictions();
+ mHandler.postUpdateSuggestions();
}
public boolean isWordSeparator(int code) {
- return mSettingsValues.isWordSeparator(code);
- }
-
- private void sendMagicSpace() {
- sendKeyChar((char)Keyboard.CODE_SPACE);
- mJustAddedMagicSpace = true;
- mKeyboardSwitcher.updateShiftState();
+ return mCurrentSettings.isWordSeparator(code);
}
public boolean preferCapitalization() {
- return mWord.isFirstCharCapitalized();
+ return mWordComposer.isFirstCharCapitalized();
}
// Notify that language or mode have been changed and toggleLanguage will update KeyboardID
// according to new language or mode.
public void onRefreshKeyboard() {
- if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
- // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view,
- // so that we need to re-create the keyboard input view here.
- setInputView(mKeyboardSwitcher.onCreateInputView());
- }
- // Reload keyboard because the current language has been changed.
- mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(),
- mSubtypeSwitcher.isShortcutImeEnabled() && mVoiceProxy.isVoiceButtonEnabled(),
- mVoiceProxy.isVoiceButtonOnPrimary());
+ // When the device locale is changed in SetupWizard etc., this method may get called via
+ // onConfigurationChanged before SoftInputWindow is shown.
+ if (mKeyboardSwitcher.getKeyboardView() != null) {
+ // Reload keyboard because the current language has been changed.
+ mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mCurrentSettings);
+ }
initSuggest();
loadSettings();
- mKeyboardSwitcher.updateShiftState();
+ // Since we just changed languages, we should re-evaluate suggestions with whatever word
+ // we are currently composing. If we are not composing anything, we may want to display
+ // predictions or punctuation signs (which is done by updateBigramPredictions anyway).
+ if (mConnection.isCursorTouchingWord(mCurrentSettings)) {
+ mHandler.postUpdateSuggestions();
+ } else {
+ mHandler.postUpdateBigramPredictions();
+ }
}
- // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER.
- private void toggleLanguage(boolean next) {
- if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()) {
- mSubtypeSwitcher.toggleLanguage(next);
- }
- // The following is necessary because on API levels < 10, we don't get notified when
- // subtype changes.
- if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED)
- onRefreshKeyboard();
- }
+ // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to
+ // {@link KeyboardSwitcher}.
+ public void hapticAndAudioFeedback(final int primaryCode) {
+ mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView());
+ }
@Override
- public void onSwipeDown() {
- if (mSettingsValues.mSwipeDownDismissKeyboardEnabled)
- handleClose();
+ public void onPressKey(int primaryCode) {
+ mKeyboardSwitcher.onPressKey(primaryCode);
}
@Override
- public void onPress(int primaryCode, boolean withSliding) {
- if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) {
- vibrate();
- playKeyClick(primaryCode);
- }
- KeyboardSwitcher switcher = mKeyboardSwitcher;
- final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
- if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
- switcher.onPressShift(withSliding);
- } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
- switcher.onPressSymbol();
- } else {
- switcher.onOtherKeyPressed();
+ public void onReleaseKey(int primaryCode, boolean withSliding) {
+ mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding);
+
+ // If accessibility is on, ensure the user receives keyboard state updates.
+ if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
+ switch (primaryCode) {
+ case Keyboard.CODE_SHIFT:
+ AccessibleKeyboardViewProxy.getInstance().notifyShiftState();
+ break;
+ case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
+ AccessibleKeyboardViewProxy.getInstance().notifySymbolsState();
+ break;
+ }
}
- }
- @Override
- public void onRelease(int primaryCode, boolean withSliding) {
- KeyboardSwitcher switcher = mKeyboardSwitcher;
- // Reset any drag flags in the keyboard
- final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
- if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) {
- switcher.onReleaseShift(withSliding);
- } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
- switcher.onReleaseSymbol();
+ if (Keyboard.CODE_DELETE == primaryCode) {
+ // This is a stopgap solution to avoid leaving a high surrogate alone in a text view.
+ // In the future, we need to deprecate deteleSurroundingText() and have a surrogate
+ // pair-friendly way of deleting characters in InputConnection.
+ final CharSequence lastChar = mConnection.getTextBeforeCursor(1, 0);
+ if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) {
+ mConnection.deleteSurroundingText(1, 0);
+ }
}
}
-
// receive ringer mode change and network state change.
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
- updateRingerMode();
- } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
mSubtypeSwitcher.onNetworkStateChanged(intent);
+ } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
+ mFeedbackManager.onRingerModeChanged();
}
}
};
- // update flags for silent mode
- private void updateRingerMode() {
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- }
- if (mAudioManager != null) {
- mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL);
- }
- }
-
- private void playKeyClick(int primaryCode) {
- // if mAudioManager is null, we don't have the ringer state yet
- // mAudioManager will be set by updateRingerMode
- if (mAudioManager == null) {
- if (mKeyboardSwitcher.getKeyboardView() != null) {
- updateRingerMode();
- }
- }
- if (isSoundOn()) {
- // FIXME: Volume and enable should come from UI settings
- // FIXME: These should be triggered after auto-repeat logic
- int sound = AudioManager.FX_KEYPRESS_STANDARD;
- switch (primaryCode) {
- case Keyboard.CODE_DELETE:
- sound = AudioManager.FX_KEYPRESS_DELETE;
- break;
- case Keyboard.CODE_ENTER:
- sound = AudioManager.FX_KEYPRESS_RETURN;
- break;
- case Keyboard.CODE_SPACE:
- sound = AudioManager.FX_KEYPRESS_SPACEBAR;
- break;
- }
- mAudioManager.playSoundEffect(sound, FX_VOLUME);
- }
- }
-
- public void vibrate() {
- if (!mSettingsValues.mVibrateOn) {
- return;
- }
- LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
- if (inputView != null) {
- inputView.performHapticFeedback(
- HapticFeedbackConstants.KEYBOARD_TAP,
- HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
- }
-
- public WordComposer getCurrentWord() {
- return mWord;
- }
-
- boolean isSoundOn() {
- return mSettingsValues.mSoundOn && !mSilentModeOn;
- }
-
- private void updateCorrectionMode() {
- // TODO: cleanup messy flags
- mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false;
- final boolean shouldAutoCorrect = (mSettingsValues.mAutoCorrectEnabled
- || mSettingsValues.mQuickFixes) && !mInputTypeNoAutoCorrect && mHasDictionary;
- mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled)
- ? Suggest.CORRECTION_FULL
- : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
- mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect
- && mSettingsValues.mAutoCorrectEnabled)
- ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode;
- if (mSuggest != null) {
- mSuggest.setCorrectionMode(mCorrectionMode);
- }
- }
-
- private void updateAutoTextEnabled() {
- if (mSuggest == null) return;
- mSuggest.setQuickFixesEnabled(mSettingsValues.mQuickFixes
- && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage());
- }
-
- private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) {
- final String suggestionVisiblityStr = prefs.getString(
- Settings.PREF_SHOW_SUGGESTIONS_SETTING,
- res.getString(R.string.prefs_suggestion_visibility_default_value));
- for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
- if (suggestionVisiblityStr.equals(res.getString(visibility))) {
- mSuggestionVisibility = visibility;
- break;
- }
- }
- }
-
- protected void launchSettings() {
- launchSettings(Settings.class);
+ private void launchSettings() {
+ launchSettingsClass(SettingsActivity.class);
}
public void launchDebugSettings() {
- launchSettings(DebugSettings.class);
+ launchSettingsClass(DebugSettingsActivity.class);
}
- protected void launchSettings(Class<? extends PreferenceActivity> settingsClass) {
+ private void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) {
handleClose();
Intent intent = new Intent();
intent.setClass(LatinIME.this, settingsClass);
@@ -2057,6 +2157,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
getString(R.string.language_selection_title),
getString(R.string.english_ime_settings),
};
+ final Context context = this;
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface di, int position) {
@@ -2064,7 +2165,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
switch (position) {
case 0:
Intent intent = CompatUtils.getInputLanguageSelectionIntent(
- mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK
+ ImfUtils.getInputMethodIdOfThisIme(context),
+ Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
@@ -2075,51 +2177,28 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
};
- showOptionsMenuInternal(title, items, listener);
- }
-
- private void showOptionsMenu() {
- final CharSequence title = getString(R.string.english_ime_input_options);
- final CharSequence[] items = new CharSequence[] {
- getString(R.string.selectInputMethod),
- getString(R.string.english_ime_settings),
- };
- final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface di, int position) {
- di.dismiss();
- switch (position) {
- case 0:
- mImm.showInputMethodPicker();
- break;
- case 1:
- launchSettings();
- break;
- }
- }
- };
- showOptionsMenuInternal(title, items, listener);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ .setItems(items, listener)
+ .setTitle(title);
+ showOptionDialog(builder.create());
}
- private void showOptionsMenuInternal(CharSequence title, CharSequence[] items,
- DialogInterface.OnClickListener listener) {
+ /* package */ void showOptionDialog(AlertDialog dialog) {
final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken();
if (windowToken == null) return;
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setCancelable(true);
- builder.setIcon(R.drawable.ic_dialog_keyboard);
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.setItems(items, listener);
- builder.setTitle(title);
- mOptionsDialog = builder.create();
- mOptionsDialog.setCanceledOnTouchOutside(true);
- Window window = mOptionsDialog.getWindow();
- WindowManager.LayoutParams lp = window.getAttributes();
+
+ dialog.setCancelable(true);
+ dialog.setCanceledOnTouchOutside(true);
+
+ final Window window = dialog.getWindow();
+ final WindowManager.LayoutParams lp = window.getAttributes();
lp.token = windowToken;
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
window.setAttributes(lp);
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- mOptionsDialog.show();
+
+ mOptionsDialog = dialog;
+ dialog.show();
}
@Override
@@ -2128,35 +2207,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final Printer p = new PrintWriterPrinter(fout);
p.println("LatinIME state :");
- p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode());
- p.println(" mComposing=" + mComposing.toString());
- p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn);
- p.println(" mCorrectionMode=" + mCorrectionMode);
- p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars);
- p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled);
- p.println(" mShouldInsertMagicSpace=" + mShouldInsertMagicSpace);
- p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn);
- p.println(" TextEntryState.state=" + TextEntryState.getState());
- p.println(" mSoundOn=" + mSettingsValues.mSoundOn);
- p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn);
- p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn);
- }
-
- // Characters per second measurement
-
- private long mLastCpsTime;
- private static final int CPS_BUFFER_SIZE = 16;
- private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
- private int mCpsIndex;
-
- private void measureCps() {
- long now = System.currentTimeMillis();
- if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial
- mCpsIntervals[mCpsIndex] = now - mLastCpsTime;
- mLastCpsTime = now;
- mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE;
- long total = 0;
- for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i];
- System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
+ final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
+ final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
+ p.println(" Keyboard mode = " + keyboardMode);
+ p.println(" mIsSuggestionsSuggestionsRequested = "
+ + mCurrentSettings.isSuggestionsRequested(mDisplayOrientation));
+ p.println(" mCorrectionEnabled=" + mCurrentSettings.mCorrectionEnabled);
+ p.println(" isComposingWord=" + mWordComposer.isComposingWord());
+ p.println(" mSoundOn=" + mCurrentSettings.mSoundOn);
+ p.println(" mVibrateOn=" + mCurrentSettings.mVibrateOn);
+ p.println(" mKeyPreviewPopupOn=" + mCurrentSettings.mKeyPreviewPopupOn);
+ p.println(" inputAttributes=" + mCurrentSettings.getInputAttributesDebugString());
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index e460471a5..dc0868e7c 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -16,23 +16,22 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.latin.Dictionary.DataType;
-
-import android.content.Context;
import android.content.SharedPreferences;
+import android.view.inputmethod.EditorInfo;
-import java.util.List;
+import com.android.inputmethod.keyboard.Keyboard;
public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
public static boolean sDBG = false;
+ public static boolean sVISUALDEBUG = false;
+ public static boolean sUsabilityStudy = false;
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
- public static void init(Context context, SharedPreferences prefs) {
+ public static void init(LatinIME context, SharedPreferences prefs) {
}
public static void commit() {
@@ -42,8 +41,8 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
}
public static void logOnManualSuggestion(
- String before, String after, int position, List<CharSequence> suggestions) {
- }
+ String before, String after, int position, SuggestedWords suggestedWords) {
+ }
public static void logOnAutoCorrection(String before, String after, int separatorCode) {
}
@@ -51,7 +50,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void logOnAutoCorrectionCancelled() {
}
- public static void logOnDelete() {
+ public static void logOnDelete(int x, int y) {
}
public static void logOnInputChar() {
@@ -66,10 +65,13 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void logOnWarning(String warning) {
}
+ public static void onStartInputView(EditorInfo editorInfo) {
+ }
+
public static void onStartSuggestion(CharSequence previousWords) {
}
- public static void onAddSuggestedWord(String word, int typeId, DataType dataType) {
+ public static void onAddSuggestedWord(String word, int typeId, int dataType) {
}
public static void onSetKeyboard(Keyboard kb) {
diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java
new file mode 100644
index 000000000..b938dd336
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.text.TextUtils;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * A class to help with handling Locales in string form.
+ *
+ * This file has the same meaning and features (and shares all of its code) with
+ * the one in the dictionary pack. They need to be kept synchronized; for any
+ * update/bugfix to this file, consider also updating/fixing the version in the
+ * dictionary pack.
+ */
+public class LocaleUtils {
+ private LocaleUtils() {
+ // Intentional empty constructor for utility class.
+ }
+
+ // Locale match level constants.
+ // A higher level of match is guaranteed to have a higher numerical value.
+ // Some room is left within constants to add match cases that may arise necessary
+ // in the future, for example differentiating between the case where the countries
+ // are both present and different, and the case where one of the locales does not
+ // specify the countries. This difference is not needed now.
+
+ // Nothing matches.
+ public static final int LOCALE_NO_MATCH = 0;
+ // The languages matches, but the country are different. Or, the reference locale requires a
+ // country and the tested locale does not have one.
+ public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
+ // The languages and country match, but the variants are different. Or, the reference locale
+ // requires a variant and the tested locale does not have one.
+ public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
+ // The required locale is null or empty so it will accept anything, and the tested locale
+ // is non-null and non-empty.
+ public static final int LOCALE_ANY_MATCH = 10;
+ // The language matches, and the tested locale specifies a country but the reference locale
+ // does not require one.
+ public static final int LOCALE_LANGUAGE_MATCH = 15;
+ // The language and the country match, and the tested locale specifies a variant but the
+ // reference locale does not require one.
+ public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
+ // The compared locales are fully identical. This is the best match level.
+ public static final int LOCALE_FULL_MATCH = 30;
+
+ // The level at which a match is "normally" considered a locale match with standard algorithms.
+ // Don't use this directly, use #isMatch to test.
+ private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
+
+ // Make this match the maximum match level. If this evolves to have more than 2 digits
+ // when written in base 10, also adjust the getMatchLevelSortedString method.
+ private static final int MATCH_LEVEL_MAX = 30;
+
+ /**
+ * Return how well a tested locale matches a reference locale.
+ *
+ * This will check the tested locale against the reference locale and return a measure of how
+ * a well it matches the reference. The general idea is that the tested locale has to match
+ * every specified part of the required locale. A full match occur when they are equal, a
+ * partial match when the tested locale agrees with the reference locale but is more specific,
+ * and a difference when the tested locale does not comply with all requirements from the
+ * reference locale.
+ * In more detail, if the reference locale specifies at least a language and the testedLocale
+ * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
+ * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
+ * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
+ * tested locale agree on the language, but not on the country,
+ * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
+ * and LOCALE_LANGUAGE_MATCH otherwise.
+ * If they agree on both the language and the country, but not on the variant,
+ * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
+ * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
+ * LOCALE_FULL_MATCH is returned.
+ * Examples:
+ * en <=> en_US => LOCALE_LANGUAGE_MATCH
+ * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
+ * en_US_POSIX <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
+ * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
+ * sp_US <=> en_US => LOCALE_NO_MATCH
+ * de <=> de => LOCALE_FULL_MATCH
+ * en_US <=> en_US => LOCALE_FULL_MATCH
+ * "" <=> en_US => LOCALE_ANY_MATCH
+ *
+ * @param referenceLocale the reference locale to test against.
+ * @param testedLocale the locale to test.
+ * @return a constant that measures how well the tested locale matches the reference locale.
+ */
+ public static int getMatchLevel(String referenceLocale, String testedLocale) {
+ if (TextUtils.isEmpty(referenceLocale)) {
+ return TextUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
+ }
+ if (null == testedLocale) return LOCALE_NO_MATCH;
+ String[] referenceParams = referenceLocale.split("_", 3);
+ String[] testedParams = testedLocale.split("_", 3);
+ // By spec of String#split, [0] cannot be null and length cannot be 0.
+ if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
+ switch (referenceParams.length) {
+ case 1:
+ return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
+ case 2:
+ if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (!referenceParams[1].equals(testedParams[1]))
+ return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
+ return LOCALE_FULL_MATCH;
+ case 3:
+ if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (!referenceParams[1].equals(testedParams[1]))
+ return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+ if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
+ if (!referenceParams[2].equals(testedParams[2]))
+ return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
+ return LOCALE_FULL_MATCH;
+ }
+ // It should be impossible to come here
+ return LOCALE_NO_MATCH;
+ }
+
+ /**
+ * Return a string that represents this match level, with better matches first.
+ *
+ * The strings are sorted in lexicographic order: a better match will always be less than
+ * a worse match when compared together.
+ */
+ public static String getMatchLevelSortedString(int matchLevel) {
+ // This works because the match levels are 0~99 (actually 0~30)
+ // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
+ return String.format("%02d", MATCH_LEVEL_MAX - matchLevel);
+ }
+
+ /**
+ * Find out whether a match level should be considered a match.
+ *
+ * This method takes a match level as returned by the #getMatchLevel method, and returns whether
+ * it should be considered a match in the usual sense with standard Locale functions.
+ *
+ * @param level the match level, as returned by getMatchLevel.
+ * @return whether this is a match or not.
+ */
+ public static boolean isMatch(int level) {
+ return LOCALE_MATCH <= level;
+ }
+
+ static final Object sLockForRunInLocale = new Object();
+
+ public abstract static class RunInLocale<T> {
+ protected abstract T job(Resources res);
+
+ /**
+ * Execute {@link #job(Resources)} method in specified system locale exclusively.
+ *
+ * @param res the resources to use. Pass current resources.
+ * @param newLocale the locale to change to
+ * @return the value returned from {@link #job(Resources)}.
+ */
+ public T runInLocale(final Resources res, final Locale newLocale) {
+ synchronized (sLockForRunInLocale) {
+ final Configuration conf = res.getConfiguration();
+ final Locale oldLocale = conf.locale;
+ try {
+ if (newLocale != null && !newLocale.equals(oldLocale)) {
+ conf.locale = newLocale;
+ res.updateConfiguration(conf, null);
+ }
+ return job(res);
+ } finally {
+ if (newLocale != null && !newLocale.equals(oldLocale)) {
+ conf.locale = oldLocale;
+ res.updateConfiguration(conf, null);
+ }
+ }
+ }
+ }
+ }
+
+ private static final HashMap<String, Locale> sLocaleCache = new HashMap<String, Locale>();
+
+ /**
+ * Creates a locale from a string specification.
+ */
+ public static Locale constructLocaleFromString(final String localeStr) {
+ if (localeStr == null)
+ return null;
+ synchronized (sLocaleCache) {
+ if (sLocaleCache.containsKey(localeStr))
+ return sLocaleCache.get(localeStr);
+ Locale retval = null;
+ String[] localeParams = localeStr.split("_", 3);
+ if (localeParams.length == 1) {
+ retval = new Locale(localeParams[0]);
+ } else if (localeParams.length == 2) {
+ retval = new Locale(localeParams[0], localeParams[1]);
+ } else if (localeParams.length == 3) {
+ retval = new Locale(localeParams[0], localeParams[1], localeParams[2]);
+ }
+ if (retval != null) {
+ sLocaleCache.put(localeStr, retval);
+ }
+ return retval;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java b/java/src/com/android/inputmethod/latin/NativeUtils.java
index 8518a4a78..9cc2bc02e 100644
--- a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java
+++ b/java/src/com/android/inputmethod/latin/NativeUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,10 +14,19 @@
* limitations under the License.
*/
-package com.android.inputmethod.compat;
+package com.android.inputmethod.latin;
-public class MotionEventCompatUtils {
- public static final int ACTION_HOVER_MOVE = 0x7;
- public static final int ACTION_HOVER_ENTER = 0x9;
- public static final int ACTION_HOVER_EXIT = 0xA;
+public class NativeUtils {
+ static {
+ JniUtils.loadNativeLibrary();
+ }
+
+ private NativeUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ /**
+ * This method just calls up libm's powf() directly.
+ */
+ public static native float powf(float x, float y);
}
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
new file mode 100644
index 000000000..cf3cc7873
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -0,0 +1,1043 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.inputmethodservice.InputMethodService;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.JsonWriter;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.Toast;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.RichInputConnection.Range;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.define.ProductionFlag;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Logs the use of the LatinIME keyboard.
+ *
+ * This class logs operations on the IME keyboard, including what the user has typed.
+ * Data is stored locally in a file in app-specific storage.
+ *
+ * This functionality is off by default. See {@link ProductionFlag#IS_EXPERIMENTAL}.
+ */
+public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = ResearchLogger.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final boolean OUTPUT_ENTIRE_BUFFER = false; // true may disclose private info
+ /* package */ static boolean sIsLogging = false;
+ private static final int OUTPUT_FORMAT_VERSION = 1;
+ private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+ private static final String FILENAME_PREFIX = "researchLog";
+ private static final String FILENAME_SUFFIX = ".txt";
+ private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
+ new OutputStreamWriter(new NullOutputStream()));
+ private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
+ new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
+
+ // constants related to specific log points
+ private static final String WHITESPACE_SEPARATORS = " \t\n\r";
+ private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
+ private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid";
+
+ private static final ResearchLogger sInstance = new ResearchLogger();
+ private HandlerThread mHandlerThread;
+ /* package */ Handler mLoggingHandler;
+ // to write to a different filename, e.g., for testing, set mFile before calling start()
+ private File mFilesDir;
+ /* package */ File mFile;
+ private JsonWriter mJsonWriter = NULL_JSON_WRITER; // should never be null
+
+ private int mLoggingState;
+ private static final int LOGGING_STATE_OFF = 0;
+ private static final int LOGGING_STATE_ON = 1;
+ private static final int LOGGING_STATE_STOPPING = 2;
+ private boolean mIsPasswordView = false;
+
+ // digits entered by the user are replaced with this codepoint.
+ /* package for test */ static final int DIGIT_REPLACEMENT_CODEPOINT =
+ Character.codePointAt("\uE000", 0); // U+E000 is in the "private-use area"
+ // U+E001 is in the "private-use area"
+ /* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001";
+ // set when LatinIME should ignore an onUpdateSelection() callback that
+ // arises from operations in this class
+ private static boolean sLatinIMEExpectingUpdateSelection = false;
+
+ // used to check whether words are not unique
+ private Suggest mSuggest;
+ private Dictionary mDictionary;
+
+ private static class NullOutputStream extends OutputStream {
+ /** {@inheritDoc} */
+ @Override
+ public void write(byte[] buffer, int offset, int count) {
+ // nop
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(byte[] buffer) {
+ // nop
+ }
+
+ @Override
+ public void write(int oneByte) {
+ }
+ }
+
+ private ResearchLogger() {
+ mLoggingState = LOGGING_STATE_OFF;
+ }
+
+ public static ResearchLogger getInstance() {
+ return sInstance;
+ }
+
+ public void init(final InputMethodService ims, final SharedPreferences prefs) {
+ assert ims != null;
+ if (ims == null) {
+ Log.w(TAG, "IMS is null; logging is off");
+ } else {
+ mFilesDir = ims.getFilesDir();
+ if (mFilesDir == null || !mFilesDir.exists()) {
+ Log.w(TAG, "IME storage directory does not exist.");
+ }
+ }
+ if (prefs != null) {
+ sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ }
+ }
+
+ public synchronized void start() {
+ Log.d(TAG, "start called");
+ if (!sIsLogging) {
+ // Log.w(TAG, "not in usability mode; not logging");
+ return;
+ }
+ if (mFilesDir == null || !mFilesDir.exists()) {
+ Log.w(TAG, "IME storage directory does not exist. Cannot start logging.");
+ } else {
+ if (mHandlerThread == null || !mHandlerThread.isAlive()) {
+ mHandlerThread = new HandlerThread("ResearchLogger logging task",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+ mLoggingHandler = null;
+ mLoggingState = LOGGING_STATE_OFF;
+ }
+ if (mLoggingHandler == null) {
+ mLoggingHandler = new Handler(mHandlerThread.getLooper());
+ mLoggingState = LOGGING_STATE_OFF;
+ }
+ if (mFile == null) {
+ final String timestampString = TIMESTAMP_DATEFORMAT.format(new Date());
+ mFile = new File(mFilesDir, FILENAME_PREFIX + timestampString + FILENAME_SUFFIX);
+ }
+ if (mLoggingState == LOGGING_STATE_OFF) {
+ try {
+ mJsonWriter = new JsonWriter(new BufferedWriter(new FileWriter(mFile)));
+ mJsonWriter.setLenient(true);
+ mJsonWriter.beginArray();
+ mLoggingState = LOGGING_STATE_ON;
+ } catch (IOException e) {
+ Log.w(TAG, "cannot start JsonWriter");
+ mJsonWriter = NULL_JSON_WRITER;
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public synchronized void stop() {
+ Log.d(TAG, "stop called");
+ if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
+ mLoggingState = LOGGING_STATE_STOPPING;
+ // put this in the Handler queue so pending writes are processed first.
+ mLoggingHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Log.d(TAG, "closing jsonwriter");
+ mJsonWriter.endArray();
+ mJsonWriter.flush();
+ mJsonWriter.close();
+ } catch (IllegalStateException e1) {
+ // assume that this is just the json not being terminated properly.
+ // ignore
+ e1.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mJsonWriter = NULL_JSON_WRITER;
+ mFile = null;
+ mLoggingState = LOGGING_STATE_OFF;
+ if (DEBUG) {
+ Log.d(TAG, "logfile closed");
+ }
+ Log.d(TAG, "finished stop(), notifying");
+ synchronized (ResearchLogger.this) {
+ ResearchLogger.this.notify();
+ }
+ }
+ }
+ });
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public synchronized boolean abort() {
+ Log.d(TAG, "abort called");
+ boolean isLogFileDeleted = false;
+ if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
+ mLoggingState = LOGGING_STATE_STOPPING;
+ try {
+ Log.d(TAG, "closing jsonwriter");
+ mJsonWriter.endArray();
+ mJsonWriter.close();
+ } catch (IllegalStateException e1) {
+ // assume that this is just the json not being terminated properly.
+ // ignore
+ e1.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mJsonWriter = NULL_JSON_WRITER;
+ // delete file
+ final boolean isDeleted = mFile.delete();
+ if (isDeleted) {
+ isLogFileDeleted = true;
+ }
+ mFile = null;
+ mLoggingState = LOGGING_STATE_OFF;
+ if (DEBUG) {
+ Log.d(TAG, "logfile closed");
+ }
+ }
+ }
+ return isLogFileDeleted;
+ }
+
+ /* package */ synchronized void flush() {
+ try {
+ mJsonWriter.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if (key == null || prefs == null) {
+ return;
+ }
+ sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
+ if (sIsLogging == false) {
+ abort();
+ }
+ }
+
+ /* package */ void presentResearchDialog(final LatinIME latinIME) {
+ final CharSequence title = latinIME.getString(R.string.english_ime_research_log);
+ final CharSequence[] items = new CharSequence[] {
+ latinIME.getString(R.string.note_timestamp_for_researchlog),
+ latinIME.getString(R.string.do_not_log_this_session),
+ };
+ final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface di, int position) {
+ di.dismiss();
+ switch (position) {
+ case 0:
+ ResearchLogger.getInstance().userTimestamp();
+ Toast.makeText(latinIME, R.string.notify_recorded_timestamp,
+ Toast.LENGTH_LONG).show();
+ break;
+ case 1:
+ Toast toast = Toast.makeText(latinIME,
+ R.string.notify_session_log_deleting, Toast.LENGTH_LONG);
+ toast.show();
+ final ResearchLogger logger = ResearchLogger.getInstance();
+ boolean isLogDeleted = logger.abort();
+ toast.cancel();
+ if (isLogDeleted) {
+ Toast.makeText(latinIME, R.string.notify_session_log_deleted,
+ Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(latinIME,
+ R.string.notify_session_log_not_deleted, Toast.LENGTH_LONG)
+ .show();
+ }
+ break;
+ }
+ }
+ };
+ final AlertDialog.Builder builder = new AlertDialog.Builder(latinIME)
+ .setItems(items, listener)
+ .setTitle(title);
+ latinIME.showOptionDialog(builder.create());
+ }
+
+ public void initSuggest(Suggest suggest) {
+ mSuggest = suggest;
+ }
+
+ private void setIsPasswordView(boolean isPasswordView) {
+ mIsPasswordView = isPasswordView;
+ }
+
+ private boolean isAllowedToLog() {
+ return mLoggingState == LOGGING_STATE_ON && !mIsPasswordView;
+ }
+
+ private static final String CURRENT_TIME_KEY = "_ct";
+ private static final String UPTIME_KEY = "_ut";
+ private static final String EVENT_TYPE_KEY = "_ty";
+ private static final Object[] EVENTKEYS_NULLVALUES = {};
+
+ private LogUnit mCurrentLogUnit = new LogUnit();
+
+ /**
+ * Buffer a research log event, flagging it as privacy-sensitive.
+ *
+ * This event contains potentially private information. If the word that this event is a part
+ * of is determined to be privacy-sensitive, then this event should not be included in the
+ * output log. The system waits to output until the containing word is known.
+ *
+ * @param keys an array containing a descriptive name for the event, followed by the keys
+ * @param values an array of values, either a String or Number. length should be one
+ * less than the keys array
+ */
+ private synchronized void enqueuePotentiallyPrivateEvent(final String[] keys,
+ final Object[] values) {
+ assert values.length + 1 == keys.length;
+ mCurrentLogUnit.addLogAtom(keys, values, true);
+ }
+
+ /**
+ * Buffer a research log event, flaggint it as not privacy-sensitive.
+ *
+ * This event contains no potentially private information. Even if the word that this event
+ * is privacy-sensitive, this event can still safely be sent to the output log. The system
+ * waits until the containing word is known so that this event can be written in the proper
+ * temporal order with other events that may be privacy sensitive.
+ *
+ * @param keys an array containing a descriptive name for the event, followed by the keys
+ * @param values an array of values, either a String or Number. length should be one
+ * less than the keys array
+ */
+ private synchronized void enqueueEvent(final String[] keys, final Object[] values) {
+ assert values.length + 1 == keys.length;
+ mCurrentLogUnit.addLogAtom(keys, values, false);
+ }
+
+ /* package for test */ boolean isPrivacyThreat(String word) {
+ // currently: word not in dictionary or contains numbers.
+ if (TextUtils.isEmpty(word)) {
+ return false;
+ }
+ final int length = word.length();
+ boolean hasLetter = false;
+ for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
+ final int codePoint = Character.codePointAt(word, i);
+ if (Character.isDigit(codePoint)) {
+ return true;
+ }
+ if (Character.isLetter(codePoint)) {
+ hasLetter = true;
+ break; // Word may contain digits, but will only be allowed if in the dictionary.
+ }
+ }
+ if (hasLetter) {
+ if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) {
+ mDictionary = mSuggest.getMainDictionary();
+ }
+ if (mDictionary == null) {
+ // Can't access dictionary. Assume privacy threat.
+ return true;
+ }
+ return !(mDictionary.isValidWord(word));
+ }
+ // No letters, no numbers. Punctuation, space, or something else.
+ return false;
+ }
+
+ /**
+ * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events.
+ */
+ /* package for test */ synchronized void flushQueue(boolean removePotentiallyPrivateEvents) {
+ if (isAllowedToLog()) {
+ mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents);
+ mLoggingHandler.post(mCurrentLogUnit);
+ mCurrentLogUnit = new LogUnit();
+ }
+ }
+
+ private synchronized void outputEvent(final String[] keys, final Object[] values) {
+ try {
+ mJsonWriter.beginObject();
+ mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
+ mJsonWriter.name(UPTIME_KEY).value(SystemClock.uptimeMillis());
+ mJsonWriter.name(EVENT_TYPE_KEY).value(keys[0]);
+ final int length = values.length;
+ for (int i = 0; i < length; i++) {
+ mJsonWriter.name(keys[i + 1]);
+ Object value = values[i];
+ if (value instanceof String) {
+ mJsonWriter.value((String) value);
+ } else if (value instanceof Number) {
+ mJsonWriter.value((Number) value);
+ } else if (value instanceof Boolean) {
+ mJsonWriter.value((Boolean) value);
+ } else if (value instanceof CompletionInfo[]) {
+ CompletionInfo[] ci = (CompletionInfo[]) value;
+ mJsonWriter.beginArray();
+ for (int j = 0; j < ci.length; j++) {
+ mJsonWriter.value(ci[j].toString());
+ }
+ mJsonWriter.endArray();
+ } else if (value instanceof SharedPreferences) {
+ SharedPreferences prefs = (SharedPreferences) value;
+ mJsonWriter.beginObject();
+ for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
+ mJsonWriter.name(entry.getKey());
+ final Object innerValue = entry.getValue();
+ if (innerValue == null) {
+ mJsonWriter.nullValue();
+ } else if (innerValue instanceof Boolean) {
+ mJsonWriter.value((Boolean) innerValue);
+ } else if (innerValue instanceof Number) {
+ mJsonWriter.value((Number) innerValue);
+ } else {
+ mJsonWriter.value(innerValue.toString());
+ }
+ }
+ mJsonWriter.endObject();
+ } else if (value instanceof Key[]) {
+ Key[] keyboardKeys = (Key[]) value;
+ mJsonWriter.beginArray();
+ for (Key keyboardKey : keyboardKeys) {
+ mJsonWriter.beginObject();
+ mJsonWriter.name("code").value(keyboardKey.mCode);
+ mJsonWriter.name("altCode").value(keyboardKey.mAltCode);
+ mJsonWriter.name("x").value(keyboardKey.mX);
+ mJsonWriter.name("y").value(keyboardKey.mY);
+ mJsonWriter.name("w").value(keyboardKey.mWidth);
+ mJsonWriter.name("h").value(keyboardKey.mHeight);
+ mJsonWriter.endObject();
+ }
+ mJsonWriter.endArray();
+ } else if (value instanceof SuggestedWords) {
+ SuggestedWords words = (SuggestedWords) value;
+ mJsonWriter.beginObject();
+ mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
+ mJsonWriter.name("hasAutoCorrectionCandidate")
+ .value(words.mHasAutoCorrectionCandidate);
+ mJsonWriter.name("isPunctuationSuggestions")
+ .value(words.mIsPunctuationSuggestions);
+ mJsonWriter.name("allowsToBeAutoCorrected")
+ .value(words.mAllowsToBeAutoCorrected);
+ mJsonWriter.name("isObsoleteSuggestions")
+ .value(words.mIsObsoleteSuggestions);
+ mJsonWriter.name("isPrediction")
+ .value(words.mIsPrediction);
+ mJsonWriter.name("words");
+ mJsonWriter.beginArray();
+ final int size = words.size();
+ for (int j = 0; j < size; j++) {
+ SuggestedWordInfo wordInfo = words.getWordInfo(j);
+ mJsonWriter.value(wordInfo.toString());
+ }
+ mJsonWriter.endArray();
+ mJsonWriter.endObject();
+ } else if (value == null) {
+ mJsonWriter.nullValue();
+ } else {
+ Log.w(TAG, "Unrecognized type to be logged: " +
+ (value == null ? "<null>" : value.getClass().getName()));
+ mJsonWriter.nullValue();
+ }
+ }
+ mJsonWriter.endObject();
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.w(TAG, "Error in JsonWriter; disabling logging");
+ try {
+ mJsonWriter.close();
+ } catch (IllegalStateException e1) {
+ // assume that this is just the json not being terminated properly.
+ // ignore
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ } finally {
+ mJsonWriter = NULL_JSON_WRITER;
+ }
+ }
+ }
+
+ private static class LogUnit implements Runnable {
+ private final List<String[]> mKeysList = new ArrayList<String[]>();
+ private final List<Object[]> mValuesList = new ArrayList<Object[]>();
+ private final List<Boolean> mIsPotentiallyPrivate = new ArrayList<Boolean>();
+ private boolean mRemovePotentiallyPrivateEvents = true;
+
+ private void addLogAtom(final String[] keys, final Object[] values,
+ final Boolean isPotentiallyPrivate) {
+ mKeysList.add(keys);
+ mValuesList.add(values);
+ mIsPotentiallyPrivate.add(isPotentiallyPrivate);
+ }
+
+ void setRemovePotentiallyPrivateEvents(boolean removePotentiallyPrivateEvents) {
+ mRemovePotentiallyPrivateEvents = removePotentiallyPrivateEvents;
+ }
+
+ @Override
+ public void run() {
+ final int numAtoms = mKeysList.size();
+ for (int atomIndex = 0; atomIndex < numAtoms; atomIndex++) {
+ if (mRemovePotentiallyPrivateEvents && mIsPotentiallyPrivate.get(atomIndex)) {
+ continue;
+ }
+ final String[] keys = mKeysList.get(atomIndex);
+ final Object[] values = mValuesList.get(atomIndex);
+ ResearchLogger.getInstance().outputEvent(keys, values);
+ }
+ }
+ }
+
+ private static int scrubDigitFromCodePoint(int codePoint) {
+ return Character.isDigit(codePoint) ? DIGIT_REPLACEMENT_CODEPOINT : codePoint;
+ }
+
+ /* package for test */ static String scrubDigitsFromString(String s) {
+ StringBuilder sb = null;
+ final int length = s.length();
+ for (int i = 0; i < length; i = s.offsetByCodePoints(i, 1)) {
+ final int codePoint = Character.codePointAt(s, i);
+ if (Character.isDigit(codePoint)) {
+ if (sb == null) {
+ sb = new StringBuilder(length);
+ sb.append(s.substring(0, i));
+ }
+ sb.appendCodePoint(DIGIT_REPLACEMENT_CODEPOINT);
+ } else {
+ if (sb != null) {
+ sb.appendCodePoint(codePoint);
+ }
+ }
+ }
+ if (sb == null) {
+ return s;
+ } else {
+ return sb.toString();
+ }
+ }
+
+ private String scrubWord(String word) {
+ if (mDictionary == null) {
+ return WORD_REPLACEMENT_STRING;
+ }
+ if (mDictionary.isValidWord(word)) {
+ return word;
+ }
+ return WORD_REPLACEMENT_STRING;
+ }
+
+ private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = {
+ "LatinKeyboardViewProcessMotionEvent", "action", "eventTime", "id", "x", "y", "size",
+ "pressure"
+ };
+ public static void latinKeyboardView_processMotionEvent(final MotionEvent me, final int action,
+ final long eventTime, final int index, final int id, final int x, final int y) {
+ if (me != null) {
+ final String actionString;
+ switch (action) {
+ case MotionEvent.ACTION_CANCEL: actionString = "CANCEL"; break;
+ case MotionEvent.ACTION_UP: actionString = "UP"; break;
+ case MotionEvent.ACTION_DOWN: actionString = "DOWN"; break;
+ case MotionEvent.ACTION_POINTER_UP: actionString = "POINTER_UP"; break;
+ case MotionEvent.ACTION_POINTER_DOWN: actionString = "POINTER_DOWN"; break;
+ case MotionEvent.ACTION_MOVE: actionString = "MOVE"; break;
+ case MotionEvent.ACTION_OUTSIDE: actionString = "OUTSIDE"; break;
+ default: actionString = "ACTION_" + action; break;
+ }
+ final float size = me.getSize(index);
+ final float pressure = me.getPressure(index);
+ final Object[] values = {
+ actionString, eventTime, id, x, y, size, pressure
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT, values);
+ }
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_ONCODEINPUT = {
+ "LatinIMEOnCodeInput", "code", "x", "y"
+ };
+ public static void latinIME_onCodeInput(final int code, final int x, final int y) {
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(code)), x, y
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values);
+ }
+
+ private static final String[] EVENTKEYS_CORRECTION = {
+ "LogCorrection", "subgroup", "before", "after", "position"
+ };
+ public static void logCorrection(final String subgroup, final String before, final String after,
+ final int position) {
+ final Object[] values = {
+ subgroup, scrubDigitsFromString(before), scrubDigitsFromString(after), position
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_CORRECTION, values);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = {
+ "LatinIMECommitCurrentAutoCorrection", "typedWord", "autoCorrection"
+ };
+ public static void latinIME_commitCurrentAutoCorrection(final String typedWord,
+ final String autoCorrection) {
+ final Object[] values = {
+ scrubDigitsFromString(typedWord), scrubDigitsFromString(autoCorrection)
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values);
+ researchLogger.flushQueue(researchLogger.isPrivacyThreat(autoCorrection));
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = {
+ "LatinIMECommitText", "typedWord"
+ };
+ public static void latinIME_commitText(final CharSequence typedWord) {
+ final String scrubbedWord = scrubDigitsFromString(typedWord.toString());
+ final Object[] values = {
+ scrubbedWord
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values);
+ researchLogger.flushQueue(researchLogger.isPrivacyThreat(scrubbedWord));
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = {
+ "LatinIMEDeleteSurroundingText", "length"
+ };
+ public static void latinIME_deleteSurroundingText(final int length) {
+ final Object[] values = {
+ length
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT, values);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD = {
+ "LatinIMEDoubleSpaceAutoPeriod"
+ };
+ public static void latinIME_doubleSpaceAutoPeriod() {
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS = {
+ "LatinIMEOnDisplayCompletions", "applicationSpecifiedCompletions"
+ };
+ public static void latinIME_onDisplayCompletions(
+ final CompletionInfo[] applicationSpecifiedCompletions) {
+ final Object[] values = {
+ applicationSpecifiedCompletions
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS,
+ values);
+ }
+
+ /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() {
+ boolean returnValue = sLatinIMEExpectingUpdateSelection;
+ sLatinIMEExpectingUpdateSelection = false;
+ return returnValue;
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_ONWINDOWHIDDEN = {
+ "LatinIMEOnWindowHidden", "isTextTruncated", "text"
+ };
+ public static void latinIME_onWindowHidden(final int savedSelectionStart,
+ final int savedSelectionEnd, final InputConnection ic) {
+ if (ic != null) {
+ ic.beginBatchEdit();
+ ic.performContextMenuAction(android.R.id.selectAll);
+ CharSequence charSequence = ic.getSelectedText(0);
+ ic.setSelection(savedSelectionStart, savedSelectionEnd);
+ ic.endBatchEdit();
+ sLatinIMEExpectingUpdateSelection = true;
+ final Object[] values = new Object[2];
+ if (OUTPUT_ENTIRE_BUFFER) {
+ if (TextUtils.isEmpty(charSequence)) {
+ values[0] = false;
+ values[1] = "";
+ } else {
+ if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) {
+ int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE;
+ // do not cut in the middle of a supplementary character
+ final char c = charSequence.charAt(length - 1);
+ if (Character.isHighSurrogate(c)) {
+ length--;
+ }
+ final CharSequence truncatedCharSequence = charSequence.subSequence(0,
+ length);
+ values[0] = true;
+ values[1] = truncatedCharSequence.toString();
+ } else {
+ values[0] = false;
+ values[1] = charSequence.toString();
+ }
+ }
+ } else {
+ values[0] = true;
+ values[1] = "";
+ }
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values);
+ researchLogger.flushQueue(true); // Play it safe. Remove privacy-sensitive events.
+ }
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = {
+ "LatinIMEOnStartInputViewInternal", "uuid", "packageName", "inputType", "imeOptions",
+ "fieldId", "display", "model", "prefs", "outputFormatVersion"
+ };
+ public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
+ final SharedPreferences prefs) {
+ if (editorInfo != null) {
+ final Object[] values = {
+ getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
+ Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY,
+ Build.MODEL, prefs, OUTPUT_FORMAT_VERSION
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values);
+ }
+ }
+
+ private static String getUUID(final SharedPreferences prefs) {
+ String uuidString = prefs.getString(PREF_RESEARCH_LOGGER_UUID_STRING, null);
+ if (null == uuidString) {
+ UUID uuid = UUID.randomUUID();
+ uuidString = uuid.toString();
+ Editor editor = prefs.edit();
+ editor.putString(PREF_RESEARCH_LOGGER_UUID_STRING, uuidString);
+ editor.apply();
+ }
+ return uuidString;
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_ONUPDATESELECTION = {
+ "LatinIMEOnUpdateSelection", "lastSelectionStart", "lastSelectionEnd", "oldSelStart",
+ "oldSelEnd", "newSelStart", "newSelEnd", "composingSpanStart", "composingSpanEnd",
+ "expectingUpdateSelection", "expectingUpdateSelectionFromLogger", "context"
+ };
+ public static void latinIME_onUpdateSelection(final int lastSelectionStart,
+ final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
+ final int newSelStart, final int newSelEnd, final int composingSpanStart,
+ final int composingSpanEnd, final boolean expectingUpdateSelection,
+ final boolean expectingUpdateSelectionFromLogger,
+ final RichInputConnection connection) {
+ String word = "";
+ if (connection != null) {
+ Range range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1);
+ if (range != null) {
+ word = range.mWord;
+ }
+ }
+ final ResearchLogger researchLogger = getInstance();
+ final String scrubbedWord = researchLogger.scrubWord(word);
+ final Object[] values = {
+ lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart,
+ newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection,
+ expectingUpdateSelectionFromLogger, scrubbedWord
+ };
+ researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_PERFORMEDITORACTION = {
+ "LatinIMEPerformEditorAction", "imeActionNext"
+ };
+ public static void latinIME_performEditorAction(final int imeActionNext) {
+ final Object[] values = {
+ imeActionNext
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_PERFORMEDITORACTION, values);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION = {
+ "LatinIMEPickApplicationSpecifiedCompletion", "index", "text", "x", "y"
+ };
+ public static void latinIME_pickApplicationSpecifiedCompletion(final int index,
+ final CharSequence cs, int x, int y) {
+ final Object[] values = {
+ index, cs, x, y
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
+ researchLogger.flushQueue(researchLogger.isPrivacyThreat(cs.toString()));
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = {
+ "LatinIMEPickSuggestionManually", "replacedWord", "index", "suggestion", "x", "y"
+ };
+ public static void latinIME_pickSuggestionManually(final String replacedWord,
+ final int index, CharSequence suggestion, int x, int y) {
+ final Object[] values = {
+ scrubDigitsFromString(replacedWord), index, suggestion == null ? null :
+ scrubDigitsFromString(suggestion.toString()), x, y
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY,
+ values);
+ researchLogger.flushQueue(researchLogger.isPrivacyThreat(suggestion.toString()));
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = {
+ "LatinIMEPunctuationSuggestion", "index", "suggestion", "x", "y"
+ };
+ public static void latinIME_punctuationSuggestion(final int index,
+ final CharSequence suggestion, int x, int y) {
+ final Object[] values = {
+ index, suggestion, x, y
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT = {
+ "LatinIMERevertDoubleSpaceWhileInBatchEdit"
+ };
+ public static void latinIME_revertDoubleSpaceWhileInBatchEdit() {
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT,
+ EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION = {
+ "LatinIMERevertSwapPunctuation"
+ };
+ public static void latinIME_revertSwapPunctuation() {
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_SENDKEYCODEPOINT = {
+ "LatinIMESendKeyCodePoint", "code"
+ };
+ public static void latinIME_sendKeyCodePoint(final int code) {
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(code))
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT = {
+ "LatinIMESwapSwapperAndSpaceWhileInBatchEdit"
+ };
+ public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() {
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT,
+ EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = {
+ "LatinIMESwitchToKeyboardView"
+ };
+ public static void latinIME_switchToKeyboardView() {
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = {
+ "LatinKeyboardViewOnLongPress"
+ };
+ public static void latinKeyboardView_onLongPress() {
+ getInstance().enqueueEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = {
+ "LatinKeyboardViewSetKeyboard", "elementId", "locale", "orientation", "width",
+ "modeName", "action", "navigateNext", "navigatePrevious", "clobberSettingsKey",
+ "passwordInput", "shortcutKeyEnabled", "hasShortcutKey", "languageSwitchKeyEnabled",
+ "isMultiLine", "tw", "th", "keys"
+ };
+ public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) {
+ if (keyboard != null) {
+ final KeyboardId kid = keyboard.mId;
+ final boolean isPasswordView = kid.passwordInput();
+ final Object[] values = {
+ KeyboardId.elementIdToName(kid.mElementId),
+ kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
+ kid.mOrientation,
+ kid.mWidth,
+ KeyboardId.modeName(kid.mMode),
+ kid.imeAction(),
+ kid.navigateNext(),
+ kid.navigatePrevious(),
+ kid.mClobberSettingsKey,
+ isPasswordView,
+ kid.mShortcutKeyEnabled,
+ kid.mHasShortcutKey,
+ kid.mLanguageSwitchKeyEnabled,
+ kid.isMultiLine(),
+ keyboard.mOccupiedWidth,
+ keyboard.mOccupiedHeight,
+ keyboard.mKeys
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values);
+ getInstance().setIsPasswordView(isPasswordView);
+ }
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_REVERTCOMMIT = {
+ "LatinIMERevertCommit", "originallyTypedWord"
+ };
+ public static void latinIME_revertCommit(final String originallyTypedWord) {
+ final Object[] values = {
+ originallyTypedWord
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_REVERTCOMMIT, values);
+ }
+
+ private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT = {
+ "PointerTrackerCallListenerOnCancelInput"
+ };
+ public static void pointerTracker_callListenerOnCancelInput() {
+ getInstance().enqueueEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT,
+ EVENTKEYS_NULLVALUES);
+ }
+
+ private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT = {
+ "PointerTrackerCallListenerOnCodeInput", "code", "outputText", "x", "y",
+ "ignoreModifierKey", "altersCode", "isEnabled"
+ };
+ public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x,
+ final int y, final boolean ignoreModifierKey, final boolean altersCode,
+ final int code) {
+ if (key != null) {
+ CharSequence outputText = key.mOutputText;
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(code)), outputText == null ? null
+ : scrubDigitsFromString(outputText.toString()),
+ x, y, ignoreModifierKey, altersCode, key.isEnabled()
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values);
+ }
+ }
+
+ private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = {
+ "PointerTrackerCallListenerOnRelease", "code", "withSliding", "ignoreModifierKey",
+ "isEnabled"
+ };
+ public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode,
+ final boolean withSliding, final boolean ignoreModifierKey) {
+ if (key != null) {
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding,
+ ignoreModifierKey, key.isEnabled()
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values);
+ }
+ }
+
+ private static final String[] EVENTKEYS_POINTERTRACKER_ONDOWNEVENT = {
+ "PointerTrackerOnDownEvent", "deltaT", "distanceSquared"
+ };
+ public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) {
+ final Object[] values = {
+ deltaT, distanceSquared
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_POINTERTRACKER_ONDOWNEVENT, values);
+ }
+
+ private static final String[] EVENTKEYS_POINTERTRACKER_ONMOVEEVENT = {
+ "PointerTrackerOnMoveEvent", "x", "y", "lastX", "lastY"
+ };
+ public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX,
+ final int lastY) {
+ final Object[] values = {
+ x, y, lastX, lastY
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_POINTERTRACKER_ONMOVEEVENT, values);
+ }
+
+ private static final String[] EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT = {
+ "SuddenJumpingTouchEventHandlerOnTouchEvent", "motionEvent"
+ };
+ public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) {
+ if (me != null) {
+ final Object[] values = {
+ me.toString()
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT, values);
+ }
+ }
+
+ private static final String[] EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS = {
+ "SuggestionsViewSetSuggestions", "suggestedWords"
+ };
+ public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) {
+ if (suggestedWords != null) {
+ final Object[] values = {
+ suggestedWords
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS,
+ values);
+ }
+ }
+
+ private static final String[] EVENTKEYS_USER_TIMESTAMP = {
+ "UserTimestamp"
+ };
+ public void userTimestamp() {
+ getInstance().enqueueEvent(EVENTKEYS_USER_TIMESTAMP, EVENTKEYS_NULLVALUES);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
new file mode 100644
index 000000000..0c19bed05
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InputConnection;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.define.ProductionFlag;
+
+import java.util.regex.Pattern;
+
+/**
+ * Wrapper for InputConnection to simplify interaction
+ */
+public class RichInputConnection {
+ private static final String TAG = RichInputConnection.class.getSimpleName();
+ private static final boolean DBG = false;
+ // Provision for a long word pair and a separator
+ private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1;
+ private static final Pattern spaceRegex = Pattern.compile("\\s+");
+ private static final int INVALID_CURSOR_POSITION = -1;
+
+ InputConnection mIC;
+ int mNestLevel;
+ public RichInputConnection() {
+ mIC = null;
+ mNestLevel = 0;
+ }
+
+ public void beginBatchEdit(final InputConnection newInputConnection) {
+ if (++mNestLevel == 1) {
+ mIC = newInputConnection;
+ if (null != mIC) mIC.beginBatchEdit();
+ } else {
+ if (DBG) {
+ throw new RuntimeException("Nest level too deep");
+ } else {
+ Log.e(TAG, "Nest level too deep : " + mNestLevel);
+ }
+ }
+ }
+ public void endBatchEdit() {
+ if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+ if (--mNestLevel == 0 && null != mIC) mIC.endBatchEdit();
+ }
+
+ private void checkBatchEdit() {
+ if (mNestLevel != 1) {
+ // TODO: exception instead
+ Log.e(TAG, "Batch edit level incorrect : " + mNestLevel);
+ Log.e(TAG, Utils.getStackTrace(4));
+ }
+ }
+
+ public void finishComposingText() {
+ checkBatchEdit();
+ if (null != mIC) mIC.finishComposingText();
+ }
+
+ public void commitText(final CharSequence text, final int i) {
+ checkBatchEdit();
+ if (null != mIC) mIC.commitText(text, i);
+ }
+
+ public int getCursorCapsMode(final int inputType) {
+ if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
+ return mIC.getCursorCapsMode(inputType);
+ }
+
+ public CharSequence getTextBeforeCursor(final int i, final int j) {
+ if (null != mIC) return mIC.getTextBeforeCursor(i, j);
+ return null;
+ }
+
+ public CharSequence getTextAfterCursor(final int i, final int j) {
+ if (null != mIC) return mIC.getTextAfterCursor(i, j);
+ return null;
+ }
+
+ public void deleteSurroundingText(final int i, final int j) {
+ checkBatchEdit();
+ if (null != mIC) mIC.deleteSurroundingText(i, j);
+ }
+
+ public void performEditorAction(final int actionId) {
+ if (null != mIC) mIC.performEditorAction(actionId);
+ }
+
+ public void sendKeyEvent(final KeyEvent keyEvent) {
+ checkBatchEdit();
+ if (null != mIC) mIC.sendKeyEvent(keyEvent);
+ }
+
+ public void setComposingText(final CharSequence text, final int i) {
+ checkBatchEdit();
+ if (null != mIC) mIC.setComposingText(text, i);
+ }
+
+ public void setSelection(final int from, final int to) {
+ checkBatchEdit();
+ if (null != mIC) mIC.setSelection(from, to);
+ }
+
+ public void commitCorrection(final CorrectionInfo correctionInfo) {
+ checkBatchEdit();
+ if (null != mIC) mIC.commitCorrection(correctionInfo);
+ }
+
+ public void commitCompletion(final CompletionInfo completionInfo) {
+ checkBatchEdit();
+ if (null != mIC) mIC.commitCompletion(completionInfo);
+ }
+
+ public CharSequence getPreviousWord(final String sentenceSeperators) {
+ //TODO: Should fix this. This could be slow!
+ if (null == mIC) return null;
+ CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
+ return getPreviousWord(prev, sentenceSeperators);
+ }
+
+ /**
+ * Represents a range of text, relative to the current cursor position.
+ */
+ public static class Range {
+ /** Characters before selection start */
+ public final int mCharsBefore;
+
+ /**
+ * Characters after selection start, including one trailing word
+ * separator.
+ */
+ public final int mCharsAfter;
+
+ /** The actual characters that make up a word */
+ public final String mWord;
+
+ public Range(int charsBefore, int charsAfter, String word) {
+ if (charsBefore < 0 || charsAfter < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ this.mCharsBefore = charsBefore;
+ this.mCharsAfter = charsAfter;
+ this.mWord = word;
+ }
+ }
+
+ private static boolean isSeparator(int code, String sep) {
+ return sep.indexOf(code) != -1;
+ }
+
+ // Get the word before the whitespace preceding the non-whitespace preceding the cursor.
+ // Also, it won't return words that end in a separator.
+ // Example :
+ // "abc def|" -> abc
+ // "abc def |" -> abc
+ // "abc def. |" -> abc
+ // "abc def . |" -> def
+ // "abc|" -> null
+ // "abc |" -> null
+ // "abc. def|" -> null
+ public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) {
+ if (prev == null) return null;
+ String[] w = spaceRegex.split(prev);
+
+ // If we can't find two words, or we found an empty word, return null.
+ if (w.length < 2 || w[w.length - 2].length() <= 0) return null;
+
+ // If ends in a separator, return null
+ char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1);
+ if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
+
+ return w[w.length - 2];
+ }
+
+ public CharSequence getThisWord(String sentenceSeperators) {
+ if (null == mIC) return null;
+ final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
+ return getThisWord(prev, sentenceSeperators);
+ }
+
+ // Get the word immediately before the cursor, even if there is whitespace between it and
+ // the cursor - but not if there is punctuation.
+ // Example :
+ // "abc def|" -> def
+ // "abc def |" -> def
+ // "abc def. |" -> null
+ // "abc def . |" -> null
+ public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) {
+ if (prev == null) return null;
+ String[] w = spaceRegex.split(prev);
+
+ // No word : return null
+ if (w.length < 1 || w[w.length - 1].length() <= 0) return null;
+
+ // If ends in a separator, return null
+ char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1);
+ if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
+
+ return w[w.length - 1];
+ }
+
+ /**
+ * @param separators characters which may separate words
+ * @return the word that surrounds the cursor, including up to one trailing
+ * separator. For example, if the field contains "he|llo world", where |
+ * represents the cursor, then "hello " will be returned.
+ */
+ public String getWordAtCursor(String separators) {
+ // getWordRangeAtCursor returns null if the connection is null
+ Range r = getWordRangeAtCursor(separators, 0);
+ return (r == null) ? null : r.mWord;
+ }
+
+ private int getCursorPosition() {
+ if (null == mIC) return INVALID_CURSOR_POSITION;
+ final ExtractedText extracted = mIC.getExtractedText(new ExtractedTextRequest(), 0);
+ if (extracted == null) {
+ return INVALID_CURSOR_POSITION;
+ }
+ return extracted.startOffset + extracted.selectionStart;
+ }
+
+ /**
+ * Returns the text surrounding the cursor.
+ *
+ * @param sep a string of characters that split words.
+ * @param additionalPrecedingWordsCount the number of words before the current word that should
+ * be included in the returned range
+ * @return a range containing the text surrounding the cursor
+ */
+ public Range getWordRangeAtCursor(String sep, int additionalPrecedingWordsCount) {
+ if (mIC == null || sep == null) {
+ return null;
+ }
+ CharSequence before = mIC.getTextBeforeCursor(1000, 0);
+ CharSequence after = mIC.getTextAfterCursor(1000, 0);
+ if (before == null || after == null) {
+ return null;
+ }
+
+ // Going backward, alternate skipping non-separators and separators until enough words
+ // have been read.
+ int start = before.length();
+ boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at
+ while (true) { // see comments below for why this is guaranteed to halt
+ while (start > 0) {
+ final int codePoint = Character.codePointBefore(before, start);
+ if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) {
+ break; // inner loop
+ }
+ --start;
+ if (Character.isSupplementaryCodePoint(codePoint)) {
+ --start;
+ }
+ }
+ // isStoppingAtWhitespace is true every other time through the loop,
+ // so additionalPrecedingWordsCount is guaranteed to become < 0, which
+ // guarantees outer loop termination
+ if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) {
+ break; // outer loop
+ }
+ isStoppingAtWhitespace = !isStoppingAtWhitespace;
+ }
+
+ // Find last word separator after the cursor
+ int end = -1;
+ while (++end < after.length()) {
+ final int codePoint = Character.codePointAt(after, end);
+ if (isSeparator(codePoint, sep)) {
+ break;
+ }
+ if (Character.isSupplementaryCodePoint(codePoint)) {
+ ++end;
+ }
+ }
+
+ int cursor = getCursorPosition();
+ if (start >= 0 && cursor + end <= after.length() + before.length()) {
+ String word = before.toString().substring(start, before.length())
+ + after.toString().substring(0, end);
+ return new Range(before.length() - start, end, word);
+ }
+
+ return null;
+ }
+
+ public boolean isCursorTouchingWord(final SettingsValues settingsValues) {
+ CharSequence before = getTextBeforeCursor(1, 0);
+ CharSequence after = getTextAfterCursor(1, 0);
+ if (!TextUtils.isEmpty(before) && !settingsValues.isWordSeparator(before.charAt(0))
+ && !settingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) {
+ return true;
+ }
+ if (!TextUtils.isEmpty(after) && !settingsValues.isWordSeparator(after.charAt(0))
+ && !settingsValues.isSymbolExcludedFromWordSeparators(after.charAt(0))) {
+ return true;
+ }
+ return false;
+ }
+
+ public void removeTrailingSpace() {
+ checkBatchEdit();
+ final CharSequence lastOne = getTextBeforeCursor(1, 0);
+ if (lastOne != null && lastOne.length() == 1
+ && lastOne.charAt(0) == Keyboard.CODE_SPACE) {
+ deleteSurroundingText(1, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(1);
+ }
+ }
+ }
+
+ public boolean sameAsTextBeforeCursor(final CharSequence text) {
+ final CharSequence beforeText = getTextBeforeCursor(text.length(), 0);
+ return TextUtils.equals(text, beforeText);
+ }
+
+ /* (non-javadoc)
+ * Returns the word before the cursor if the cursor is at the end of a word, null otherwise
+ */
+ public CharSequence getWordBeforeCursorIfAtEndOfWord(final SettingsValues settings) {
+ // Bail out if the cursor is not at the end of a word (cursor must be preceded by
+ // non-whitespace, non-separator, non-start-of-text)
+ // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
+ final CharSequence textBeforeCursor = getTextBeforeCursor(1, 0);
+ if (TextUtils.isEmpty(textBeforeCursor)
+ || settings.isWordSeparator(textBeforeCursor.charAt(0))) return null;
+
+ // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
+ // separator or end of line/text)
+ // Example: "test|"<EOL> "te|st" get rejected here
+ final CharSequence textAfterCursor = getTextAfterCursor(1, 0);
+ if (!TextUtils.isEmpty(textAfterCursor)
+ && !settings.isWordSeparator(textAfterCursor.charAt(0))) return null;
+
+ // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe)
+ // Example: " -|" gets rejected here but "e-|" and "e|" are okay
+ CharSequence word = getWordAtCursor(settings.mWordSeparators);
+ // We don't suggest on leading single quotes, so we have to remove them from the word if
+ // it starts with single quotes.
+ while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) {
+ word = word.subSequence(1, word.length());
+ }
+ if (TextUtils.isEmpty(word)) return null;
+ final char firstChar = word.charAt(0); // we just tested that word is not empty
+ if (word.length() == 1 && !Character.isLetter(firstChar)) return null;
+
+ // We only suggest on words that start with a letter or a symbol that is excluded from
+ // word separators (see #handleCharacterWhileInBatchEdit).
+ if (!(Character.isLetter(firstChar)
+ || settings.isSymbolExcludedFromWordSeparators(firstChar))) {
+ return null;
+ }
+
+ return word;
+ }
+
+ public boolean revertDoubleSpace() {
+ checkBatchEdit();
+ // Here we test whether we indeed have a period and a space before us. This should not
+ // be needed, but it's there just in case something went wrong.
+ final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
+ if (!". ".equals(textBeforeCursor)) {
+ // Theoretically we should not be coming here if there isn't ". " before the
+ // cursor, but the application may be changing the text while we are typing, so
+ // anything goes. We should not crash.
+ Log.d(TAG, "Tried to revert double-space combo but we didn't find "
+ + "\". \" just before the cursor.");
+ return false;
+ }
+ deleteSurroundingText(2, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(2);
+ }
+ commitText(" ", 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_revertDoubleSpaceWhileInBatchEdit();
+ }
+ return true;
+ }
+
+ public boolean revertSwapPunctuation() {
+ checkBatchEdit();
+ // Here we test whether we indeed have a space and something else before us. This should not
+ // be needed, but it's there just in case something went wrong.
+ final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
+ // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
+ // enter surrogate pairs this code will have been removed.
+ if (TextUtils.isEmpty(textBeforeCursor)
+ || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) {
+ // We may only come here if the application is changing the text while we are typing.
+ // This is quite a broken case, but not logically impossible, so we shouldn't crash,
+ // but some debugging log may be in order.
+ Log.d(TAG, "Tried to revert a swap of punctuation but we didn't "
+ + "find a space just before the cursor.");
+ return false;
+ }
+ deleteSurroundingText(2, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(2);
+ }
+ commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_revertSwapPunctuation();
+ }
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 6c515c845..4c67b4957 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -16,354 +16,126 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.compat.CompatUtils;
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
-import com.android.inputmethod.deprecated.VoiceProxy;
-import com.android.inputmethod.compat.VibratorCompatWrapper;
-
import android.app.AlertDialog;
-import android.app.Dialog;
import android.app.backup.BackupManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.media.AudioManager;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
-import android.speech.SpeechRecognizer;
-import android.text.AutoText;
-import android.text.TextUtils;
-import android.text.method.LinkMovementMethod;
-import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
-import java.util.Arrays;
-import java.util.Locale;
+import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethodcommon.InputMethodSettingsFragment;
-public class Settings extends PreferenceActivity
- implements SharedPreferences.OnSharedPreferenceChangeListener,
- DialogInterface.OnDismissListener, OnPreferenceClickListener {
- private static final String TAG = "Settings";
+public class Settings extends InputMethodSettingsFragment
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
+ public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false;
- public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings";
+ // In the same order as xml/prefs.xml
+ public static final String PREF_GENERAL_SETTINGS = "general_settings";
+ public static final String PREF_AUTO_CAP = "auto_cap";
public static final String PREF_VIBRATE_ON = "vibrate_on";
public static final String PREF_SOUND_ON = "sound_on";
- public static final String PREF_KEY_PREVIEW_POPUP_ON = "popup_on";
- public static final String PREF_RECORRECTION_ENABLED = "recorrection_enabled";
- public static final String PREF_AUTO_CAP = "auto_cap";
- public static final String PREF_SETTINGS_KEY = "settings_key";
- public static final String PREF_VOICE_SETTINGS_KEY = "voice_mode";
- public static final String PREF_INPUT_LANGUAGE = "input_language";
- public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
- public static final String PREF_SUBTYPES = "subtype_settings";
-
+ public static final String PREF_POPUP_ON = "popup_on";
+ public static final String PREF_VOICE_MODE = "voice_mode";
+ public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
- public static final String PREF_CORRECTION_SETTINGS_KEY = "correction_settings";
- public static final String PREF_QUICK_FIXES = "quick_fixes";
- public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
- public static final String PREF_DEBUG_SETTINGS = "debug_settings";
-
- public static final String PREF_NGRAM_SETTINGS_KEY = "ngram_settings";
- public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion";
- public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction";
-
- public static final String PREF_MISC_SETTINGS_KEY = "misc_settings";
-
+ public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
+ public static final String PREF_MISC_SETTINGS = "misc_settings";
+ public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+ public static final String PREF_LAST_USER_DICTIONARY_WRITE_TIME =
+ "last_user_dictionary_write_time";
+ public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
+ public static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
+ "pref_suppress_language_switch_key";
+ public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
+ "pref_include_other_imes_in_language_switch_list";
+ public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
"pref_key_preview_popup_dismiss_delay";
- public static final String PREF_KEY_USE_CONTACTS_DICT =
- "pref_key_use_contacts_dict";
-
- public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
-
- // Dialog ids
- private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
-
- public static class Values {
- // From resources:
- public final boolean mSwipeDownDismissKeyboardEnabled;
- public final int mDelayBeforeFadeoutLanguageOnSpacebar;
- public final int mDelayUpdateSuggestions;
- public final int mDelayUpdateOldSuggestions;
- public final int mDelayUpdateShiftState;
- public final int mDurationOfFadeoutLanguageOnSpacebar;
- public final float mFinalFadeoutFactorOfLanguageOnSpacebar;
- public final long mDoubleSpacesTurnIntoPeriodTimeout;
- public final String mWordSeparators;
- public final String mMagicSpaceStrippers;
- public final String mMagicSpaceSwappers;
- public final String mSuggestPuncs;
- public final SuggestedWords mSuggestPuncList;
-
- // From preferences:
- public final boolean mSoundOn; // Sound setting private to Latin IME (see mSilentModeOn)
- public final boolean mVibrateOn;
- public final boolean mKeyPreviewPopupOn;
- public final int mKeyPreviewPopupDismissDelay;
- public final boolean mAutoCap;
- public final boolean mQuickFixes;
- public final boolean mAutoCorrectEnabled;
- public final double mAutoCorrectionThreshold;
- // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
- public final boolean mBigramSuggestionEnabled;
- // Prediction: use bigrams to predict the next word when there is no input for it yet
- public final boolean mBigramPredictionEnabled;
- public final boolean mUseContactsDict;
-
- public Values(final SharedPreferences prefs, final Context context,
- final String localeStr) {
- final Resources res = context.getResources();
- final Locale savedLocale;
- if (null != localeStr) {
- final Locale keyboardLocale = Utils.constructLocaleFromString(localeStr);
- savedLocale = Utils.setSystemLocale(res, keyboardLocale);
- } else {
- savedLocale = null;
- }
-
- // Get the resources
- mSwipeDownDismissKeyboardEnabled = res.getBoolean(
- R.bool.config_swipe_down_dismiss_keyboard_enabled);
- mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger(
- R.integer.config_delay_before_fadeout_language_on_spacebar);
- mDelayUpdateSuggestions =
- res.getInteger(R.integer.config_delay_update_suggestions);
- mDelayUpdateOldSuggestions = res.getInteger(
- R.integer.config_delay_update_old_suggestions);
- mDelayUpdateShiftState =
- res.getInteger(R.integer.config_delay_update_shift_state);
- mDurationOfFadeoutLanguageOnSpacebar = res.getInteger(
- R.integer.config_duration_of_fadeout_language_on_spacebar);
- mFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger(
- R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f;
- mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger(
- R.integer.config_double_spaces_turn_into_period_timeout);
- mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
- mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
- String wordSeparators = mMagicSpaceStrippers + mMagicSpaceSwappers
- + res.getString(R.string.magic_space_promoting_symbols);
- final String notWordSeparators = res.getString(R.string.non_word_separator_symbols);
- for (int i = notWordSeparators.length() - 1; i >= 0; --i) {
- wordSeparators = wordSeparators.replace(notWordSeparators.substring(i, i + 1), "");
- }
- mWordSeparators = wordSeparators;
- mSuggestPuncs = res.getString(R.string.suggested_punctuations);
- // TODO: it would be nice not to recreate this each time we change the configuration
- mSuggestPuncList = createSuggestPuncList(mSuggestPuncs);
-
- // Get the settings preferences
- final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator();
- mVibrateOn = hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON, false);
- mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
- res.getBoolean(R.bool.config_default_sound_enabled));
-
- mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
- mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
- mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
- mQuickFixes = isQuickFixesEnabled(prefs, res);
-
- mAutoCorrectEnabled = isAutoCorrectEnabled(prefs, res);
- mBigramSuggestionEnabled = mAutoCorrectEnabled
- && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled);
- mBigramPredictionEnabled = mBigramSuggestionEnabled
- && isBigramPredictionEnabled(prefs, res);
-
- mAutoCorrectionThreshold = getAutoCorrectionThreshold(prefs, res);
-
- mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
-
- Utils.setSystemLocale(res, savedLocale);
- }
-
- public boolean isSuggestedPunctuation(int code) {
- return mSuggestPuncs.contains(String.valueOf((char)code));
- }
-
- public boolean isWordSeparator(int code) {
- return mWordSeparators.contains(String.valueOf((char)code));
- }
-
- public boolean isMagicSpaceStripper(int code) {
- return mMagicSpaceStrippers.contains(String.valueOf((char)code));
- }
+ public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
+ public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
+ public static final String PREF_VIBRATION_DURATION_SETTINGS =
+ "pref_vibration_duration_settings";
+ public static final String PREF_KEYPRESS_SOUND_VOLUME =
+ "pref_keypress_sound_volume";
- public boolean isMagicSpaceSwapper(int code) {
- return mMagicSpaceSwappers.contains(String.valueOf((char)code));
- }
-
- // Helper methods
- private static boolean isQuickFixesEnabled(SharedPreferences sp, Resources resources) {
- final boolean showQuickFixesOption = resources.getBoolean(
- R.bool.config_enable_quick_fixes_option);
- if (!showQuickFixesOption) {
- return isAutoCorrectEnabled(sp, resources);
- }
- return sp.getBoolean(Settings.PREF_QUICK_FIXES, resources.getBoolean(
- R.bool.config_default_quick_fixes));
- }
-
- private static boolean isAutoCorrectEnabled(SharedPreferences sp, Resources resources) {
- final String currentAutoCorrectionSetting = sp.getString(
- Settings.PREF_AUTO_CORRECTION_THRESHOLD,
- resources.getString(R.string.auto_correction_threshold_mode_index_modest));
- final String autoCorrectionOff = resources.getString(
- R.string.auto_correction_threshold_mode_index_off);
- return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
- }
-
- // Public to access from KeyboardSwitcher. Should it have access to some
- // process-global instance instead?
- public static boolean isKeyPreviewPopupEnabled(SharedPreferences sp, Resources resources) {
- final boolean showPopupOption = resources.getBoolean(
- R.bool.config_enable_show_popup_on_keypress_option);
- if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview);
- return sp.getBoolean(Settings.PREF_KEY_PREVIEW_POPUP_ON,
- resources.getBoolean(R.bool.config_default_popup_preview));
- }
-
- // Likewise
- public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp,
- Resources resources) {
- return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
- Integer.toString(resources.getInteger(R.integer.config_delay_after_preview))));
- }
-
- private static boolean isBigramSuggestionEnabled(SharedPreferences sp, Resources resources,
- boolean autoCorrectEnabled) {
- final boolean showBigramSuggestionsOption = resources.getBoolean(
- R.bool.config_enable_bigram_suggestions_option);
- if (!showBigramSuggestionsOption) {
- return autoCorrectEnabled;
- }
- return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, resources.getBoolean(
- R.bool.config_default_bigram_suggestions));
- }
-
- private static boolean isBigramPredictionEnabled(SharedPreferences sp,
- Resources resources) {
- return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean(
- R.bool.config_default_bigram_prediction));
- }
-
- private static double getAutoCorrectionThreshold(SharedPreferences sp,
- Resources resources) {
- final String currentAutoCorrectionSetting = sp.getString(
- Settings.PREF_AUTO_CORRECTION_THRESHOLD,
- resources.getString(R.string.auto_correction_threshold_mode_index_modest));
- final String[] autoCorrectionThresholdValues = resources.getStringArray(
- R.array.auto_correction_threshold_values);
- // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
- double autoCorrectionThreshold = Double.MAX_VALUE;
- try {
- final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting);
- if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) {
- autoCorrectionThreshold = Double.parseDouble(
- autoCorrectionThresholdValues[arrayIndex]);
- }
- } catch (NumberFormatException e) {
- // Whenever the threshold settings are correct, never come here.
- autoCorrectionThreshold = Double.MAX_VALUE;
- Log.w(TAG, "Cannot load auto correction threshold setting."
- + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting
- + ", autoCorrectionThresholdValues: "
- + Arrays.toString(autoCorrectionThresholdValues));
- }
- return autoCorrectionThreshold;
- }
-
- private static SuggestedWords createSuggestPuncList(final String puncs) {
- SuggestedWords.Builder builder = new SuggestedWords.Builder();
- if (puncs != null) {
- for (int i = 0; i < puncs.length(); i++) {
- builder.addWord(puncs.subSequence(i, i + 1));
- }
- }
- return builder.build();
- }
- }
+ public static final String PREF_INPUT_LANGUAGE = "input_language";
+ public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
+ public static final String PREF_DEBUG_SETTINGS = "debug_settings";
- private PreferenceScreen mInputLanguageSelection;
- private CheckBoxPreference mQuickFixes;
+ private PreferenceScreen mKeypressVibrationDurationSettingsPref;
+ private PreferenceScreen mKeypressSoundVolumeSettingsPref;
private ListPreference mVoicePreference;
- private ListPreference mSettingsKeyPreference;
private ListPreference mShowCorrectionSuggestionsPreference;
- private ListPreference mAutoCorrectionThreshold;
+ private ListPreference mAutoCorrectionThresholdPreference;
private ListPreference mKeyPreviewPopupDismissDelay;
- // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
- private CheckBoxPreference mBigramSuggestion;
- // Prediction: use bigrams to predict the next word when there is no input for it yet
+ // Use bigrams to predict the next word when there is no input for it yet
private CheckBoxPreference mBigramPrediction;
private Preference mDebugSettingsPreference;
- private boolean mVoiceOn;
-
- private AlertDialog mDialog;
- private VoiceProxy.VoiceLoggerWrapper mVoiceLogger;
-
- private boolean mOkClicked = false;
- private String mVoiceModeOff;
+ private TextView mKeypressVibrationDurationSettingsTextView;
+ private TextView mKeypressSoundVolumeSettingsTextView;
private void ensureConsistencyOfAutoCorrectionSettings() {
final String autoCorrectionOff = getResources().getString(
R.string.auto_correction_threshold_mode_index_off);
- final String currentSetting = mAutoCorrectionThreshold.getValue();
- mBigramSuggestion.setEnabled(!currentSetting.equals(autoCorrectionOff));
- mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff));
+ final String currentSetting = mAutoCorrectionThresholdPreference.getValue();
+ if (null != mBigramPrediction) {
+ mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff));
+ }
}
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
+ setSubtypeEnablerTitle(R.string.select_language);
+ addPreferencesFromResource(R.xml.prefs);
+
final Resources res = getResources();
+ final Context context = getActivity();
- addPreferencesFromResource(R.xml.prefs);
- mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES);
- mInputLanguageSelection.setOnPreferenceClickListener(this);
- mQuickFixes = (CheckBoxPreference) findPreference(PREF_QUICK_FIXES);
- mVoicePreference = (ListPreference) findPreference(PREF_VOICE_SETTINGS_KEY);
- mSettingsKeyPreference = (ListPreference) findPreference(PREF_SETTINGS_KEY);
+ mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE);
mShowCorrectionSuggestionsPreference =
(ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING);
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
prefs.registerOnSharedPreferenceChangeListener(this);
- mVoiceModeOff = getString(R.string.voice_mode_off);
- mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
- .equals(mVoiceModeOff));
- mVoiceLogger = VoiceProxy.VoiceLoggerWrapper.getInstance(this);
-
- mAutoCorrectionThreshold = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
- mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS);
+ mAutoCorrectionThresholdPreference =
+ (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS);
mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS);
if (mDebugSettingsPreference != null) {
final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
- debugSettingsIntent.setClassName(getPackageName(), DebugSettings.class.getName());
+ debugSettingsIntent.setClassName(
+ context.getPackageName(), DebugSettings.class.getName());
mDebugSettingsPreference.setIntent(debugSettingsIntent);
}
ensureConsistencyOfAutoCorrectionSettings();
final PreferenceGroup generalSettings =
- (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY);
+ (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS);
final PreferenceGroup textCorrectionGroup =
- (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY);
-
- final boolean showSettingsKeyOption = res.getBoolean(
- R.bool.config_enable_show_settings_key_option);
- if (!showSettingsKeyOption) {
- generalSettings.removePreference(mSettingsKeyPreference);
- }
+ (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS);
+ final PreferenceGroup miscSettings =
+ (PreferenceGroup) findPreference(PREF_MISC_SETTINGS);
final boolean showVoiceKeyOption = res.getBoolean(
R.bool.config_enable_show_voice_key_option);
@@ -371,44 +143,25 @@ public class Settings extends PreferenceActivity
generalSettings.removePreference(mVoicePreference);
}
- if (!VibratorCompatWrapper.getInstance(this).hasVibrator()) {
+ if (!VibratorUtils.getInstance(context).hasVibrator()) {
+ final PreferenceGroup advancedSettings =
+ (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
- }
-
- if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
- generalSettings.removePreference(findPreference(PREF_SUBTYPES));
+ if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
+ advancedSettings.removePreference(findPreference(PREF_VIBRATION_DURATION_SETTINGS));
+ }
}
final boolean showPopupOption = res.getBoolean(
R.bool.config_enable_show_popup_on_keypress_option);
if (!showPopupOption) {
- generalSettings.removePreference(findPreference(PREF_KEY_PREVIEW_POPUP_ON));
- }
-
- final boolean showRecorrectionOption = res.getBoolean(
- R.bool.config_enable_show_recorrection_option);
- if (!showRecorrectionOption) {
- generalSettings.removePreference(findPreference(PREF_RECORRECTION_ENABLED));
+ generalSettings.removePreference(findPreference(PREF_POPUP_ON));
}
- final boolean showQuickFixesOption = res.getBoolean(
- R.bool.config_enable_quick_fixes_option);
- if (!showQuickFixesOption) {
- textCorrectionGroup.removePreference(findPreference(PREF_QUICK_FIXES));
- }
-
- final boolean showBigramSuggestionsOption = res.getBoolean(
- R.bool.config_enable_bigram_suggestions_option);
- if (!showBigramSuggestionsOption) {
- textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_SUGGESTIONS));
- textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_PREDICTIONS));
- }
-
- final boolean showUsabilityModeStudyOption = res.getBoolean(
- R.bool.config_enable_usability_study_mode_option);
- if (!showUsabilityModeStudyOption) {
- getPreferenceScreen().removePreference(findPreference(PREF_USABILITY_STUDY_MODE));
- }
+ final CheckBoxPreference includeOtherImesInLanguageSwitchList =
+ (CheckBoxPreference)findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST);
+ includeOtherImesInLanguageSwitchList.setEnabled(
+ !SettingsValues.isLanguageSwitchKeySupressed(prefs));
mKeyPreviewPopupDismissDelay =
(ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
@@ -417,7 +170,7 @@ public class Settings extends PreferenceActivity
res.getString(R.string.key_preview_popup_dismiss_default_delay),
};
final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
- R.integer.config_delay_after_preview));
+ R.integer.config_key_preview_linger_timeout));
mKeyPreviewPopupDismissDelay.setEntries(entries);
mKeyPreviewPopupDismissDelay.setEntryValues(
new String[] { "0", popupDismissDelayDefaultValue });
@@ -425,39 +178,80 @@ public class Settings extends PreferenceActivity
mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
}
mKeyPreviewPopupDismissDelay.setEnabled(
- Settings.Values.isKeyPreviewPopupEnabled(prefs, res));
+ SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
final Intent intent = dictionaryLink.getIntent();
- final int number = getPackageManager().queryIntentActivities(intent, 0).size();
+ final int number = context.getPackageManager().queryIntentActivities(intent, 0).size();
if (0 >= number) {
textCorrectionGroup.removePreference(dictionaryLink);
}
+
+ final boolean showUsabilityStudyModeOption =
+ res.getBoolean(R.bool.config_enable_usability_study_mode_option)
+ || ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS;
+ final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE);
+ if (!showUsabilityStudyModeOption) {
+ if (usabilityStudyPref != null) {
+ miscSettings.removePreference(usabilityStudyPref);
+ }
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ if (usabilityStudyPref instanceof CheckBoxPreference) {
+ CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref;
+ checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, true));
+ checkbox.setSummary(R.string.settings_warning_researcher_mode);
+ }
+ }
+
+ mKeypressVibrationDurationSettingsPref =
+ (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
+ if (mKeypressVibrationDurationSettingsPref != null) {
+ mKeypressVibrationDurationSettingsPref.setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference arg0) {
+ showKeypressVibrationDurationSettingsDialog();
+ return true;
+ }
+ });
+ updateKeypressVibrationDurationSettingsSummary(prefs, res);
+ }
+
+ mKeypressSoundVolumeSettingsPref =
+ (PreferenceScreen) findPreference(PREF_KEYPRESS_SOUND_VOLUME);
+ if (mKeypressSoundVolumeSettingsPref != null) {
+ mKeypressSoundVolumeSettingsPref.setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference arg0) {
+ showKeypressSoundVolumeSettingDialog();
+ return true;
+ }
+ });
+ updateKeypressSoundVolumeSummary(prefs, res);
+ }
+ refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res);
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
- int autoTextSize = AutoText.getSize(getListView());
- if (autoTextSize < 1) {
- ((PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY))
- .removePreference(mQuickFixes);
- }
- if (!VoiceProxy.VOICE_INSTALLED
- || !SpeechRecognizer.isRecognitionAvailable(this)) {
- getPreferenceScreen().removePreference(mVoicePreference);
- } else {
+ final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
+ if (isShortcutImeEnabled) {
updateVoiceModeSummary();
+ } else {
+ getPreferenceScreen().removePreference(mVoicePreference);
}
- updateSettingsKeySummary();
updateShowCorrectionSuggestionsSummary();
updateKeyPreviewPopupDelaySummary();
+ updateCustomInputStylesSummary();
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
this);
super.onDestroy();
@@ -465,38 +259,25 @@ public class Settings extends PreferenceActivity
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- (new BackupManager(this)).dataChanged();
- // If turning on voice input, show dialog
- if (key.equals(PREF_VOICE_SETTINGS_KEY) && !mVoiceOn) {
- if (!prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
- .equals(mVoiceModeOff)) {
- showVoiceConfirmation();
- }
- } else if (key.equals(PREF_KEY_PREVIEW_POPUP_ON)) {
+ (new BackupManager(getActivity())).dataChanged();
+ if (key.equals(PREF_POPUP_ON)) {
final ListPreference popupDismissDelay =
(ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
if (null != popupDismissDelay) {
- popupDismissDelay.setEnabled(prefs.getBoolean(PREF_KEY_PREVIEW_POPUP_ON, true));
+ popupDismissDelay.setEnabled(prefs.getBoolean(PREF_POPUP_ON, true));
}
+ } else if (key.equals(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) {
+ final CheckBoxPreference includeOtherImesInLanguageSwicthList =
+ (CheckBoxPreference)findPreference(
+ PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST);
+ includeOtherImesInLanguageSwicthList.setEnabled(
+ !SettingsValues.isLanguageSwitchKeySupressed(prefs));
}
ensureConsistencyOfAutoCorrectionSettings();
- mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
- .equals(mVoiceModeOff));
updateVoiceModeSummary();
- updateSettingsKeySummary();
updateShowCorrectionSuggestionsSummary();
updateKeyPreviewPopupDelaySummary();
- }
-
- @Override
- public boolean onPreferenceClick(Preference pref) {
- if (pref == mInputLanguageSelection) {
- startActivity(CompatUtils.getInputLanguageSelectionIntent(
- Utils.getInputMethodId(InputMethodManagerCompatWrapper.getInstance(this),
- getApplicationInfo().packageName), 0));
- return true;
- }
- return false;
+ refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources());
}
private void updateShowCorrectionSuggestionsSummary() {
@@ -506,10 +287,20 @@ public class Settings extends PreferenceActivity
mShowCorrectionSuggestionsPreference.getValue())]);
}
- private void updateSettingsKeySummary() {
- mSettingsKeyPreference.setSummary(
- getResources().getStringArray(R.array.settings_key_modes)
- [mSettingsKeyPreference.findIndexOfValue(mSettingsKeyPreference.getValue())]);
+ private void updateCustomInputStylesSummary() {
+ final PreferenceScreen customInputStyles =
+ (PreferenceScreen)findPreference(PREF_CUSTOM_INPUT_STYLES);
+ final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+ final Resources res = getResources();
+ final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, res);
+ final InputMethodSubtype[] subtypes =
+ AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
+ final StringBuilder styles = new StringBuilder();
+ for (final InputMethodSubtype subtype : subtypes) {
+ if (styles.length() > 0) styles.append(", ");
+ styles.append(SubtypeLocale.getSubtypeDisplayName(subtype, res));
+ }
+ customInputStyles.setSummary(styles);
}
private void updateKeyPreviewPopupDelaySummary() {
@@ -517,87 +308,144 @@ public class Settings extends PreferenceActivity
lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
}
- private void showVoiceConfirmation() {
- mOkClicked = false;
- showDialog(VOICE_INPUT_CONFIRM_DIALOG);
- // Make URL in the dialog message clickable
- if (mDialog != null) {
- TextView textView = (TextView) mDialog.findViewById(android.R.id.message);
- if (textView != null) {
- textView.setMovementMethod(LinkMovementMethod.getInstance());
- }
- }
- }
-
private void updateVoiceModeSummary() {
mVoicePreference.setSummary(
getResources().getStringArray(R.array.voice_input_modes_summary)
[mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
}
- @Override
- protected Dialog onCreateDialog(int id) {
- switch (id) {
- case VOICE_INPUT_CONFIRM_DIALOG:
- DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
- mVoicePreference.setValue(mVoiceModeOff);
- mVoiceLogger.settingsWarningDialogCancel();
- } else if (whichButton == DialogInterface.BUTTON_POSITIVE) {
- mOkClicked = true;
- mVoiceLogger.settingsWarningDialogOk();
- }
- updateVoicePreference();
- }
- };
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
- .setTitle(R.string.voice_warning_title)
- .setPositiveButton(android.R.string.ok, listener)
- .setNegativeButton(android.R.string.cancel, listener);
-
- // Get the current list of supported locales and check the current locale against
- // that list, to decide whether to put a warning that voice input will not work in
- // the current language as part of the pop-up confirmation dialog.
- boolean localeSupported = SubtypeSwitcher.getInstance().isVoiceSupported(
- Locale.getDefault().toString());
-
- final CharSequence message;
- if (localeSupported) {
- message = TextUtils.concat(
- getText(R.string.voice_warning_may_not_understand), "\n\n",
- getText(R.string.voice_hint_dialog_message));
- } else {
- message = TextUtils.concat(
- getText(R.string.voice_warning_locale_not_supported), "\n\n",
- getText(R.string.voice_warning_may_not_understand), "\n\n",
- getText(R.string.voice_hint_dialog_message));
- }
- builder.setMessage(message);
- AlertDialog dialog = builder.create();
- mDialog = dialog;
- dialog.setOnDismissListener(this);
- mVoiceLogger.settingsWarningDialogShown();
- return dialog;
- default:
- Log.e(TAG, "unknown dialog " + id);
- return null;
+ private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
+ SharedPreferences sp, Resources res) {
+ if (mKeypressVibrationDurationSettingsPref != null) {
+ final boolean hasVibrator = VibratorUtils.getInstance(getActivity()).hasVibrator();
+ final boolean vibrateOn = hasVibrator && sp.getBoolean(Settings.PREF_VIBRATE_ON,
+ res.getBoolean(R.bool.config_default_vibration_enabled));
+ mKeypressVibrationDurationSettingsPref.setEnabled(vibrateOn);
+ }
+
+ if (mKeypressSoundVolumeSettingsPref != null) {
+ final boolean soundOn = sp.getBoolean(Settings.PREF_SOUND_ON,
+ res.getBoolean(R.bool.config_default_sound_enabled));
+ mKeypressSoundVolumeSettingsPref.setEnabled(soundOn);
}
}
- @Override
- public void onDismiss(DialogInterface dialog) {
- mVoiceLogger.settingsWarningDialogDismissed();
- if (!mOkClicked) {
- // This assumes that onPreferenceClick gets called first, and this if the user
- // agreed after the warning, we set the mOkClicked value to true.
- mVoicePreference.setValue(mVoiceModeOff);
+ private void updateKeypressVibrationDurationSettingsSummary(
+ SharedPreferences sp, Resources res) {
+ if (mKeypressVibrationDurationSettingsPref != null) {
+ mKeypressVibrationDurationSettingsPref.setSummary(
+ SettingsValues.getCurrentVibrationDuration(sp, res)
+ + res.getString(R.string.settings_ms));
}
}
- private void updateVoicePreference() {
- boolean isChecked = !mVoicePreference.getValue().equals(mVoiceModeOff);
- mVoiceLogger.voiceInputSettingEnabled(isChecked);
+ private void showKeypressVibrationDurationSettingsDialog() {
+ final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
+ final Context context = getActivity();
+ final Resources res = context.getResources();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.prefs_keypress_vibration_duration_settings);
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ final int ms = Integer.valueOf(
+ mKeypressVibrationDurationSettingsTextView.getText().toString());
+ sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
+ updateKeypressVibrationDurationSettingsSummary(sp, res);
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dialog.dismiss();
+ }
+ });
+ final View v = LayoutInflater.from(context).inflate(
+ R.layout.vibration_settings_dialog, null);
+ final int currentMs = SettingsValues.getCurrentVibrationDuration(
+ getPreferenceManager().getSharedPreferences(), getResources());
+ mKeypressVibrationDurationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value);
+ final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings);
+ sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
+ final int tempMs = arg1;
+ mKeypressVibrationDurationSettingsTextView.setText(String.valueOf(tempMs));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar arg0) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar arg0) {
+ final int tempMs = arg0.getProgress();
+ VibratorUtils.getInstance(context).vibrate(tempMs);
+ }
+ });
+ sb.setProgress(currentMs);
+ mKeypressVibrationDurationSettingsTextView.setText(String.valueOf(currentMs));
+ builder.setView(v);
+ builder.create().show();
+ }
+
+ private void updateKeypressSoundVolumeSummary(SharedPreferences sp, Resources res) {
+ if (mKeypressSoundVolumeSettingsPref != null) {
+ mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf(
+ (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100)));
+ }
+ }
+
+ private void showKeypressSoundVolumeSettingDialog() {
+ final Context context = getActivity();
+ final AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
+ final Resources res = context.getResources();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.prefs_keypress_sound_volume_settings);
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ final float volume =
+ ((float)Integer.valueOf(
+ mKeypressSoundVolumeSettingsTextView.getText().toString())) / 100;
+ sp.edit().putFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, volume).apply();
+ updateKeypressSoundVolumeSummary(sp, res);
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dialog.dismiss();
+ }
+ });
+ final View v = LayoutInflater.from(context).inflate(
+ R.layout.sound_effect_volume_dialog, null);
+ final int currentVolumeInt =
+ (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100);
+ mKeypressSoundVolumeSettingsTextView =
+ (TextView)v.findViewById(R.id.sound_effect_volume_value);
+ final SeekBar sb = (SeekBar)v.findViewById(R.id.sound_effect_volume_bar);
+ sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
+ final int tempVolume = arg1;
+ mKeypressSoundVolumeSettingsTextView.setText(String.valueOf(tempVolume));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar arg0) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar arg0) {
+ final float tempVolume = ((float)arg0.getProgress()) / 100;
+ am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, tempVolume);
+ }
+ });
+ sb.setProgress(currentVolumeInt);
+ mKeypressSoundVolumeSettingsTextView.setText(String.valueOf(currentVolumeInt));
+ builder.setView(v);
+ builder.create().show();
}
}
diff --git a/java/src/com/android/inputmethod/latin/SettingsActivity.java b/java/src/com/android/inputmethod/latin/SettingsActivity.java
new file mode 100644
index 000000000..68f8582fc
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SettingsActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Intent;
+import android.preference.PreferenceActivity;
+
+public class SettingsActivity extends PreferenceActivity {
+ private static final String DEFAULT_FRAGMENT = Settings.class.getName();
+
+ @Override
+ public Intent getIntent() {
+ final Intent intent = super.getIntent();
+ if (!intent.hasExtra(EXTRA_SHOW_FRAGMENT)) {
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT);
+ }
+ intent.putExtra(EXTRA_NO_HEADERS, true);
+ return intent;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
new file mode 100644
index 000000000..ef423f19b
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeySpecParser;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+/**
+ * When you call the constructor of this class, you may want to change the current system locale by
+ * using {@link LocaleUtils.RunInLocale}.
+ */
+public class SettingsValues {
+ private static final String TAG = SettingsValues.class.getSimpleName();
+
+ private static final int SUGGESTION_VISIBILITY_SHOW_VALUE
+ = R.string.prefs_suggestion_visibility_show_value;
+ private static final int SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE
+ = R.string.prefs_suggestion_visibility_show_only_portrait_value;
+ private static final int SUGGESTION_VISIBILITY_HIDE_VALUE
+ = R.string.prefs_suggestion_visibility_hide_value;
+
+ private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] {
+ SUGGESTION_VISIBILITY_SHOW_VALUE,
+ SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE,
+ SUGGESTION_VISIBILITY_HIDE_VALUE
+ };
+
+ // From resources:
+ public final int mDelayUpdateOldSuggestions;
+ public final String mWeakSpaceStrippers;
+ public final String mWeakSpaceSwappers;
+ private final String mPhantomSpacePromotingSymbols;
+ public final SuggestedWords mSuggestPuncList;
+ private final String mSymbolsExcludedFromWordSeparators;
+ public final String mWordSeparators;
+ public final CharSequence mHintToSaveText;
+
+ // From preferences, in the same order as xml/prefs.xml:
+ public final boolean mAutoCap;
+ public final boolean mVibrateOn;
+ public final boolean mSoundOn;
+ public final boolean mKeyPreviewPopupOn;
+ private final String mVoiceMode;
+ private final String mAutoCorrectionThresholdRawValue;
+ public final String mShowSuggestionsSetting;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final boolean mUsabilityStudyMode;
+ public final boolean mIncludesOtherImesInLanguageSwitchList;
+ public final boolean mIsLanguageSwitchKeySuppressed;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final String mKeyPreviewPopupDismissDelayRawValue;
+ public final boolean mUseContactsDict;
+ // Use bigrams to predict the next word when there is no input for it yet
+ public final boolean mBigramPredictionEnabled;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final int mVibrationDurationSettingsRawValue;
+ @SuppressWarnings("unused") // TODO: Use this
+ private final float mKeypressSoundVolumeRawValue;
+ private final InputMethodSubtype[] mAdditionalSubtypes;
+
+ // From the input box
+ private final InputAttributes mInputAttributes;
+
+ // Deduced settings
+ public final int mKeypressVibrationDuration;
+ public final float mFxVolume;
+ public final int mKeyPreviewPopupDismissDelay;
+ private final boolean mAutoCorrectEnabled;
+ public final float mAutoCorrectionThreshold;
+ public final boolean mCorrectionEnabled;
+ public final int mSuggestionVisibility;
+ private final boolean mVoiceKeyEnabled;
+ private final boolean mVoiceKeyOnMain;
+
+ public SettingsValues(final SharedPreferences prefs, final InputAttributes inputAttributes,
+ final Context context) {
+ final Resources res = context.getResources();
+
+ // Get the resources
+ mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
+ mWeakSpaceStrippers = res.getString(R.string.weak_space_stripping_symbols);
+ mWeakSpaceSwappers = res.getString(R.string.weak_space_swapping_symbols);
+ mPhantomSpacePromotingSymbols = res.getString(R.string.phantom_space_promoting_symbols);
+ if (LatinImeLogger.sDBG) {
+ final int length = mWeakSpaceStrippers.length();
+ for (int i = 0; i < length; i = mWeakSpaceStrippers.offsetByCodePoints(i, 1)) {
+ if (isWeakSpaceSwapper(mWeakSpaceStrippers.codePointAt(i))) {
+ throw new RuntimeException("Char code " + mWeakSpaceStrippers.codePointAt(i)
+ + " is both a weak space swapper and stripper.");
+ }
+ }
+ }
+ final String[] suggestPuncsSpec = KeySpecParser.parseCsvString(
+ res.getString(R.string.suggested_punctuations), null);
+ mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
+ mSymbolsExcludedFromWordSeparators =
+ res.getString(R.string.symbols_excluded_from_word_separators);
+ mWordSeparators = createWordSeparators(mWeakSpaceStrippers, mWeakSpaceSwappers,
+ mSymbolsExcludedFromWordSeparators, res);
+ mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
+
+ // Store the input attributes
+ if (null == inputAttributes) {
+ mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
+ } else {
+ mInputAttributes = inputAttributes;
+ }
+
+ // Get the settings preferences
+ mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
+ mVibrateOn = isVibrateOn(context, prefs, res);
+ mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
+ res.getBoolean(R.bool.config_default_sound_enabled));
+ mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
+ final String voiceModeMain = res.getString(R.string.voice_mode_main);
+ final String voiceModeOff = res.getString(R.string.voice_mode_off);
+ mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain);
+ mAutoCorrectionThresholdRawValue = prefs.getString(Settings.PREF_AUTO_CORRECTION_THRESHOLD,
+ res.getString(R.string.auto_correction_threshold_mode_index_modest));
+ mShowSuggestionsSetting = prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING,
+ res.getString(R.string.prefs_suggestion_visibility_default_value));
+ mUsabilityStudyMode = getUsabilityStudyMode(prefs);
+ mIncludesOtherImesInLanguageSwitchList = prefs.getBoolean(
+ Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false);
+ mIsLanguageSwitchKeySuppressed = isLanguageSwitchKeySupressed(prefs);
+ mKeyPreviewPopupDismissDelayRawValue = prefs.getString(
+ Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+ Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout)));
+ mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
+ mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
+ mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res);
+ mVibrationDurationSettingsRawValue =
+ prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+ mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
+
+ // Compute other readable settings
+ mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res);
+ mFxVolume = getCurrentKeypressSoundVolume(prefs, res);
+ mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
+ mAutoCorrectionThreshold = getAutoCorrectionThreshold(res,
+ mAutoCorrectionThresholdRawValue);
+ mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff);
+ mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
+ mAdditionalSubtypes = AdditionalSubtype.createAdditionalSubtypesArray(
+ getPrefAdditionalSubtypes(prefs, res));
+ mCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
+ mSuggestionVisibility = createSuggestionVisibility(res);
+ }
+
+ // Helper functions to create member values.
+ private static SuggestedWords createSuggestPuncList(final String[] puncs) {
+ final ArrayList<SuggestedWordInfo> puncList = new ArrayList<SuggestedWordInfo>();
+ if (puncs != null) {
+ for (final String puncSpec : puncs) {
+ puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec),
+ SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED));
+ }
+ }
+ return new SuggestedWords(puncList,
+ false /* typedWordValid */,
+ false /* hasAutoCorrectionCandidate */,
+ false /* allowsToBeAutoCorrected */,
+ true /* isPunctuationSuggestions */,
+ false /* isObsoleteSuggestions */,
+ false /* isPrediction */);
+ }
+
+ private static String createWordSeparators(final String weakSpaceStrippers,
+ final String weakSpaceSwappers, final String symbolsExcludedFromWordSeparators,
+ final Resources res) {
+ String wordSeparators = weakSpaceStrippers + weakSpaceSwappers
+ + res.getString(R.string.phantom_space_promoting_symbols);
+ for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
+ wordSeparators = wordSeparators.replace(
+ symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
+ }
+ return wordSeparators;
+ }
+
+ private int createSuggestionVisibility(final Resources res) {
+ final String suggestionVisiblityStr = mShowSuggestionsSetting;
+ for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
+ if (suggestionVisiblityStr.equals(res.getString(visibility))) {
+ return visibility;
+ }
+ }
+ throw new RuntimeException("Bug: visibility string is not configured correctly");
+ }
+
+ private static boolean isVibrateOn(final Context context, final SharedPreferences prefs,
+ final Resources res) {
+ final boolean hasVibrator = VibratorUtils.getInstance(context).hasVibrator();
+ return hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
+ res.getBoolean(R.bool.config_default_vibration_enabled));
+ }
+
+ public boolean isApplicationSpecifiedCompletionsOn() {
+ return mInputAttributes.mApplicationSpecifiedCompletionOn;
+ }
+
+ public boolean isEditorActionNext() {
+ return mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT;
+ }
+
+ public boolean isSuggestionsRequested(final int displayOrientation) {
+ return mInputAttributes.mIsSettingsSuggestionStripOn
+ && (mCorrectionEnabled
+ || isSuggestionStripVisibleInOrientation(displayOrientation));
+ }
+
+ public boolean isSuggestionStripVisibleInOrientation(final int orientation) {
+ return (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_VALUE)
+ || (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE
+ && orientation == Configuration.ORIENTATION_PORTRAIT);
+ }
+
+ public boolean isWordSeparator(int code) {
+ return mWordSeparators.contains(String.valueOf((char)code));
+ }
+
+ public boolean isSymbolExcludedFromWordSeparators(int code) {
+ return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
+ }
+
+ public boolean isWeakSpaceStripper(int code) {
+ // TODO: this does not work if the code does not fit in a char
+ return mWeakSpaceStrippers.contains(String.valueOf((char)code));
+ }
+
+ public boolean isWeakSpaceSwapper(int code) {
+ // TODO: this does not work if the code does not fit in a char
+ return mWeakSpaceSwappers.contains(String.valueOf((char)code));
+ }
+
+ public boolean isPhantomSpacePromotingSymbol(int code) {
+ // TODO: this does not work if the code does not fit in a char
+ return mPhantomSpacePromotingSymbols.contains(String.valueOf((char)code));
+ }
+
+ private static boolean isAutoCorrectEnabled(final Resources resources,
+ final String currentAutoCorrectionSetting) {
+ final String autoCorrectionOff = resources.getString(
+ R.string.auto_correction_threshold_mode_index_off);
+ return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
+ }
+
+ // Public to access from KeyboardSwitcher. Should it have access to some
+ // process-global instance instead?
+ public static boolean isKeyPreviewPopupEnabled(SharedPreferences sp, Resources resources) {
+ final boolean showPopupOption = resources.getBoolean(
+ R.bool.config_enable_show_popup_on_keypress_option);
+ if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview);
+ return sp.getBoolean(Settings.PREF_POPUP_ON,
+ resources.getBoolean(R.bool.config_default_popup_preview));
+ }
+
+ // Likewise
+ public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp,
+ Resources resources) {
+ // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here.
+ return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+ Integer.toString(resources.getInteger(
+ R.integer.config_key_preview_linger_timeout))));
+ }
+
+ private static boolean isBigramPredictionEnabled(final SharedPreferences sp,
+ final Resources resources) {
+ return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean(
+ R.bool.config_default_next_word_prediction));
+ }
+
+ private static float getAutoCorrectionThreshold(final Resources resources,
+ final String currentAutoCorrectionSetting) {
+ final String[] autoCorrectionThresholdValues = resources.getStringArray(
+ R.array.auto_correction_threshold_values);
+ // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
+ float autoCorrectionThreshold = Float.MAX_VALUE;
+ try {
+ final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting);
+ if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) {
+ autoCorrectionThreshold = Float.parseFloat(
+ autoCorrectionThresholdValues[arrayIndex]);
+ }
+ } catch (NumberFormatException e) {
+ // Whenever the threshold settings are correct, never come here.
+ autoCorrectionThreshold = Float.MAX_VALUE;
+ Log.w(TAG, "Cannot load auto correction threshold setting."
+ + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting
+ + ", autoCorrectionThresholdValues: "
+ + Arrays.toString(autoCorrectionThresholdValues));
+ }
+ return autoCorrectionThreshold;
+ }
+
+ public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) {
+ final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
+ final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
+ return shortcutImeEnabled && mVoiceKeyEnabled
+ && !InputTypeUtils.isPasswordInputType(inputType);
+ }
+
+ public boolean isVoiceKeyOnMain() {
+ return mVoiceKeyOnMain;
+ }
+
+ public static boolean isLanguageSwitchKeySupressed(SharedPreferences sp) {
+ return sp.getBoolean(Settings.PREF_SUPPRESS_LANGUAGE_SWITCH_KEY, false);
+ }
+
+ public boolean isLanguageSwitchKeyEnabled(Context context) {
+ if (mIsLanguageSwitchKeySuppressed) {
+ return false;
+ }
+ if (mIncludesOtherImesInLanguageSwitchList) {
+ return ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
+ context, /* include aux subtypes */false);
+ } else {
+ return ImfUtils.hasMultipleEnabledSubtypesInThisIme(
+ context, /* include aux subtypes */false);
+ }
+ }
+
+ public boolean isFullscreenModeAllowed(Resources res) {
+ return res.getBoolean(R.bool.config_use_fullscreen_mode);
+ }
+
+ public InputMethodSubtype[] getAdditionalSubtypes() {
+ return mAdditionalSubtypes;
+ }
+
+ public static String getPrefAdditionalSubtypes(final SharedPreferences prefs,
+ final Resources res) {
+ final String prefSubtypes = res.getString(R.string.predefined_subtypes, "");
+ return prefs.getString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes);
+ }
+
+ // Accessed from the settings interface, hence public
+ public static float getCurrentKeypressSoundVolume(final SharedPreferences sp,
+ final Resources res) {
+ // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here
+ final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
+ if (volume >= 0) {
+ return volume;
+ }
+
+ return Float.parseFloat(
+ Utils.getDeviceOverrideValue(res, R.array.keypress_volumes, "-1.0f"));
+ }
+
+ // Likewise
+ public static int getCurrentVibrationDuration(final SharedPreferences sp,
+ final Resources res) {
+ // TODO: use mKeypressVibrationDuration instead of reading it again here
+ final int ms = sp.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+ if (ms >= 0) {
+ return ms;
+ }
+
+ return Integer.parseInt(
+ Utils.getDeviceOverrideValue(res, R.array.keypress_vibration_durations, "-1"));
+ }
+
+ // Likewise
+ public static boolean getUsabilityStudyMode(final SharedPreferences prefs) {
+ // TODO: use mUsabilityStudyMode instead of reading it again here
+ return prefs.getBoolean(Settings.PREF_USABILITY_STUDY_MODE, true);
+ }
+
+ public static long getLastUserHistoryWriteTime(
+ final SharedPreferences prefs, final String locale) {
+ final String str = prefs.getString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, "");
+ final HashMap<String, Long> map = Utils.localeAndTimeStrToHashMap(str);
+ if (map.containsKey(locale)) {
+ return map.get(locale);
+ }
+ return 0;
+ }
+
+ public static void setLastUserHistoryWriteTime(
+ final SharedPreferences prefs, final String locale) {
+ final String oldStr = prefs.getString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, "");
+ final HashMap<String, Long> map = Utils.localeAndTimeStrToHashMap(oldStr);
+ map.put(locale, System.currentTimeMillis());
+ final String newStr = Utils.localeAndTimeHashMapToStr(map);
+ prefs.edit().putString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, newStr).apply();
+ }
+
+ // For debug.
+ public String getInputAttributesDebugString() {
+ return mInputAttributes.toString();
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java b/java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java
deleted file mode 100644
index 1d36c0b98..000000000
--- a/java/src/com/android/inputmethod/latin/SharedPreferencesCompat.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.SharedPreferences;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Reflection utils to call SharedPreferences$Editor.apply when possible,
- * falling back to commit when apply isn't available.
- */
-public class SharedPreferencesCompat {
- private static final Method sApplyMethod = findApplyMethod();
-
- private static Method findApplyMethod() {
- try {
- return SharedPreferences.Editor.class.getMethod("apply");
- } catch (NoSuchMethodException unused) {
- // fall through
- }
- return null;
- }
-
- public static void apply(SharedPreferences.Editor editor) {
- if (sApplyMethod != null) {
- try {
- sApplyMethod.invoke(editor);
- return;
- } catch (InvocationTargetException unused) {
- // fall through
- } catch (IllegalAccessException unused) {
- // fall through
- }
- }
- editor.commit();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
new file mode 100644
index 000000000..a43b90525
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class StringUtils {
+ private StringUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static int codePointCount(String text) {
+ if (TextUtils.isEmpty(text)) return 0;
+ return text.codePointCount(0, text.length());
+ }
+
+ public static boolean containsInArray(String key, String[] array) {
+ for (final String element : array) {
+ if (key.equals(element)) return true;
+ }
+ return false;
+ }
+
+ public static boolean containsInCsv(String key, String csv) {
+ if (TextUtils.isEmpty(csv)) return false;
+ return containsInArray(key, csv.split(","));
+ }
+
+ public static String appendToCsvIfNotExists(String key, String csv) {
+ if (TextUtils.isEmpty(csv)) return key;
+ if (containsInCsv(key, csv)) return csv;
+ return csv + "," + key;
+ }
+
+ public static String removeFromCsvIfExists(String key, String csv) {
+ if (TextUtils.isEmpty(csv)) return "";
+ final String[] elements = csv.split(",");
+ if (!containsInArray(key, elements)) return csv;
+ final ArrayList<String> result = new ArrayList<String>(elements.length - 1);
+ for (final String element : elements) {
+ if (!key.equals(element)) result.add(element);
+ }
+ return TextUtils.join(",", result);
+ }
+
+ /**
+ * Returns true if a and b are equal ignoring the case of the character.
+ * @param a first character to check
+ * @param b second character to check
+ * @return {@code true} if a and b are equal, {@code false} otherwise.
+ */
+ public static boolean equalsIgnoreCase(char a, char b) {
+ // Some language, such as Turkish, need testing both cases.
+ return a == b
+ || Character.toLowerCase(a) == Character.toLowerCase(b)
+ || Character.toUpperCase(a) == Character.toUpperCase(b);
+ }
+
+ /**
+ * Returns true if a and b are equal ignoring the case of the characters, including if they are
+ * both null.
+ * @param a first CharSequence to check
+ * @param b second CharSequence to check
+ * @return {@code true} if a and b are equal, {@code false} otherwise.
+ */
+ public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) {
+ if (a == b)
+ return true; // including both a and b are null.
+ if (a == null || b == null)
+ return false;
+ final int length = a.length();
+ if (length != b.length())
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!equalsIgnoreCase(a.charAt(i), b.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if a and b are equal ignoring the case of the characters, including if a is null
+ * and b is zero length.
+ * @param a CharSequence to check
+ * @param b character array to check
+ * @param offset start offset of array b
+ * @param length length of characters in array b
+ * @return {@code true} if a and b are equal, {@code false} otherwise.
+ * @throws IndexOutOfBoundsException
+ * if {@code offset < 0 || length < 0 || offset + length > data.length}.
+ * @throws NullPointerException if {@code b == null}.
+ */
+ public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) {
+ if (offset < 0 || length < 0 || length > b.length - offset)
+ throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset
+ + " length=" + length);
+ if (a == null)
+ return length == 0; // including a is null and b is zero length.
+ if (a.length() != length)
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!equalsIgnoreCase(a.charAt(i), b[offset + i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if cs contains any upper case characters.
+ *
+ * @param cs the CharSequence to check
+ * @return {@code true} if cs contains any upper case characters, {@code false} otherwise.
+ */
+ public static boolean hasUpperCase(final CharSequence cs) {
+ final int length = cs.length();
+ for (int i = 0, cp = 0; i < length; i += Character.charCount(cp)) {
+ cp = Character.codePointAt(cs, i);
+ if (Character.isUpperCase(cp)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove duplicates from an array of strings.
+ *
+ * This method will always keep the first occurrence of all strings at their position
+ * in the array, removing the subsequent ones.
+ */
+ public static void removeDupes(final ArrayList<CharSequence> suggestions) {
+ if (suggestions.size() < 2) return;
+ int i = 1;
+ // Don't cache suggestions.size(), since we may be removing items
+ while (i < suggestions.size()) {
+ final CharSequence cur = suggestions.get(i);
+ // Compare each suggestion with each previous suggestion
+ for (int j = 0; j < i; j++) {
+ CharSequence previous = suggestions.get(j);
+ if (TextUtils.equals(cur, previous)) {
+ suggestions.remove(i);
+ i--;
+ break;
+ }
+ }
+ i++;
+ }
+ }
+
+ public static String toTitleCase(String s, Locale locale) {
+ if (s.length() <= 1) {
+ // TODO: is this really correct? Shouldn't this be s.toUpperCase()?
+ return s;
+ }
+ // TODO: fix the bugs below
+ // - This does not work for Greek, because it returns upper case instead of title case.
+ // - It does not work for Serbian, because it fails to account for the "lj" character,
+ // which should be "Lj" in title case and "LJ" in upper case.
+ // - It does not work for Dutch, because it fails to account for the "ij" digraph, which
+ // are two different characters but both should be capitalized as "IJ" as if they were
+ // a single letter.
+ // - It also does not work with unicode surrogate code points.
+ return s.toUpperCase(locale).charAt(0) + s.substring(1);
+ }
+
+ public static int[] toCodePointArray(final String string) {
+ final char[] characters = string.toCharArray();
+ final int length = characters.length;
+ final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
+ int codePoint = Character.codePointAt(characters, 0);
+ int dsti = 0;
+ for (int srci = Character.charCount(codePoint);
+ srci < length; srci += Character.charCount(codePoint), ++dsti) {
+ codePoints[dsti] = codePoint;
+ codePoint = Character.codePointAt(characters, srci);
+ }
+ codePoints[dsti] = codePoint;
+ return codePoints;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index 917521c40..ca293060a 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -16,14 +16,50 @@
package com.android.inputmethod.latin;
+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.content.Context;
import android.content.res.Resources;
+import android.os.Build;
+import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
+import java.util.HashMap;
import java.util.Locale;
public class SubtypeLocale {
- private static String[] sExceptionKeys;
- private static String[] sExceptionValues;
+ static final String TAG = SubtypeLocale.class.getSimpleName();
+ // This class must be located in the same package as LatinIME.java.
+ private static final String RESOURCE_PACKAGE_NAME =
+ DictionaryFactory.class.getPackage().getName();
+
+ // Special language code to represent "no language".
+ public static final String NO_LANGUAGE = "zz";
+ public static final String QWERTY = "qwerty";
+ public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic;
+
+ private static String[] sPredefinedKeyboardLayoutSet;
+ // Keyboard layout to its display name map.
+ private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap =
+ new HashMap<String, String>();
+ // Keyboard layout to subtype name resource id map.
+ private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap =
+ new HashMap<String, Integer>();
+ // Exceptional locale to subtype name resource id map.
+ private static final HashMap<String, Integer> sExceptionalLocaleToWithLayoutNameIdsMap =
+ new HashMap<String, Integer>();
+ private static final String SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX =
+ "string/subtype_generic_";
+ private static final String SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX =
+ "string/subtype_with_layout_";
+ private static final String SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX =
+ "string/subtype_no_language_";
+ // Exceptional locales to display name map.
+ private static final HashMap<String, String> sExceptionalDisplayNamesMap =
+ new HashMap<String, String>();
private SubtypeLocale() {
// Intentional empty constructor for utility class.
@@ -31,16 +67,140 @@ public class SubtypeLocale {
public static void init(Context context) {
final Resources res = context.getResources();
- sExceptionKeys = res.getStringArray(R.array.subtype_locale_exception_keys);
- sExceptionValues = res.getStringArray(R.array.subtype_locale_exception_values);
+
+ final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
+ sPredefinedKeyboardLayoutSet = predefinedLayoutSet;
+ final String[] layoutDisplayNames = res.getStringArray(
+ R.array.predefined_layout_display_names);
+ for (int i = 0; i < predefinedLayoutSet.length; i++) {
+ final String layoutName = predefinedLayoutSet[i];
+ sKeyboardLayoutToDisplayNameMap.put(layoutName, layoutDisplayNames[i]);
+ final String resourceName = SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX + layoutName;
+ final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
+ sKeyboardLayoutToNameIdsMap.put(layoutName, resId);
+ // Register subtype name resource id of "No language" with key "zz_<layout>"
+ final String noLanguageResName = SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX + layoutName;
+ final int noLanguageResId = res.getIdentifier(
+ noLanguageResName, null, RESOURCE_PACKAGE_NAME);
+ final String key = getNoLanguageLayoutKey(layoutName);
+ sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId);
+ }
+
+ final String[] exceptionalLocales = res.getStringArray(
+ R.array.subtype_locale_exception_keys);
+ final String[] exceptionalDisplayNames = res.getStringArray(
+ R.array.subtype_locale_exception_values);
+ for (int i = 0; i < exceptionalLocales.length; i++) {
+ final String localeString = exceptionalLocales[i];
+ sExceptionalDisplayNamesMap.put(localeString, exceptionalDisplayNames[i]);
+ final String resourceName = SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX + localeString;
+ final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
+ sExceptionalLocaleToWithLayoutNameIdsMap.put(localeString, resId);
+ }
+ }
+
+ public static String[] getPredefinedKeyboardLayoutSet() {
+ return sPredefinedKeyboardLayoutSet;
+ }
+
+ public static boolean isExceptionalLocale(String localeString) {
+ return sExceptionalLocaleToWithLayoutNameIdsMap.containsKey(localeString);
+ }
+
+ private static final String getNoLanguageLayoutKey(String keyboardLayoutName) {
+ return NO_LANGUAGE + "_" + keyboardLayoutName;
+ }
+
+ public static int getSubtypeNameId(String localeString, String keyboardLayoutName) {
+ if (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15 && isExceptionalLocale(localeString)) {
+ return sExceptionalLocaleToWithLayoutNameIdsMap.get(localeString);
+ }
+ final String key = localeString.equals(NO_LANGUAGE)
+ ? getNoLanguageLayoutKey(keyboardLayoutName)
+ : keyboardLayoutName;
+ final Integer nameId = sKeyboardLayoutToNameIdsMap.get(key);
+ return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
+ }
+
+ public static String getSubtypeLocaleDisplayName(String localeString) {
+ final String exceptionalValue = sExceptionalDisplayNamesMap.get(localeString);
+ if (exceptionalValue != null) {
+ return exceptionalValue;
+ }
+ final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
+ return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
+ }
+
+ // InputMethodSubtype's display name in its locale.
+ // isAdditionalSubtype (T=true, F=false)
+ // locale layout | display name
+ // ------ ------ - ----------------------
+ // en_US qwerty F English (US) exception
+ // en_GB qwerty F English (UK) exception
+ // fr azerty F Français
+ // fr_CA qwerty F Français (Canada)
+ // de qwertz F Deutsch
+ // zz qwerty F No language (QWERTY) in system locale
+ // fr qwertz T Français (QWERTZ)
+ // de qwerty T Deutsch (QWERTY)
+ // en_US azerty T English (US) (AZERTY)
+ // zz azerty T No language (AZERTY) in system locale
+
+ public static String getSubtypeDisplayName(final InputMethodSubtype subtype, Resources res) {
+ final String replacementString = (Build.VERSION.SDK_INT >= /* JELLY_BEAN */ 15
+ && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME))
+ ? subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
+ : getSubtypeLocaleDisplayName(subtype.getLocale());
+ final int nameResId = subtype.getNameResId();
+ final RunInLocale<String> getSubtypeName = new RunInLocale<String>() {
+ @Override
+ protected String job(Resources res) {
+ try {
+ return res.getString(nameResId, replacementString);
+ } catch (Resources.NotFoundException e) {
+ // TODO: Remove this catch when InputMethodManager.getCurrentInputMethodSubtype
+ // is fixed.
+ Log.w(TAG, "Unknown subtype: mode=" + subtype.getMode()
+ + " locale=" + subtype.getLocale()
+ + " extra=" + subtype.getExtraValue()
+ + "\n" + Utils.getStackTrace());
+ return "";
+ }
+ }
+ };
+ final Locale locale = isNoLanguage(subtype)
+ ? res.getConfiguration().locale : getSubtypeLocale(subtype);
+ return getSubtypeName.runInLocale(res, locale);
+ }
+
+ public static boolean isNoLanguage(InputMethodSubtype subtype) {
+ final String localeString = subtype.getLocale();
+ return localeString.equals(NO_LANGUAGE);
+ }
+
+ public static Locale getSubtypeLocale(InputMethodSubtype subtype) {
+ final String localeString = subtype.getLocale();
+ return LocaleUtils.constructLocaleFromString(localeString);
+ }
+
+ public static String getKeyboardLayoutSetDisplayName(InputMethodSubtype subtype) {
+ final String layoutName = getKeyboardLayoutSetName(subtype);
+ return getKeyboardLayoutSetDisplayName(layoutName);
+ }
+
+ public static String getKeyboardLayoutSetDisplayName(String layoutName) {
+ return sKeyboardLayoutToDisplayNameMap.get(layoutName);
}
- public static String getFullDisplayName(Locale locale) {
- String localeCode = locale.toString();
- for (int index = 0; index < sExceptionKeys.length; index++) {
- if (sExceptionKeys[index].equals(localeCode))
- return sExceptionValues[index];
+ public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) {
+ final String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
+ // TODO: Remove this null check when InputMethodManager.getCurrentInputMethodSubtype is
+ // fixed.
+ if (keyboardLayoutSet == null) {
+ android.util.Log.w(TAG, "KeyboardLayoutSet not found, use QWERTY: " +
+ "locale=" + subtype.getLocale() + " extraValue=" + subtype.getExtraValue());
+ return QWERTY;
}
- return locale.getDisplayName(locale);
+ return keyboardLayoutSet;
}
}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 6ca12c0c5..664de6774 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -16,29 +16,23 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
-import com.android.inputmethod.deprecated.VoiceProxy;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.LatinKeyboard;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.IBinder;
-import android.text.TextUtils;
import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -47,53 +41,49 @@ public class SubtypeSwitcher {
private static boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = SubtypeSwitcher.class.getSimpleName();
- private static final char LOCALE_SEPARATER = '_';
- private static final String KEYBOARD_MODE = "keyboard";
- private static final String VOICE_MODE = "voice";
- private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY =
- "requireNetworkConnectivity";
- public static final String USE_SPACEBAR_LANGUAGE_SWITCH_KEY = "use_spacebar_language_switch";
-
- private final TextUtils.SimpleStringSplitter mLocaleSplitter =
- new TextUtils.SimpleStringSplitter(LOCALE_SEPARATER);
-
private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
private /* final */ LatinIME mService;
- private /* final */ InputMethodManagerCompatWrapper mImm;
+ private /* final */ InputMethodManager mImm;
private /* final */ Resources mResources;
private /* final */ ConnectivityManager mConnectivityManager;
- private /* final */ boolean mConfigUseSpacebarLanguageSwitcher;
- private /* final */ SharedPreferences mPrefs;
- private final ArrayList<InputMethodSubtypeCompatWrapper>
- mEnabledKeyboardSubtypesOfCurrentInputMethod =
- new ArrayList<InputMethodSubtypeCompatWrapper>();
- private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>();
- private final LanguageBarInfo mLanguageBarInfo = new LanguageBarInfo();
/*-----------------------------------------------------------*/
// Variants which should be changed only by reload functions.
- private boolean mNeedsToDisplayLanguage;
- private boolean mIsSystemLanguageSameAsInputLanguage;
- private InputMethodInfoCompatWrapper mShortcutInputMethodInfo;
- private InputMethodSubtypeCompatWrapper mShortcutSubtype;
- private List<InputMethodSubtypeCompatWrapper> mAllEnabledSubtypesOfCurrentInputMethod;
- private InputMethodSubtypeCompatWrapper mCurrentSubtype;
- private Locale mSystemLocale;
- private Locale mInputLocale;
- private String mInputLocaleStr;
- private String mInputMethodId;
- private VoiceProxy.VoiceInputWrapper mVoiceInputWrapper;
+ private NeedsToDisplayLanguage mNeedsToDisplayLanguage = new NeedsToDisplayLanguage();
+ private InputMethodInfo mShortcutInputMethodInfo;
+ private InputMethodSubtype mShortcutSubtype;
+ private InputMethodSubtype mNoLanguageSubtype;
+ // Note: This variable is always non-null after {@link #initialize(LatinIME)}.
+ private InputMethodSubtype mCurrentSubtype;
+ private Locale mCurrentSystemLocale;
/*-----------------------------------------------------------*/
private boolean mIsNetworkConnected;
+ static class NeedsToDisplayLanguage {
+ private int mEnabledSubtypeCount;
+ private boolean mIsSystemLanguageSameAsInputLanguage;
+
+ public boolean getValue() {
+ return mEnabledSubtypeCount >= 2 || !mIsSystemLanguageSameAsInputLanguage;
+ }
+
+ public void updateEnabledSubtypeCount(int count) {
+ mEnabledSubtypeCount = count;
+ }
+
+ public void updateIsSystemLanguageSameAsInputLanguage(boolean isSame) {
+ mIsSystemLanguageSameAsInputLanguage = isSame;
+ }
+ }
+
public static SubtypeSwitcher getInstance() {
return sInstance;
}
- public static void init(LatinIME service, SharedPreferences prefs) {
+ public static void init(LatinIME service) {
SubtypeLocale.init(service);
- sInstance.initialize(service, prefs);
+ sInstance.initialize(service);
sInstance.updateAllParameters();
}
@@ -101,31 +91,28 @@ public class SubtypeSwitcher {
// Intentional empty constructor for singleton.
}
- private void initialize(LatinIME service, SharedPreferences prefs) {
+ private void initialize(LatinIME service) {
mService = service;
mResources = service.getResources();
- mImm = InputMethodManagerCompatWrapper.getInstance(service);
+ mImm = ImfUtils.getInputMethodManager(service);
mConnectivityManager = (ConnectivityManager) service.getSystemService(
Context.CONNECTIVITY_SERVICE);
- mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
- mEnabledLanguagesOfCurrentInputMethod.clear();
- mSystemLocale = null;
- mInputLocale = null;
- mInputLocaleStr = null;
- mCurrentSubtype = null;
- mAllEnabledSubtypesOfCurrentInputMethod = null;
- mVoiceInputWrapper = null;
- mPrefs = prefs;
+ mCurrentSystemLocale = mResources.getConfiguration().locale;
+ mCurrentSubtype = mImm.getCurrentInputMethodSubtype();
+ mNoLanguageSubtype = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+ service, SubtypeLocale.NO_LANGUAGE, SubtypeLocale.QWERTY);
+ if (mNoLanguageSubtype == null) {
+ throw new RuntimeException("Can't find no lanugage with QWERTY subtype");
+ }
final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
mIsNetworkConnected = (info != null && info.isConnected());
- mInputMethodId = Utils.getInputMethodId(mImm, service.getPackageName());
}
// Update all parameters stored in SubtypeSwitcher.
// Only configuration changed event is allowed to call this because this is heavy.
private void updateAllParameters() {
- mSystemLocale = mResources.getConfiguration().locale;
+ mCurrentSystemLocale = mResources.getConfiguration().locale;
updateSubtype(mImm.getCurrentInputMethodSubtype());
updateParametersOnStartInputView();
}
@@ -133,47 +120,29 @@ public class SubtypeSwitcher {
// Update parameters which are changed outside LatinIME. This parameters affect UI so they
// should be updated every time onStartInputview.
public void updateParametersOnStartInputView() {
- mConfigUseSpacebarLanguageSwitcher = mPrefs.getBoolean(USE_SPACEBAR_LANGUAGE_SWITCH_KEY,
- mService.getResources().getBoolean(
- R.bool.config_use_spacebar_language_switcher));
updateEnabledSubtypes();
updateShortcutIME();
}
// Reload enabledSubtypes from the framework.
private void updateEnabledSubtypes() {
- final String currentMode = getCurrentSubtypeMode();
+ final InputMethodSubtype currentSubtype = mCurrentSubtype;
boolean foundCurrentSubtypeBecameDisabled = true;
- mAllEnabledSubtypesOfCurrentInputMethod = mImm.getEnabledInputMethodSubtypeList(
- null, true);
- mEnabledLanguagesOfCurrentInputMethod.clear();
- mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
- for (InputMethodSubtypeCompatWrapper ims : mAllEnabledSubtypesOfCurrentInputMethod) {
- final String locale = ims.getLocale();
- final String mode = ims.getMode();
- mLocaleSplitter.setString(locale);
- if (mLocaleSplitter.hasNext()) {
- mEnabledLanguagesOfCurrentInputMethod.add(mLocaleSplitter.next());
- }
- if (locale.equals(mInputLocaleStr) && mode.equals(currentMode)) {
+ final List<InputMethodSubtype> enabledSubtypesOfThisIme =
+ mImm.getEnabledInputMethodSubtypeList(null, true);
+ for (InputMethodSubtype ims : enabledSubtypesOfThisIme) {
+ if (ims.equals(currentSubtype)) {
foundCurrentSubtypeBecameDisabled = false;
}
- if (KEYBOARD_MODE.equals(ims.getMode())) {
- mEnabledKeyboardSubtypesOfCurrentInputMethod.add(ims);
- }
}
- mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
- && mIsSystemLanguageSameAsInputLanguage);
+ mNeedsToDisplayLanguage.updateEnabledSubtypeCount(enabledSubtypesOfThisIme.size());
if (foundCurrentSubtypeBecameDisabled) {
if (DBG) {
- Log.w(TAG, "Current subtype: " + mInputLocaleStr + ", " + currentMode);
+ Log.w(TAG, "Last subtype: "
+ + currentSubtype.getLocale() + "/" + currentSubtype.getExtraValue());
Log.w(TAG, "Last subtype was disabled. Update to the current one.");
}
updateSubtype(mImm.getCurrentInputMethodSubtype());
- } else {
- // mLanguageBarInfo.update() will be called in updateSubtype so there is no need
- // to call this in the if-clause above.
- mLanguageBarInfo.update();
}
}
@@ -182,14 +151,16 @@ public class SubtypeSwitcher {
Log.d(TAG, "Update shortcut IME from : "
+ (mShortcutInputMethodInfo == null
? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
- + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale()
- + ", " + mShortcutSubtype.getMode())));
+ + (mShortcutSubtype == null ? "<null>" : (
+ mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
}
// TODO: Update an icon for shortcut IME
- final Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> shortcuts =
+ final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
mImm.getShortcutInputMethodsAndSubtypes();
- for (InputMethodInfoCompatWrapper imi : shortcuts.keySet()) {
- List<InputMethodSubtypeCompatWrapper> subtypes = shortcuts.get(imi);
+ mShortcutInputMethodInfo = null;
+ mShortcutSubtype = null;
+ for (InputMethodInfo imi : shortcuts.keySet()) {
+ List<InputMethodSubtype> subtypes = shortcuts.get(imi);
// TODO: Returns the first found IMI for now. Should handle all shortcuts as
// appropriate.
mShortcutInputMethodInfo = imi;
@@ -202,97 +173,28 @@ public class SubtypeSwitcher {
Log.d(TAG, "Update shortcut IME to : "
+ (mShortcutInputMethodInfo == null
? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
- + (mShortcutSubtype == null ? "<null>" : (mShortcutSubtype.getLocale()
- + ", " + mShortcutSubtype.getMode())));
+ + (mShortcutSubtype == null ? "<null>" : (
+ mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
}
}
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
- public void updateSubtype(InputMethodSubtypeCompatWrapper newSubtype) {
- final String newLocale;
- final String newMode;
- final String oldMode = getCurrentSubtypeMode();
- if (newSubtype == null) {
- // Normally, newSubtype shouldn't be null. But just in case newSubtype was null,
- // fallback to the default locale.
- Log.w(TAG, "Couldn't get the current subtype.");
- newLocale = "en_US";
- newMode = KEYBOARD_MODE;
- } else {
- newLocale = newSubtype.getLocale();
- newMode = newSubtype.getMode();
- }
+ public void updateSubtype(InputMethodSubtype newSubtype) {
if (DBG) {
- Log.w(TAG, "Update subtype to:" + newLocale + "," + newMode
- + ", from: " + mInputLocaleStr + ", " + oldMode);
- }
- boolean languageChanged = false;
- if (!newLocale.equals(mInputLocaleStr)) {
- if (mInputLocaleStr != null) {
- languageChanged = true;
- }
- updateInputLocale(newLocale);
- }
- boolean modeChanged = false;
- if (!newMode.equals(oldMode)) {
- if (oldMode != null) {
- modeChanged = true;
- }
+ Log.w(TAG, "onCurrentInputMethodSubtypeChanged: to: "
+ + newSubtype.getLocale() + "/" + newSubtype.getExtraValue() + ", from: "
+ + mCurrentSubtype.getLocale() + "/" + mCurrentSubtype.getExtraValue());
}
- mCurrentSubtype = newSubtype;
- // If the old mode is voice input, we need to reset or cancel its status.
- // We cancel its status when we change mode, while we reset otherwise.
- if (isKeyboardMode()) {
- if (modeChanged) {
- if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) {
- mVoiceInputWrapper.cancel();
- }
- }
- if (modeChanged || languageChanged) {
- updateShortcutIME();
- mService.onRefreshKeyboard();
- }
- } else if (isVoiceMode() && mVoiceInputWrapper != null) {
- if (VOICE_MODE.equals(oldMode)) {
- mVoiceInputWrapper.reset();
- }
- // If needsToShowWarningDialog is true, voice input need to show warning before
- // show recognition view.
- if (languageChanged || modeChanged
- || VoiceProxy.getInstance().needsToShowWarningDialog()) {
- triggerVoiceIME();
- }
- } else {
- Log.w(TAG, "Unknown subtype mode: " + newMode);
- if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) {
- // We need to reset the voice input to release the resources and to reset its status
- // as it is not the current input mode.
- mVoiceInputWrapper.reset();
- }
- }
- mLanguageBarInfo.update();
- }
+ final Locale newLocale = SubtypeLocale.getSubtypeLocale(newSubtype);
+ mNeedsToDisplayLanguage.updateIsSystemLanguageSameAsInputLanguage(
+ mCurrentSystemLocale.equals(newLocale));
- // Update the current input locale from Locale string.
- private void updateInputLocale(String inputLocaleStr) {
- // example: inputLocaleStr = "en_US" "en" ""
- // "en_US" --> language: en & country: US
- // "en" --> language: en
- // "" --> the system locale
- if (!TextUtils.isEmpty(inputLocaleStr)) {
- mInputLocale = Utils.constructLocaleFromString(inputLocaleStr);
- mInputLocaleStr = inputLocaleStr;
- } else {
- mInputLocale = mSystemLocale;
- String country = mSystemLocale.getCountry();
- mInputLocaleStr = mSystemLocale.getLanguage()
- + (TextUtils.isEmpty(country) ? "" : "_" + mSystemLocale.getLanguage());
- }
- mIsSystemLanguageSameAsInputLanguage = getSystemLocale().getLanguage().equalsIgnoreCase(
- getInputLocale().getLanguage());
- mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1
- && mIsSystemLanguageSameAsInputLanguage);
+ if (newSubtype.equals(mCurrentSubtype)) return;
+
+ mCurrentSubtype = newSubtype;
+ updateShortcutIME();
+ mService.onRefreshKeyboard();
}
////////////////////////////
@@ -305,87 +207,34 @@ public class SubtypeSwitcher {
}
final String imiId = mShortcutInputMethodInfo.getId();
- final InputMethodSubtypeCompatWrapper subtype = mShortcutSubtype;
- switchToTargetIME(imiId, subtype);
+ switchToTargetIME(imiId, mShortcutSubtype);
}
- private void switchToTargetIME(
- final String imiId, final InputMethodSubtypeCompatWrapper subtype) {
+ private void switchToTargetIME(final String imiId, final InputMethodSubtype subtype) {
final IBinder token = mService.getWindow().getWindow().getAttributes().token;
if (token == null) {
return;
}
+ final InputMethodManager imm = mImm;
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
- mImm.setInputMethodAndSubtype(token, imiId, subtype);
+ imm.setInputMethodAndSubtype(token, imiId, subtype);
return null;
}
-
- @Override
- protected void onPostExecute(Void result) {
- // Calls in this method need to be done in the same thread as the thread which
- // called switchToShortcutIME().
-
- // Notify an event that the current subtype was changed. This event will be
- // handled if "onCurrentInputMethodSubtypeChanged" can't be implemented
- // when the API level is 10 or previous.
- mService.notifyOnCurrentInputMethodSubtypeChanged(subtype);
- }
- }.execute();
- }
-
- public Drawable getShortcutIcon() {
- return getSubtypeIcon(mShortcutInputMethodInfo, mShortcutSubtype);
- }
-
- private Drawable getSubtypeIcon(
- InputMethodInfoCompatWrapper imi, InputMethodSubtypeCompatWrapper subtype) {
- final PackageManager pm = mService.getPackageManager();
- if (imi != null) {
- final String imiPackageName = imi.getPackageName();
- if (DBG) {
- Log.d(TAG, "Update icons of IME: " + imiPackageName + ","
- + subtype.getLocale() + "," + subtype.getMode());
- }
- if (subtype != null) {
- return pm.getDrawable(imiPackageName, subtype.getIconResId(),
- imi.getServiceInfo().applicationInfo);
- } else if (imi.getSubtypeCount() > 0 && imi.getSubtypeAt(0) != null) {
- return pm.getDrawable(imiPackageName,
- imi.getSubtypeAt(0).getIconResId(),
- imi.getServiceInfo().applicationInfo);
- } else {
- try {
- return pm.getApplicationInfo(imiPackageName, 0).loadIcon(pm);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "IME can't be found: " + imiPackageName);
- }
- }
- }
- return null;
- }
-
- private static boolean contains(String[] hay, String needle) {
- for (String element : hay) {
- if (element.equals(needle))
- return true;
- }
- return false;
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public boolean isShortcutImeEnabled() {
- if (mShortcutInputMethodInfo == null)
+ if (mShortcutInputMethodInfo == null) {
return false;
- if (mShortcutSubtype == null)
+ }
+ if (mShortcutSubtype == null) {
return true;
- // For compatibility, if the shortcut subtype is dummy, we assume the shortcut IME
- // (built-in voice dummy subtype) is available.
- if (!mShortcutSubtype.hasOriginalObject()) return true;
+ }
final boolean allowsImplicitlySelectedSubtypes = true;
- for (final InputMethodSubtypeCompatWrapper enabledSubtype :
- mImm.getEnabledInputMethodSubtypeList(
- mShortcutInputMethodInfo, allowsImplicitlySelectedSubtypes)) {
+ for (final InputMethodSubtype enabledSubtype : mImm.getEnabledInputMethodSubtypeList(
+ mShortcutInputMethodInfo, allowsImplicitlySelectedSubtypes)) {
if (enabledSubtype.equals(mShortcutSubtype)) {
return true;
}
@@ -398,8 +247,7 @@ public class SubtypeSwitcher {
return false;
if (mShortcutSubtype == null)
return true;
- if (contains(mShortcutSubtype.getExtraValue().split(","),
- SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY)) {
+ if (mShortcutSubtype.containsExtraValueKey(REQ_NETWORK_CONNECTIVITY)) {
return mIsNetworkConnected;
}
return true;
@@ -410,265 +258,40 @@ public class SubtypeSwitcher {
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
mIsNetworkConnected = !noConnection;
- final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance();
- final LatinKeyboard keyboard = switcher.getLatinKeyboard();
- if (keyboard != null) {
- keyboard.updateShortcutKey(isShortcutImeReady(), switcher.getKeyboardView());
- }
+ KeyboardSwitcher.getInstance().onNetworkStateChanged();
}
//////////////////////////////////
- // Language Switching functions //
+ // Subtype Switching functions //
//////////////////////////////////
- public int getEnabledKeyboardLocaleCount() {
- return mEnabledKeyboardSubtypesOfCurrentInputMethod.size();
- }
-
- public boolean useSpacebarLanguageSwitcher() {
- return mConfigUseSpacebarLanguageSwitcher;
- }
-
- public boolean needsToDisplayLanguage() {
- return mNeedsToDisplayLanguage;
- }
-
- public Locale getInputLocale() {
- return mInputLocale;
- }
-
- public String getInputLocaleStr() {
- return mInputLocaleStr;
- }
-
- public String[] getEnabledLanguages() {
- int enabledLanguageCount = mEnabledLanguagesOfCurrentInputMethod.size();
- // Workaround for explicitly specifying the voice language
- if (enabledLanguageCount == 1) {
- mEnabledLanguagesOfCurrentInputMethod.add(mEnabledLanguagesOfCurrentInputMethod
- .get(0));
- ++enabledLanguageCount;
+ public boolean needsToDisplayLanguage(Locale keyboardLocale) {
+ if (keyboardLocale.toString().equals(SubtypeLocale.NO_LANGUAGE)) {
+ return true;
}
- return mEnabledLanguagesOfCurrentInputMethod.toArray(new String[enabledLanguageCount]);
- }
-
- public Locale getSystemLocale() {
- return mSystemLocale;
+ if (!keyboardLocale.equals(getCurrentSubtypeLocale())) {
+ return false;
+ }
+ return mNeedsToDisplayLanguage.getValue();
}
- public boolean isSystemLanguageSameAsInputLanguage() {
- return mIsSystemLanguageSameAsInputLanguage;
+ public Locale getCurrentSubtypeLocale() {
+ return SubtypeLocale.getSubtypeLocale(mCurrentSubtype);
}
public void onConfigurationChanged(Configuration conf) {
final Locale systemLocale = conf.locale;
// If system configuration was changed, update all parameters.
- if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) {
+ if (!systemLocale.equals(mCurrentSystemLocale)) {
updateAllParameters();
}
}
- public boolean isKeyboardMode() {
- return KEYBOARD_MODE.equals(getCurrentSubtypeMode());
+ public InputMethodSubtype getCurrentSubtype() {
+ return mCurrentSubtype;
}
-
- ///////////////////////////
- // Voice Input functions //
- ///////////////////////////
-
- public boolean setVoiceInputWrapper(VoiceProxy.VoiceInputWrapper vi) {
- if (mVoiceInputWrapper == null && vi != null) {
- mVoiceInputWrapper = vi;
- if (isVoiceMode()) {
- if (DBG) {
- Log.d(TAG, "Set and call voice input.: " + getInputLocaleStr());
- }
- triggerVoiceIME();
- return true;
- }
- }
- return false;
- }
-
- public boolean isVoiceMode() {
- return null == mCurrentSubtype ? false : VOICE_MODE.equals(getCurrentSubtypeMode());
- }
-
- public boolean isDummyVoiceMode() {
- return mCurrentSubtype != null && mCurrentSubtype.getOriginalObject() == null
- && VOICE_MODE.equals(getCurrentSubtypeMode());
- }
-
- private void triggerVoiceIME() {
- if (!mService.isInputViewShown()) return;
- VoiceProxy.getInstance().startListening(false,
- KeyboardSwitcher.getInstance().getKeyboardView().getWindowToken());
- }
-
- //////////////////////////////////////
- // Spacebar Language Switch support //
- //////////////////////////////////////
-
- private class LanguageBarInfo {
- private int mCurrentKeyboardSubtypeIndex;
- private InputMethodSubtypeCompatWrapper mNextKeyboardSubtype;
- private InputMethodSubtypeCompatWrapper mPreviousKeyboardSubtype;
- private String mNextLanguage;
- private String mPreviousLanguage;
- public LanguageBarInfo() {
- update();
- }
-
- private String getNextLanguage() {
- return mNextLanguage;
- }
-
- private String getPreviousLanguage() {
- return mPreviousLanguage;
- }
-
- public InputMethodSubtypeCompatWrapper getNextKeyboardSubtype() {
- return mNextKeyboardSubtype;
- }
-
- public InputMethodSubtypeCompatWrapper getPreviousKeyboardSubtype() {
- return mPreviousKeyboardSubtype;
- }
-
- public void update() {
- if (!mConfigUseSpacebarLanguageSwitcher
- || mEnabledKeyboardSubtypesOfCurrentInputMethod == null
- || mEnabledKeyboardSubtypesOfCurrentInputMethod.size() == 0) return;
- mCurrentKeyboardSubtypeIndex = getCurrentIndex();
- mNextKeyboardSubtype = getNextKeyboardSubtypeInternal(mCurrentKeyboardSubtypeIndex);
- Locale locale = Utils.constructLocaleFromString(mNextKeyboardSubtype.getLocale());
- mNextLanguage = getFullDisplayName(locale, true);
- mPreviousKeyboardSubtype = getPreviousKeyboardSubtypeInternal(
- mCurrentKeyboardSubtypeIndex);
- locale = Utils.constructLocaleFromString(mPreviousKeyboardSubtype.getLocale());
- mPreviousLanguage = getFullDisplayName(locale, true);
- }
-
- private int normalize(int index) {
- final int N = mEnabledKeyboardSubtypesOfCurrentInputMethod.size();
- final int ret = index % N;
- return ret < 0 ? ret + N : ret;
- }
-
- private int getCurrentIndex() {
- final int N = mEnabledKeyboardSubtypesOfCurrentInputMethod.size();
- for (int i = 0; i < N; ++i) {
- if (mEnabledKeyboardSubtypesOfCurrentInputMethod.get(i).equals(mCurrentSubtype)) {
- return i;
- }
- }
- return 0;
- }
-
- private InputMethodSubtypeCompatWrapper getNextKeyboardSubtypeInternal(int index) {
- return mEnabledKeyboardSubtypesOfCurrentInputMethod.get(normalize(index + 1));
- }
-
- private InputMethodSubtypeCompatWrapper getPreviousKeyboardSubtypeInternal(int index) {
- return mEnabledKeyboardSubtypesOfCurrentInputMethod.get(normalize(index - 1));
- }
- }
-
- public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) {
- if (returnsNameInThisLocale) {
- return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale);
- } else {
- return toTitleCase(locale.getDisplayName(), locale);
- }
- }
-
- public static String getDisplayLanguage(Locale locale) {
- return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale);
- }
-
- public static String getMiddleDisplayLanguage(Locale locale) {
- return toTitleCase((Utils.constructLocaleFromString(
- locale.getLanguage()).getDisplayLanguage(locale)), locale);
- }
-
- public static String getShortDisplayLanguage(Locale locale) {
- return toTitleCase(locale.getLanguage(), locale);
- }
-
- private static String toTitleCase(String s, Locale locale) {
- if (s.length() == 0) {
- return s;
- }
- return s.toUpperCase(locale).charAt(0) + s.substring(1);
- }
-
- public String getInputLanguageName() {
- return getDisplayLanguage(getInputLocale());
- }
-
- public String getNextInputLanguageName() {
- return mLanguageBarInfo.getNextLanguage();
- }
-
- public String getPreviousInputLanguageName() {
- return mLanguageBarInfo.getPreviousLanguage();
- }
-
- /////////////////////////////
- // Other utility functions //
- /////////////////////////////
-
- public String getCurrentSubtypeExtraValue() {
- // If null, return what an empty ExtraValue would return : the empty string.
- return null != mCurrentSubtype ? mCurrentSubtype.getExtraValue() : "";
- }
-
- public boolean currentSubtypeContainsExtraValueKey(String key) {
- // If null, return what an empty ExtraValue would return : false.
- return null != mCurrentSubtype ? mCurrentSubtype.containsExtraValueKey(key) : false;
- }
-
- public String getCurrentSubtypeExtraValueOf(String key) {
- // If null, return what an empty ExtraValue would return : null.
- return null != mCurrentSubtype ? mCurrentSubtype.getExtraValueOf(key) : null;
- }
-
- public String getCurrentSubtypeMode() {
- return null != mCurrentSubtype ? mCurrentSubtype.getMode() : KEYBOARD_MODE;
- }
-
-
- public boolean isVoiceSupported(String locale) {
- // Get the current list of supported locales and check the current locale against that
- // list. We cache this value so as not to check it every time the user starts a voice
- // input. Because this method is called by onStartInputView, this should mean that as
- // long as the locale doesn't change while the user is keeping the IME open, the
- // value should never be stale.
- String supportedLocalesString = VoiceProxy.getSupportedLocalesString(
- mService.getContentResolver());
- List<String> voiceInputSupportedLocales = Arrays.asList(
- supportedLocalesString.split("\\s+"));
- return voiceInputSupportedLocales.contains(locale);
- }
-
- private void changeToNextSubtype() {
- final InputMethodSubtypeCompatWrapper subtype =
- mLanguageBarInfo.getNextKeyboardSubtype();
- switchToTargetIME(mInputMethodId, subtype);
- }
-
- private void changeToPreviousSubtype() {
- final InputMethodSubtypeCompatWrapper subtype =
- mLanguageBarInfo.getPreviousKeyboardSubtype();
- switchToTargetIME(mInputMethodId, subtype);
- }
-
- public void toggleLanguage(boolean next) {
- if (next) {
- changeToNextSubtype();
- } else {
- changeToPreviousSubtype();
- }
+ public InputMethodSubtype getNoLanguageSubtype() {
+ return mNoLanguageSubtype;
}
}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index eb5ed5a65..892245402 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -17,117 +17,110 @@
package com.android.inputmethod.latin;
import android.content.Context;
-import android.text.AutoText;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.io.File;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This class loads a dictionary and provides a list of suggestions for a given sequence of
* characters. This includes corrections and completions.
*/
public class Suggest implements Dictionary.WordCallback {
-
public static final String TAG = Suggest.class.getSimpleName();
public static final int APPROX_MAX_WORD_LENGTH = 32;
+ // TODO: rename this to CORRECTION_OFF
public static final int CORRECTION_NONE = 0;
- public static final int CORRECTION_BASIC = 1;
- public static final int CORRECTION_FULL = 2;
- public static final int CORRECTION_FULL_BIGRAM = 3;
-
- /**
- * Words that appear in both bigram and unigram data gets multiplier ranging from
- * BIGRAM_MULTIPLIER_MIN to BIGRAM_MULTIPLIER_MAX depending on the score from
- * bigram data.
- */
- public static final double BIGRAM_MULTIPLIER_MIN = 1.2;
- public static final double BIGRAM_MULTIPLIER_MAX = 1.5;
-
- /**
- * Maximum possible bigram frequency. Will depend on how many bits are being used in data
- * structure. Maximum bigram frequency will get the BIGRAM_MULTIPLIER_MAX as the multiplier.
- */
- public static final int MAXIMUM_BIGRAM_FREQUENCY = 127;
+ // TODO: rename this to CORRECTION_ON
+ public static final int CORRECTION_FULL = 1;
+ // It seems the following values are only used for logging.
public static final int DIC_USER_TYPED = 0;
public static final int DIC_MAIN = 1;
public static final int DIC_USER = 2;
- public static final int DIC_AUTO = 3;
+ public static final int DIC_USER_HISTORY = 3;
public static final int DIC_CONTACTS = 4;
+ public static final int DIC_WHITELIST = 6;
// If you add a type of dictionary, increment DIC_TYPE_LAST_ID
- public static final int DIC_TYPE_LAST_ID = 4;
-
+ // TODO: this value seems unused. Remove it?
+ public static final int DIC_TYPE_LAST_ID = 6;
public static final String DICT_KEY_MAIN = "main";
public static final String DICT_KEY_CONTACTS = "contacts";
- public static final String DICT_KEY_AUTO = "auto";
+ // User dictionary, the system-managed one.
public static final String DICT_KEY_USER = "user";
- public static final String DICT_KEY_USER_BIGRAM = "user_bigram";
+ // User history dictionary for the unigram map, internal to LatinIME
+ public static final String DICT_KEY_USER_HISTORY_UNIGRAM = "history_unigram";
+ // User history dictionary for the bigram map, internal to LatinIME
+ public static final String DICT_KEY_USER_HISTORY_BIGRAM = "history_bigram";
public static final String DICT_KEY_WHITELIST ="whitelist";
private static final boolean DBG = LatinImeLogger.sDBG;
- private AutoCorrection mAutoCorrection;
-
- private Dictionary mMainDict;
+ private Dictionary mMainDictionary;
+ private ContactsBinaryDictionary mContactsDict;
private WhitelistDictionary mWhiteListDictionary;
- private final Map<String, Dictionary> mUnigramDictionaries = new HashMap<String, Dictionary>();
- private final Map<String, Dictionary> mBigramDictionaries = new HashMap<String, Dictionary>();
+ private final ConcurrentHashMap<String, Dictionary> mUnigramDictionaries =
+ new ConcurrentHashMap<String, Dictionary>();
+ private final ConcurrentHashMap<String, Dictionary> mBigramDictionaries =
+ new ConcurrentHashMap<String, Dictionary>();
- private int mPrefMaxSuggestions = 18;
+ public static final int MAX_SUGGESTIONS = 18;
private static final int PREF_MAX_BIGRAMS = 60;
- private boolean mQuickFixesEnabled;
-
- private double mAutoCorrectionThreshold;
- private int[] mScores = new int[mPrefMaxSuggestions];
- private int[] mBigramScores = new int[PREF_MAX_BIGRAMS];
+ private float mAutoCorrectionThreshold;
- private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
- ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
- private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
- private CharSequence mTypedWord;
+ private ArrayList<SuggestedWordInfo> mSuggestions = new ArrayList<SuggestedWordInfo>();
+ private ArrayList<SuggestedWordInfo> mBigramSuggestions = new ArrayList<SuggestedWordInfo>();
+ private CharSequence mConsideredWord;
// TODO: Remove these member variables by passing more context to addWord() callback method
private boolean mIsFirstCharCapitalized;
private boolean mIsAllUpperCase;
+ private int mTrailingSingleQuotesCount;
- private int mCorrectionMode = CORRECTION_BASIC;
+ private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
- public Suggest(Context context, int dictionaryResId, Locale locale) {
- init(context, DictionaryFactory.createDictionaryFromManager(context, locale,
- dictionaryResId));
+ public Suggest(final Context context, final Locale locale) {
+ initAsynchronously(context, locale);
}
- /* package for test */ Suggest(Context context, File dictionary, long startOffset, long length,
- Flag[] flagArray) {
- init(null, DictionaryFactory.createDictionaryForTest(context, dictionary, startOffset,
- length, flagArray));
- }
-
- private void init(Context context, Dictionary mainDict) {
- mMainDict = mainDict;
+ /* package for test */ Suggest(final Context context, final File dictionary,
+ final long startOffset, final long length, final Locale locale) {
+ final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
+ startOffset, length /* useFullEditDistance */, false, locale);
+ mMainDictionary = mainDict;
addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
- mWhiteListDictionary = WhitelistDictionary.init(context);
+ initWhitelistAndAutocorrectAndPool(context, locale);
+ }
+
+ private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
+ mWhiteListDictionary = new WhitelistDictionary(context, locale);
addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
- mAutoCorrection = new AutoCorrection();
- initPool();
}
- private void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key,
- Dictionary dict) {
+ private void initAsynchronously(final Context context, final Locale locale) {
+ resetMainDict(context, locale);
+
+ // TODO: read the whitelist and init the pool asynchronously too.
+ // initPool should be done asynchronously now that the pool is thread-safe.
+ initWhitelistAndAutocorrectAndPool(context, locale);
+ }
+
+ private static void addOrReplaceDictionary(
+ final ConcurrentHashMap<String, Dictionary> dictionaries,
+ final String key, final Dictionary dict) {
final Dictionary oldDict = (dict == null)
? dictionaries.remove(key)
: dictionaries.put(key, dict);
@@ -136,50 +129,47 @@ public class Suggest implements Dictionary.WordCallback {
}
}
- public void resetMainDict(Context context, int dictionaryResId, Locale locale) {
- final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager(
- context, locale, dictionaryResId);
- mMainDict = newMainDict;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
- }
-
- private void initPool() {
- for (int i = 0; i < mPrefMaxSuggestions; i++) {
- StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
- mStringPool.add(sb);
- }
- }
-
- public void setQuickFixesEnabled(boolean enabled) {
- mQuickFixesEnabled = enabled;
+ public void resetMainDict(final Context context, final Locale locale) {
+ mMainDictionary = null;
+ new Thread("InitializeBinaryDictionary") {
+ @Override
+ public void run() {
+ final DictionaryCollection newMainDict =
+ DictionaryFactory.createMainDictionaryFromManager(context, locale);
+ addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
+ addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
+ mMainDictionary = newMainDict;
+ }
+ }.start();
}
- public int getCorrectionMode() {
- return mCorrectionMode;
+ // The main dictionary could have been loaded asynchronously. Don't cache the return value
+ // of this method.
+ public boolean hasMainDictionary() {
+ return null != mMainDictionary && mMainDictionary.isInitialized();
}
- public void setCorrectionMode(int mode) {
- mCorrectionMode = mode;
+ public Dictionary getMainDictionary() {
+ return mMainDictionary;
}
- public boolean hasMainDictionary() {
- return mMainDict != null;
+ public ContactsBinaryDictionary getContactsDictionary() {
+ return mContactsDict;
}
- public Map<String, Dictionary> getUnigramDictionaries() {
+ public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
return mUnigramDictionaries;
}
- public int getApproxMaxWordLength() {
+ public static int getApproxMaxWordLength() {
return APPROX_MAX_WORD_LENGTH;
}
/**
* Sets an optional user dictionary resource to be loaded. The user dictionary is consulted
- * before the main dictionary, if set.
+ * before the main dictionary, if set. This refers to the system-managed user dictionary.
*/
- public void setUserDictionary(Dictionary userDictionary) {
+ public void setUserDictionary(UserBinaryDictionary userDictionary) {
addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER, userDictionary);
}
@@ -188,68 +178,28 @@ public class Suggest implements Dictionary.WordCallback {
* the contacts dictionary by passing null to this method. In this case no contacts dictionary
* won't be used.
*/
- public void setContactsDictionary(Dictionary contactsDictionary) {
+ public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) {
+ mContactsDict = contactsDictionary;
addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
}
- public void setAutoDictionary(Dictionary autoDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_AUTO, autoDictionary);
- }
-
- public void setUserBigramDictionary(Dictionary userBigramDictionary) {
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_BIGRAM, userBigramDictionary);
+ public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) {
+ addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_HISTORY_UNIGRAM,
+ userHistoryDictionary);
+ addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_HISTORY_BIGRAM,
+ userHistoryDictionary);
}
- public void setAutoCorrectionThreshold(double threshold) {
+ public void setAutoCorrectionThreshold(float threshold) {
mAutoCorrectionThreshold = threshold;
}
- public boolean isAggressiveAutoCorrectionMode() {
- return (mAutoCorrectionThreshold == 0);
- }
-
- /**
- * Number of suggestions to generate from the input key sequence. This has
- * to be a number between 1 and 100 (inclusive).
- * @param maxSuggestions
- * @throws IllegalArgumentException if the number is out of range
- */
- public void setMaxSuggestions(int maxSuggestions) {
- if (maxSuggestions < 1 || maxSuggestions > 100) {
- throw new IllegalArgumentException("maxSuggestions must be between 1 and 100");
- }
- mPrefMaxSuggestions = maxSuggestions;
- mScores = new int[mPrefMaxSuggestions];
- mBigramScores = new int[PREF_MAX_BIGRAMS];
- collectGarbage(mSuggestions, mPrefMaxSuggestions);
- while (mStringPool.size() < mPrefMaxSuggestions) {
- StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
- mStringPool.add(sb);
- }
- }
-
- /**
- * Returns a object which represents suggested words that match the list of character codes
- * passed in. This object contents will be overwritten the next time this function is called.
- * @param view a view for retrieving the context for AutoText
- * @param wordComposer contains what is currently being typed
- * @param prevWordForBigram previous word (used only for bigram)
- * @return suggested words object.
- */
- public SuggestedWords getSuggestions(View view, WordComposer wordComposer,
- CharSequence prevWordForBigram) {
- return getSuggestedWordBuilder(view, wordComposer, prevWordForBigram).build();
- }
-
- private CharSequence capitalizeWord(boolean all, boolean first, CharSequence word) {
+ private static CharSequence capitalizeWord(final boolean all, final boolean first,
+ final CharSequence word) {
if (TextUtils.isEmpty(word) || !(all || first)) return word;
final int wordLength = word.length();
- final int poolSize = mStringPool.size();
- final StringBuilder sb =
- poolSize > 0 ? (StringBuilder) mStringPool.remove(poolSize - 1)
- : new StringBuilder(getApproxMaxWordLength());
- sb.setLength(0);
+ final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
// TODO: Must pay attention to locale when changing case.
if (all) {
sb.append(word.toString().toUpperCase());
@@ -262,249 +212,271 @@ public class Suggest implements Dictionary.WordCallback {
return sb;
}
- protected void addBigramToSuggestions(CharSequence bigram) {
- final int poolSize = mStringPool.size();
- final StringBuilder sb = poolSize > 0 ?
- (StringBuilder) mStringPool.remove(poolSize - 1)
- : new StringBuilder(getApproxMaxWordLength());
- sb.setLength(0);
- sb.append(bigram);
- mSuggestions.add(sb);
+ protected void addBigramToSuggestions(SuggestedWordInfo bigram) {
+ mSuggestions.add(bigram);
+ }
+
+ private static final WordComposer sEmptyWordComposer = new WordComposer();
+ public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) {
+ LatinImeLogger.onStartSuggestion(prevWordForBigram);
+ mIsFirstCharCapitalized = false;
+ mIsAllUpperCase = false;
+ mTrailingSingleQuotesCount = 0;
+ mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
+
+ // Treating USER_TYPED as UNIGRAM suggestion for logging now.
+ LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
+ mConsideredWord = "";
+
+ mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
+
+ getAllBigrams(prevWordForBigram, sEmptyWordComposer);
+
+ // Nothing entered: return all bigrams for the previous word
+ int insertCount = Math.min(mBigramSuggestions.size(), MAX_SUGGESTIONS);
+ for (int i = 0; i < insertCount; ++i) {
+ addBigramToSuggestions(mBigramSuggestions.get(i));
+ }
+
+ SuggestedWordInfo.removeDups(mSuggestions);
+
+ return new SuggestedWords(mSuggestions,
+ false /* typedWordValid */,
+ false /* hasAutoCorrectionCandidate */,
+ false /* allowsToBeAutoCorrected */,
+ false /* isPunctuationSuggestions */,
+ false /* isObsoleteSuggestions */,
+ true /* isPrediction */);
}
// TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
- public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer,
- CharSequence prevWordForBigram) {
+ public SuggestedWords getSuggestedWords(
+ final WordComposer wordComposer, CharSequence prevWordForBigram,
+ final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mAutoCorrection.init();
mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
mIsAllUpperCase = wordComposer.isAllUpperCase();
- collectGarbage(mSuggestions, mPrefMaxSuggestions);
- Arrays.fill(mScores, 0);
-
- // Save a lowercase version of the original word
- CharSequence typedWord = wordComposer.getTypedWord();
- if (typedWord != null) {
- final String typedWordString = typedWord.toString();
- typedWord = typedWordString;
- // Treating USER_TYPED as UNIGRAM suggestion for logging now.
- LatinImeLogger.onAddSuggestedWord(typedWordString, Suggest.DIC_USER_TYPED,
- Dictionary.DataType.UNIGRAM);
- }
- mTypedWord = typedWord;
-
- if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM
- || mCorrectionMode == CORRECTION_BASIC)) {
+ mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
+ mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
+
+ final String typedWord = wordComposer.getTypedWord();
+ final String consideredWord = mTrailingSingleQuotesCount > 0
+ ? typedWord.substring(0, typedWord.length() - mTrailingSingleQuotesCount)
+ : typedWord;
+ // Treating USER_TYPED as UNIGRAM suggestion for logging now.
+ LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
+ mConsideredWord = consideredWord;
+
+ if (wordComposer.size() <= 1 && isCorrectionEnabled) {
// At first character typed, search only the bigrams
- Arrays.fill(mBigramScores, 0);
- collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS);
+ mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
if (!TextUtils.isEmpty(prevWordForBigram)) {
- CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase();
- if (mMainDict != null && mMainDict.isValidWord(lowerPrevWord)) {
- prevWordForBigram = lowerPrevWord;
- }
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, prevWordForBigram, this);
- }
- if (TextUtils.isEmpty(typedWord)) {
+ getAllBigrams(prevWordForBigram, wordComposer);
+ if (TextUtils.isEmpty(consideredWord)) {
// Nothing entered: return all bigrams for the previous word
- int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions);
+ int insertCount = Math.min(mBigramSuggestions.size(), MAX_SUGGESTIONS);
for (int i = 0; i < insertCount; ++i) {
addBigramToSuggestions(mBigramSuggestions.get(i));
}
} else {
// Word entered: return only bigrams that match the first char of the typed word
- final char currentChar = typedWord.charAt(0);
+ final char currentChar = consideredWord.charAt(0);
// TODO: Must pay attention to locale when changing case.
+ // TODO: Use codepoint instead of char
final char currentCharUpper = Character.toUpperCase(currentChar);
int count = 0;
final int bigramSuggestionSize = mBigramSuggestions.size();
for (int i = 0; i < bigramSuggestionSize; i++) {
- final CharSequence bigramSuggestion = mBigramSuggestions.get(i);
- final char bigramSuggestionFirstChar = bigramSuggestion.charAt(0);
+ final SuggestedWordInfo bigramSuggestion = mBigramSuggestions.get(i);
+ final char bigramSuggestionFirstChar =
+ (char)bigramSuggestion.codePointAt(0);
if (bigramSuggestionFirstChar == currentChar
|| bigramSuggestionFirstChar == currentCharUpper) {
addBigramToSuggestions(bigramSuggestion);
- if (++count > mPrefMaxSuggestions) break;
+ if (++count > MAX_SUGGESTIONS) break;
}
}
}
}
} else if (wordComposer.size() > 1) {
+ final WordComposer wordComposerForLookup;
+ if (mTrailingSingleQuotesCount > 0) {
+ wordComposerForLookup = new WordComposer(wordComposer);
+ for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ wordComposerForLookup.deleteLast();
+ }
+ } else {
+ wordComposerForLookup = wordComposer;
+ }
// At second character typed, search the unigrams (scores being affected by bigrams)
for (final String key : mUnigramDictionaries.keySet()) {
- // Skip AutoDictionary and WhitelistDictionary to lookup
- if (key.equals(DICT_KEY_AUTO) || key.equals(DICT_KEY_WHITELIST))
+ // Skip UserUnigramDictionary and WhitelistDictionary to lookup
+ if (key.equals(DICT_KEY_USER_HISTORY_UNIGRAM) || key.equals(DICT_KEY_WHITELIST))
continue;
final Dictionary dictionary = mUnigramDictionaries.get(key);
- dictionary.getWords(wordComposer, this);
- }
- }
- CharSequence autoText = null;
- final String typedWordString = typedWord == null ? null : typedWord.toString();
- if (typedWord != null) {
- // Apply quick fix only for the typed word.
- if (mQuickFixesEnabled) {
- final String lowerCaseTypedWord = typedWordString.toLowerCase();
- CharSequence tempAutoText = capitalizeWord(
- mIsAllUpperCase, mIsFirstCharCapitalized, AutoText.get(
- lowerCaseTypedWord, 0, lowerCaseTypedWord.length(), view));
- // TODO: cleanup canAdd
- // Is there an AutoText (also known as Quick Fixes) correction?
- // Capitalize as needed
- boolean canAdd = tempAutoText != null;
- // Is that correction already the current prediction (or original word)?
- canAdd &= !TextUtils.equals(tempAutoText, typedWord);
- // Is that correction already the next predicted word?
- if (canAdd && mSuggestions.size() > 0 && mCorrectionMode != CORRECTION_BASIC) {
- canAdd &= !TextUtils.equals(tempAutoText, mSuggestions.get(0));
- }
- if (canAdd) {
- if (DBG) {
- Log.d(TAG, "Auto corrected by AUTOTEXT.");
- }
- autoText = tempAutoText;
- }
+ dictionary.getWords(wordComposerForLookup, prevWordForBigram, this, proximityInfo);
}
}
- CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase, mIsFirstCharCapitalized,
- mWhiteListDictionary.getWhiteListedWord(typedWordString));
+ final CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase,
+ mIsFirstCharCapitalized, mWhiteListDictionary.getWhitelistedWord(consideredWord));
- mAutoCorrection.updateAutoCorrectionStatus(mUnigramDictionaries, wordComposer,
- mSuggestions, mScores, typedWord, mAutoCorrectionThreshold, mCorrectionMode,
- autoText, whitelistedWord);
-
- if (autoText != null) {
- mSuggestions.add(0, autoText);
+ final boolean hasAutoCorrection;
+ if (isCorrectionEnabled) {
+ final CharSequence autoCorrection =
+ AutoCorrection.computeAutoCorrectionWord(mUnigramDictionaries, wordComposer,
+ mSuggestions, consideredWord, mAutoCorrectionThreshold,
+ whitelistedWord);
+ hasAutoCorrection = (null != autoCorrection);
+ } else {
+ hasAutoCorrection = false;
}
if (whitelistedWord != null) {
- mSuggestions.add(0, whitelistedWord);
+ if (mTrailingSingleQuotesCount > 0) {
+ final StringBuilder sb = new StringBuilder(whitelistedWord);
+ for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
+ }
+ mSuggestions.add(0, new SuggestedWordInfo(sb.toString(),
+ SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST));
+ } else {
+ mSuggestions.add(0, new SuggestedWordInfo(whitelistedWord,
+ SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST));
+ }
}
- if (typedWord != null) {
- mSuggestions.add(0, typedWordString);
- }
- removeDupes();
+ mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
+ SuggestedWordInfo.KIND_TYPED));
+ SuggestedWordInfo.removeDups(mSuggestions);
+ final ArrayList<SuggestedWordInfo> suggestionsList;
if (DBG) {
- double normalizedScore = mAutoCorrection.getNormalizedScore();
- ArrayList<SuggestedWords.SuggestedWordInfo> scoreInfoList =
- new ArrayList<SuggestedWords.SuggestedWordInfo>();
- scoreInfoList.add(new SuggestedWords.SuggestedWordInfo("+", false));
- for (int i = 0; i < mScores.length; ++i) {
- if (normalizedScore > 0) {
- final String scoreThreshold = String.format("%d (%4.2f)", mScores[i],
- normalizedScore);
- scoreInfoList.add(
- new SuggestedWords.SuggestedWordInfo(scoreThreshold, false));
- normalizedScore = 0.0;
- } else {
- final String score = Integer.toString(mScores[i]);
- scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(score, false));
- }
- }
- for (int i = mScores.length; i < mSuggestions.size(); ++i) {
- scoreInfoList.add(new SuggestedWords.SuggestedWordInfo("--", false));
- }
- return new SuggestedWords.Builder().addWords(mSuggestions, scoreInfoList);
+ suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, mSuggestions);
+ } else {
+ suggestionsList = mSuggestions;
}
- return new SuggestedWords.Builder().addWords(mSuggestions, null);
- }
- private void removeDupes() {
- final ArrayList<CharSequence> suggestions = mSuggestions;
- if (suggestions.size() < 2) return;
- int i = 1;
- // Don't cache suggestions.size(), since we may be removing items
- while (i < suggestions.size()) {
- final CharSequence cur = suggestions.get(i);
- // Compare each candidate with each previous candidate
- for (int j = 0; j < i; j++) {
- CharSequence previous = suggestions.get(j);
- if (TextUtils.equals(cur, previous)) {
- removeFromSuggestions(i);
- i--;
- break;
- }
- }
- i++;
+ // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
+ // but still autocorrected from - in the case the whitelist only capitalizes the word.
+ // The whitelist should be case-insensitive, so it's not possible to be consistent with
+ // a boolean flag. Right now this is handled with a slight hack in
+ // WhitelistDictionary#shouldForciblyAutoCorrectFrom.
+ final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
+ getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized())
+ // If we don't have a main dictionary, we never want to auto-correct. The reason for this
+ // is, the user may have a contact whose name happens to match a valid word in their
+ // language, and it will unexpectedly auto-correct. For example, if the user types in
+ // English with no dictionary and has a "Will" in their contact list, "will" would
+ // always auto-correct to "Will" which is unwanted. Hence, no main dict => no auto-correct.
+ && hasMainDictionary();
+
+ boolean autoCorrectionAvailable = hasAutoCorrection;
+ if (isCorrectionEnabled) {
+ autoCorrectionAvailable |= !allowsToBeAutoCorrected;
}
+ // Don't auto-correct words with multiple capital letter
+ autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
+ autoCorrectionAvailable &= !wordComposer.isResumed();
+ if (allowsToBeAutoCorrected && suggestionsList.size() > 1 && mAutoCorrectionThreshold > 0
+ && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord,
+ suggestionsList.get(1).mWord)) {
+ autoCorrectionAvailable = false;
+ }
+ return new SuggestedWords(suggestionsList,
+ !allowsToBeAutoCorrected /* typedWordValid */,
+ autoCorrectionAvailable /* hasAutoCorrectionCandidate */,
+ allowsToBeAutoCorrected /* allowsToBeAutoCorrected */,
+ false /* isPunctuationSuggestions */,
+ false /* isObsoleteSuggestions */,
+ false /* isPrediction */);
}
- private void removeFromSuggestions(int index) {
- CharSequence garbage = mSuggestions.remove(index);
- if (garbage != null && garbage instanceof StringBuilder) {
- mStringPool.add(garbage);
+ /**
+ * Adds all bigram predictions for prevWord. Also checks the lower case version of prevWord if
+ * it contains any upper case characters.
+ */
+ private void getAllBigrams(final CharSequence prevWord, final WordComposer wordComposer) {
+ if (StringUtils.hasUpperCase(prevWord)) {
+ // TODO: Must pay attention to locale when changing case.
+ final CharSequence lowerPrevWord = prevWord.toString().toLowerCase();
+ for (final Dictionary dictionary : mBigramDictionaries.values()) {
+ dictionary.getBigrams(wordComposer, lowerPrevWord, this);
+ }
+ }
+ for (final Dictionary dictionary : mBigramDictionaries.values()) {
+ dictionary.getBigrams(wordComposer, prevWord, this);
}
}
- public boolean hasAutoCorrection() {
- return mAutoCorrection.hasAutoCorrection();
+ private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
+ final String typedWord, final ArrayList<SuggestedWordInfo> suggestions) {
+ final SuggestedWordInfo typedWordInfo = suggestions.get(0);
+ typedWordInfo.setDebugString("+");
+ final int suggestionsSize = suggestions.size();
+ final ArrayList<SuggestedWordInfo> suggestionsList =
+ new ArrayList<SuggestedWordInfo>(suggestionsSize);
+ suggestionsList.add(typedWordInfo);
+ // Note: i here is the index in mScores[], but the index in mSuggestions is one more
+ // than i because we added the typed word to mSuggestions without touching mScores.
+ for (int i = 0; i < suggestionsSize - 1; ++i) {
+ final SuggestedWordInfo cur = suggestions.get(i + 1);
+ final float normalizedScore = BinaryDictionary.calcNormalizedScore(
+ typedWord, cur.toString(), cur.mScore);
+ final String scoreInfoString;
+ if (normalizedScore > 0) {
+ scoreInfoString = String.format("%d (%4.2f)", cur.mScore, normalizedScore);
+ } else {
+ scoreInfoString = Integer.toString(cur.mScore);
+ }
+ cur.setDebugString(scoreInfoString);
+ suggestionsList.add(cur);
+ }
+ return suggestionsList;
}
+ // TODO: Use codepoint instead of char
@Override
public boolean addWord(final char[] word, final int offset, final int length, int score,
- final int dicTypeId, final Dictionary.DataType dataType) {
- Dictionary.DataType dataTypeForLog = dataType;
- final ArrayList<CharSequence> suggestions;
- final int[] sortedScores;
+ final int dicTypeId, final int dataType) {
+ int dataTypeForLog = dataType;
+ final ArrayList<SuggestedWordInfo> suggestions;
final int prefMaxSuggestions;
- if(dataType == Dictionary.DataType.BIGRAM) {
+ if (dataType == Dictionary.BIGRAM) {
suggestions = mBigramSuggestions;
- sortedScores = mBigramScores;
prefMaxSuggestions = PREF_MAX_BIGRAMS;
} else {
suggestions = mSuggestions;
- sortedScores = mScores;
- prefMaxSuggestions = mPrefMaxSuggestions;
+ prefMaxSuggestions = MAX_SUGGESTIONS;
}
int pos = 0;
// Check if it's the same word, only caps are different
- if (Utils.equalsIgnoreCase(mTypedWord, word, offset, length)) {
+ if (StringUtils.equalsIgnoreCase(mConsideredWord, word, offset, length)) {
// TODO: remove this surrounding if clause and move this logic to
// getSuggestedWordBuilder.
if (suggestions.size() > 0) {
- final String currentHighestWord = suggestions.get(0).toString();
+ final SuggestedWordInfo currentHighestWord = suggestions.get(0);
// If the current highest word is also equal to typed word, we need to compare
// frequency to determine the insertion position. This does not ensure strictly
// correct ordering, but ensures the top score is on top which is enough for
// removing duplicates correctly.
- if (Utils.equalsIgnoreCase(currentHighestWord, word, offset, length)
- && score <= sortedScores[0]) {
+ if (StringUtils.equalsIgnoreCase(currentHighestWord.mWord, word, offset, length)
+ && score <= currentHighestWord.mScore) {
pos = 1;
}
}
} else {
- if (dataType == Dictionary.DataType.UNIGRAM) {
- // Check if the word was already added before (by bigram data)
- int bigramSuggestion = searchBigramSuggestion(word,offset,length);
- if(bigramSuggestion >= 0) {
- dataTypeForLog = Dictionary.DataType.BIGRAM;
- // turn freq from bigram into multiplier specified above
- double multiplier = (((double) mBigramScores[bigramSuggestion])
- / MAXIMUM_BIGRAM_FREQUENCY)
- * (BIGRAM_MULTIPLIER_MAX - BIGRAM_MULTIPLIER_MIN)
- + BIGRAM_MULTIPLIER_MIN;
- /* Log.d(TAG,"bigram num: " + bigramSuggestion
- + " wordB: " + mBigramSuggestions.get(bigramSuggestion).toString()
- + " currentScore: " + score + " bigramScore: "
- + mBigramScores[bigramSuggestion]
- + " multiplier: " + multiplier); */
- score = (int)Math.round((score * multiplier));
- }
- }
-
// Check the last one's score and bail
- if (sortedScores[prefMaxSuggestions - 1] >= score) return true;
- while (pos < prefMaxSuggestions) {
- if (sortedScores[pos] < score
- || (sortedScores[pos] == score && length < suggestions.get(pos).length())) {
+ if (suggestions.size() >= prefMaxSuggestions
+ && suggestions.get(prefMaxSuggestions - 1).mScore >= score) return true;
+ while (pos < suggestions.size()) {
+ final int curScore = suggestions.get(pos).mScore;
+ if (curScore < score
+ || (curScore == score && length < suggestions.get(pos).codePointCount())) {
break;
}
pos++;
@@ -514,12 +486,7 @@ public class Suggest implements Dictionary.WordCallback {
return true;
}
- System.arraycopy(sortedScores, pos, sortedScores, pos + 1, prefMaxSuggestions - pos - 1);
- sortedScores[pos] = score;
- int poolSize = mStringPool.size();
- StringBuilder sb = poolSize > 0 ? (StringBuilder) mStringPool.remove(poolSize - 1)
- : new StringBuilder(getApproxMaxWordLength());
- sb.setLength(0);
+ final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
// TODO: Must pay attention to locale when changing case.
if (mIsAllUpperCase) {
sb.append(new String(word, offset, length).toUpperCase());
@@ -531,62 +498,59 @@ public class Suggest implements Dictionary.WordCallback {
} else {
sb.append(word, offset, length);
}
- suggestions.add(pos, sb);
+ for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
+ }
+ // TODO: figure out what type of suggestion this is
+ suggestions.add(pos, new SuggestedWordInfo(sb, score, SuggestedWordInfo.KIND_CORRECTION));
if (suggestions.size() > prefMaxSuggestions) {
- CharSequence garbage = suggestions.remove(prefMaxSuggestions);
- if (garbage instanceof StringBuilder) {
- mStringPool.add(garbage);
- }
+ suggestions.remove(prefMaxSuggestions);
} else {
LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog);
}
return true;
}
- private int searchBigramSuggestion(final char[] word, final int offset, final int length) {
- // TODO This is almost O(n^2). Might need fix.
- // search whether the word appeared in bigram data
- int bigramSuggestSize = mBigramSuggestions.size();
- for(int i = 0; i < bigramSuggestSize; i++) {
- if(mBigramSuggestions.get(i).length() == length) {
- boolean chk = true;
- for(int j = 0; j < length; j++) {
- if(mBigramSuggestions.get(i).charAt(j) != word[offset+j]) {
- chk = false;
- break;
- }
- }
- if(chk) return i;
- }
- }
-
- return -1;
- }
-
- private void collectGarbage(ArrayList<CharSequence> suggestions, int prefMaxSuggestions) {
- int poolSize = mStringPool.size();
- int garbageSize = suggestions.size();
- while (poolSize < prefMaxSuggestions && garbageSize > 0) {
- CharSequence garbage = suggestions.get(garbageSize - 1);
- if (garbage != null && garbage instanceof StringBuilder) {
- mStringPool.add(garbage);
- poolSize++;
- }
- garbageSize--;
- }
- if (poolSize == prefMaxSuggestions + 1) {
- Log.w("Suggest", "String pool got too big: " + poolSize);
- }
- suggestions.clear();
- }
-
public void close() {
- final Set<Dictionary> dictionaries = new HashSet<Dictionary>();
+ final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>();
dictionaries.addAll(mUnigramDictionaries.values());
dictionaries.addAll(mBigramDictionaries.values());
for (final Dictionary dictionary : dictionaries) {
dictionary.close();
}
- mMainDict = null;
+ mMainDictionary = null;
+ }
+
+ // TODO: Resolve the inconsistencies between the native auto correction algorithms and
+ // this safety net
+ public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord,
+ final CharSequence suggestion) {
+ // Safety net for auto correction.
+ // Actually if we hit this safety net, it's a bug.
+ // If user selected aggressive auto correction mode, there is no need to use the safety
+ // net.
+ // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
+ // we should not use net because relatively edit distance can be big.
+ final int typedWordLength = typedWord.length();
+ if (typedWordLength < Suggest.MINIMUM_SAFETY_NET_CHAR_LENGTH) {
+ return false;
+ }
+ final int maxEditDistanceOfNativeDictionary =
+ (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1;
+ final int distance = BinaryDictionary.editDistance(typedWord, suggestion.toString());
+ if (DBG) {
+ Log.d(TAG, "Autocorrected edit distance = " + distance
+ + ", " + maxEditDistanceOfNativeDictionary);
+ }
+ if (distance > maxEditDistanceOfNativeDictionary) {
+ if (DBG) {
+ Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion);
+ Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. "
+ + "Turning off auto-correction.");
+ }
+ return true;
+ } else {
+ return false;
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index a8cdfc02e..45ac9ff53 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -16,169 +16,180 @@
package com.android.inputmethod.latin;
+import android.text.TextUtils;
import android.view.inputmethod.CompletionInfo;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.HashSet;
-import java.util.List;
public class SuggestedWords {
- public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, null);
+ public static final SuggestedWords EMPTY = new SuggestedWords(
+ new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false, false);
- public final List<CharSequence> mWords;
public final boolean mTypedWordValid;
- public final boolean mHasMinimalSuggestion;
- public final List<SuggestedWordInfo> mSuggestedWordInfoList;
-
- private SuggestedWords(List<CharSequence> words, boolean typedWordValid,
- boolean hasMinimalSuggestion, List<SuggestedWordInfo> suggestedWordInfoList) {
- if (words != null) {
- mWords = words;
- } else {
- mWords = Collections.emptyList();
- }
- mTypedWordValid = typedWordValid;
- mHasMinimalSuggestion = hasMinimalSuggestion;
+ public final boolean mHasAutoCorrectionCandidate;
+ public final boolean mIsPunctuationSuggestions;
+ public final boolean mAllowsToBeAutoCorrected;
+ public final boolean mIsObsoleteSuggestions;
+ public final boolean mIsPrediction;
+ private final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
+
+ public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
+ final boolean typedWordValid,
+ final boolean hasAutoCorrectionCandidate,
+ final boolean allowsToBeAutoCorrected,
+ final boolean isPunctuationSuggestions,
+ final boolean isObsoleteSuggestions,
+ final boolean isPrediction) {
mSuggestedWordInfoList = suggestedWordInfoList;
+ mTypedWordValid = typedWordValid;
+ mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate;
+ mAllowsToBeAutoCorrected = allowsToBeAutoCorrected;
+ mIsPunctuationSuggestions = isPunctuationSuggestions;
+ mIsObsoleteSuggestions = isObsoleteSuggestions;
+ mIsPrediction = isPrediction;
}
public int size() {
- return mWords.size();
+ return mSuggestedWordInfoList.size();
}
public CharSequence getWord(int pos) {
- return mWords.get(pos);
+ return mSuggestedWordInfoList.get(pos).mWord;
}
- public boolean hasAutoCorrectionWord() {
- return mHasMinimalSuggestion && size() > 1 && !mTypedWordValid;
+ public SuggestedWordInfo getWordInfo(int pos) {
+ return mSuggestedWordInfoList.get(pos);
}
- public boolean hasWordAboveAutoCorrectionScoreThreshold() {
- return mHasMinimalSuggestion && ((size() > 1 && !mTypedWordValid) || mTypedWordValid);
+ public SuggestedWordInfo getInfo(int pos) {
+ return mSuggestedWordInfoList.get(pos);
}
- public static class Builder {
- private List<CharSequence> mWords = new ArrayList<CharSequence>();
- private boolean mTypedWordValid;
- private boolean mHasMinimalSuggestion;
- private List<SuggestedWordInfo> mSuggestedWordInfoList =
- new ArrayList<SuggestedWordInfo>();
-
- public Builder() {
- // Nothing to do here.
- }
-
- public Builder addWords(List<CharSequence> words,
- List<SuggestedWordInfo> suggestedWordInfoList) {
- final int N = words.size();
- for (int i = 0; i < N; ++i) {
- SuggestedWordInfo suggestedWordInfo = null;
- if (suggestedWordInfoList != null) {
- suggestedWordInfo = suggestedWordInfoList.get(i);
- }
- if (suggestedWordInfo == null) {
- suggestedWordInfo = new SuggestedWordInfo();
- }
- addWord(words.get(i), suggestedWordInfo);
- }
- return this;
- }
-
- public Builder addWord(CharSequence word) {
- return addWord(word, null, false);
- }
-
- public Builder addWord(CharSequence word, CharSequence debugString,
- boolean isPreviousSuggestedWord) {
- SuggestedWordInfo info = new SuggestedWordInfo(debugString, isPreviousSuggestedWord);
- return addWord(word, info);
- }
-
- private Builder addWord(CharSequence word, SuggestedWordInfo suggestedWordInfo) {
- mWords.add(word);
- mSuggestedWordInfoList.add(suggestedWordInfo);
- return this;
- }
-
- public Builder setApplicationSpecifiedCompletions(CompletionInfo[] infos) {
- for (CompletionInfo info : infos)
- addWord(info.getText());
- return this;
- }
+ public boolean hasAutoCorrectionWord() {
+ return mHasAutoCorrectionCandidate && size() > 1 && !mTypedWordValid;
+ }
- public Builder setTypedWordValid(boolean typedWordValid) {
- mTypedWordValid = typedWordValid;
- return this;
- }
+ public boolean willAutoCorrect() {
+ return !mTypedWordValid && mHasAutoCorrectionCandidate;
+ }
- public Builder setHasMinimalSuggestion(boolean hasMinimalSuggestion) {
- mHasMinimalSuggestion = hasMinimalSuggestion;
- return this;
- }
+ @Override
+ public String toString() {
+ // Pretty-print method to help debug
+ return "SuggestedWords:"
+ + " mTypedWordValid=" + mTypedWordValid
+ + " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate
+ + " mAllowsToBeAutoCorrected=" + mAllowsToBeAutoCorrected
+ + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
+ + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray());
+ }
- // Should get rid of the first one (what the user typed previously) from suggestions
- // and replace it with what the user currently typed.
- public Builder addTypedWordAndPreviousSuggestions(CharSequence typedWord,
- SuggestedWords previousSuggestions) {
- mWords.clear();
- mSuggestedWordInfoList.clear();
- final HashSet<String> alreadySeen = new HashSet<String>();
- addWord(typedWord, null, false);
- alreadySeen.add(typedWord.toString());
- final int previousSize = previousSuggestions.size();
- for (int pos = 1; pos < previousSize; pos++) {
- final String prevWord = previousSuggestions.getWord(pos).toString();
- // Filter out duplicate suggestion.
- if (!alreadySeen.contains(prevWord)) {
- addWord(prevWord, null, true);
- alreadySeen.add(prevWord);
- }
+ public static ArrayList<SuggestedWordInfo> getFromApplicationSpecifiedCompletions(
+ final CompletionInfo[] infos) {
+ final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>();
+ for (CompletionInfo info : infos) {
+ if (null != info && info.getText() != null) {
+ result.add(new SuggestedWordInfo(info.getText(), SuggestedWordInfo.MAX_SCORE,
+ SuggestedWordInfo.KIND_APP_DEFINED));
}
- mTypedWordValid = false;
- mHasMinimalSuggestion = false;
- return this;
}
+ return result;
+ }
- public SuggestedWords build() {
- return new SuggestedWords(mWords, mTypedWordValid, mHasMinimalSuggestion,
- mSuggestedWordInfoList);
+ // Should get rid of the first one (what the user typed previously) from suggestions
+ // and replace it with what the user currently typed.
+ public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions(
+ final CharSequence typedWord, final SuggestedWords previousSuggestions) {
+ final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>();
+ final HashSet<String> alreadySeen = new HashSet<String>();
+ suggestionsList.add(new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
+ SuggestedWordInfo.KIND_TYPED));
+ alreadySeen.add(typedWord.toString());
+ final int previousSize = previousSuggestions.size();
+ for (int pos = 1; pos < previousSize; pos++) {
+ final SuggestedWordInfo prevWordInfo = previousSuggestions.getWordInfo(pos);
+ final String prevWord = prevWordInfo.mWord.toString();
+ // Filter out duplicate suggestion.
+ if (!alreadySeen.contains(prevWord)) {
+ suggestionsList.add(prevWordInfo);
+ alreadySeen.add(prevWord);
+ }
}
+ return suggestionsList;
+ }
- public int size() {
- return mWords.size();
+ public static class SuggestedWordInfo {
+ public static final int MAX_SCORE = Integer.MAX_VALUE;
+ public static final int KIND_TYPED = 0; // What user typed
+ public static final int KIND_CORRECTION = 1; // Simple correction/suggestion
+ public static final int KIND_COMPLETION = 2; // Completion (suggestion with appended chars)
+ public static final int KIND_WHITELIST = 3; // Whitelisted word
+ public static final int KIND_BLACKLIST = 4; // Blacklisted word
+ public static final int KIND_HARDCODED = 5; // Hardcoded suggestion, e.g. punctuation
+ public static final int KIND_APP_DEFINED = 6; // Suggested by the application
+ public static final int KIND_SHORTCUT = 7; // A shortcut
+ private final String mWordStr;
+ public final CharSequence mWord;
+ public final int mScore;
+ public final int mKind; // one of the KIND_* constants above
+ public final int mCodePointCount;
+ private String mDebugString = "";
+
+ public SuggestedWordInfo(final CharSequence word, final int score, final int kind) {
+ mWordStr = word.toString();
+ mWord = word;
+ mScore = score;
+ mKind = kind;
+ mCodePointCount = mWordStr.codePointCount(0, mWordStr.length());
+ }
+
+
+ public void setDebugString(String str) {
+ if (null == str) throw new NullPointerException("Debug info is null");
+ mDebugString = str;
}
- public CharSequence getWord(int pos) {
- return mWords.get(pos);
+ public String getDebugString() {
+ return mDebugString;
}
- }
-
- public static class SuggestedWordInfo {
- private final CharSequence mDebugString;
- private final boolean mPreviousSuggestedWord;
- public SuggestedWordInfo() {
- mDebugString = "";
- mPreviousSuggestedWord = false;
+ public int codePointCount() {
+ return mCodePointCount;
}
- public SuggestedWordInfo(CharSequence debugString, boolean previousSuggestedWord) {
- mDebugString = debugString;
- mPreviousSuggestedWord = previousSuggestedWord;
+ public int codePointAt(int i) {
+ return mWordStr.codePointAt(i);
}
- public String getDebugString() {
- if (mDebugString == null) {
- return "";
+ @Override
+ public String toString() {
+ if (TextUtils.isEmpty(mDebugString)) {
+ return mWordStr;
} else {
- return mDebugString.toString();
+ return mWordStr + " (" + mDebugString.toString() + ")";
}
}
- public boolean isPreviousSuggestedWord () {
- return mPreviousSuggestedWord;
+ // TODO: Consolidate this method and StringUtils.removeDupes() in the future.
+ public static void removeDups(ArrayList<SuggestedWordInfo> candidates) {
+ if (candidates.size() <= 1) {
+ return;
+ }
+ int i = 1;
+ while(i < candidates.size()) {
+ final SuggestedWordInfo cur = candidates.get(i);
+ for (int j = 0; j < i; ++j) {
+ final SuggestedWordInfo previous = candidates.get(j);
+ if (TextUtils.equals(cur.mWord, previous.mWord)) {
+ candidates.remove(cur.mScore < previous.mScore ? i : j);
+ --i;
+ break;
+ }
+ }
+ ++i;
+ }
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
new file mode 100644
index 000000000..673b54500
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+import java.util.Locale;
+
+public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary {
+ private boolean mClosed;
+
+ public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) {
+ super(context, Suggest.DIC_CONTACTS, locale);
+ }
+
+ @Override
+ public synchronized void getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final WordCallback callback,
+ final ProximityInfo proximityInfo) {
+ syncReloadDictionaryIfRequired();
+ getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ }
+
+ @Override
+ public synchronized boolean isValidWord(CharSequence word) {
+ syncReloadDictionaryIfRequired();
+ return isValidWordInner(word);
+ }
+
+ // Protect against multiple closing
+ @Override
+ public synchronized void close() {
+ // Actually with the current implementation of ContactsDictionary it's safe to close
+ // several times, so the following protection is really only for foolproofing
+ if (mClosed) return;
+ mClosed = true;
+ super.close();
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
new file mode 100644
index 000000000..1606a34e0
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary {
+
+ public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale) {
+ this(context, locale, false);
+ }
+
+ public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale,
+ final boolean alsoUseMoreRestrictiveLocales) {
+ super(context, locale, alsoUseMoreRestrictiveLocales);
+ }
+
+ @Override
+ public synchronized void getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final WordCallback callback,
+ final ProximityInfo proximityInfo) {
+ syncReloadDictionaryIfRequired();
+ getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ }
+
+ @Override
+ public synchronized boolean isValidWord(CharSequence word) {
+ syncReloadDictionaryIfRequired();
+ return isValidWordInner(word);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java b/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java
new file mode 100644
index 000000000..4265309e5
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.util.LruCache;
+
+public class TargetApplicationGetter extends AsyncTask<String, Void, ApplicationInfo> {
+
+ private static final int MAX_CACHE_ENTRIES = 64; // arbitrary
+ private static LruCache<String, ApplicationInfo> sCache =
+ new LruCache<String, ApplicationInfo>(MAX_CACHE_ENTRIES);
+
+ public static ApplicationInfo getCachedApplicationInfo(final String packageName) {
+ if (null == packageName) return null;
+ return sCache.get(packageName);
+ }
+ public static void removeApplicationInfoCache(final String packageName) {
+ sCache.remove(packageName);
+ }
+
+ public interface OnTargetApplicationKnownListener {
+ public void onTargetApplicationKnown(final ApplicationInfo info);
+ }
+
+ private Context mContext;
+ private final OnTargetApplicationKnownListener mListener;
+
+ public TargetApplicationGetter(final Context context,
+ final OnTargetApplicationKnownListener listener) {
+ mContext = context;
+ mListener = listener;
+ }
+
+ @Override
+ protected ApplicationInfo doInBackground(final String... packageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ mContext = null; // Bazooka-powered anti-leak device
+ try {
+ final ApplicationInfo targetAppInfo =
+ pm.getApplicationInfo(packageName[0], 0 /* flags */);
+ sCache.put(packageName[0], targetAppInfo);
+ return targetAppInfo;
+ } catch (android.content.pm.PackageManager.NameNotFoundException e) {
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(final ApplicationInfo info) {
+ mListener.onTargetApplicationKnown(info);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
deleted file mode 100644
index de13f3ae4..000000000
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import com.android.inputmethod.latin.Utils.RingCharBuffer;
-
-import android.util.Log;
-
-public class TextEntryState {
- private static final String TAG = TextEntryState.class.getSimpleName();
- private static final boolean DEBUG = false;
-
- private static final int UNKNOWN = 0;
- private static final int START = 1;
- private static final int IN_WORD = 2;
- private static final int ACCEPTED_DEFAULT = 3;
- private static final int PICKED_SUGGESTION = 4;
- private static final int PUNCTUATION_AFTER_WORD = 5;
- private static final int PUNCTUATION_AFTER_ACCEPTED = 6;
- private static final int SPACE_AFTER_ACCEPTED = 7;
- private static final int SPACE_AFTER_PICKED = 8;
- private static final int UNDO_COMMIT = 9;
- private static final int RECORRECTING = 10;
- private static final int PICKED_RECORRECTION = 11;
-
- private static int sState = UNKNOWN;
- private static int sPreviousState = UNKNOWN;
-
- private static void setState(final int newState) {
- sPreviousState = sState;
- sState = newState;
- }
-
- public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord,
- int separatorCode) {
- if (typedWord == null) return;
- setState(ACCEPTED_DEFAULT);
- LatinImeLogger.logOnAutoCorrection(
- typedWord.toString(), actualWord.toString(), separatorCode);
- if (DEBUG)
- displayState("acceptedDefault", "typedWord", typedWord, "actualWord", actualWord);
- }
-
- // State.ACCEPTED_DEFAULT will be changed to other sub-states
- // (see "case ACCEPTED_DEFAULT" in typedCharacter() below),
- // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state.
- public static void backToAcceptedDefault(CharSequence typedWord) {
- if (typedWord == null) return;
- switch (sState) {
- case SPACE_AFTER_ACCEPTED:
- case PUNCTUATION_AFTER_ACCEPTED:
- case IN_WORD:
- setState(ACCEPTED_DEFAULT);
- break;
- default:
- break;
- }
- if (DEBUG) displayState("backToAcceptedDefault", "typedWord", typedWord);
- }
-
- public static void acceptedTyped(CharSequence typedWord) {
- setState(PICKED_SUGGESTION);
- if (DEBUG) displayState("acceptedTyped", "typedWord", typedWord);
- }
-
- public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
- if (sState == RECORRECTING || sState == PICKED_RECORRECTION) {
- setState(PICKED_RECORRECTION);
- } else {
- setState(PICKED_SUGGESTION);
- }
- if (DEBUG)
- displayState("acceptedSuggestion", "typedWord", typedWord, "actualWord", actualWord);
- }
-
- public static void selectedForRecorrection() {
- setState(RECORRECTING);
- if (DEBUG) displayState("selectedForRecorrection");
- }
-
- public static void onAbortRecorrection() {
- if (sState == RECORRECTING || sState == PICKED_RECORRECTION) {
- setState(START);
- }
- if (DEBUG) displayState("onAbortRecorrection");
- }
-
- public static void typedCharacter(char c, boolean isSeparator, int x, int y) {
- final boolean isSpace = (c == ' ');
- switch (sState) {
- case IN_WORD:
- if (isSpace || isSeparator) {
- setState(START);
- } else {
- // State hasn't changed.
- }
- break;
- case ACCEPTED_DEFAULT:
- case SPACE_AFTER_PICKED:
- case PUNCTUATION_AFTER_ACCEPTED:
- if (isSpace) {
- setState(SPACE_AFTER_ACCEPTED);
- } else if (isSeparator) {
- // Swap
- setState(PUNCTUATION_AFTER_ACCEPTED);
- } else {
- setState(IN_WORD);
- }
- break;
- case PICKED_SUGGESTION:
- case PICKED_RECORRECTION:
- if (isSpace) {
- setState(SPACE_AFTER_PICKED);
- } else if (isSeparator) {
- // Swap
- setState(PUNCTUATION_AFTER_ACCEPTED);
- } else {
- setState(IN_WORD);
- }
- break;
- case START:
- case UNKNOWN:
- case SPACE_AFTER_ACCEPTED:
- case PUNCTUATION_AFTER_WORD:
- if (!isSpace && !isSeparator) {
- setState(IN_WORD);
- } else {
- setState(START);
- }
- break;
- case UNDO_COMMIT:
- if (isSpace || isSeparator) {
- setState(ACCEPTED_DEFAULT);
- } else {
- setState(IN_WORD);
- }
- break;
- case RECORRECTING:
- setState(START);
- break;
- }
- RingCharBuffer.getInstance().push(c, x, y);
- if (isSeparator) {
- LatinImeLogger.logOnInputSeparator();
- } else {
- LatinImeLogger.logOnInputChar();
- }
- if (DEBUG) displayState("typedCharacter", "char", c, "isSeparator", isSeparator);
- }
-
- public static void backspace() {
- if (sState == ACCEPTED_DEFAULT) {
- setState(UNDO_COMMIT);
- LatinImeLogger.logOnAutoCorrectionCancelled();
- } else if (sState == UNDO_COMMIT) {
- setState(IN_WORD);
- }
- if (DEBUG) displayState("backspace");
- }
-
- public static void reset() {
- setState(START);
- if (DEBUG) displayState("reset");
- }
-
- public static boolean isAcceptedDefault() {
- return sState == ACCEPTED_DEFAULT;
- }
-
- public static boolean isSpaceAfterPicked() {
- return sState == SPACE_AFTER_PICKED;
- }
-
- public static boolean isUndoCommit() {
- return sState == UNDO_COMMIT;
- }
-
- public static boolean isPunctuationAfterAccepted() {
- return sState == PUNCTUATION_AFTER_ACCEPTED;
- }
-
- public static boolean isRecorrecting() {
- return sState == RECORRECTING || sState == PICKED_RECORRECTION;
- }
-
- public static String getState() {
- return stateName(sState);
- }
-
- private static String stateName(int state) {
- switch (state) {
- case START: return "START";
- case IN_WORD: return "IN_WORD";
- case ACCEPTED_DEFAULT: return "ACCEPTED_DEFAULT";
- case PICKED_SUGGESTION: return "PICKED_SUGGESTION";
- case PUNCTUATION_AFTER_WORD: return "PUNCTUATION_AFTER_WORD";
- case PUNCTUATION_AFTER_ACCEPTED: return "PUNCTUATION_AFTER_ACCEPTED";
- case SPACE_AFTER_ACCEPTED: return "SPACE_AFTER_ACCEPTED";
- case SPACE_AFTER_PICKED: return "SPACE_AFTER_PICKED";
- case UNDO_COMMIT: return "UNDO_COMMIT";
- case RECORRECTING: return "RECORRECTING";
- case PICKED_RECORRECTION: return "PICKED_RECORRECTION";
- default: return "UNKNOWN";
- }
- }
-
- private static void displayState(String title, Object ... args) {
- final StringBuilder sb = new StringBuilder(title);
- sb.append(':');
- for (int i = 0; i < args.length; i += 2) {
- sb.append(' ');
- sb.append(args[i]);
- sb.append('=');
- sb.append(args[i+1].toString());
- }
- sb.append(" state=");
- sb.append(stateName(sState));
- sb.append(" previous=");
- sb.append(stateName(sPreviousState));
- Log.d(TAG, sb.toString());
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
deleted file mode 100644
index 5b615ca29..000000000
--- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.os.AsyncTask;
-import android.provider.BaseColumns;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-
-/**
- * Stores all the pairs user types in databases. Prune the database if the size
- * gets too big. Unlike AutoDictionary, it even stores the pairs that are already
- * in the dictionary.
- */
-public class UserBigramDictionary extends ExpandableDictionary {
- private static final String TAG = "UserBigramDictionary";
-
- /** Any pair being typed or picked */
- private static final int FREQUENCY_FOR_TYPED = 2;
-
- /** Maximum frequency for all pairs */
- private static final int FREQUENCY_MAX = 127;
-
- /** Maximum number of pairs. Pruning will start when databases goes above this number. */
- private static int sMaxUserBigrams = 10000;
-
- /**
- * When it hits maximum bigram pair, it will delete until you are left with
- * only (sMaxUserBigrams - sDeleteUserBigrams) pairs.
- * Do not keep this number small to avoid deleting too often.
- */
- private static int sDeleteUserBigrams = 1000;
-
- /**
- * Database version should increase if the database structure changes
- */
- private static final int DATABASE_VERSION = 1;
-
- private static final String DATABASE_NAME = "userbigram_dict.db";
-
- /** Name of the words table in the database */
- private static final String MAIN_TABLE_NAME = "main";
- // TODO: Consume less space by using a unique id for locale instead of the whole
- // 2-5 character string. (Same TODO from AutoDictionary)
- private static final String MAIN_COLUMN_ID = BaseColumns._ID;
- private static final String MAIN_COLUMN_WORD1 = "word1";
- private static final String MAIN_COLUMN_WORD2 = "word2";
- private static final String MAIN_COLUMN_LOCALE = "locale";
-
- /** Name of the frequency table in the database */
- private static final String FREQ_TABLE_NAME = "frequency";
- private static final String FREQ_COLUMN_ID = BaseColumns._ID;
- private static final String FREQ_COLUMN_PAIR_ID = "pair_id";
- private static final String FREQ_COLUMN_FREQUENCY = "freq";
-
- private final LatinIME mIme;
-
- /** Locale for which this auto dictionary is storing words */
- private String mLocale;
-
- private HashSet<Bigram> mPendingWrites = new HashSet<Bigram>();
- private final Object mPendingWritesLock = new Object();
- private static volatile boolean sUpdatingDB = false;
-
- private final static HashMap<String, String> sDictProjectionMap;
-
- static {
- sDictProjectionMap = new HashMap<String, String>();
- sDictProjectionMap.put(MAIN_COLUMN_ID, MAIN_COLUMN_ID);
- sDictProjectionMap.put(MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD1);
- sDictProjectionMap.put(MAIN_COLUMN_WORD2, MAIN_COLUMN_WORD2);
- sDictProjectionMap.put(MAIN_COLUMN_LOCALE, MAIN_COLUMN_LOCALE);
-
- sDictProjectionMap.put(FREQ_COLUMN_ID, FREQ_COLUMN_ID);
- sDictProjectionMap.put(FREQ_COLUMN_PAIR_ID, FREQ_COLUMN_PAIR_ID);
- sDictProjectionMap.put(FREQ_COLUMN_FREQUENCY, FREQ_COLUMN_FREQUENCY);
- }
-
- private static DatabaseHelper sOpenHelper = null;
-
- private static class Bigram {
- public final String mWord1;
- public final String mWord2;
- public final int frequency;
-
- Bigram(String word1, String word2, int frequency) {
- this.mWord1 = word1;
- this.mWord2 = word2;
- this.frequency = frequency;
- }
-
- @Override
- public boolean equals(Object bigram) {
- Bigram bigram2 = (Bigram) bigram;
- return (mWord1.equals(bigram2.mWord1) && mWord2.equals(bigram2.mWord2));
- }
-
- @Override
- public int hashCode() {
- return (mWord1 + " " + mWord2).hashCode();
- }
- }
-
- public void setDatabaseMax(int maxUserBigram) {
- sMaxUserBigrams = maxUserBigram;
- }
-
- public void setDatabaseDelete(int deleteUserBigram) {
- sDeleteUserBigrams = deleteUserBigram;
- }
-
- public UserBigramDictionary(Context context, LatinIME ime, String locale, int dicTypeId) {
- super(context, dicTypeId);
- mIme = ime;
- mLocale = locale;
- if (sOpenHelper == null) {
- sOpenHelper = new DatabaseHelper(getContext());
- }
- if (mLocale != null && mLocale.length() > 1) {
- loadDictionary();
- }
- }
-
- @Override
- public void close() {
- flushPendingWrites();
- // Don't close the database as locale changes will require it to be reopened anyway
- // Also, the database is written to somewhat frequently, so it needs to be kept alive
- // throughout the life of the process.
- // mOpenHelper.close();
- super.close();
- }
-
- /**
- * Pair will be added to the userbigram database.
- */
- public int addBigrams(String word1, String word2) {
- // remove caps if second word is autocapitalized
- if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) {
- word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1);
- }
- // Do not insert a word as a bigram of itself
- if (word1.equals(word2)) {
- return 0;
- }
-
- int freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED);
- if (freq > FREQUENCY_MAX) freq = FREQUENCY_MAX;
- synchronized (mPendingWritesLock) {
- if (freq == FREQUENCY_FOR_TYPED || mPendingWrites.isEmpty()) {
- mPendingWrites.add(new Bigram(word1, word2, freq));
- } else {
- Bigram bi = new Bigram(word1, word2, freq);
- mPendingWrites.remove(bi);
- mPendingWrites.add(bi);
- }
- }
-
- return freq;
- }
-
- /**
- * Schedules a background thread to write any pending words to the database.
- */
- public void flushPendingWrites() {
- synchronized (mPendingWritesLock) {
- // Nothing pending? Return
- if (mPendingWrites.isEmpty()) return;
- // Create a background thread to write the pending entries
- new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute();
- // Create a new map for writing new entries into while the old one is written to db
- mPendingWrites = new HashSet<Bigram>();
- }
- }
-
- /** Used for testing purpose **/
- void waitUntilUpdateDBDone() {
- synchronized (mPendingWritesLock) {
- while (sUpdatingDB) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- }
- }
- return;
- }
- }
-
- @Override
- public void loadDictionaryAsync() {
- // Load the words that correspond to the current input locale
- Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale });
- try {
- if (cursor.moveToFirst()) {
- int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1);
- int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2);
- int frequencyIndex = cursor.getColumnIndex(FREQ_COLUMN_FREQUENCY);
- while (!cursor.isAfterLast()) {
- String word1 = cursor.getString(word1Index);
- String word2 = cursor.getString(word2Index);
- int frequency = cursor.getInt(frequencyIndex);
- // Safeguard against adding really long words. Stack may overflow due
- // to recursive lookup
- if (word1.length() < MAX_WORD_LENGTH && word2.length() < MAX_WORD_LENGTH) {
- super.setBigram(word1, word2, frequency);
- }
- cursor.moveToNext();
- }
- }
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Query the database
- */
- private Cursor query(String selection, String[] selectionArgs) {
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
-
- // main INNER JOIN frequency ON (main._id=freq.pair_id)
- qb.setTables(MAIN_TABLE_NAME + " INNER JOIN " + FREQ_TABLE_NAME + " ON ("
- + MAIN_TABLE_NAME + "." + MAIN_COLUMN_ID + "=" + FREQ_TABLE_NAME + "."
- + FREQ_COLUMN_PAIR_ID +")");
-
- qb.setProjectionMap(sDictProjectionMap);
-
- // Get the database and run the query
- SQLiteDatabase db = sOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db,
- new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY },
- selection, selectionArgs, null, null, null);
- return c;
- }
-
- /**
- * This class helps open, create, and upgrade the database file.
- */
- private static class DatabaseHelper extends SQLiteOpenHelper {
-
- DatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("PRAGMA foreign_keys = ON;");
- db.execSQL("CREATE TABLE " + MAIN_TABLE_NAME + " ("
- + MAIN_COLUMN_ID + " INTEGER PRIMARY KEY,"
- + MAIN_COLUMN_WORD1 + " TEXT,"
- + MAIN_COLUMN_WORD2 + " TEXT,"
- + MAIN_COLUMN_LOCALE + " TEXT"
- + ");");
- db.execSQL("CREATE TABLE " + FREQ_TABLE_NAME + " ("
- + FREQ_COLUMN_ID + " INTEGER PRIMARY KEY,"
- + FREQ_COLUMN_PAIR_ID + " INTEGER,"
- + FREQ_COLUMN_FREQUENCY + " INTEGER,"
- + "FOREIGN KEY(" + FREQ_COLUMN_PAIR_ID + ") REFERENCES " + MAIN_TABLE_NAME
- + "(" + MAIN_COLUMN_ID + ")" + " ON DELETE CASCADE"
- + ");");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
- + newVersion + ", which will destroy all old data");
- db.execSQL("DROP TABLE IF EXISTS " + MAIN_TABLE_NAME);
- db.execSQL("DROP TABLE IF EXISTS " + FREQ_TABLE_NAME);
- onCreate(db);
- }
- }
-
- /**
- * Async task to write pending words to the database so that it stays in sync with
- * the in-memory trie.
- */
- private static class UpdateDbTask extends AsyncTask<Void, Void, Void> {
- private final HashSet<Bigram> mMap;
- private final DatabaseHelper mDbHelper;
- private final String mLocale;
-
- public UpdateDbTask(Context context, DatabaseHelper openHelper,
- HashSet<Bigram> pendingWrites, String locale) {
- mMap = pendingWrites;
- mLocale = locale;
- mDbHelper = openHelper;
- }
-
- /** Prune any old data if the database is getting too big. */
- private void checkPruneData(SQLiteDatabase db) {
- db.execSQL("PRAGMA foreign_keys = ON;");
- Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID },
- null, null, null, null, null);
- try {
- int totalRowCount = c.getCount();
- // prune out old data if we have too much data
- if (totalRowCount > sMaxUserBigrams) {
- int numDeleteRows = (totalRowCount - sMaxUserBigrams) + sDeleteUserBigrams;
- int pairIdColumnId = c.getColumnIndex(FREQ_COLUMN_PAIR_ID);
- c.moveToFirst();
- int count = 0;
- while (count < numDeleteRows && !c.isAfterLast()) {
- String pairId = c.getString(pairIdColumnId);
- // Deleting from MAIN table will delete the frequencies
- // due to FOREIGN KEY .. ON DELETE CASCADE
- db.delete(MAIN_TABLE_NAME, MAIN_COLUMN_ID + "=?",
- new String[] { pairId });
- c.moveToNext();
- count++;
- }
- }
- } finally {
- c.close();
- }
- }
-
- @Override
- protected void onPreExecute() {
- sUpdatingDB = true;
- }
-
- @Override
- protected Void doInBackground(Void... v) {
- SQLiteDatabase db = mDbHelper.getWritableDatabase();
- db.execSQL("PRAGMA foreign_keys = ON;");
- // Write all the entries to the db
- Iterator<Bigram> iterator = mMap.iterator();
- while (iterator.hasNext()) {
- Bigram bi = iterator.next();
-
- // find pair id
- Cursor c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID },
- MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND "
- + MAIN_COLUMN_LOCALE + "=?",
- new String[] { bi.mWord1, bi.mWord2, mLocale }, null, null, null);
-
- int pairId;
- if (c.moveToFirst()) {
- // existing pair
- pairId = c.getInt(c.getColumnIndex(MAIN_COLUMN_ID));
- db.delete(FREQ_TABLE_NAME, FREQ_COLUMN_PAIR_ID + "=?",
- new String[] { Integer.toString(pairId) });
- } else {
- // new pair
- Long pairIdLong = db.insert(MAIN_TABLE_NAME, null,
- getContentValues(bi.mWord1, bi.mWord2, mLocale));
- pairId = pairIdLong.intValue();
- }
- c.close();
-
- // insert new frequency
- db.insert(FREQ_TABLE_NAME, null, getFrequencyContentValues(pairId, bi.frequency));
- }
- checkPruneData(db);
- sUpdatingDB = false;
-
- return null;
- }
-
- private ContentValues getContentValues(String word1, String word2, String locale) {
- ContentValues values = new ContentValues(3);
- values.put(MAIN_COLUMN_WORD1, word1);
- values.put(MAIN_COLUMN_WORD2, word2);
- values.put(MAIN_COLUMN_LOCALE, locale);
- return values;
- }
-
- private ContentValues getFrequencyContentValues(int pairId, int frequency) {
- ContentValues values = new ContentValues(2);
- values.put(FREQ_COLUMN_PAIR_ID, pairId);
- values.put(FREQ_COLUMN_FREQUENCY, frequency);
- return values;
- }
- }
-
-}
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
new file mode 100644
index 000000000..5bcdb57b5
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.provider.UserDictionary.Words;
+import android.text.TextUtils;
+
+import java.util.Arrays;
+
+/**
+ * An expandable dictionary that stores the words in the user unigram dictionary.
+ *
+ * Largely a copy of UserDictionary, will replace that class in the future.
+ */
+public class UserBinaryDictionary extends ExpandableBinaryDictionary {
+
+ // TODO: use Words.SHORTCUT when it's public in the SDK
+ final static String SHORTCUT = "shortcut";
+ private static final String[] PROJECTION_QUERY;
+ static {
+ // 16 is JellyBean, but we want this to compile against ICS.
+ if (android.os.Build.VERSION.SDK_INT >= 16) {
+ PROJECTION_QUERY = new String[] {
+ Words.WORD,
+ SHORTCUT,
+ Words.FREQUENCY,
+ };
+ } else {
+ PROJECTION_QUERY = new String[] {
+ Words.WORD,
+ Words.FREQUENCY,
+ };
+ }
+ }
+
+ private static final String NAME = "userunigram";
+
+ // This is not exported by the framework so we pretty much have to write it here verbatim
+ private static final String ACTION_USER_DICTIONARY_INSERT =
+ "com.android.settings.USER_DICTIONARY_INSERT";
+
+ private ContentObserver mObserver;
+ final private String mLocale;
+ final private boolean mAlsoUseMoreRestrictiveLocales;
+
+ public UserBinaryDictionary(final Context context, final String locale) {
+ this(context, locale, false);
+ }
+
+ public UserBinaryDictionary(final Context context, final String locale,
+ final boolean alsoUseMoreRestrictiveLocales) {
+ super(context, getFilenameWithLocale(NAME, locale), Suggest.DIC_USER);
+ if (null == locale) throw new NullPointerException(); // Catch the error earlier
+ mLocale = locale;
+ mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
+ // Perform a managed query. The Activity will handle closing and re-querying the cursor
+ // when needed.
+ ContentResolver cres = context.getContentResolver();
+
+ mObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean self) {
+ setRequiresReload(true);
+ }
+ };
+ cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
+
+ loadDictionary();
+ }
+
+ @Override
+ public synchronized void close() {
+ if (mObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ mObserver = null;
+ }
+ super.close();
+ }
+
+ @Override
+ public void loadDictionaryAsync() {
+ // Split the locale. For example "en" => ["en"], "de_DE" => ["de", "DE"],
+ // "en_US_foo_bar_qux" => ["en", "US", "foo_bar_qux"] because of the limit of 3.
+ // This is correct for locale processing.
+ // For this example, we'll look at the "en_US_POSIX" case.
+ final String[] localeElements =
+ TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3);
+ final int length = localeElements.length;
+
+ final StringBuilder request = new StringBuilder("(locale is NULL)");
+ String localeSoFar = "";
+ // At start, localeElements = ["en", "US", "POSIX"] ; localeSoFar = "" ;
+ // and request = "(locale is NULL)"
+ for (int i = 0; i < length; ++i) {
+ // i | localeSoFar | localeElements
+ // 0 | "" | ["en", "US", "POSIX"]
+ // 1 | "en_" | ["en", "US", "POSIX"]
+ // 2 | "en_US_" | ["en", "en_US", "POSIX"]
+ localeElements[i] = localeSoFar + localeElements[i];
+ localeSoFar = localeElements[i] + "_";
+ // i | request
+ // 0 | "(locale is NULL)"
+ // 1 | "(locale is NULL) or (locale=?)"
+ // 2 | "(locale is NULL) or (locale=?) or (locale=?)"
+ request.append(" or (locale=?)");
+ }
+ // At the end, localeElements = ["en", "en_US", "en_US_POSIX"]; localeSoFar = en_US_POSIX_"
+ // and request = "(locale is NULL) or (locale=?) or (locale=?) or (locale=?)"
+
+ final String[] requestArguments;
+ // If length == 3, we already have all the arguments we need (common prefix is meaningless
+ // inside variants
+ if (mAlsoUseMoreRestrictiveLocales && length < 3) {
+ request.append(" or (locale like ?)");
+ // The following creates an array with one more (null) position
+ final String[] localeElementsWithMoreRestrictiveLocalesIncluded =
+ Arrays.copyOf(localeElements, length + 1);
+ localeElementsWithMoreRestrictiveLocalesIncluded[length] =
+ localeElements[length - 1] + "_%";
+ requestArguments = localeElementsWithMoreRestrictiveLocalesIncluded;
+ // If for example localeElements = ["en"]
+ // then requestArguments = ["en", "en_%"]
+ // and request = (locale is NULL) or (locale=?) or (locale like ?)
+ // If localeElements = ["en", "en_US"]
+ // then requestArguments = ["en", "en_US", "en_US_%"]
+ } else {
+ requestArguments = localeElements;
+ }
+ final Cursor cursor = mContext.getContentResolver().query(
+ Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null);
+ try {
+ addWords(cursor);
+ } finally {
+ if (null != cursor) cursor.close();
+ }
+ }
+
+ public boolean isEnabled() {
+ final ContentResolver cr = mContext.getContentResolver();
+ final ContentProviderClient client = cr.acquireContentProviderClient(Words.CONTENT_URI);
+ if (client != null) {
+ client.release();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Adds a word to the user dictionary and makes it persistent.
+ *
+ * This will call upon the system interface to do the actual work through the intent readied by
+ * the system to this effect.
+ *
+ * @param word the word to add. If the word is capitalized, then the dictionary will
+ * recognize it as a capitalized word when searched.
+ * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
+ * the highest.
+ * @TODO use a higher or float range for frequency
+ */
+ public synchronized void addWordToUserDictionary(final String word, final int frequency) {
+ // TODO: do something for the UI. With the following, any sufficiently long word will
+ // look like it will go to the user dictionary but it won't.
+ // Safeguard against adding long words. Can cause stack overflow.
+ if (word.length() >= MAX_WORD_LENGTH) return;
+
+ // TODO: Add an argument to the intent to specify the frequency.
+ Intent intent = new Intent(ACTION_USER_DICTIONARY_INSERT);
+ intent.putExtra(Words.WORD, word);
+ intent.putExtra(Words.LOCALE, mLocale);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ }
+
+ private void addWords(Cursor cursor) {
+ // 16 is JellyBean, but we want this to compile against ICS.
+ final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16;
+ clearFusionDictionary();
+ if (cursor == null) return;
+ if (cursor.moveToFirst()) {
+ final int indexWord = cursor.getColumnIndex(Words.WORD);
+ final int indexShortcut = hasShortcutColumn ? cursor.getColumnIndex(SHORTCUT) : 0;
+ final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
+ while (!cursor.isAfterLast()) {
+ final String word = cursor.getString(indexWord);
+ final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null;
+ final int frequency = cursor.getInt(indexFrequency);
+ // Safeguard against adding really long words.
+ if (word.length() < MAX_WORD_LENGTH) {
+ super.addWord(word, null, frequency);
+ }
+ if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) {
+ super.addWord(shortcut, word, frequency);
+ }
+ cursor.moveToNext();
+ }
+ }
+ }
+
+ @Override
+ protected boolean hasContentChanged() {
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
deleted file mode 100644
index c06bd736e..000000000
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.UserDictionary.Words;
-
-public class UserDictionary extends ExpandableDictionary {
-
- private static final String[] PROJECTION_QUERY = {
- Words.WORD,
- Words.FREQUENCY,
- };
-
- private static final String[] PROJECTION_ADD = {
- Words._ID,
- Words.FREQUENCY,
- Words.LOCALE,
- };
-
- private ContentObserver mObserver;
- private String mLocale;
-
- public UserDictionary(Context context, String locale) {
- super(context, Suggest.DIC_USER);
- mLocale = locale;
- // Perform a managed query. The Activity will handle closing and requerying the cursor
- // when needed.
- ContentResolver cres = context.getContentResolver();
-
- cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean self) {
- setRequiresReload(true);
- }
- });
-
- loadDictionary();
- }
-
- @Override
- public synchronized void close() {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- super.close();
- }
-
- @Override
- public void loadDictionaryAsync() {
- Cursor cursor = getContext().getContentResolver()
- .query(Words.CONTENT_URI, PROJECTION_QUERY, "(locale IS NULL) or (locale=?)",
- new String[] { mLocale }, null);
- addWords(cursor);
- }
-
- /**
- * Adds a word to the dictionary and makes it persistent.
- * @param word the word to add. If the word is capitalized, then the dictionary will
- * recognize it as a capitalized word when searched.
- * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
- * the highest.
- * @TODO use a higher or float range for frequency
- */
- @Override
- public synchronized void addWord(final String word, final int frequency) {
- // Force load the dictionary here synchronously
- if (getRequiresReload()) loadDictionaryAsync();
- // Safeguard against adding long words. Can cause stack overflow.
- if (word.length() >= getMaxWordLength()) return;
-
- super.addWord(word, frequency);
-
- // Update the user dictionary provider
- final ContentValues values = new ContentValues(5);
- values.put(Words.WORD, word);
- values.put(Words.FREQUENCY, frequency);
- values.put(Words.LOCALE, mLocale);
- values.put(Words.APP_ID, 0);
-
- final ContentResolver contentResolver = getContext().getContentResolver();
- new Thread("addWord") {
- @Override
- public void run() {
- Cursor cursor = contentResolver.query(Words.CONTENT_URI, PROJECTION_ADD,
- "word=? and ((locale IS NULL) or (locale=?))",
- new String[] { word, mLocale }, null);
- if (cursor != null && cursor.moveToFirst()) {
- String locale = cursor.getString(cursor.getColumnIndex(Words.LOCALE));
- // If locale is null, we will not override the entry.
- if (locale != null && locale.equals(mLocale.toString())) {
- long id = cursor.getLong(cursor.getColumnIndex(Words._ID));
- Uri uri = Uri.withAppendedPath(Words.CONTENT_URI, Long.toString(id));
- // Update the entry with new frequency value.
- contentResolver.update(uri, values, null, null);
- }
- } else {
- // Insert new entry.
- contentResolver.insert(Words.CONTENT_URI, values);
- }
- }
- }.start();
-
- // In case the above does a synchronous callback of the change observer
- setRequiresReload(false);
- }
-
- @Override
- public synchronized void getWords(final WordComposer codes, final WordCallback callback) {
- super.getWords(codes, callback);
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- return super.isValidWord(word);
- }
-
- private void addWords(Cursor cursor) {
- clearDictionary();
- if (cursor == null) return;
- final int maxWordLength = getMaxWordLength();
- if (cursor.moveToFirst()) {
- final int indexWord = cursor.getColumnIndex(Words.WORD);
- final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
- while (!cursor.isAfterLast()) {
- String word = cursor.getString(indexWord);
- int frequency = cursor.getInt(indexFrequency);
- // Safeguard against adding really long words. Stack may overflow due
- // to recursion
- if (word.length() < maxWordLength) {
- super.addWord(word, frequency);
- }
- cursor.moveToNext();
- }
- }
- cursor.close();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
new file mode 100644
index 000000000..5095f6582
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.os.AsyncTask;
+import android.provider.BaseColumns;
+import android.util.Log;
+
+import com.android.inputmethod.latin.UserHistoryForgettingCurveUtils.ForgettingCurveParams;
+
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Locally gathers stats about the words user types and various other signals like auto-correction
+ * cancellation or manual picks. This allows the keyboard to adapt to the typist over time.
+ */
+public class UserHistoryDictionary extends ExpandableDictionary {
+ private static final String TAG = "UserHistoryDictionary";
+ public static final boolean DBG_SAVE_RESTORE = false;
+ public static final boolean DBG_STRESS_TEST = false;
+ public static final boolean DBG_ALWAYS_WRITE = false;
+ public static final boolean PROFILE_SAVE_RESTORE = LatinImeLogger.sDBG;
+
+ /** Any pair being typed or picked */
+ private static final int FREQUENCY_FOR_TYPED = 2;
+
+ /** Maximum number of pairs. Pruning will start when databases goes above this number. */
+ private static int sMaxHistoryBigrams = 10000;
+
+ /**
+ * When it hits maximum bigram pair, it will delete until you are left with
+ * only (sMaxHistoryBigrams - sDeleteHistoryBigrams) pairs.
+ * Do not keep this number small to avoid deleting too often.
+ */
+ private static int sDeleteHistoryBigrams = 1000;
+
+ /**
+ * Database version should increase if the database structure changes
+ */
+ private static final int DATABASE_VERSION = 1;
+
+ private static final String DATABASE_NAME = "userbigram_dict.db";
+
+ /** Name of the words table in the database */
+ private static final String MAIN_TABLE_NAME = "main";
+ // TODO: Consume less space by using a unique id for locale instead of the whole
+ // 2-5 character string.
+ private static final String MAIN_COLUMN_ID = BaseColumns._ID;
+ private static final String MAIN_COLUMN_WORD1 = "word1";
+ private static final String MAIN_COLUMN_WORD2 = "word2";
+ private static final String MAIN_COLUMN_LOCALE = "locale";
+
+ /** Name of the frequency table in the database */
+ private static final String FREQ_TABLE_NAME = "frequency";
+ private static final String FREQ_COLUMN_ID = BaseColumns._ID;
+ private static final String FREQ_COLUMN_PAIR_ID = "pair_id";
+ private static final String COLUMN_FORGETTING_CURVE_VALUE = "freq";
+
+ /** Locale for which this user history dictionary is storing words */
+ private final String mLocale;
+
+ private final UserHistoryDictionaryBigramList mBigramList =
+ new UserHistoryDictionaryBigramList();
+ private final ReentrantLock mBigramListLock = new ReentrantLock();
+ private final SharedPreferences mPrefs;
+
+ private final static HashMap<String, String> sDictProjectionMap;
+ private final static ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>
+ sLangDictCache = new ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>();
+
+ static {
+ sDictProjectionMap = new HashMap<String, String>();
+ sDictProjectionMap.put(MAIN_COLUMN_ID, MAIN_COLUMN_ID);
+ sDictProjectionMap.put(MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD1);
+ sDictProjectionMap.put(MAIN_COLUMN_WORD2, MAIN_COLUMN_WORD2);
+ sDictProjectionMap.put(MAIN_COLUMN_LOCALE, MAIN_COLUMN_LOCALE);
+
+ sDictProjectionMap.put(FREQ_COLUMN_ID, FREQ_COLUMN_ID);
+ sDictProjectionMap.put(FREQ_COLUMN_PAIR_ID, FREQ_COLUMN_PAIR_ID);
+ sDictProjectionMap.put(COLUMN_FORGETTING_CURVE_VALUE, COLUMN_FORGETTING_CURVE_VALUE);
+ }
+
+ private static DatabaseHelper sOpenHelper = null;
+
+ public void setDatabaseMax(int maxHistoryBigram) {
+ sMaxHistoryBigrams = maxHistoryBigram;
+ }
+
+ public void setDatabaseDelete(int deleteHistoryBigram) {
+ sDeleteHistoryBigrams = deleteHistoryBigram;
+ }
+
+ public synchronized static UserHistoryDictionary getInstance(
+ final Context context, final String locale,
+ final int dictTypeId, final SharedPreferences sp) {
+ if (sLangDictCache.containsKey(locale)) {
+ final SoftReference<UserHistoryDictionary> ref = sLangDictCache.get(locale);
+ final UserHistoryDictionary dict = ref == null ? null : ref.get();
+ if (dict != null) {
+ if (PROFILE_SAVE_RESTORE) {
+ Log.w(TAG, "Use cached UserHistoryDictionary for " + locale);
+ }
+ return dict;
+ }
+ }
+ final UserHistoryDictionary dict =
+ new UserHistoryDictionary(context, locale, dictTypeId, sp);
+ sLangDictCache.put(locale, new SoftReference<UserHistoryDictionary>(dict));
+ return dict;
+ }
+
+ private UserHistoryDictionary(final Context context, final String locale, final int dicTypeId,
+ SharedPreferences sp) {
+ super(context, dicTypeId);
+ mLocale = locale;
+ mPrefs = sp;
+ if (sOpenHelper == null) {
+ sOpenHelper = new DatabaseHelper(getContext());
+ }
+ if (mLocale != null && mLocale.length() > 1) {
+ loadDictionary();
+ }
+ }
+
+ @Override
+ public void close() {
+ flushPendingWrites();
+ // Don't close the database as locale changes will require it to be reopened anyway
+ // Also, the database is written to somewhat frequently, so it needs to be kept alive
+ // throughout the life of the process.
+ // mOpenHelper.close();
+ // Ignore close because we cache UserHistoryDictionary for each language. See getInstance()
+ // above.
+ // super.close();
+ }
+
+ /**
+ * Return whether the passed charsequence is in the dictionary.
+ */
+ @Override
+ public synchronized boolean isValidWord(final CharSequence word) {
+ // TODO: figure out what is the correct thing to do here.
+ return false;
+ }
+
+ /**
+ * Pair will be added to the user history dictionary.
+ *
+ * The first word may be null. That means we don't know the context, in other words,
+ * it's only a unigram. The first word may also be an empty string : this means start
+ * context, as in beginning of a sentence for example.
+ * The second word may not be null (a NullPointerException would be thrown).
+ */
+ public int addToUserHistory(final String word1, String word2, boolean isValid) {
+ if (mBigramListLock.tryLock()) {
+ try {
+ super.addWord(
+ word2, null /* the "shortcut" parameter is null */, FREQUENCY_FOR_TYPED);
+ // Do not insert a word as a bigram of itself
+ if (word2.equals(word1)) {
+ return 0;
+ }
+ final int freq;
+ if (null == word1) {
+ freq = FREQUENCY_FOR_TYPED;
+ } else {
+ freq = super.setBigramAndGetFrequency(
+ word1, word2, new ForgettingCurveParams(isValid));
+ }
+ mBigramList.addBigram(word1, word2);
+ return freq;
+ } finally {
+ mBigramListLock.unlock();
+ }
+ }
+ return -1;
+ }
+
+ public boolean cancelAddingUserHistory(String word1, String word2) {
+ if (mBigramListLock.tryLock()) {
+ try {
+ if (mBigramList.removeBigram(word1, word2)) {
+ return super.removeBigram(word1, word2);
+ }
+ } finally {
+ mBigramListLock.unlock();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Schedules a background thread to write any pending words to the database.
+ */
+ private void flushPendingWrites() {
+ if (mBigramListLock.isLocked()) {
+ return;
+ }
+ // Create a background thread to write the pending entries
+ new UpdateDbTask(sOpenHelper, mBigramList, mLocale, this, mPrefs).execute();
+ }
+
+ @Override
+ public void loadDictionaryAsync() {
+ // This must be run on non-main thread
+ mBigramListLock.lock();
+ try {
+ loadDictionaryAsyncLocked();
+ } finally {
+ mBigramListLock.unlock();
+ }
+ }
+
+ private void loadDictionaryAsyncLocked() {
+ if (DBG_STRESS_TEST) {
+ try {
+ Log.w(TAG, "Start stress in loading: " + mLocale);
+ Thread.sleep(15000);
+ Log.w(TAG, "End stress in loading");
+ } catch (InterruptedException e) {
+ }
+ }
+ final long last = SettingsValues.getLastUserHistoryWriteTime(mPrefs, mLocale);
+ final boolean initializing = last == 0;
+ final long now = System.currentTimeMillis();
+ // Load the words that correspond to the current input locale
+ final Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale });
+ if (null == cursor) return;
+ try {
+ // TODO: Call SQLiteDataBase.beginTransaction / SQLiteDataBase.endTransaction
+ if (cursor.moveToFirst()) {
+ final int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1);
+ final int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2);
+ final int fcIndex = cursor.getColumnIndex(COLUMN_FORGETTING_CURVE_VALUE);
+ while (!cursor.isAfterLast()) {
+ final String word1 = cursor.getString(word1Index);
+ final String word2 = cursor.getString(word2Index);
+ final int fc = cursor.getInt(fcIndex);
+ if (DBG_SAVE_RESTORE) {
+ Log.d(TAG, "--- Load user history: " + word1 + ", " + word2 + ","
+ + mLocale + "," + this);
+ }
+ // Safeguard against adding really long words. Stack may overflow due
+ // to recursive lookup
+ if (null == word1) {
+ super.addWord(word2, null /* shortcut */, fc);
+ } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH
+ && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) {
+ super.setBigramAndGetFrequency(
+ word1, word2, initializing ? new ForgettingCurveParams(true)
+ : new ForgettingCurveParams(fc, now, last));
+ }
+ mBigramList.addBigram(word1, word2, (byte)fc);
+ cursor.moveToNext();
+ }
+ }
+ } finally {
+ cursor.close();
+ if (PROFILE_SAVE_RESTORE) {
+ final long diff = System.currentTimeMillis() - now;
+ Log.w(TAG, "PROF: Load User HistoryDictionary: "
+ + mLocale + ", " + diff + "ms.");
+ }
+ }
+ }
+
+ /**
+ * Query the database
+ */
+ private static Cursor query(String selection, String[] selectionArgs) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+ // main INNER JOIN frequency ON (main._id=freq.pair_id)
+ qb.setTables(MAIN_TABLE_NAME + " INNER JOIN " + FREQ_TABLE_NAME + " ON ("
+ + MAIN_TABLE_NAME + "." + MAIN_COLUMN_ID + "=" + FREQ_TABLE_NAME + "."
+ + FREQ_COLUMN_PAIR_ID +")");
+
+ qb.setProjectionMap(sDictProjectionMap);
+
+ // Get the database and run the query
+ try {
+ SQLiteDatabase db = sOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db,
+ new String[] {
+ MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, COLUMN_FORGETTING_CURVE_VALUE },
+ selection, selectionArgs, null, null, null);
+ return c;
+ } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
+ // Can't open the database : presumably we can't access storage. That may happen
+ // when the device is wedged; do a best effort to still start the keyboard.
+ return null;
+ }
+ }
+
+ /**
+ * This class helps open, create, and upgrade the database file.
+ */
+ private static class DatabaseHelper extends SQLiteOpenHelper {
+
+ DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("PRAGMA foreign_keys = ON;");
+ db.execSQL("CREATE TABLE " + MAIN_TABLE_NAME + " ("
+ + MAIN_COLUMN_ID + " INTEGER PRIMARY KEY,"
+ + MAIN_COLUMN_WORD1 + " TEXT,"
+ + MAIN_COLUMN_WORD2 + " TEXT,"
+ + MAIN_COLUMN_LOCALE + " TEXT"
+ + ");");
+ db.execSQL("CREATE TABLE " + FREQ_TABLE_NAME + " ("
+ + FREQ_COLUMN_ID + " INTEGER PRIMARY KEY,"
+ + FREQ_COLUMN_PAIR_ID + " INTEGER,"
+ + COLUMN_FORGETTING_CURVE_VALUE + " INTEGER,"
+ + "FOREIGN KEY(" + FREQ_COLUMN_PAIR_ID + ") REFERENCES " + MAIN_TABLE_NAME
+ + "(" + MAIN_COLUMN_ID + ")" + " ON DELETE CASCADE"
+ + ");");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ + newVersion + ", which will destroy all old data");
+ db.execSQL("DROP TABLE IF EXISTS " + MAIN_TABLE_NAME);
+ db.execSQL("DROP TABLE IF EXISTS " + FREQ_TABLE_NAME);
+ onCreate(db);
+ }
+ }
+
+ /**
+ * Async task to write pending words to the database so that it stays in sync with
+ * the in-memory trie.
+ */
+ private static class UpdateDbTask extends AsyncTask<Void, Void, Void> {
+ private final UserHistoryDictionaryBigramList mBigramList;
+ private final DatabaseHelper mDbHelper;
+ private final String mLocale;
+ private final UserHistoryDictionary mUserHistoryDictionary;
+ private final SharedPreferences mPrefs;
+
+ public UpdateDbTask(
+ DatabaseHelper openHelper, UserHistoryDictionaryBigramList pendingWrites,
+ String locale, UserHistoryDictionary dict, SharedPreferences prefs) {
+ mBigramList = pendingWrites;
+ mLocale = locale;
+ mDbHelper = openHelper;
+ mUserHistoryDictionary = dict;
+ mPrefs = prefs;
+ }
+
+ /** Prune any old data if the database is getting too big. */
+ private static void checkPruneData(SQLiteDatabase db) {
+ db.execSQL("PRAGMA foreign_keys = ON;");
+ Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID },
+ null, null, null, null, null);
+ try {
+ int totalRowCount = c.getCount();
+ // prune out old data if we have too much data
+ if (totalRowCount > sMaxHistoryBigrams) {
+ int numDeleteRows = (totalRowCount - sMaxHistoryBigrams)
+ + sDeleteHistoryBigrams;
+ int pairIdColumnId = c.getColumnIndex(FREQ_COLUMN_PAIR_ID);
+ c.moveToFirst();
+ int count = 0;
+ while (count < numDeleteRows && !c.isAfterLast()) {
+ String pairId = c.getString(pairIdColumnId);
+ // Deleting from MAIN table will delete the frequencies
+ // due to FOREIGN KEY .. ON DELETE CASCADE
+ db.delete(MAIN_TABLE_NAME, MAIN_COLUMN_ID + "=?",
+ new String[] { pairId });
+ c.moveToNext();
+ count++;
+ }
+ }
+ } finally {
+ c.close();
+ }
+ }
+
+ @Override
+ protected Void doInBackground(Void... v) {
+ SQLiteDatabase db = null;
+ if (mUserHistoryDictionary.mBigramListLock.tryLock()) {
+ try {
+ try {
+ db = mDbHelper.getWritableDatabase();
+ } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) {
+ // If we can't open the db, don't do anything. Exit through the next test
+ // for non-nullity of the db variable.
+ }
+ if (null == db) {
+ // Not much we can do. Just exit.
+ return null;
+ }
+ db.beginTransaction();
+ return doLoadTaskLocked(db);
+ } finally {
+ if (db != null) {
+ db.endTransaction();
+ }
+ mUserHistoryDictionary.mBigramListLock.unlock();
+ }
+ }
+ return null;
+ }
+
+ private Void doLoadTaskLocked(SQLiteDatabase db) {
+ if (DBG_STRESS_TEST) {
+ try {
+ Log.w(TAG, "Start stress in closing: " + mLocale);
+ Thread.sleep(15000);
+ Log.w(TAG, "End stress in closing");
+ } catch (InterruptedException e) {
+ }
+ }
+ final long now = PROFILE_SAVE_RESTORE ? System.currentTimeMillis() : 0;
+ int profTotal = 0;
+ int profInsert = 0;
+ int profDelete = 0;
+ db.execSQL("PRAGMA foreign_keys = ON;");
+ final boolean addLevel0Bigram = mBigramList.size() <= sMaxHistoryBigrams;
+
+ // Write all the entries to the db
+ for (String word1 : mBigramList.keySet()) {
+ final HashMap<String, Byte> word1Bigrams = mBigramList.getBigrams(word1);
+ for (String word2 : word1Bigrams.keySet()) {
+ if (PROFILE_SAVE_RESTORE) {
+ ++profTotal;
+ }
+ // Get new frequency. Do not insert unigrams/bigrams which freq is "-1".
+ final int freq; // -1, or 0~255
+ if (word1 == null) { // unigram
+ freq = FREQUENCY_FOR_TYPED;
+ final byte prevFc = word1Bigrams.get(word2);
+ if (prevFc == FREQUENCY_FOR_TYPED) {
+ // No need to update since we found no changes for this entry.
+ // Just skip to the next entry.
+ if (DBG_SAVE_RESTORE) {
+ Log.d(TAG, "Skip update user history: " + word1 + "," + word2
+ + "," + prevFc);
+ }
+ if (!DBG_ALWAYS_WRITE) {
+ continue;
+ }
+ }
+ } else { // bigram
+ final NextWord nw = mUserHistoryDictionary.getBigramWord(word1, word2);
+ if (nw != null) {
+ final ForgettingCurveParams fcp = nw.getFcParams();
+ final byte prevFc = word1Bigrams.get(word2);
+ final byte fc = (byte)fcp.getFc();
+ final boolean isValid = fcp.isValid();
+ if (prevFc > 0 && prevFc == fc) {
+ // No need to update since we found no changes for this entry.
+ // Just skip to the next entry.
+ if (DBG_SAVE_RESTORE) {
+ Log.d(TAG, "Skip update user history: " + word1 + ","
+ + word2 + "," + prevFc);
+ }
+ if (!DBG_ALWAYS_WRITE) {
+ continue;
+ } else {
+ freq = fc;
+ }
+ } else if (UserHistoryForgettingCurveUtils.
+ needsToSave(fc, isValid, addLevel0Bigram)) {
+ freq = fc;
+ } else {
+ freq = -1;
+ }
+ } else {
+ freq = -1;
+ }
+ }
+ // TODO: this process of making a text search for each pair each time
+ // is terribly inefficient. Optimize this.
+ // Find pair id
+ Cursor c = null;
+ try {
+ if (null != word1) {
+ c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID },
+ MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND "
+ + MAIN_COLUMN_LOCALE + "=?",
+ new String[] { word1, word2, mLocale }, null, null,
+ null);
+ } else {
+ c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID },
+ MAIN_COLUMN_WORD1 + " IS NULL AND " + MAIN_COLUMN_WORD2
+ + "=? AND " + MAIN_COLUMN_LOCALE + "=?",
+ new String[] { word2, mLocale }, null, null, null);
+ }
+
+ final int pairId;
+ if (c.moveToFirst()) {
+ if (PROFILE_SAVE_RESTORE) {
+ ++profDelete;
+ }
+ // Delete existing pair
+ pairId = c.getInt(c.getColumnIndex(MAIN_COLUMN_ID));
+ db.delete(FREQ_TABLE_NAME, FREQ_COLUMN_PAIR_ID + "=?",
+ new String[] { Integer.toString(pairId) });
+ } else {
+ // Create new pair
+ Long pairIdLong = db.insert(MAIN_TABLE_NAME, null,
+ getContentValues(word1, word2, mLocale));
+ pairId = pairIdLong.intValue();
+ }
+ if (freq > 0) {
+ if (PROFILE_SAVE_RESTORE) {
+ ++profInsert;
+ }
+ if (DBG_SAVE_RESTORE) {
+ Log.d(TAG, "--- Save user history: " + word1 + ", " + word2
+ + mLocale + "," + this);
+ }
+ // Insert new frequency
+ db.insert(FREQ_TABLE_NAME, null,
+ getFrequencyContentValues(pairId, freq));
+ // Update an existing bigram entry in mBigramList too in order to
+ // synchronize the SQL DB and mBigramList.
+ mBigramList.updateBigram(word1, word2, (byte)freq);
+ }
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ }
+ }
+
+ checkPruneData(db);
+ // Save the timestamp after we finish writing the SQL DB.
+ SettingsValues.setLastUserHistoryWriteTime(mPrefs, mLocale);
+ if (PROFILE_SAVE_RESTORE) {
+ final long diff = System.currentTimeMillis() - now;
+ Log.w(TAG, "PROF: Write User HistoryDictionary: " + mLocale + ", "+ diff
+ + "ms. Total: " + profTotal + ". Insert: " + profInsert + ". Delete: "
+ + profDelete);
+ }
+ db.setTransactionSuccessful();
+ return null;
+ }
+
+ private static ContentValues getContentValues(String word1, String word2, String locale) {
+ ContentValues values = new ContentValues(3);
+ values.put(MAIN_COLUMN_WORD1, word1);
+ values.put(MAIN_COLUMN_WORD2, word2);
+ values.put(MAIN_COLUMN_LOCALE, locale);
+ return values;
+ }
+
+ private static ContentValues getFrequencyContentValues(int pairId, int frequency) {
+ ContentValues values = new ContentValues(2);
+ values.put(FREQ_COLUMN_PAIR_ID, pairId);
+ values.put(COLUMN_FORGETTING_CURVE_VALUE, frequency);
+ return values;
+ }
+ }
+
+}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
new file mode 100644
index 000000000..28847745e
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * A store of bigrams which will be updated when the user history dictionary is closed
+ * All bigrams including stale ones in SQL DB should be stored in this class to avoid adding stale
+ * bigrams when we write to the SQL DB.
+ */
+public class UserHistoryDictionaryBigramList {
+ public static final byte FORGETTING_CURVE_INITIAL_VALUE = 0;
+ private static final String TAG = UserHistoryDictionaryBigramList.class.getSimpleName();
+ private static final HashMap<String, Byte> EMPTY_BIGRAM_MAP = new HashMap<String, Byte>();
+ private final HashMap<String, HashMap<String, Byte>> mBigramMap =
+ new HashMap<String, HashMap<String, Byte>>();
+ private int mSize = 0;
+
+ public void evictAll() {
+ mSize = 0;
+ mBigramMap.clear();
+ }
+
+ /**
+ * Called when the user typed a word.
+ */
+ public void addBigram(String word1, String word2) {
+ addBigram(word1, word2, FORGETTING_CURVE_INITIAL_VALUE);
+ }
+
+ /**
+ * Called when loaded from the SQL DB.
+ */
+ public void addBigram(String word1, String word2, byte fcValue) {
+ if (UserHistoryDictionary.DBG_SAVE_RESTORE) {
+ Log.d(TAG, "--- add bigram: " + word1 + ", " + word2 + ", " + fcValue);
+ }
+ final HashMap<String, Byte> map;
+ if (mBigramMap.containsKey(word1)) {
+ map = mBigramMap.get(word1);
+ } else {
+ map = new HashMap<String, Byte>();
+ mBigramMap.put(word1, map);
+ }
+ if (!map.containsKey(word2)) {
+ ++mSize;
+ map.put(word2, fcValue);
+ }
+ }
+
+ /**
+ * Called when inserted to the SQL DB.
+ */
+ public void updateBigram(String word1, String word2, byte fcValue) {
+ if (UserHistoryDictionary.DBG_SAVE_RESTORE) {
+ Log.d(TAG, "--- update bigram: " + word1 + ", " + word2 + ", " + fcValue);
+ }
+ final HashMap<String, Byte> map;
+ if (mBigramMap.containsKey(word1)) {
+ map = mBigramMap.get(word1);
+ } else {
+ return;
+ }
+ if (!map.containsKey(word2)) {
+ return;
+ }
+ map.put(word2, fcValue);
+ }
+
+ public int size() {
+ return mSize;
+ }
+
+ public boolean isEmpty() {
+ return mBigramMap.isEmpty();
+ }
+
+ public Set<String> keySet() {
+ return mBigramMap.keySet();
+ }
+
+ public HashMap<String, Byte> getBigrams(String word1) {
+ if (!mBigramMap.containsKey(word1)) {
+ return EMPTY_BIGRAM_MAP;
+ } else {
+ return mBigramMap.get(word1);
+ }
+ }
+
+ public boolean removeBigram(String word1, String word2) {
+ final HashMap<String, Byte> set = getBigrams(word1);
+ if (set.isEmpty()) {
+ return false;
+ }
+ if (set.containsKey(word2)) {
+ set.remove(word2);
+ --mSize;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
new file mode 100644
index 000000000..1de95d7b8
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.format.DateUtils;
+import android.util.Log;
+
+public class UserHistoryForgettingCurveUtils {
+ private static final String TAG = UserHistoryForgettingCurveUtils.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final int FC_FREQ_MAX = 127;
+ /* package */ static final int COUNT_MAX = 3;
+ private static final int FC_LEVEL_MAX = 3;
+ /* package */ static final int ELAPSED_TIME_MAX = 15;
+ private static final int ELAPSED_TIME_INTERVAL_HOURS = 6;
+ private static final long ELAPSED_TIME_INTERVAL_MILLIS = ELAPSED_TIME_INTERVAL_HOURS
+ * DateUtils.HOUR_IN_MILLIS;
+ private static final int HALF_LIFE_HOURS = 48;
+ private static final int MAX_PUSH_ELAPSED = (FC_LEVEL_MAX + 1) * (ELAPSED_TIME_MAX + 1);
+
+ private UserHistoryForgettingCurveUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static class ForgettingCurveParams {
+ private byte mFc;
+ long mLastTouchedTime = 0;
+ private final boolean mIsValid;
+
+ private void updateLastTouchedTime() {
+ mLastTouchedTime = System.currentTimeMillis();
+ }
+
+ public ForgettingCurveParams(boolean isValid) {
+ this(System.currentTimeMillis(), isValid);
+ }
+
+ private ForgettingCurveParams(long now, boolean isValid) {
+ this(pushCount((byte)0, isValid), now, now, isValid);
+ }
+
+ /** This constructor is called when the user history bigram dictionary is being restored. */
+ public ForgettingCurveParams(int fc, long now, long last) {
+ // All words with level >= 1 had been saved.
+ // Invalid words with level == 0 had been saved.
+ // Valid words words with level == 0 had *not* been saved.
+ this(fc, now, last, fcToLevel((byte)fc) > 0);
+ }
+
+ private ForgettingCurveParams(int fc, long now, long last, boolean isValid) {
+ mIsValid = isValid;
+ mFc = (byte)fc;
+ mLastTouchedTime = last;
+ updateElapsedTime(now);
+ }
+
+ public boolean isValid() {
+ return mIsValid;
+ }
+
+ public byte getFc() {
+ updateElapsedTime(System.currentTimeMillis());
+ return mFc;
+ }
+
+ public int getFrequency() {
+ updateElapsedTime(System.currentTimeMillis());
+ return UserHistoryForgettingCurveUtils.fcToFreq(mFc);
+ }
+
+ public int notifyTypedAgainAndGetFrequency() {
+ updateLastTouchedTime();
+ // TODO: Check whether this word is valid or not
+ mFc = pushCount(mFc, false);
+ return UserHistoryForgettingCurveUtils.fcToFreq(mFc);
+ }
+
+ private void updateElapsedTime(long now) {
+ final int elapsedTimeCount =
+ (int)((now - mLastTouchedTime) / ELAPSED_TIME_INTERVAL_MILLIS);
+ if (elapsedTimeCount <= 0) {
+ return;
+ }
+ if (elapsedTimeCount >= MAX_PUSH_ELAPSED) {
+ mLastTouchedTime = now;
+ mFc = 0;
+ return;
+ }
+ for (int i = 0; i < elapsedTimeCount; ++i) {
+ mLastTouchedTime += ELAPSED_TIME_INTERVAL_MILLIS;
+ mFc = pushElapsedTime(mFc);
+ }
+ }
+ }
+
+ /* package */ static int fcToElapsedTime(byte fc) {
+ return fc & 0x0F;
+ }
+
+ /* package */ static int fcToCount(byte fc) {
+ return (fc >> 4) & 0x03;
+ }
+
+ /* package */ static int fcToLevel(byte fc) {
+ return (fc >> 6) & 0x03;
+ }
+
+ private static int calcFreq(int elapsedTime, int count, int level) {
+ if (level <= 0) {
+ // Reserved words, just return -1
+ return -1;
+ }
+ if (count == COUNT_MAX) {
+ // Temporary promote because it's frequently typed recently
+ ++level;
+ }
+ final int et = Math.min(FC_FREQ_MAX, Math.max(0, elapsedTime));
+ final int l = Math.min(FC_LEVEL_MAX, Math.max(0, level));
+ return MathUtils.SCORE_TABLE[l - 1][et];
+ }
+
+ /* pakcage */ static byte calcFc(int elapsedTime, int count, int level) {
+ final int et = Math.min(FC_FREQ_MAX, Math.max(0, elapsedTime));
+ final int c = Math.min(COUNT_MAX, Math.max(0, count));
+ final int l = Math.min(FC_LEVEL_MAX, Math.max(0, level));
+ return (byte)(et | (c << 4) | (l << 6));
+ }
+
+ public static int fcToFreq(byte fc) {
+ final int elapsedTime = fcToElapsedTime(fc);
+ final int count = fcToCount(fc);
+ final int level = fcToLevel(fc);
+ return calcFreq(elapsedTime, count, level);
+ }
+
+ public static byte pushElapsedTime(byte fc) {
+ int elapsedTime = fcToElapsedTime(fc);
+ int count = fcToCount(fc);
+ int level = fcToLevel(fc);
+ if (elapsedTime >= ELAPSED_TIME_MAX) {
+ // Downgrade level
+ elapsedTime = 0;
+ count = COUNT_MAX;
+ --level;
+ } else {
+ ++elapsedTime;
+ }
+ return calcFc(elapsedTime, count, level);
+ }
+
+ public static byte pushCount(byte fc, boolean isValid) {
+ final int elapsedTime = fcToElapsedTime(fc);
+ int count = fcToCount(fc);
+ int level = fcToLevel(fc);
+ if ((elapsedTime == 0 && count >= COUNT_MAX) || (isValid && level == 0)) {
+ // Upgrade level
+ ++level;
+ count = 0;
+ if (DEBUG) {
+ Log.d(TAG, "Upgrade level.");
+ }
+ } else {
+ ++count;
+ }
+ return calcFc(0, count, level);
+ }
+
+ // TODO: isValid should be false for a word whose frequency is 0,
+ // or that is not in the dictionary.
+ /**
+ * Check wheather we should save the bigram to the SQL DB or not
+ */
+ public static boolean needsToSave(byte fc, boolean isValid, boolean addLevel0Bigram) {
+ int level = fcToLevel(fc);
+ if (level == 0) {
+ if (isValid || !addLevel0Bigram) {
+ return false;
+ }
+ }
+ final int elapsedTime = fcToElapsedTime(fc);
+ return (elapsedTime < ELAPSED_TIME_MAX - 1 || level > 0);
+ }
+
+ private static class MathUtils {
+ public static final int[][] SCORE_TABLE = new int[FC_LEVEL_MAX][ELAPSED_TIME_MAX + 1];
+ static {
+ for (int i = 0; i < FC_LEVEL_MAX; ++i) {
+ final float initialFreq;
+ if (i >= 2) {
+ initialFreq = FC_FREQ_MAX;
+ } else if (i == 1) {
+ initialFreq = FC_FREQ_MAX / 2;
+ } else if (i == 0) {
+ initialFreq = FC_FREQ_MAX / 4;
+ } else {
+ continue;
+ }
+ for (int j = 0; j < ELAPSED_TIME_MAX; ++j) {
+ final float elapsedHours = j * ELAPSED_TIME_INTERVAL_HOURS;
+ final float freq = initialFreq
+ * NativeUtils.powf(initialFreq, elapsedHours / HALF_LIFE_HOURS);
+ final int intFreq = Math.min(FC_FREQ_MAX, Math.max(0, (int)freq));
+ SCORE_TABLE[i][j] = intFreq;
+ }
+ }
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 245fc20bc..a44b1f9ad 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -16,48 +16,41 @@
package com.android.inputmethod.latin;
-import com.android.inputmethod.compat.InputMethodInfoCompatWrapper;
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
-import com.android.inputmethod.compat.InputTypeCompatUtils;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-
import android.content.Context;
-import android.content.res.Configuration;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
+import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
-import android.text.InputType;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
-import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
public class Utils {
- private static final String TAG = Utils.class.getSimpleName();
- private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
- private static boolean DBG = LatinImeLogger.sDBG;
- private static boolean DBG_EDIT_DISTANCE = false;
-
private Utils() {
- // Intentional empty constructor for utility class.
+ // This utility class is not publicly instantiable.
}
/**
@@ -111,85 +104,6 @@ public class Utils {
}
}
- public static boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManagerCompatWrapper imm) {
- final List<InputMethodInfoCompatWrapper> enabledImis = imm.getEnabledInputMethodList();
-
- // Filters out IMEs that have auxiliary subtypes only (including either implicitly or
- // explicitly enabled ones).
- final ArrayList<InputMethodInfoCompatWrapper> filteredImis =
- new ArrayList<InputMethodInfoCompatWrapper>();
-
- outerloop:
- for (InputMethodInfoCompatWrapper imi : enabledImis) {
- // We can return true immediately after we find two or more filtered IMEs.
- if (filteredImis.size() > 1) return true;
- final List<InputMethodSubtypeCompatWrapper> subtypes =
- imm.getEnabledInputMethodSubtypeList(imi, true);
- // IMEs that have no subtypes should be included.
- if (subtypes.isEmpty()) {
- filteredImis.add(imi);
- continue;
- }
- // IMEs that have one or more non-auxiliary subtypes should be included.
- for (InputMethodSubtypeCompatWrapper subtype : subtypes) {
- if (!subtype.isAuxiliary()) {
- filteredImis.add(imi);
- continue outerloop;
- }
- }
- }
-
- return filteredImis.size() > 1
- // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
- // input method subtype (The current IME should be LatinIME.)
- || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
- }
-
- public static String getInputMethodId(InputMethodManagerCompatWrapper imm, String packageName) {
- return getInputMethodInfo(imm, packageName).getId();
- }
-
- public static InputMethodInfoCompatWrapper getInputMethodInfo(
- InputMethodManagerCompatWrapper imm, String packageName) {
- for (final InputMethodInfoCompatWrapper imi : imm.getEnabledInputMethodList()) {
- if (imi.getPackageName().equals(packageName))
- return imi;
- }
- throw new RuntimeException("Can not find input method id for " + packageName);
- }
-
- public static boolean shouldBlockedBySafetyNetForAutoCorrection(SuggestedWords suggestions,
- Suggest suggest) {
- // Safety net for auto correction.
- // Actually if we hit this safety net, it's actually a bug.
- if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false;
- // If user selected aggressive auto correction mode, there is no need to use the safety
- // net.
- if (suggest.isAggressiveAutoCorrectionMode()) return false;
- CharSequence typedWord = suggestions.getWord(0);
- // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
- // we should not use net because relatively edit distance can be big.
- if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) return false;
- CharSequence candidateWord = suggestions.getWord(1);
- final int typedWordLength = typedWord.length();
- final int maxEditDistanceOfNativeDictionary = typedWordLength < 5 ? 2 : typedWordLength / 2;
- final int distance = Utils.editDistance(typedWord, candidateWord);
- if (DBG) {
- Log.d(TAG, "Autocorrected edit distance = " + distance
- + ", " + maxEditDistanceOfNativeDictionary);
- }
- if (distance > maxEditDistanceOfNativeDictionary) {
- if (DBG) {
- Log.d(TAG, "Safety net: before = " + typedWord + ", after = " + candidateWord);
- Log.w(TAG, "(Error) The edit distance of this correction exceeds limit. "
- + "Turning off auto-correction.");
- }
- return true;
- } else {
- return false;
- }
- }
-
/* package */ static class RingCharBuffer {
private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
@@ -197,7 +111,6 @@ public class Utils {
/* package */ static final int BUFSIZE = 20;
private InputMethodService mContext;
private boolean mEnabled = false;
- private boolean mUsabilityStudy = false;
private int mEnd = 0;
/* package */ int mLength = 0;
private char[] mCharBuf = new char[BUFSIZE];
@@ -212,21 +125,19 @@ public class Utils {
}
public static RingCharBuffer init(InputMethodService context, boolean enabled,
boolean usabilityStudy) {
+ if (!(enabled || usabilityStudy)) return null;
sRingCharBuffer.mContext = context;
- sRingCharBuffer.mEnabled = enabled || usabilityStudy;
- sRingCharBuffer.mUsabilityStudy = usabilityStudy;
+ sRingCharBuffer.mEnabled = true;
UsabilityStudyLogUtils.getInstance().init(context);
return sRingCharBuffer;
}
- private int normalize(int in) {
+ private static int normalize(int in) {
int ret = in % BUFSIZE;
return ret < 0 ? ret + BUFSIZE : ret;
}
+ // TODO: accept code points
public void push(char c, int x, int y) {
if (!mEnabled) return;
- if (mUsabilityStudy) {
- UsabilityStudyLogUtils.getInstance().writeChar(c, x, y);
- }
mCharBuf[mEnd] = c;
mXBuf[mEnd] = x;
mYBuf[mEnd] = y;
@@ -293,116 +204,29 @@ public class Utils {
}
}
-
- /* Damerau-Levenshtein distance */
- public static int editDistance(CharSequence s, CharSequence t) {
- if (s == null || t == null) {
- throw new IllegalArgumentException("editDistance: Arguments should not be null.");
- }
- final int sl = s.length();
- final int tl = t.length();
- int[][] dp = new int [sl + 1][tl + 1];
- for (int i = 0; i <= sl; i++) {
- dp[i][0] = i;
- }
- for (int j = 0; j <= tl; j++) {
- dp[0][j] = j;
- }
- for (int i = 0; i < sl; ++i) {
- for (int j = 0; j < tl; ++j) {
- final char sc = Character.toLowerCase(s.charAt(i));
- final char tc = Character.toLowerCase(t.charAt(j));
- final int cost = sc == tc ? 0 : 1;
- dp[i + 1][j + 1] = Math.min(
- dp[i][j + 1] + 1, Math.min(dp[i + 1][j] + 1, dp[i][j] + cost));
- // Overwrite for transposition cases
- if (i > 0 && j > 0
- && sc == Character.toLowerCase(t.charAt(j - 1))
- && tc == Character.toLowerCase(s.charAt(i - 1))) {
- dp[i + 1][j + 1] = Math.min(dp[i + 1][j + 1], dp[i - 1][j - 1] + cost);
- }
- }
- }
- if (DBG_EDIT_DISTANCE) {
- Log.d(TAG, "editDistance:" + s + "," + t);
- for (int i = 0; i < dp.length; ++i) {
- StringBuffer sb = new StringBuffer();
- for (int j = 0; j < dp[i].length; ++j) {
- sb.append(dp[i][j]).append(',');
- }
- Log.d(TAG, i + ":" + sb.toString());
- }
- }
- return dp[sl][tl];
- }
-
// Get the current stack trace
- public static String getStackTrace() {
+ public static String getStackTrace(final int limit) {
StringBuilder sb = new StringBuilder();
try {
throw new RuntimeException();
} catch (RuntimeException e) {
StackTraceElement[] frames = e.getStackTrace();
// Start at 1 because the first frame is here and we don't care about it
- for (int j = 1; j < frames.length; ++j) sb.append(frames[j].toString() + "\n");
+ for (int j = 1; j < frames.length && j < limit + 1; ++j) {
+ sb.append(frames[j].toString() + "\n");
+ }
}
return sb.toString();
}
- // In dictionary.cpp, getSuggestion() method,
- // suggestion scores are computed using the below formula.
- // original score
- // := pow(mTypedLetterMultiplier (this is defined 2),
- // (the number of matched characters between typed word and suggested word))
- // * (individual word's score which defined in the unigram dictionary,
- // and this score is defined in range [0, 255].)
- // Then, the following processing is applied.
- // - If the dictionary word is matched up to the point of the user entry
- // (full match up to min(before.length(), after.length())
- // => Then multiply by FULL_MATCHED_WORDS_PROMOTION_RATE (this is defined 1.2)
- // - If the word is a true full match except for differences in accents or
- // capitalization, then treat it as if the score was 255.
- // - If before.length() == after.length()
- // => multiply by mFullWordMultiplier (this is defined 2))
- // So, maximum original score is pow(2, min(before.length(), after.length())) * 255 * 2 * 1.2
- // For historical reasons we ignore the 1.2 modifier (because the measure for a good
- // autocorrection threshold was done at a time when it didn't exist). This doesn't change
- // the result.
- // So, we can normalize original score by dividing pow(2, min(b.l(),a.l())) * 255 * 2.
- private static final int MAX_INITIAL_SCORE = 255;
- private static final int TYPED_LETTER_MULTIPLIER = 2;
- private static final int FULL_WORD_MULTIPLIER = 2;
- private static final int S_INT_MAX = 2147483647;
- public static double calcNormalizedScore(CharSequence before, CharSequence after, int score) {
- final int beforeLength = before.length();
- final int afterLength = after.length();
- if (beforeLength == 0 || afterLength == 0) return 0;
- final int distance = editDistance(before, after);
- // If afterLength < beforeLength, the algorithm is suggesting a word by excessive character
- // correction.
- int spaceCount = 0;
- for (int i = 0; i < afterLength; ++i) {
- if (after.charAt(i) == Keyboard.CODE_SPACE) {
- ++spaceCount;
- }
- }
- if (spaceCount == afterLength) return 0;
- final double maximumScore = score == S_INT_MAX ? S_INT_MAX : MAX_INITIAL_SCORE
- * Math.pow(
- TYPED_LETTER_MULTIPLIER, Math.min(beforeLength, afterLength - spaceCount))
- * FULL_WORD_MULTIPLIER;
- // add a weight based on edit distance.
- // distance <= max(afterLength, beforeLength) == afterLength,
- // so, 0 <= distance / afterLength <= 1
- final double weight = 1.0 - (double) distance / afterLength;
- return (score / maximumScore) * weight;
+ public static String getStackTrace() {
+ return getStackTrace(Integer.MAX_VALUE);
}
public static class UsabilityStudyLogUtils {
+ // TODO: remove code duplication with ResearchLog class
private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();
private static final String FILENAME = "log.txt";
- private static final UsabilityStudyLogUtils sInstance =
- new UsabilityStudyLogUtils();
private final Handler mLoggingHandler;
private File mFile;
private File mDirectory;
@@ -413,7 +237,7 @@ public class Utils {
private UsabilityStudyLogUtils() {
mDate = new Date();
- mDateFormat = new SimpleDateFormat("dd MMM HH:mm:ss.SSS");
+ mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ");
HandlerThread handlerThread = new HandlerThread("UsabilityStudyLogUtils logging task",
Process.THREAD_PRIORITY_BACKGROUND);
@@ -421,8 +245,13 @@ public class Utils {
mLoggingHandler = new Handler(handlerThread.getLooper());
}
+ // Initialization-on-demand holder
+ private static class OnDemandInitializationHolder {
+ public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils();
+ }
+
public static UsabilityStudyLogUtils getInstance() {
- return sInstance;
+ return OnDemandInitializationHolder.sInstance;
}
public void init(InputMethodService ims) {
@@ -441,8 +270,8 @@ public class Utils {
}
}
- public void writeBackSpace() {
- UsabilityStudyLogUtils.getInstance().write("<backspace>\t0\t0");
+ public static void writeBackSpace(int x, int y) {
+ UsabilityStudyLogUtils.getInstance().write("<backspace>\t" + x + "\t" + y);
}
public void writeChar(char c, int x, int y) {
@@ -480,32 +309,89 @@ public class Utils {
});
}
- public void printAll() {
+ private synchronized String getBufferedLogs() {
+ mWriter.flush();
+ StringBuilder sb = new StringBuilder();
+ BufferedReader br = getBufferedReader();
+ String line;
+ try {
+ while ((line = br.readLine()) != null) {
+ sb.append('\n');
+ sb.append(line);
+ }
+ } catch (IOException e) {
+ Log.e(USABILITY_TAG, "Can't read log file.");
+ } finally {
+ if (LatinImeLogger.sDBG) {
+ Log.d(USABILITY_TAG, "Got all buffered logs\n" + sb.toString());
+ }
+ try {
+ br.close();
+ } catch (IOException e) {
+ // ignore.
+ }
+ }
+ return sb.toString();
+ }
+
+ public void emailResearcherLogsAll() {
mLoggingHandler.post(new Runnable() {
@Override
public void run() {
+ final Date date = new Date();
+ date.setTime(System.currentTimeMillis());
+ final String currentDateTimeString =
+ new SimpleDateFormat("yyyyMMdd-HHmmssZ").format(date);
+ if (mFile == null) {
+ Log.w(USABILITY_TAG, "No internal log file found.");
+ return;
+ }
+ if (mIms.checkCallingOrSelfPermission(
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(USABILITY_TAG, "Doesn't have the permission WRITE_EXTERNAL_STORAGE");
+ return;
+ }
mWriter.flush();
- StringBuilder sb = new StringBuilder();
- BufferedReader br = getBufferedReader();
- String line;
+ final String destPath = Environment.getExternalStorageDirectory()
+ + "/research-" + currentDateTimeString + ".log";
+ final File destFile = new File(destPath);
try {
- while ((line = br.readLine()) != null) {
- sb.append('\n');
- sb.append(line);
- }
- } catch (IOException e) {
- Log.e(USABILITY_TAG, "Can't read log file.");
- } finally {
- if (LatinImeLogger.sDBG) {
- Log.d(USABILITY_TAG, "output all logs\n" + sb.toString());
- }
- mIms.getCurrentInputConnection().commitText(sb.toString(), 0);
- try {
- br.close();
- } catch (IOException e) {
- // ignore.
- }
+ final FileChannel src = (new FileInputStream(mFile)).getChannel();
+ final FileChannel dest = (new FileOutputStream(destFile)).getChannel();
+ src.transferTo(0, src.size(), dest);
+ src.close();
+ dest.close();
+ } catch (FileNotFoundException e1) {
+ Log.w(USABILITY_TAG, e1);
+ return;
+ } catch (IOException e2) {
+ Log.w(USABILITY_TAG, e2);
+ return;
+ }
+ if (destFile == null || !destFile.exists()) {
+ Log.w(USABILITY_TAG, "Dest file doesn't exist.");
+ return;
+ }
+ final Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (LatinImeLogger.sDBG) {
+ Log.d(USABILITY_TAG, "Destination file URI is " + destFile.toURI());
}
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + destPath));
+ intent.putExtra(Intent.EXTRA_SUBJECT,
+ "[Research Logs] " + currentDateTimeString);
+ mIms.startActivity(intent);
+ }
+ });
+ }
+
+ public void printAll() {
+ mLoggingHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mIms.getCurrentInputConnection().commitText(getBufferedLogs(), 0);
}
});
}
@@ -546,173 +432,113 @@ public class Utils {
}
}
- public static int getKeyboardMode(EditorInfo attribute) {
- if (attribute == null)
- return KeyboardId.MODE_TEXT;
-
- final int inputType = attribute.inputType;
- final int variation = inputType & InputType.TYPE_MASK_VARIATION;
-
- switch (inputType & InputType.TYPE_MASK_CLASS) {
- case InputType.TYPE_CLASS_NUMBER:
- case InputType.TYPE_CLASS_DATETIME:
- return KeyboardId.MODE_NUMBER;
- case InputType.TYPE_CLASS_PHONE:
- return KeyboardId.MODE_PHONE;
- case InputType.TYPE_CLASS_TEXT:
- if (InputTypeCompatUtils.isEmailVariation(variation)) {
- return KeyboardId.MODE_EMAIL;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
- return KeyboardId.MODE_URL;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
- return KeyboardId.MODE_IM;
- } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
- return KeyboardId.MODE_TEXT;
- } else {
- return KeyboardId.MODE_TEXT;
- }
- default:
- return KeyboardId.MODE_TEXT;
- }
- }
-
- public static boolean containsInCsv(String key, String csv) {
- if (csv == null)
- return false;
- for (String option : csv.split(",")) {
- if (option.equals(key))
- return true;
- }
- return false;
- }
-
- public static boolean inPrivateImeOptions(String packageName, String key,
- EditorInfo attribute) {
- if (attribute == null)
- return false;
- return containsInCsv(packageName != null ? packageName + "." + key : key,
- attribute.privateImeOptions);
+ public static float getDipScale(Context context) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return scale;
}
- /**
- * Returns a main dictionary resource id
- * @return main dictionary resource id
- */
- public static int getMainDictionaryResourceId(Resources res) {
- final String MAIN_DIC_NAME = "main";
- String packageName = LatinIME.class.getPackage().getName();
- return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName);
+ /** Convert pixel to DIP */
+ public static int dipToPixel(float scale, int dip) {
+ return (int) (dip * scale + 0.5);
}
- public static void loadNativeLibrary() {
- try {
- System.loadLibrary("jni_latinime2");
- } catch (UnsatisfiedLinkError ule) {
- Log.e(TAG, "Could not load native library jni_latinime2");
+ public static class Stats {
+ public static void onNonSeparator(final char code, final int x,
+ final int y) {
+ RingCharBuffer.getInstance().push(code, x, y);
+ LatinImeLogger.logOnInputChar();
}
- }
- /**
- * Returns true if a and b are equal ignoring the case of the character.
- * @param a first character to check
- * @param b second character to check
- * @return {@code true} if a and b are equal, {@code false} otherwise.
- */
- public static boolean equalsIgnoreCase(char a, char b) {
- // Some language, such as Turkish, need testing both cases.
- return a == b
- || Character.toLowerCase(a) == Character.toLowerCase(b)
- || Character.toUpperCase(a) == Character.toUpperCase(b);
- }
+ public static void onSeparator(final int code, final int x,
+ final int y) {
+ // TODO: accept code points
+ RingCharBuffer.getInstance().push((char)code, x, y);
+ LatinImeLogger.logOnInputSeparator();
+ }
- /**
- * Returns true if a and b are equal ignoring the case of the characters, including if they are
- * both null.
- * @param a first CharSequence to check
- * @param b second CharSequence to check
- * @return {@code true} if a and b are equal, {@code false} otherwise.
- */
- public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) {
- if (a == b)
- return true; // including both a and b are null.
- if (a == null || b == null)
- return false;
- final int length = a.length();
- if (length != b.length())
- return false;
- for (int i = 0; i < length; i++) {
- if (!equalsIgnoreCase(a.charAt(i), b.charAt(i)))
- return false;
+ public static void onAutoCorrection(final String typedWord, final String correctedWord,
+ final int separatorCode) {
+ if (TextUtils.isEmpty(typedWord)) return;
+ LatinImeLogger.logOnAutoCorrection(typedWord, correctedWord, separatorCode);
}
- return true;
- }
- /**
- * Returns true if a and b are equal ignoring the case of the characters, including if a is null
- * and b is zero length.
- * @param a CharSequence to check
- * @param b character array to check
- * @param offset start offset of array b
- * @param length length of characters in array b
- * @return {@code true} if a and b are equal, {@code false} otherwise.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0 || length < 0 || offset + length > data.length}.
- * @throws NullPointerException if {@code b == null}.
- */
- public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) {
- if (offset < 0 || length < 0 || length > b.length - offset)
- throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset
- + " length=" + length);
- if (a == null)
- return length == 0; // including a is null and b is zero length.
- if (a.length() != length)
- return false;
- for (int i = 0; i < length; i++) {
- if (!equalsIgnoreCase(a.charAt(i), b[offset + i]))
- return false;
+ public static void onAutoCorrectionCancellation() {
+ LatinImeLogger.logOnAutoCorrectionCancelled();
}
- return true;
}
- public static float getDipScale(Context context) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return scale;
+ public static String getDebugInfo(final SuggestedWords suggestions, final int pos) {
+ if (!LatinImeLogger.sDBG) return null;
+ final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
+ if (wordInfo == null) return null;
+ final String info = wordInfo.getDebugString();
+ if (TextUtils.isEmpty(info)) return null;
+ return info;
}
- /** Convert pixel to DIP */
- public static int dipToPixel(float scale, int dip) {
- return (int) (dip * scale + 0.5);
+ private static final String HARDWARE_PREFIX = Build.HARDWARE + ",";
+ private static final HashMap<String, String> sDeviceOverrideValueMap =
+ new HashMap<String, String>();
+
+ public static String getDeviceOverrideValue(Resources res, int overrideResId, String defValue) {
+ final int orientation = res.getConfiguration().orientation;
+ final String key = overrideResId + "-" + orientation;
+ if (!sDeviceOverrideValueMap.containsKey(key)) {
+ String overrideValue = defValue;
+ for (final String element : res.getStringArray(overrideResId)) {
+ if (element.startsWith(HARDWARE_PREFIX)) {
+ overrideValue = element.substring(HARDWARE_PREFIX.length());
+ break;
+ }
+ }
+ sDeviceOverrideValueMap.put(key, overrideValue);
+ }
+ return sDeviceOverrideValueMap.get(key);
}
- public static Locale setSystemLocale(Resources res, Locale newLocale) {
- final Configuration conf = res.getConfiguration();
- final Locale saveLocale = conf.locale;
- conf.locale = newLocale;
- res.updateConfiguration(conf, res.getDisplayMetrics());
- return saveLocale;
+ private static final HashMap<String, Long> EMPTY_LT_HASH_MAP = new HashMap<String, Long>();
+ private static final String LOCALE_AND_TIME_STR_SEPARATER = ",";
+ public static HashMap<String, Long> localeAndTimeStrToHashMap(String str) {
+ if (TextUtils.isEmpty(str)) {
+ return EMPTY_LT_HASH_MAP;
+ }
+ final String[] ss = str.split(LOCALE_AND_TIME_STR_SEPARATER);
+ final int N = ss.length;
+ if (N < 2 || N % 2 != 0) {
+ return EMPTY_LT_HASH_MAP;
+ }
+ final HashMap<String, Long> retval = new HashMap<String, Long>();
+ for (int i = 0; i < N / 2; ++i) {
+ final String localeStr = ss[i * 2];
+ final long time = Long.valueOf(ss[i * 2 + 1]);
+ retval.put(localeStr, time);
+ }
+ return retval;
}
- private static final HashMap<String, Locale> sLocaleCache = new HashMap<String, Locale>();
-
- public static Locale constructLocaleFromString(String localeStr) {
- if (localeStr == null)
- return null;
- synchronized (sLocaleCache) {
- if (sLocaleCache.containsKey(localeStr))
- return sLocaleCache.get(localeStr);
- Locale retval = null;
- String[] localeParams = localeStr.split("_", 3);
- if (localeParams.length == 1) {
- retval = new Locale(localeParams[0]);
- } else if (localeParams.length == 2) {
- retval = new Locale(localeParams[0], localeParams[1]);
- } else if (localeParams.length == 3) {
- retval = new Locale(localeParams[0], localeParams[1], localeParams[2]);
- }
- if (retval != null) {
- sLocaleCache.put(localeStr, retval);
+ public static String localeAndTimeHashMapToStr(HashMap<String, Long> map) {
+ if (map == null || map.isEmpty()) {
+ return "";
+ }
+ final StringBuilder builder = new StringBuilder();
+ for (String localeStr : map.keySet()) {
+ if (builder.length() > 0) {
+ builder.append(LOCALE_AND_TIME_STR_SEPARATER);
}
- return retval;
+ final Long time = map.get(localeStr);
+ builder.append(localeStr).append(LOCALE_AND_TIME_STR_SEPARATER);
+ builder.append(String.valueOf(time));
+ }
+ return builder.toString();
+ }
+
+ public static void addAllSuggestions(final int dicTypeId, final int dataType,
+ final ArrayList<SuggestedWords.SuggestedWordInfo> suggestions,
+ final Dictionary.WordCallback callback) {
+ for (SuggestedWordInfo suggestion : suggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ callback.addWord(suggestionStr.toCharArray(), 0, suggestionStr.length(),
+ suggestion.mScore, dicTypeId, dataType);
}
}
}
diff --git a/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java b/java/src/com/android/inputmethod/latin/VibratorUtils.java
index 8e2a2e0b8..33ffdd9c9 100644
--- a/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java
+++ b/java/src/com/android/inputmethod/latin/VibratorUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,34 +14,37 @@
* limitations under the License.
*/
-package com.android.inputmethod.compat;
+package com.android.inputmethod.latin;
import android.content.Context;
import android.os.Vibrator;
-import java.lang.reflect.Method;
-
-public class VibratorCompatWrapper {
- private static final Method METHOD_hasVibrator = CompatUtils.getMethod(Vibrator.class,
- "hasVibrator", int.class);
-
- private static final VibratorCompatWrapper sInstance = new VibratorCompatWrapper();
+public class VibratorUtils {
+ private static final VibratorUtils sInstance = new VibratorUtils();
private Vibrator mVibrator;
- private VibratorCompatWrapper() {
+ private VibratorUtils() {
+ // This utility class is not publicly instantiable.
}
- public static VibratorCompatWrapper getInstance(Context context) {
+ public static VibratorUtils getInstance(Context context) {
if (sInstance.mVibrator == null) {
- sInstance.mVibrator =
- (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+ sInstance.mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}
return sInstance;
}
public boolean hasVibrator() {
- if (mVibrator == null)
+ if (mVibrator == null) {
return false;
- return (Boolean) CompatUtils.invoke(mVibrator, true, METHOD_hasVibrator);
+ }
+ return mVibrator.hasVibrator();
+ }
+
+ public void vibrate(long milliseconds) {
+ if (mVibrator == null) {
+ return;
+ }
+ mVibrator.vibrate(milliseconds);
}
}
diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
index 4377373d2..a0de2f970 100644
--- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
+++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
@@ -17,13 +17,17 @@
package com.android.inputmethod.latin;
import android.content.Context;
+import android.content.res.Resources;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import com.android.inputmethod.latin.LocaleUtils.RunInLocale;
+
import java.util.HashMap;
+import java.util.Locale;
-public class WhitelistDictionary extends Dictionary {
+public class WhitelistDictionary extends ExpandableDictionary {
private static final boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = WhitelistDictionary.class.getSimpleName();
@@ -31,22 +35,18 @@ public class WhitelistDictionary extends Dictionary {
private final HashMap<String, Pair<Integer, String>> mWhitelistWords =
new HashMap<String, Pair<Integer, String>>();
- private static final WhitelistDictionary sInstance = new WhitelistDictionary();
-
- private WhitelistDictionary() {
- }
-
- public static WhitelistDictionary init(Context context) {
- synchronized (sInstance) {
- if (context != null) {
- // Wordlist is initialized by the proper language in Suggestion.java#init
- sInstance.initWordlist(
- context.getResources().getStringArray(R.array.wordlist_whitelist));
- } else {
- sInstance.mWhitelistWords.clear();
+ // TODO: Conform to the async load contact of ExpandableDictionary
+ public WhitelistDictionary(final Context context, final Locale locale) {
+ super(context, Suggest.DIC_WHITELIST);
+ // TODO: Move whitelist dictionary into main dictionary.
+ final RunInLocale<Void> job = new RunInLocale<Void>() {
+ @Override
+ protected Void job(Resources res) {
+ initWordlist(res.getStringArray(R.array.wordlist_whitelist));
+ return null;
}
- }
- return sInstance;
+ };
+ job.runInLocale(context.getResources(), locale);
}
private void initWordlist(String[] wordlist) {
@@ -66,6 +66,7 @@ public class WhitelistDictionary extends Dictionary {
if (before != null && after != null) {
mWhitelistWords.put(
before.toLowerCase(), new Pair<Integer, String>(score, after));
+ addWord(after, null /* shortcut */, score);
}
}
} catch (NumberFormatException e) {
@@ -75,26 +76,34 @@ public class WhitelistDictionary extends Dictionary {
}
}
- public String getWhiteListedWord(String before) {
+ public String getWhitelistedWord(String before) {
if (before == null) return null;
final String lowerCaseBefore = before.toLowerCase();
if(mWhitelistWords.containsKey(lowerCaseBefore)) {
if (DBG) {
- Log.d(TAG, "--- found whiteListedWord: " + lowerCaseBefore);
+ Log.d(TAG, "--- found whitelistedWord: " + lowerCaseBefore);
}
return mWhitelistWords.get(lowerCaseBefore).second;
}
return null;
}
- // Not used for WhitelistDictionary. We use getWhitelistedWord() in Suggest.java instead
- @Override
- public void getWords(WordComposer composer, WordCallback callback) {
- }
-
- @Override
- public boolean isValidWord(CharSequence word) {
+ // See LatinIME#updateSuggestions. This breaks in the (queer) case that the whitelist
+ // lists that word a should autocorrect to word b, and word c would autocorrect to
+ // an upper-cased version of a. In this case, the way this return value is used would
+ // remove the first candidate when the user typed the upper-cased version of A.
+ // Example : abc -> def and xyz -> Abc
+ // A user typing Abc would experience it being autocorrected to something else (not
+ // necessarily def).
+ // There is no such combination in the whitelist at the time and there probably won't
+ // ever be - it doesn't make sense. But still.
+ public boolean shouldForciblyAutoCorrectFrom(CharSequence word) {
if (TextUtils.isEmpty(word)) return false;
- return !TextUtils.isEmpty(getWhiteListedWord(word.toString()));
+ final String correction = getWhitelistedWord(word.toString());
+ if (TextUtils.isEmpty(correction)) return false;
+ return !correction.equals(word);
}
+
+ // Leave implementation of getWords and isValidWord to the superclass.
+ // The words have been added to the ExpandableDictionary with addWord() inside initWordlist.
}
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index af5e4b179..ca9caa1d3 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,9 +16,12 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardActionListener;
-import java.util.ArrayList;
+import java.util.Arrays;
/**
* A place to store the currently composing word with information such as adjacent key codes as well
@@ -28,38 +31,35 @@ public class WordComposer {
public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE;
public static final int NOT_A_COORDINATE = -1;
- /**
- * The list of unicode values for each keystroke (including surrounding keys)
- */
- private ArrayList<int[]> mCodes;
+ private static final int N = BinaryDictionary.MAX_WORD_LENGTH;
- private int mTypedLength;
+ private int[] mPrimaryKeyCodes;
private int[] mXCoordinates;
private int[] mYCoordinates;
-
- /**
- * The word chosen from the candidate list, until it is committed.
- */
- private String mPreferredWord;
-
private StringBuilder mTypedWord;
+ private CharSequence mAutoCorrection;
+ private boolean mIsResumed;
+ // Cache these values for performance
private int mCapsCount;
-
private boolean mAutoCapitalized;
-
+ private int mTrailingSingleQuotesCount;
+ private int mCodePointSize;
+
/**
* Whether the user chose to capitalize the first char of the word.
*/
private boolean mIsFirstCharCapitalized;
public WordComposer() {
- final int N = BinaryDictionary.MAX_WORD_LENGTH;
- mCodes = new ArrayList<int[]>(N);
+ mPrimaryKeyCodes = new int[N];
mTypedWord = new StringBuilder(N);
- mTypedLength = 0;
mXCoordinates = new int[N];
mYCoordinates = new int[N];
+ mAutoCorrection = null;
+ mTrailingSingleQuotesCount = 0;
+ mIsResumed = false;
+ refreshSize();
}
public WordComposer(WordComposer source) {
@@ -67,44 +67,53 @@ public class WordComposer {
}
public void init(WordComposer source) {
- mCodes = new ArrayList<int[]>(source.mCodes);
- mPreferredWord = source.mPreferredWord;
+ mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
mTypedWord = new StringBuilder(source.mTypedWord);
+ mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length);
+ mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length);
mCapsCount = source.mCapsCount;
- mAutoCapitalized = source.mAutoCapitalized;
mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
- mTypedLength = source.mTypedLength;
- mXCoordinates = source.mXCoordinates;
- mYCoordinates = source.mYCoordinates;
+ mAutoCapitalized = source.mAutoCapitalized;
+ mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount;
+ mIsResumed = source.mIsResumed;
+ refreshSize();
}
/**
* Clear out the keys registered so far.
*/
public void reset() {
- mCodes.clear();
- mTypedLength = 0;
- mIsFirstCharCapitalized = false;
- mPreferredWord = null;
mTypedWord.setLength(0);
+ mAutoCorrection = null;
mCapsCount = 0;
+ mIsFirstCharCapitalized = false;
+ mTrailingSingleQuotesCount = 0;
+ mIsResumed = false;
+ refreshSize();
+ }
+
+ public final void refreshSize() {
+ mCodePointSize = mTypedWord.codePointCount(0, mTypedWord.length());
}
/**
* Number of keystrokes in the composing word.
* @return the number of keystrokes
*/
- public int size() {
- return mCodes.size();
+ public final int size() {
+ return mCodePointSize;
}
- /**
- * Returns the codes at a particular position in the word.
- * @param index the position in the word
- * @return the unicode for the pressed and surrounding keys
- */
- public int[] getCodesAt(int index) {
- return mCodes.get(index);
+ public final boolean isComposingWord() {
+ return size() > 0;
+ }
+
+ // TODO: make sure that the index should not exceed MAX_WORD_LENGTH
+ public int getCodeAt(int index) {
+ if (index >= BinaryDictionary.MAX_WORD_LENGTH) {
+ return -1;
+ }
+ return mPrimaryKeyCodes[index];
}
public int[] getXCoordinates() {
@@ -115,71 +124,128 @@ public class WordComposer {
return mYCoordinates;
}
+ private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) {
+ if (index == 0) return Character.isUpperCase(codePoint);
+ return previous && !Character.isUpperCase(codePoint);
+ }
+
+ // TODO: remove input keyDetector
+ public void add(int primaryCode, int x, int y, KeyDetector keyDetector) {
+ final int keyX;
+ final int keyY;
+ if (null == keyDetector
+ || x == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE
+ || y == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE
+ || x == KeyboardActionListener.NOT_A_TOUCH_COORDINATE
+ || y == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) {
+ keyX = x;
+ keyY = y;
+ } else {
+ keyX = keyDetector.getTouchX(x);
+ keyY = keyDetector.getTouchY(y);
+ }
+ add(primaryCode, keyX, keyY);
+ }
+
/**
- * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of
- * the array containing unicode for adjacent keys, sorted by reducing probability/proximity.
- * @param codes the array of unicode values
+ * Add a new keystroke, with the pressed key's code point with the touch point coordinates.
*/
- public void add(int primaryCode, int[] codes, int x, int y) {
- mTypedWord.append((char) primaryCode);
- correctPrimaryJuxtapos(primaryCode, codes);
- mCodes.add(codes);
- if (mTypedLength < BinaryDictionary.MAX_WORD_LENGTH) {
- mXCoordinates[mTypedLength] = x;
- mYCoordinates[mTypedLength] = y;
+ private void add(int primaryCode, int keyX, int keyY) {
+ final int newIndex = size();
+ mTypedWord.appendCodePoint(primaryCode);
+ refreshSize();
+ if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
+ mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE
+ ? Character.toLowerCase(primaryCode) : primaryCode;
+ mXCoordinates[newIndex] = keyX;
+ mYCoordinates[newIndex] = keyY;
}
- ++mTypedLength;
- if (Character.isUpperCase((char) primaryCode)) mCapsCount++;
+ mIsFirstCharCapitalized = isFirstCharCapitalized(
+ newIndex, primaryCode, mIsFirstCharCapitalized);
+ if (Character.isUpperCase(primaryCode)) mCapsCount++;
+ if (Keyboard.CODE_SINGLE_QUOTE == primaryCode) {
+ ++mTrailingSingleQuotesCount;
+ } else {
+ mTrailingSingleQuotesCount = 0;
+ }
+ mAutoCorrection = null;
+ }
+
+ /**
+ * Internal method to retrieve reasonable proximity info for a character.
+ */
+ private void addKeyInfo(final int codePoint, final Keyboard keyboard) {
+ for (final Key key : keyboard.mKeys) {
+ if (key.mCode == codePoint) {
+ final int x = key.mX + key.mWidth / 2;
+ final int y = key.mY + key.mHeight / 2;
+ add(codePoint, x, y);
+ return;
+ }
+ }
+ add(codePoint, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
}
/**
- * Swaps the first and second values in the codes array if the primary code is not the first
- * value in the array but the second. This happens when the preferred key is not the key that
- * the user released the finger on.
- * @param primaryCode the preferred character
- * @param codes array of codes based on distance from touch point
+ * Set the currently composing word to the one passed as an argument.
+ * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity.
*/
- private void correctPrimaryJuxtapos(int primaryCode, int[] codes) {
- if (codes.length < 2) return;
- if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) {
- codes[1] = codes[0];
- codes[0] = primaryCode;
+ public void setComposingWord(final CharSequence word, final Keyboard keyboard) {
+ reset();
+ final int length = word.length();
+ for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) {
+ int codePoint = Character.codePointAt(word, i);
+ addKeyInfo(codePoint, keyboard);
}
+ mIsResumed = true;
}
/**
* Delete the last keystroke as a result of hitting backspace.
*/
public void deleteLast() {
- final int codesSize = mCodes.size();
- if (codesSize > 0) {
- mCodes.remove(codesSize - 1);
- final int lastPos = mTypedWord.length() - 1;
- char last = mTypedWord.charAt(lastPos);
- mTypedWord.deleteCharAt(lastPos);
- if (Character.isUpperCase(last)) mCapsCount--;
+ final int size = size();
+ if (size > 0) {
+ // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs
+ final int stringBuilderLength = mTypedWord.length();
+ if (stringBuilderLength < size) {
+ throw new RuntimeException(
+ "In WordComposer: mCodes and mTypedWords have non-matching lengths");
+ }
+ final int lastChar = mTypedWord.codePointBefore(stringBuilderLength);
+ if (Character.isSupplementaryCodePoint(lastChar)) {
+ mTypedWord.delete(stringBuilderLength - 2, stringBuilderLength);
+ } else {
+ mTypedWord.deleteCharAt(stringBuilderLength - 1);
+ }
+ if (Character.isUpperCase(lastChar)) mCapsCount--;
+ refreshSize();
}
- if (mTypedLength > 0) {
- --mTypedLength;
+ // We may have deleted the last one.
+ if (0 == size()) {
+ mIsFirstCharCapitalized = false;
}
+ if (mTrailingSingleQuotesCount > 0) {
+ --mTrailingSingleQuotesCount;
+ } else {
+ int i = mTypedWord.length();
+ while (i > 0) {
+ i = mTypedWord.offsetByCodePoints(i, -1);
+ if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break;
+ ++mTrailingSingleQuotesCount;
+ }
+ }
+ mAutoCorrection = null;
}
/**
* Returns the word as it was typed, without any correction applied.
- * @return the word that was typed so far
+ * @return the word that was typed so far. Never returns null.
*/
- public CharSequence getTypedWord() {
- int wordSize = mCodes.size();
- if (wordSize == 0) {
- return null;
- }
- return mTypedWord;
+ public String getTypedWord() {
+ return mTypedWord.toString();
}
- public void setFirstCharCapitalized(boolean capitalized) {
- mIsFirstCharCapitalized = capitalized;
- }
-
/**
* Whether or not the user typed a capital letter as the first letter in the word
* @return capitalization preference
@@ -188,6 +254,10 @@ public class WordComposer {
return mIsFirstCharCapitalized;
}
+ public int trailingSingleQuotesCount() {
+ return mTrailingSingleQuotesCount;
+ }
+
/**
* Whether or not all of the user typed chars are upper case
* @return true if all user typed chars are upper case, false otherwise
@@ -197,29 +267,13 @@ public class WordComposer {
}
/**
- * Stores the user's selected word, before it is actually committed to the text field.
- * @param preferred
- */
- public void setPreferredWord(String preferred) {
- mPreferredWord = preferred;
- }
-
- /**
- * Return the word chosen by the user, or the typed word if no other word was chosen.
- * @return the preferred word
- */
- public CharSequence getPreferredWord() {
- return mPreferredWord != null ? mPreferredWord : getTypedWord();
- }
-
- /**
* Returns true if more than one character is upper case, otherwise returns false.
*/
public boolean isMostlyCaps() {
return mCapsCount > 1;
}
- /**
+ /**
* Saves the reason why the word is capitalized - whether it was automatic or
* due to the user hitting shift in the middle of a sentence.
* @param auto whether it was an automatic capitalization due to start of sentence
@@ -235,4 +289,62 @@ public class WordComposer {
public boolean isAutoCapitalized() {
return mAutoCapitalized;
}
+
+ /**
+ * Sets the auto-correction for this word.
+ */
+ public void setAutoCorrection(final CharSequence correction) {
+ mAutoCorrection = correction;
+ }
+
+ /**
+ * @return the auto-correction for this word, or null if none.
+ */
+ public CharSequence getAutoCorrectionOrNull() {
+ return mAutoCorrection;
+ }
+
+ /**
+ * @return whether we started composing this word by resuming suggestion on an existing string
+ */
+ public boolean isResumed() {
+ return mIsResumed;
+ }
+
+ // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above.
+ public LastComposedWord commitWord(final int type, final String committedWord,
+ final int separatorCode, final CharSequence prevWord) {
+ // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK
+ // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
+ // the last composed word to ensure this does not happen.
+ final int[] primaryKeyCodes = mPrimaryKeyCodes;
+ final int[] xCoordinates = mXCoordinates;
+ final int[] yCoordinates = mYCoordinates;
+ mPrimaryKeyCodes = new int[N];
+ mXCoordinates = new int[N];
+ mYCoordinates = new int[N];
+ final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes,
+ xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode,
+ prevWord);
+ if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
+ && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
+ lastComposedWord.deactivate();
+ }
+ mTypedWord.setLength(0);
+ refreshSize();
+ mAutoCorrection = null;
+ mIsResumed = false;
+ return lastComposedWord;
+ }
+
+ public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) {
+ mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes;
+ mXCoordinates = lastComposedWord.mXCoordinates;
+ mYCoordinates = lastComposedWord.mYCoordinates;
+ mTypedWord.setLength(0);
+ mTypedWord.append(lastComposedWord.mTypedWord);
+ refreshSize();
+ mAutoCorrection = null; // This will be filled by the next call to updateSuggestion.
+ mIsResumed = true;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/PrivateBinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/WordListInfo.java
index eb740e111..54f04d78f 100644
--- a/java/src/com/android/inputmethod/latin/PrivateBinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/WordListInfo.java
@@ -1,4 +1,4 @@
-/*
+/**
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -16,14 +16,14 @@
package com.android.inputmethod.latin;
-import android.content.Context;
-
-import java.util.List;
-import java.util.Locale;
-
-class PrivateBinaryDictionaryGetter {
- private PrivateBinaryDictionaryGetter() {}
- public static List<AssetFileAddress> getDictionaryFiles(Locale locale, Context context) {
- return null;
+/**
+ * Information container for a word list.
+ */
+public class WordListInfo {
+ public final String mId;
+ public final String mLocale;
+ public WordListInfo(final String id, final String locale) {
+ mId = id;
+ mLocale = locale;
}
}
diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
new file mode 100644
index 000000000..481cdfa47
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.res.TypedArray;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class XmlParseUtils {
+ private XmlParseUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ @SuppressWarnings("serial")
+ public static class ParseException extends XmlPullParserException {
+ public ParseException(String msg, XmlPullParser parser) {
+ super(msg + " at " + parser.getPositionDescription());
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalStartTag extends ParseException {
+ public IllegalStartTag(XmlPullParser parser, String parent) {
+ super("Illegal start tag " + parser.getName() + " in " + parent, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalEndTag extends ParseException {
+ public IllegalEndTag(XmlPullParser parser, String parent) {
+ super("Illegal end tag " + parser.getName() + " in " + parent, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class IllegalAttribute extends ParseException {
+ public IllegalAttribute(XmlPullParser parser, String attribute) {
+ super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class NonEmptyTag extends ParseException{
+ public NonEmptyTag(String tag, XmlPullParser parser) {
+ super(tag + " must be empty tag", parser);
+ }
+ }
+
+ public static void checkEndTag(String tag, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName()))
+ return;
+ throw new NonEmptyTag(tag, parser);
+ }
+
+ public static void checkAttributeExists(TypedArray attr, int attrId, String attrName,
+ String tag, XmlPullParser parser) throws XmlPullParserException {
+ if (attr.hasValue(attrId))
+ return;
+ throw new ParseException(
+ "No " + attrName + " attribute found in <" + tag + "/>", parser);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java/src/com/android/inputmethod/latin/define/JniLibName.java
new file mode 100644
index 000000000..e23e1a968
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.define;
+
+public final class JniLibName {
+ private JniLibName() {
+ // This class is not publicly instantiable.
+ }
+
+ public static final String JNI_LIB_NAME = "jni_latinime";
+}
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
new file mode 100644
index 000000000..de2057669
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.define;
+
+public final class ProductionFlag {
+ private ProductionFlag() {
+ // This class is not publicly instantiable.
+ }
+
+ public static final boolean IS_EXPERIMENTAL = false;
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
new file mode 100644
index 000000000..2c3eee74c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -0,0 +1,1413 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
+import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
+import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
+import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Reads and writes XML files for a FusionDictionary.
+ *
+ * All the methods in this class are static.
+ */
+public class BinaryDictInputOutput {
+
+ final static boolean DBG = MakedictLog.DBG;
+
+ /* Node layout is as follows:
+ * | addressType xx : mask with MASK_GROUP_ADDRESS_TYPE
+ * 2 bits, 00 = no children : FLAG_GROUP_ADDRESS_TYPE_NOADDRESS
+ * f | 01 = 1 byte : FLAG_GROUP_ADDRESS_TYPE_ONEBYTE
+ * l | 10 = 2 bytes : FLAG_GROUP_ADDRESS_TYPE_TWOBYTES
+ * a | 11 = 3 bytes : FLAG_GROUP_ADDRESS_TYPE_THREEBYTES
+ * g | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS
+ * s | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL
+ * | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS
+ * | has bigrams ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_BIGRAMS
+ *
+ * c | IF FLAG_HAS_MULTIPLE_CHARS
+ * h | char, char, char, char n * (1 or 3 bytes) : use CharGroupInfo for i/o helpers
+ * a | end 1 byte, = 0
+ * r | ELSE
+ * s | char 1 or 3 bytes
+ * | END
+ *
+ * f |
+ * r | IF FLAG_IS_TERMINAL
+ * e | frequency 1 byte
+ * q |
+ *
+ * c | IF 00 = FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = addressType
+ * h | // nothing
+ * i | ELSIF 01 = FLAG_GROUP_ADDRESS_TYPE_ONEBYTE == addressType
+ * l | children address, 1 byte
+ * d | ELSIF 10 = FLAG_GROUP_ADDRESS_TYPE_TWOBYTES == addressType
+ * r | children address, 2 bytes
+ * e | ELSE // 11 = FLAG_GROUP_ADDRESS_TYPE_THREEBYTES = addressType
+ * n | children address, 3 bytes
+ * A | END
+ * d
+ * dress
+ *
+ * | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS
+ * | shortcut string list
+ * | IF FLAG_IS_TERMINAL && FLAG_HAS_BIGRAMS
+ * | bigrams address list
+ *
+ * Char format is:
+ * 1 byte = bbbbbbbb match
+ * case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
+ * else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
+ * unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
+ * 00011111 would be outside unicode.
+ * else: iso-latin-1 code
+ * This allows for the whole unicode range to be encoded, including chars outside of
+ * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
+ * characters which should never happen anyway (and still work, but take 3 bytes).
+ *
+ * bigram address list is:
+ * <flags> = | hasNext = 1 bit, 1 = yes, 0 = no : FLAG_ATTRIBUTE_HAS_NEXT
+ * | addressSign = 1 bit, : FLAG_ATTRIBUTE_OFFSET_NEGATIVE
+ * | 1 = must take -address, 0 = must take +address
+ * | xx : mask with MASK_ATTRIBUTE_ADDRESS_TYPE
+ * | addressFormat = 2 bits, 00 = unused : FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE
+ * | 01 = 1 byte : FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE
+ * | 10 = 2 bytes : FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES
+ * | 11 = 3 bytes : FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES
+ * | 4 bits : frequency : mask with FLAG_ATTRIBUTE_FREQUENCY
+ * <address> | IF (01 == FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE == addressFormat)
+ * | read 1 byte, add top 4 bits
+ * | ELSIF (10 == FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES == addressFormat)
+ * | read 2 bytes, add top 4 bits
+ * | ELSE // 11 == FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES == addressFormat
+ * | read 3 bytes, add top 4 bits
+ * | END
+ * | if (FLAG_ATTRIBUTE_OFFSET_NEGATIVE) then address = -address
+ * if (FLAG_ATTRIBUTE_HAS_NEXT) goto bigram_and_shortcut_address_list_is
+ *
+ * shortcut string list is:
+ * <byte size> = GROUP_SHORTCUT_LIST_SIZE_SIZE bytes, big-endian: size of the list, in bytes.
+ * <flags> = | hasNext = 1 bit, 1 = yes, 0 = no : FLAG_ATTRIBUTE_HAS_NEXT
+ * | reserved = 3 bits, must be 0
+ * | 4 bits : frequency : mask with FLAG_ATTRIBUTE_FREQUENCY
+ * <shortcut> = | string of characters at the char format described above, with the terminator
+ * | used to signal the end of the string.
+ * if (FLAG_ATTRIBUTE_HAS_NEXT goto flags
+ */
+
+ private static final int VERSION_1_MAGIC_NUMBER = 0x78B1;
+ private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE;
+ private static final int MINIMUM_SUPPORTED_VERSION = 1;
+ private static final int MAXIMUM_SUPPORTED_VERSION = 2;
+ private static final int NOT_A_VERSION_NUMBER = -1;
+ private static final int FIRST_VERSION_WITH_HEADER_SIZE = 2;
+
+ // These options need to be the same numeric values as the one in the native reading code.
+ private static final int GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
+ private static final int FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
+ private static final int CONTAINS_BIGRAMS_FLAG = 0x8;
+
+ // TODO: Make this value adaptative to content data, store it in the header, and
+ // use it in the reading code.
+ private static final int MAX_WORD_LENGTH = 48;
+
+ private static final int MASK_GROUP_ADDRESS_TYPE = 0xC0;
+ private static final int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00;
+ private static final int FLAG_GROUP_ADDRESS_TYPE_ONEBYTE = 0x40;
+ private static final int FLAG_GROUP_ADDRESS_TYPE_TWOBYTES = 0x80;
+ private static final int FLAG_GROUP_ADDRESS_TYPE_THREEBYTES = 0xC0;
+
+ private static final int FLAG_HAS_MULTIPLE_CHARS = 0x20;
+
+ private static final int FLAG_IS_TERMINAL = 0x10;
+ private static final int FLAG_HAS_SHORTCUT_TARGETS = 0x08;
+ private static final int FLAG_HAS_BIGRAMS = 0x04;
+
+ private static final int FLAG_ATTRIBUTE_HAS_NEXT = 0x80;
+ private static final int FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40;
+ private static final int MASK_ATTRIBUTE_ADDRESS_TYPE = 0x30;
+ private static final int FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10;
+ private static final int FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20;
+ private static final int FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30;
+ private static final int FLAG_ATTRIBUTE_FREQUENCY = 0x0F;
+
+ private static final int GROUP_CHARACTERS_TERMINATOR = 0x1F;
+
+ private static final int GROUP_TERMINATOR_SIZE = 1;
+ private static final int GROUP_FLAGS_SIZE = 1;
+ private static final int GROUP_FREQUENCY_SIZE = 1;
+ private static final int GROUP_MAX_ADDRESS_SIZE = 3;
+ private static final int GROUP_ATTRIBUTE_FLAGS_SIZE = 1;
+ private static final int GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE = 3;
+ private static final int GROUP_SHORTCUT_LIST_SIZE_SIZE = 2;
+
+ private static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE;
+ private static final int INVALID_CHARACTER = -1;
+
+ private static final int MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT = 0x7F; // 127
+ private static final int MAX_CHARGROUPS_IN_A_NODE = 0x7FFF; // 32767
+
+ private static final int MAX_TERMINAL_FREQUENCY = 255;
+ private static final int MAX_BIGRAM_FREQUENCY = 15;
+
+ // Arbitrary limit to how much passes we consider address size compression should
+ // terminate in. At the time of this writing, our largest dictionary completes
+ // compression in five passes.
+ // If the number of passes exceeds this number, makedict bails with an exception on
+ // suspicion that a bug might be causing an infinite loop.
+ private static final int MAX_PASSES = 24;
+
+ /**
+ * A class grouping utility function for our specific character encoding.
+ */
+ private static class CharEncoding {
+
+ private static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20;
+ private static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF;
+
+ /**
+ * Helper method to find out whether this code fits on one byte
+ */
+ private static boolean fitsOnOneByte(int character) {
+ return character >= MINIMAL_ONE_BYTE_CHARACTER_VALUE
+ && character <= MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
+ }
+
+ /**
+ * Compute the size of a character given its character code.
+ *
+ * Char format is:
+ * 1 byte = bbbbbbbb match
+ * case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
+ * else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
+ * unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
+ * 00011111 would be outside unicode.
+ * else: iso-latin-1 code
+ * This allows for the whole unicode range to be encoded, including chars outside of
+ * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
+ * characters which should never happen anyway (and still work, but take 3 bytes).
+ *
+ * @param character the character code.
+ * @return the size in binary encoded-form, either 1 or 3 bytes.
+ */
+ private static int getCharSize(int character) {
+ // See char encoding in FusionDictionary.java
+ if (fitsOnOneByte(character)) return 1;
+ if (INVALID_CHARACTER == character) return 1;
+ return 3;
+ }
+
+ /**
+ * Compute the byte size of a character array.
+ */
+ private static int getCharArraySize(final int[] chars) {
+ int size = 0;
+ for (int character : chars) size += getCharSize(character);
+ return size;
+ }
+
+ /**
+ * Writes a char array to a byte buffer.
+ *
+ * @param codePoints the code point array to write.
+ * @param buffer the byte buffer to write to.
+ * @param index the index in buffer to write the character array to.
+ * @return the index after the last character.
+ */
+ private static int writeCharArray(final int[] codePoints, final byte[] buffer, int index) {
+ for (int codePoint : codePoints) {
+ if (1 == getCharSize(codePoint)) {
+ buffer[index++] = (byte)codePoint;
+ } else {
+ buffer[index++] = (byte)(0xFF & (codePoint >> 16));
+ buffer[index++] = (byte)(0xFF & (codePoint >> 8));
+ buffer[index++] = (byte)(0xFF & codePoint);
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Writes a string with our character format to a byte buffer.
+ *
+ * This will also write the terminator byte.
+ *
+ * @param buffer the byte buffer to write to.
+ * @param origin the offset to write from.
+ * @param word the string to write.
+ * @return the size written, in bytes.
+ */
+ private 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)) {
+ final int codePoint = word.codePointAt(i);
+ if (1 == getCharSize(codePoint)) {
+ buffer[index++] = (byte)codePoint;
+ } else {
+ buffer[index++] = (byte)(0xFF & (codePoint >> 16));
+ buffer[index++] = (byte)(0xFF & (codePoint >> 8));
+ buffer[index++] = (byte)(0xFF & codePoint);
+ }
+ }
+ buffer[index++] = GROUP_CHARACTERS_TERMINATOR;
+ return index - origin;
+ }
+
+ /**
+ * Writes a string with our character format to a ByteArrayOutputStream.
+ *
+ * This will also write the terminator byte.
+ *
+ * @param buffer the ByteArrayOutputStream to write to.
+ * @param word the string to write.
+ */
+ private static void writeString(ByteArrayOutputStream buffer, final String word) {
+ final int length = word.length();
+ 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);
+ } else {
+ buffer.write((byte) (0xFF & (codePoint >> 16)));
+ buffer.write((byte) (0xFF & (codePoint >> 8)));
+ buffer.write((byte) (0xFF & codePoint));
+ }
+ }
+ buffer.write(GROUP_CHARACTERS_TERMINATOR);
+ }
+
+ /**
+ * Reads a string from a RandomAccessFile. This is the converse of the above method.
+ */
+ private static String readString(final RandomAccessFile source) throws IOException {
+ final StringBuilder s = new StringBuilder();
+ int character = readChar(source);
+ while (character != INVALID_CHARACTER) {
+ s.appendCodePoint(character);
+ character = readChar(source);
+ }
+ return s.toString();
+ }
+
+ /**
+ * Reads a character from the file.
+ *
+ * This follows the character format documented earlier in this source file.
+ *
+ * @param source the file, positioned over an encoded character.
+ * @return the character code.
+ */
+ private static int readChar(RandomAccessFile source) throws IOException {
+ int character = source.readUnsignedByte();
+ if (!fitsOnOneByte(character)) {
+ if (GROUP_CHARACTERS_TERMINATOR == character)
+ return INVALID_CHARACTER;
+ character <<= 16;
+ character += source.readUnsignedShort();
+ }
+ return character;
+ }
+ }
+
+ /**
+ * Compute the binary size of the character array in a group
+ *
+ * If only one character, this is the size of this character. If many, it's the sum of their
+ * sizes + 1 byte for the terminator.
+ *
+ * @param group the group
+ * @return the size of the char array, including the terminator if any
+ */
+ private static int getGroupCharactersSize(CharGroup group) {
+ int size = CharEncoding.getCharArraySize(group.mChars);
+ if (group.hasSeveralChars()) size += GROUP_TERMINATOR_SIZE;
+ return size;
+ }
+
+ /**
+ * Compute the binary size of the group count
+ * @param count the group count
+ * @return the size of the group count, either 1 or 2 bytes.
+ */
+ private static int getGroupCountSize(final int count) {
+ if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= count) {
+ return 1;
+ } else if (MAX_CHARGROUPS_IN_A_NODE >= count) {
+ return 2;
+ } else {
+ throw new RuntimeException("Can't have more than " + MAX_CHARGROUPS_IN_A_NODE
+ + " groups in a node (found " + count +")");
+ }
+ }
+
+ /**
+ * Compute the binary size of the group count for a node
+ * @param node the node
+ * @return the size of the group count, either 1 or 2 bytes.
+ */
+ private static int getGroupCountSize(final Node node) {
+ return getGroupCountSize(node.mData.size());
+ }
+
+ /**
+ * Compute the size of a shortcut in bytes.
+ */
+ private static int getShortcutSize(final WeightedString shortcut) {
+ int size = GROUP_ATTRIBUTE_FLAGS_SIZE;
+ final String word = shortcut.mWord;
+ final int length = word.length();
+ for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
+ final int codePoint = word.codePointAt(i);
+ size += CharEncoding.getCharSize(codePoint);
+ }
+ size += GROUP_TERMINATOR_SIZE;
+ return size;
+ }
+
+ /**
+ * Compute the size of a shortcut list in bytes.
+ *
+ * This is known in advance and does not change according to position in the file
+ * like address lists do.
+ */
+ private static int getShortcutListSize(final ArrayList<WeightedString> shortcutList) {
+ if (null == shortcutList) return 0;
+ int size = GROUP_SHORTCUT_LIST_SIZE_SIZE;
+ for (final WeightedString shortcut : shortcutList) {
+ size += getShortcutSize(shortcut);
+ }
+ return size;
+ }
+
+ /**
+ * Compute the maximum size of a CharGroup, assuming 3-byte addresses for everything.
+ *
+ * @param group the CharGroup to compute the size of.
+ * @return the maximum size of the group.
+ */
+ private static int getCharGroupMaximumSize(CharGroup group) {
+ int size = getGroupCharactersSize(group) + GROUP_FLAGS_SIZE;
+ // If terminal, one byte for the frequency
+ if (group.isTerminal()) size += GROUP_FREQUENCY_SIZE;
+ size += GROUP_MAX_ADDRESS_SIZE; // For children address
+ size += getShortcutListSize(group.mShortcutTargets);
+ if (null != group.mBigrams) {
+ size += (GROUP_ATTRIBUTE_FLAGS_SIZE + GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE)
+ * group.mBigrams.size();
+ }
+ return size;
+ }
+
+ /**
+ * Compute the maximum size of a node, assuming 3-byte addresses for everything, and caches
+ * it in the 'actualSize' member of the node.
+ *
+ * @param node the node to compute the maximum size of.
+ */
+ private static void setNodeMaximumSize(Node node) {
+ int size = getGroupCountSize(node);
+ for (CharGroup g : node.mData) {
+ final int groupSize = getCharGroupMaximumSize(g);
+ g.mCachedSize = groupSize;
+ size += groupSize;
+ }
+ node.mCachedSize = size;
+ }
+
+ /**
+ * Helper method to hide the actual value of the no children address.
+ */
+ private static boolean hasChildrenAddress(int address) {
+ return NO_CHILDREN_ADDRESS != address;
+ }
+
+ /**
+ * Compute the size, in bytes, that an address will occupy.
+ *
+ * This can be used either for children addresses (which are always positive) or for
+ * attribute, which may be positive or negative but
+ * store their sign bit separately.
+ *
+ * @param address the address
+ * @return the byte size.
+ */
+ private static int getByteSize(int address) {
+ assert(address < 0x1000000);
+ if (!hasChildrenAddress(address)) {
+ return 0;
+ } else if (Math.abs(address) < 0x100) {
+ return 1;
+ } else if (Math.abs(address) < 0x10000) {
+ return 2;
+ } else {
+ return 3;
+ }
+ }
+ // End utility methods.
+
+ // This method is responsible for finding a nice ordering of the nodes that favors run-time
+ // cache performance and dictionary size.
+ /* package for tests */ static ArrayList<Node> flattenTree(Node root) {
+ final int treeSize = FusionDictionary.countCharGroups(root);
+ MakedictLog.i("Counted nodes : " + treeSize);
+ final ArrayList<Node> flatTree = new ArrayList<Node>(treeSize);
+ return flattenTreeInner(flatTree, root);
+ }
+
+ private static ArrayList<Node> flattenTreeInner(ArrayList<Node> list, Node node) {
+ // Removing the node is necessary if the tails are merged, because we would then
+ // add the same node several times when we only want it once. A number of places in
+ // the code also depends on any node being only once in the list.
+ // Merging tails can only be done if there are no attributes. Searching for attributes
+ // in LatinIME code depends on a total breadth-first ordering, which merging tails
+ // breaks. If there are no attributes, it should be fine (and reduce the file size)
+ // to merge tails, and removing the node from the list would be necessary. However,
+ // we don't merge tails because breaking the breadth-first ordering would result in
+ // extreme overhead at bigram lookup time (it would make the search function O(n) instead
+ // of the current O(log(n)), where n=number of nodes in the dictionary which is pretty
+ // high).
+ // If no nodes are ever merged, we can't have the same node twice in the list, hence
+ // searching for duplicates in unnecessary. It is also very performance consuming,
+ // since `list' is an ArrayList so it's an O(n) operation that runs on all nodes, making
+ // this simple list.remove operation O(n*n) overall. On Android this overhead is very
+ // high.
+ // For future reference, the code to remove duplicate is a simple : list.remove(node);
+ list.add(node);
+ final ArrayList<CharGroup> branches = node.mData;
+ final int nodeSize = branches.size();
+ for (CharGroup group : branches) {
+ if (null != group.mChildren) flattenTreeInner(list, group.mChildren);
+ }
+ return list;
+ }
+
+ /**
+ * Finds the absolute address of a word in the dictionary.
+ *
+ * @param dict the dictionary in which to search.
+ * @param word the word we are searching for.
+ * @return the word address. If it is not found, an exception is thrown.
+ */
+ private static int findAddressOfWord(final FusionDictionary dict, final String word) {
+ return FusionDictionary.findWordInTree(dict.mRoot, word).mCachedAddress;
+ }
+
+ /**
+ * Computes the actual node size, based on the cached addresses of the children nodes.
+ *
+ * Each node stores its tentative address. During dictionary address computing, these
+ * are not final, but they can be used to compute the node size (the node size depends
+ * on the address of the children because the number of bytes necessary to store an
+ * address depends on its numeric value. The return value indicates whether the node
+ * contents (as in, any of the addresses stored in the cache fields) have changed with
+ * respect to their previous value.
+ *
+ * @param node the node to compute the size of.
+ * @param dict the dictionary in which the word/attributes are to be found.
+ * @return false if none of the cached addresses inside the node changed, true otherwise.
+ */
+ private static boolean computeActualNodeSize(Node node, FusionDictionary dict) {
+ boolean changed = false;
+ int size = getGroupCountSize(node);
+ for (CharGroup group : node.mData) {
+ if (group.mCachedAddress != node.mCachedAddress + size) {
+ changed = true;
+ group.mCachedAddress = node.mCachedAddress + size;
+ }
+ int groupSize = GROUP_FLAGS_SIZE + getGroupCharactersSize(group);
+ if (group.isTerminal()) groupSize += GROUP_FREQUENCY_SIZE;
+ if (null != group.mChildren) {
+ final int offsetBasePoint= groupSize + node.mCachedAddress + size;
+ final int offset = group.mChildren.mCachedAddress - offsetBasePoint;
+ groupSize += getByteSize(offset);
+ }
+ groupSize += getShortcutListSize(group.mShortcutTargets);
+ if (null != group.mBigrams) {
+ for (WeightedString bigram : group.mBigrams) {
+ final int offsetBasePoint = groupSize + node.mCachedAddress + size
+ + GROUP_FLAGS_SIZE;
+ final int addressOfBigram = findAddressOfWord(dict, bigram.mWord);
+ final int offset = addressOfBigram - offsetBasePoint;
+ groupSize += getByteSize(offset) + GROUP_FLAGS_SIZE;
+ }
+ }
+ group.mCachedSize = groupSize;
+ size += groupSize;
+ }
+ if (node.mCachedSize != size) {
+ node.mCachedSize = size;
+ changed = true;
+ }
+ return changed;
+ }
+
+ /**
+ * Computes the byte size of a list of nodes and updates each node cached position.
+ *
+ * @param flatNodes the array of nodes.
+ * @return the byte size of the entire stack.
+ */
+ private static int stackNodes(ArrayList<Node> flatNodes) {
+ int nodeOffset = 0;
+ for (Node n : flatNodes) {
+ n.mCachedAddress = nodeOffset;
+ int groupCountSize = getGroupCountSize(n);
+ int groupOffset = 0;
+ for (CharGroup g : n.mData) {
+ g.mCachedAddress = groupCountSize + nodeOffset + groupOffset;
+ groupOffset += g.mCachedSize;
+ }
+ if (groupOffset + groupCountSize != n.mCachedSize) {
+ throw new RuntimeException("Bug : Stored and computed node size differ");
+ }
+ nodeOffset += n.mCachedSize;
+ }
+ return nodeOffset;
+ }
+
+ /**
+ * Compute the addresses and sizes of an ordered node array.
+ *
+ * This method takes a node array and will update its cached address and size values
+ * so that they can be written into a file. It determines the smallest size each of the
+ * nodes can be given the addresses of its children and attributes, and store that into
+ * each node.
+ * The order of the node is given by the order of the array. This method makes no effort
+ * to find a good order; it only mechanically computes the size this order results in.
+ *
+ * @param dict the dictionary
+ * @param flatNodes the ordered array of nodes
+ * @return the same array it was passed. The nodes have been updated for address and size.
+ */
+ private static ArrayList<Node> computeAddresses(FusionDictionary dict,
+ ArrayList<Node> flatNodes) {
+ // First get the worst sizes and offsets
+ for (Node n : flatNodes) setNodeMaximumSize(n);
+ final int offset = stackNodes(flatNodes);
+
+ MakedictLog.i("Compressing the array addresses. Original size : " + offset);
+ MakedictLog.i("(Recursively seen size : " + offset + ")");
+
+ int passes = 0;
+ boolean changesDone = false;
+ do {
+ changesDone = false;
+ for (Node n : flatNodes) {
+ final int oldNodeSize = n.mCachedSize;
+ final boolean changed = computeActualNodeSize(n, dict);
+ final int newNodeSize = n.mCachedSize;
+ if (oldNodeSize < newNodeSize) throw new RuntimeException("Increased size ?!");
+ changesDone |= changed;
+ }
+ stackNodes(flatNodes);
+ ++passes;
+ if (passes > MAX_PASSES) throw new RuntimeException("Too many passes - probably a bug");
+ } while (changesDone);
+
+ final Node lastNode = flatNodes.get(flatNodes.size() - 1);
+ MakedictLog.i("Compression complete in " + passes + " passes.");
+ MakedictLog.i("After address compression : "
+ + (lastNode.mCachedAddress + lastNode.mCachedSize));
+
+ return flatNodes;
+ }
+
+ /**
+ * Sanity-checking method.
+ *
+ * This method checks an array of node for juxtaposition, that is, it will do
+ * nothing if each node's cached address is actually the previous node's address
+ * plus the previous node's size.
+ * If this is not the case, it will throw an exception.
+ *
+ * @param array the array node to check
+ */
+ private static void checkFlatNodeArray(ArrayList<Node> array) {
+ int offset = 0;
+ int index = 0;
+ for (Node n : array) {
+ if (n.mCachedAddress != offset) {
+ throw new RuntimeException("Wrong address for node " + index
+ + " : expected " + offset + ", got " + n.mCachedAddress);
+ }
+ ++index;
+ offset += n.mCachedSize;
+ }
+ }
+
+ /**
+ * Helper method to write a variable-size address to a file.
+ *
+ * @param buffer the buffer to write to.
+ * @param index the index in the buffer to write the address to.
+ * @param address the address to write.
+ * @return the size in bytes the address actually took.
+ */
+ private static int writeVariableAddress(final byte[] buffer, int index, final int address) {
+ switch (getByteSize(address)) {
+ case 1:
+ buffer[index++] = (byte)address;
+ return 1;
+ case 2:
+ buffer[index++] = (byte)(0xFF & (address >> 8));
+ buffer[index++] = (byte)(0xFF & address);
+ return 2;
+ case 3:
+ buffer[index++] = (byte)(0xFF & (address >> 16));
+ buffer[index++] = (byte)(0xFF & (address >> 8));
+ buffer[index++] = (byte)(0xFF & address);
+ return 3;
+ case 0:
+ return 0;
+ default:
+ throw new RuntimeException("Address " + address + " has a strange size");
+ }
+ }
+
+ private static byte makeCharGroupFlags(final CharGroup group, final int groupAddress,
+ final int childrenOffset) {
+ byte flags = 0;
+ if (group.mChars.length > 1) flags |= FLAG_HAS_MULTIPLE_CHARS;
+ if (group.mFrequency >= 0) {
+ flags |= FLAG_IS_TERMINAL;
+ }
+ if (null != group.mChildren) {
+ switch (getByteSize(childrenOffset)) {
+ case 1:
+ flags |= FLAG_GROUP_ADDRESS_TYPE_ONEBYTE;
+ break;
+ case 2:
+ flags |= FLAG_GROUP_ADDRESS_TYPE_TWOBYTES;
+ break;
+ case 3:
+ flags |= FLAG_GROUP_ADDRESS_TYPE_THREEBYTES;
+ break;
+ default:
+ throw new RuntimeException("Node with a strange address");
+ }
+ }
+ if (null != group.mShortcutTargets) {
+ if (DBG && 0 == group.mShortcutTargets.size()) {
+ throw new RuntimeException("0-sized shortcut list must be null");
+ }
+ flags |= FLAG_HAS_SHORTCUT_TARGETS;
+ }
+ if (null != group.mBigrams) {
+ if (DBG && 0 == group.mBigrams.size()) {
+ throw new RuntimeException("0-sized bigram list must be null");
+ }
+ flags |= FLAG_HAS_BIGRAMS;
+ }
+ return flags;
+ }
+
+ /**
+ * Makes the flag value for a bigram.
+ *
+ * @param more whether there are more bigrams after this one.
+ * @param offset the offset of the bigram.
+ * @param bigramFrequency the frequency of the bigram, 0..255.
+ * @param unigramFrequency the unigram frequency of the same word, 0..255.
+ * @param word the second bigram, for debugging purposes
+ * @return the flags
+ */
+ private static final int makeBigramFlags(final boolean more, final int offset,
+ int bigramFrequency, final int unigramFrequency, final String word) {
+ int bigramFlags = (more ? FLAG_ATTRIBUTE_HAS_NEXT : 0)
+ + (offset < 0 ? FLAG_ATTRIBUTE_OFFSET_NEGATIVE : 0);
+ switch (getByteSize(offset)) {
+ case 1:
+ bigramFlags |= FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE;
+ break;
+ case 2:
+ bigramFlags |= FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES;
+ break;
+ case 3:
+ bigramFlags |= FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES;
+ break;
+ default:
+ throw new RuntimeException("Strange offset size");
+ }
+ if (unigramFrequency > bigramFrequency) {
+ MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
+ + "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
+ + word + " is " + unigramFrequency);
+ bigramFrequency = unigramFrequency;
+ }
+ // 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
+ // represents an increase of 16 steps: a value of 15 will be interpreted as the median
+ // value of the 16th step. In all justice, if the bigram frequency is low enough to be
+ // rounded below the first step (which means it is less than half a step higher than the
+ // unigram frequency) then the unigram frequency itself is the best approximation of the
+ // bigram freq that we could possibly supply, hence we should *not* include this bigram
+ // in the file at all.
+ // until this is done, we'll write 0 and slightly overestimate this case.
+ // In other words, 0 means "between 0.5 step and 1.5 step", 1 means "between 1.5 step
+ // and 2.5 steps", and 15 means "between 15.5 steps and 16.5 steps". So we want to
+ // divide our range [unigramFreq..MAX_TERMINAL_FREQUENCY] in 16.5 steps to get the
+ // step size. Then we compute the start of the first step (the one where value 0 starts)
+ // by adding half-a-step to the unigramFrequency. From there, we compute the integer
+ // number of steps to the bigramFrequency. One last thing: we want our steps to include
+ // their lower bound and exclude their higher bound so we need to have the first step
+ // start at exactly 1 unit higher than floor(unigramFreq + half a step).
+ // Note : to reconstruct the score, the dictionary reader will need to divide
+ // MAX_TERMINAL_FREQUENCY - unigramFreq by 16.5 likewise, and add
+ // (discretizedFrequency + 0.5) times this value to get the median value of the step,
+ // which is the best approximation. This is how we get the most precise result with
+ // only four bits.
+ final float stepSize =
+ (MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5f + MAX_BIGRAM_FREQUENCY);
+ final float firstStepStart = 1 + unigramFrequency + (stepSize / 2.0f);
+ final int discretizedFrequency = (int)((bigramFrequency - firstStepStart) / stepSize);
+ // If the bigram freq is less than half-a-step higher than the unigram freq, we get -1
+ // here. The best approximation would be the unigram freq itself, so we should not
+ // 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 & FLAG_ATTRIBUTE_FREQUENCY;
+ return bigramFlags;
+ }
+
+ /**
+ * Makes the 2-byte value for options flags.
+ */
+ private static final int makeOptionsValue(final FusionDictionary dictionary) {
+ final DictionaryOptions options = dictionary.mOptions;
+ final boolean hasBigrams = dictionary.hasBigrams();
+ return (options.mFrenchLigatureProcessing ? FRENCH_LIGATURE_PROCESSING_FLAG : 0)
+ + (options.mGermanUmlautProcessing ? GERMAN_UMLAUT_PROCESSING_FLAG : 0)
+ + (hasBigrams ? CONTAINS_BIGRAMS_FLAG : 0);
+ }
+
+ /**
+ * Makes the flag value for a shortcut.
+ *
+ * @param more whether there are more attributes after this one.
+ * @param frequency the frequency of the attribute, 0..15
+ * @return the flags
+ */
+ private static final int makeShortcutFlags(final boolean more, final int frequency) {
+ return (more ? FLAG_ATTRIBUTE_HAS_NEXT : 0) + (frequency & FLAG_ATTRIBUTE_FREQUENCY);
+ }
+
+ /**
+ * Write a node to memory. The node is expected to have its final position cached.
+ *
+ * This can be an empty map, but the more is inside the faster the lookups will be. It can
+ * be carried on as long as nodes do not move.
+ *
+ * @param dict the dictionary the node is a part of (for relative offsets).
+ * @param buffer the memory buffer to write to.
+ * @param node the node to write.
+ * @return the address of the END of the node.
+ */
+ private static int writePlacedNode(FusionDictionary dict, byte[] buffer, Node node) {
+ int index = node.mCachedAddress;
+
+ final int groupCount = node.mData.size();
+ final int countSize = getGroupCountSize(node);
+ if (1 == countSize) {
+ buffer[index++] = (byte)groupCount;
+ } else if (2 == countSize) {
+ // We need to signal 2-byte size by setting the top bit of the MSB to 1, so
+ // we | 0x80 to do this.
+ buffer[index++] = (byte)((groupCount >> 8) | 0x80);
+ buffer[index++] = (byte)(groupCount & 0xFF);
+ } else {
+ throw new RuntimeException("Strange size from getGroupCountSize : " + countSize);
+ }
+ int groupAddress = index;
+ for (int i = 0; i < groupCount; ++i) {
+ CharGroup group = node.mData.get(i);
+ if (index != group.mCachedAddress) throw new RuntimeException("Bug: write index is not "
+ + "the same as the cached address of the group : "
+ + index + " <> " + group.mCachedAddress);
+ groupAddress += GROUP_FLAGS_SIZE + getGroupCharactersSize(group);
+ // Sanity checks.
+ if (DBG && group.mFrequency > MAX_TERMINAL_FREQUENCY) {
+ throw new RuntimeException("A node has a frequency > " + MAX_TERMINAL_FREQUENCY
+ + " : " + group.mFrequency);
+ }
+ if (group.mFrequency >= 0) groupAddress += GROUP_FREQUENCY_SIZE;
+ final int childrenOffset = null == group.mChildren
+ ? NO_CHILDREN_ADDRESS : group.mChildren.mCachedAddress - groupAddress;
+ byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset);
+ buffer[index++] = flags;
+ index = CharEncoding.writeCharArray(group.mChars, buffer, index);
+ if (group.hasSeveralChars()) {
+ buffer[index++] = GROUP_CHARACTERS_TERMINATOR;
+ }
+ if (group.mFrequency >= 0) {
+ buffer[index++] = (byte) group.mFrequency;
+ }
+ final int shift = writeVariableAddress(buffer, index, childrenOffset);
+ index += shift;
+ groupAddress += shift;
+
+ // Write shortcuts
+ if (null != group.mShortcutTargets) {
+ final int indexOfShortcutByteSize = index;
+ index += GROUP_SHORTCUT_LIST_SIZE_SIZE;
+ groupAddress += GROUP_SHORTCUT_LIST_SIZE_SIZE;
+ final Iterator<WeightedString> shortcutIterator = group.mShortcutTargets.iterator();
+ while (shortcutIterator.hasNext()) {
+ final WeightedString target = shortcutIterator.next();
+ ++groupAddress;
+ int shortcutFlags = makeShortcutFlags(shortcutIterator.hasNext(),
+ target.mFrequency);
+ buffer[index++] = (byte)shortcutFlags;
+ final int shortcutShift = CharEncoding.writeString(buffer, index, target.mWord);
+ index += shortcutShift;
+ groupAddress += shortcutShift;
+ }
+ final int shortcutByteSize = index - indexOfShortcutByteSize;
+ if (shortcutByteSize > 0xFFFF) {
+ throw new RuntimeException("Shortcut list too large");
+ }
+ buffer[indexOfShortcutByteSize] = (byte)(shortcutByteSize >> 8);
+ buffer[indexOfShortcutByteSize + 1] = (byte)(shortcutByteSize & 0xFF);
+ }
+ // Write bigrams
+ if (null != group.mBigrams) {
+ final Iterator<WeightedString> bigramIterator = group.mBigrams.iterator();
+ while (bigramIterator.hasNext()) {
+ final WeightedString bigram = bigramIterator.next();
+ final CharGroup target =
+ FusionDictionary.findWordInTree(dict.mRoot, bigram.mWord);
+ final int addressOfBigram = target.mCachedAddress;
+ final int unigramFrequencyForThisWord = target.mFrequency;
+ ++groupAddress;
+ final int offset = addressOfBigram - groupAddress;
+ int bigramFlags = makeBigramFlags(bigramIterator.hasNext(), offset,
+ bigram.mFrequency, unigramFrequencyForThisWord, bigram.mWord);
+ buffer[index++] = (byte)bigramFlags;
+ final int bigramShift = writeVariableAddress(buffer, index, Math.abs(offset));
+ index += bigramShift;
+ groupAddress += bigramShift;
+ }
+ }
+
+ }
+ if (index != node.mCachedAddress + node.mCachedSize) throw new RuntimeException(
+ "Not the same size : written "
+ + (index - node.mCachedAddress) + " bytes out of a node that should have "
+ + node.mCachedSize + " bytes");
+ return index;
+ }
+
+ /**
+ * Dumps a collection of useful statistics about a node array.
+ *
+ * This prints purely informative stuff, like the total estimated file size, the
+ * number of nodes, of character groups, the repartition of each address size, etc
+ *
+ * @param nodes the node array.
+ */
+ private static void showStatistics(ArrayList<Node> nodes) {
+ int firstTerminalAddress = Integer.MAX_VALUE;
+ int lastTerminalAddress = Integer.MIN_VALUE;
+ int size = 0;
+ int charGroups = 0;
+ int maxGroups = 0;
+ int maxRuns = 0;
+ for (Node n : nodes) {
+ if (maxGroups < n.mData.size()) maxGroups = n.mData.size();
+ for (CharGroup cg : n.mData) {
+ ++charGroups;
+ if (cg.mChars.length > maxRuns) maxRuns = cg.mChars.length;
+ if (cg.mFrequency >= 0) {
+ if (n.mCachedAddress < firstTerminalAddress)
+ firstTerminalAddress = n.mCachedAddress;
+ if (n.mCachedAddress > lastTerminalAddress)
+ lastTerminalAddress = n.mCachedAddress;
+ }
+ }
+ if (n.mCachedAddress + n.mCachedSize > size) size = n.mCachedAddress + n.mCachedSize;
+ }
+ final int[] groupCounts = new int[maxGroups + 1];
+ final int[] runCounts = new int[maxRuns + 1];
+ for (Node n : nodes) {
+ ++groupCounts[n.mData.size()];
+ for (CharGroup cg : n.mData) {
+ ++runCounts[cg.mChars.length];
+ }
+ }
+
+ MakedictLog.i("Statistics:\n"
+ + " total file size " + size + "\n"
+ + " " + nodes.size() + " nodes\n"
+ + " " + charGroups + " groups (" + ((float)charGroups / nodes.size())
+ + " groups per node)\n"
+ + " first terminal at " + firstTerminalAddress + "\n"
+ + " last terminal at " + lastTerminalAddress + "\n"
+ + " Group stats : max = " + maxGroups);
+ for (int i = 0; i < groupCounts.length; ++i) {
+ MakedictLog.i(" " + i + " : " + groupCounts[i]);
+ }
+ MakedictLog.i(" Character run stats : max = " + maxRuns);
+ for (int i = 0; i < runCounts.length; ++i) {
+ MakedictLog.i(" " + i + " : " + runCounts[i]);
+ }
+ }
+
+ /**
+ * Dumps a FusionDictionary to a file.
+ *
+ * This is the public entry point to write a dictionary to a file.
+ *
+ * @param destination the stream to write the binary data to.
+ * @param dict the dictionary to write.
+ * @param version the version of the format to write, currently either 1 or 2.
+ */
+ public static void writeDictionaryBinary(final OutputStream destination,
+ final FusionDictionary dict, final int version)
+ throws IOException, UnsupportedFormatException {
+
+ // Addresses are limited to 3 bytes, but since addresses can be relative to each node, the
+ // structure itself is not limited to 16MB. However, if it is over 16MB deciding the order
+ // of the nodes becomes a quite complicated problem, because though the dictionary itself
+ // does not have a size limit, each node must still be within 16MB of all its children and
+ // parents. As long as this is ensured, the dictionary file may grow to any size.
+
+ if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION) {
+ throw new UnsupportedFormatException("Requested file format version " + version
+ + ", but this implementation only supports versions "
+ + MINIMUM_SUPPORTED_VERSION + " through " + MAXIMUM_SUPPORTED_VERSION);
+ }
+
+ ByteArrayOutputStream headerBuffer = new ByteArrayOutputStream(256);
+
+ // The magic number in big-endian order.
+ if (version >= FIRST_VERSION_WITH_HEADER_SIZE) {
+ // Magic number for version 2+.
+ headerBuffer.write((byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 24)));
+ headerBuffer.write((byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 16)));
+ headerBuffer.write((byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 8)));
+ headerBuffer.write((byte) (0xFF & VERSION_2_MAGIC_NUMBER));
+ // Dictionary version.
+ headerBuffer.write((byte) (0xFF & (version >> 8)));
+ headerBuffer.write((byte) (0xFF & version));
+ } else {
+ // Magic number for version 1.
+ headerBuffer.write((byte) (0xFF & (VERSION_1_MAGIC_NUMBER >> 8)));
+ headerBuffer.write((byte) (0xFF & VERSION_1_MAGIC_NUMBER));
+ // Dictionary version.
+ headerBuffer.write((byte) (0xFF & version));
+ }
+ // Options flags
+ final int options = makeOptionsValue(dict);
+ headerBuffer.write((byte) (0xFF & (options >> 8)));
+ headerBuffer.write((byte) (0xFF & options));
+ if (version >= FIRST_VERSION_WITH_HEADER_SIZE) {
+ final int headerSizeOffset = headerBuffer.size();
+ // Placeholder to be written later with header size.
+ for (int i = 0; i < 4; ++i) {
+ headerBuffer.write(0);
+ }
+ // Write out the options.
+ for (final String key : dict.mOptions.mAttributes.keySet()) {
+ final String value = dict.mOptions.mAttributes.get(key);
+ CharEncoding.writeString(headerBuffer, key);
+ CharEncoding.writeString(headerBuffer, value);
+ }
+ final int size = headerBuffer.size();
+ final byte[] bytes = headerBuffer.toByteArray();
+ // Write out the header size.
+ bytes[headerSizeOffset] = (byte) (0xFF & (size >> 24));
+ bytes[headerSizeOffset + 1] = (byte) (0xFF & (size >> 16));
+ bytes[headerSizeOffset + 2] = (byte) (0xFF & (size >> 8));
+ bytes[headerSizeOffset + 3] = (byte) (0xFF & (size >> 0));
+ destination.write(bytes);
+ } else {
+ headerBuffer.writeTo(destination);
+ }
+
+ headerBuffer.close();
+
+ // Leave the choice of the optimal node order to the flattenTree function.
+ MakedictLog.i("Flattening the tree...");
+ ArrayList<Node> flatNodes = flattenTree(dict.mRoot);
+
+ MakedictLog.i("Computing addresses...");
+ computeAddresses(dict, flatNodes);
+ MakedictLog.i("Checking array...");
+ if (DBG) checkFlatNodeArray(flatNodes);
+
+ // Create a buffer that matches the final dictionary size.
+ final Node lastNode = flatNodes.get(flatNodes.size() - 1);
+ final int bufferSize =(lastNode.mCachedAddress + lastNode.mCachedSize);
+ final byte[] buffer = new byte[bufferSize];
+ int index = 0;
+
+ MakedictLog.i("Writing file...");
+ int dataEndOffset = 0;
+ for (Node n : flatNodes) {
+ dataEndOffset = writePlacedNode(dict, buffer, n);
+ }
+
+ if (DBG) showStatistics(flatNodes);
+
+ destination.write(buffer, 0, dataEndOffset);
+
+ destination.close();
+ MakedictLog.i("Done");
+ }
+
+
+ // Input methods: Read a binary dictionary to memory.
+ // readDictionaryBinary is the public entry point for them.
+
+ static final int[] characterBuffer = new int[MAX_WORD_LENGTH];
+ private static CharGroupInfo readCharGroup(RandomAccessFile source,
+ final int originalGroupAddress) throws IOException {
+ int addressPointer = originalGroupAddress;
+ final int flags = source.readUnsignedByte();
+ ++addressPointer;
+ final int characters[];
+ if (0 != (flags & FLAG_HAS_MULTIPLE_CHARS)) {
+ int index = 0;
+ int character = CharEncoding.readChar(source);
+ addressPointer += CharEncoding.getCharSize(character);
+ while (-1 != character) {
+ characterBuffer[index++] = character;
+ character = CharEncoding.readChar(source);
+ addressPointer += CharEncoding.getCharSize(character);
+ }
+ characters = Arrays.copyOfRange(characterBuffer, 0, index);
+ } else {
+ final int character = CharEncoding.readChar(source);
+ addressPointer += CharEncoding.getCharSize(character);
+ characters = new int[] { character };
+ }
+ final int frequency;
+ if (0 != (FLAG_IS_TERMINAL & flags)) {
+ ++addressPointer;
+ frequency = source.readUnsignedByte();
+ } else {
+ frequency = CharGroup.NOT_A_TERMINAL;
+ }
+ int childrenAddress = addressPointer;
+ switch (flags & MASK_GROUP_ADDRESS_TYPE) {
+ case FLAG_GROUP_ADDRESS_TYPE_ONEBYTE:
+ childrenAddress += source.readUnsignedByte();
+ addressPointer += 1;
+ break;
+ case FLAG_GROUP_ADDRESS_TYPE_TWOBYTES:
+ childrenAddress += source.readUnsignedShort();
+ addressPointer += 2;
+ break;
+ case FLAG_GROUP_ADDRESS_TYPE_THREEBYTES:
+ childrenAddress += (source.readUnsignedByte() << 16) + source.readUnsignedShort();
+ addressPointer += 3;
+ break;
+ case FLAG_GROUP_ADDRESS_TYPE_NOADDRESS:
+ default:
+ childrenAddress = NO_CHILDREN_ADDRESS;
+ break;
+ }
+ ArrayList<WeightedString> shortcutTargets = null;
+ if (0 != (flags & FLAG_HAS_SHORTCUT_TARGETS)) {
+ final long pointerBefore = source.getFilePointer();
+ shortcutTargets = new ArrayList<WeightedString>();
+ source.readUnsignedShort(); // Skip the size
+ while (true) {
+ final int targetFlags = source.readUnsignedByte();
+ final String word = CharEncoding.readString(source);
+ shortcutTargets.add(new WeightedString(word,
+ targetFlags & FLAG_ATTRIBUTE_FREQUENCY));
+ if (0 == (targetFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break;
+ }
+ addressPointer += (source.getFilePointer() - pointerBefore);
+ }
+ ArrayList<PendingAttribute> bigrams = null;
+ if (0 != (flags & FLAG_HAS_BIGRAMS)) {
+ bigrams = new ArrayList<PendingAttribute>();
+ while (true) {
+ final int bigramFlags = source.readUnsignedByte();
+ ++addressPointer;
+ final int sign = 0 == (bigramFlags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) ? 1 : -1;
+ int bigramAddress = addressPointer;
+ switch (bigramFlags & MASK_ATTRIBUTE_ADDRESS_TYPE) {
+ case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE:
+ bigramAddress += sign * source.readUnsignedByte();
+ addressPointer += 1;
+ break;
+ case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES:
+ bigramAddress += sign * source.readUnsignedShort();
+ addressPointer += 2;
+ break;
+ case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES:
+ final int offset = ((source.readUnsignedByte() << 16)
+ + source.readUnsignedShort());
+ bigramAddress += sign * offset;
+ addressPointer += 3;
+ break;
+ default:
+ throw new RuntimeException("Has bigrams with no address");
+ }
+ bigrams.add(new PendingAttribute(bigramFlags & FLAG_ATTRIBUTE_FREQUENCY,
+ bigramAddress));
+ if (0 == (bigramFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break;
+ }
+ }
+ return new CharGroupInfo(originalGroupAddress, addressPointer, flags, characters, frequency,
+ childrenAddress, shortcutTargets, bigrams);
+ }
+
+ /**
+ * Reads and returns the char group count out of a file and forwards the pointer.
+ */
+ private static int readCharGroupCount(RandomAccessFile source) throws IOException {
+ final int msb = source.readUnsignedByte();
+ if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= msb) {
+ return msb;
+ } else {
+ return ((MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT & msb) << 8)
+ + source.readUnsignedByte();
+ }
+ }
+
+ // The word cache here is a stopgap bandaid to help the catastrophic performance
+ // of this method. Since it performs direct, unbuffered random access to the file and
+ // may be called hundreds of thousands of times, the resulting performance is not
+ // reasonable without some kind of cache. Thus:
+ // TODO: perform buffered I/O here and in other places in the code.
+ private static TreeMap<Integer, String> wordCache = new TreeMap<Integer, String>();
+ /**
+ * Finds, as a string, the word at the address passed as an argument.
+ *
+ * @param source the file to read from.
+ * @param headerSize the size of the header.
+ * @param address the address to seek.
+ * @return the word, as a string.
+ * @throws IOException if the file can't be read.
+ */
+ private static String getWordAtAddress(final RandomAccessFile source, final long headerSize,
+ int address) throws IOException {
+ final String cachedString = wordCache.get(address);
+ if (null != cachedString) return cachedString;
+ final long originalPointer = source.getFilePointer();
+ source.seek(headerSize);
+ final int count = readCharGroupCount(source);
+ int groupOffset = getGroupCountSize(count);
+ final StringBuilder builder = new StringBuilder();
+ String result = null;
+
+ CharGroupInfo last = null;
+ for (int i = count - 1; i >= 0; --i) {
+ CharGroupInfo info = readCharGroup(source, groupOffset);
+ groupOffset = info.mEndAddress;
+ if (info.mOriginalAddress == address) {
+ builder.append(new String(info.mCharacters, 0, info.mCharacters.length));
+ result = builder.toString();
+ break; // and return
+ }
+ if (hasChildrenAddress(info.mChildrenAddress)) {
+ if (info.mChildrenAddress > address) {
+ if (null == last) continue;
+ builder.append(new String(last.mCharacters, 0, last.mCharacters.length));
+ source.seek(last.mChildrenAddress + headerSize);
+ groupOffset = last.mChildrenAddress + 1;
+ i = source.readUnsignedByte();
+ last = null;
+ continue;
+ }
+ last = info;
+ }
+ if (0 == i && hasChildrenAddress(last.mChildrenAddress)) {
+ builder.append(new String(last.mCharacters, 0, last.mCharacters.length));
+ source.seek(last.mChildrenAddress + headerSize);
+ groupOffset = last.mChildrenAddress + 1;
+ i = source.readUnsignedByte();
+ last = null;
+ continue;
+ }
+ }
+ source.seek(originalPointer);
+ wordCache.put(address, result);
+ return result;
+ }
+
+ /**
+ * Reads a single node from a binary file.
+ *
+ * This methods reads the file at the current position of its file pointer. A node is
+ * fully expected to start at the current position.
+ * This will recursively read other nodes into the structure, populating the reverse
+ * maps on the fly and using them to keep track of already read nodes.
+ *
+ * @param source the data file, correctly positioned at the start of a node.
+ * @param headerSize the size, in bytes, of the file header.
+ * @param reverseNodeMap a mapping from addresses to already read nodes.
+ * @param reverseGroupMap a mapping from addresses to already read character groups.
+ * @return the read node with all his children already read.
+ */
+ private static Node readNode(RandomAccessFile source, long headerSize,
+ Map<Integer, Node> reverseNodeMap, Map<Integer, CharGroup> reverseGroupMap)
+ throws IOException {
+ final int nodeOrigin = (int)(source.getFilePointer() - headerSize);
+ final int count = readCharGroupCount(source);
+ final ArrayList<CharGroup> nodeContents = new ArrayList<CharGroup>();
+ int groupOffset = nodeOrigin + getGroupCountSize(count);
+ for (int i = count; i > 0; --i) {
+ CharGroupInfo info = readCharGroup(source, groupOffset);
+ ArrayList<WeightedString> shortcutTargets = info.mShortcutTargets;
+ ArrayList<WeightedString> bigrams = null;
+ if (null != info.mBigrams) {
+ bigrams = new ArrayList<WeightedString>();
+ for (PendingAttribute bigram : info.mBigrams) {
+ final String word = getWordAtAddress(source, headerSize, bigram.mAddress);
+ bigrams.add(new WeightedString(word, bigram.mFrequency));
+ }
+ }
+ if (hasChildrenAddress(info.mChildrenAddress)) {
+ Node children = reverseNodeMap.get(info.mChildrenAddress);
+ if (null == children) {
+ final long currentPosition = source.getFilePointer();
+ source.seek(info.mChildrenAddress + headerSize);
+ children = readNode(source, headerSize, reverseNodeMap, reverseGroupMap);
+ source.seek(currentPosition);
+ }
+ nodeContents.add(
+ new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency,
+ children));
+ } else {
+ nodeContents.add(
+ new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency));
+ }
+ groupOffset = info.mEndAddress;
+ }
+ final Node node = new Node(nodeContents);
+ node.mCachedAddress = nodeOrigin;
+ reverseNodeMap.put(node.mCachedAddress, node);
+ return node;
+ }
+
+ /**
+ * Helper function to get the binary format version from the header.
+ */
+ private static int getFormatVersion(final RandomAccessFile source) throws IOException {
+ final int magic_v1 = source.readUnsignedShort();
+ if (VERSION_1_MAGIC_NUMBER == magic_v1) return source.readUnsignedByte();
+ final int magic_v2 = (magic_v1 << 16) + source.readUnsignedShort();
+ if (VERSION_2_MAGIC_NUMBER == magic_v2) return source.readUnsignedShort();
+ return NOT_A_VERSION_NUMBER;
+ }
+
+ /**
+ * Reads a random access file and returns the memory representation of the dictionary.
+ *
+ * This high-level method takes a binary file and reads its contents, populating a
+ * FusionDictionary structure. The optional dict argument is an existing dictionary to
+ * which words from the file should be added. If it is null, a new dictionary is created.
+ *
+ * @param source the file to read.
+ * @param dict an optional dictionary to add words to, or null.
+ * @return the created (or merged) dictionary.
+ */
+ public static FusionDictionary readDictionaryBinary(final RandomAccessFile source,
+ final FusionDictionary dict) throws IOException, UnsupportedFormatException {
+ // Check file version
+ final int version = getFormatVersion(source);
+ if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION ) {
+ throw new UnsupportedFormatException("This file has version " + version
+ + ", but this implementation does not support versions above "
+ + MAXIMUM_SUPPORTED_VERSION);
+ }
+
+ // Read options
+ final int optionsFlags = source.readUnsignedShort();
+
+ final long headerSize;
+ final HashMap<String, String> options = new HashMap<String, String>();
+ if (version < FIRST_VERSION_WITH_HEADER_SIZE) {
+ headerSize = source.getFilePointer();
+ } else {
+ headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16)
+ + (source.readUnsignedByte() << 8) + source.readUnsignedByte();
+ while (source.getFilePointer() < headerSize) {
+ final String key = CharEncoding.readString(source);
+ final String value = CharEncoding.readString(source);
+ options.put(key, value);
+ }
+ source.seek(headerSize);
+ }
+
+ Map<Integer, Node> reverseNodeMapping = new TreeMap<Integer, Node>();
+ Map<Integer, CharGroup> reverseGroupMapping = new TreeMap<Integer, CharGroup>();
+ final Node root = readNode(source, headerSize, reverseNodeMapping, reverseGroupMapping);
+
+ FusionDictionary newDict = new FusionDictionary(root,
+ new FusionDictionary.DictionaryOptions(options,
+ 0 != (optionsFlags & GERMAN_UMLAUT_PROCESSING_FLAG),
+ 0 != (optionsFlags & FRENCH_LIGATURE_PROCESSING_FLAG)));
+ if (null != dict) {
+ for (final Word w : dict) {
+ newDict.add(w.mWord, w.mFrequency, w.mShortcutTargets);
+ }
+ for (final Word w : dict) {
+ // By construction a binary dictionary may not have bigrams pointing to
+ // words that are not also registered as unigrams so we don't have to avoid
+ // them explicitly here.
+ for (final WeightedString bigram : w.mBigrams) {
+ newDict.setBigram(w.mWord, bigram.mWord, bigram.mFrequency);
+ }
+ }
+ }
+
+ return newDict;
+ }
+
+ /**
+ * Basic test to find out whether the file is a binary dictionary or not.
+ *
+ * Concretely this only tests the magic number.
+ *
+ * @param filename The name of the file to test.
+ * @return true if it's a binary dictionary, false otherwise
+ */
+ public static boolean isBinaryDictionary(final String filename) {
+ try {
+ RandomAccessFile f = new RandomAccessFile(filename, "r");
+ final int version = getFormatVersion(f);
+ return (version >= MINIMUM_SUPPORTED_VERSION && version <= MAXIMUM_SUPPORTED_VERSION);
+ } catch (FileNotFoundException e) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java b/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java
new file mode 100644
index 000000000..ef7dbb251
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+
+import java.util.ArrayList;
+
+/**
+ * Raw char group info straight out of a file. This will contain numbers for addresses.
+ */
+public class CharGroupInfo {
+
+ public final int mOriginalAddress;
+ public final int mEndAddress;
+ public final int mFlags;
+ public final int[] mCharacters;
+ public final int mFrequency;
+ public final int mChildrenAddress;
+ public final ArrayList<WeightedString> mShortcutTargets;
+ public final ArrayList<PendingAttribute> mBigrams;
+
+ public CharGroupInfo(final int originalAddress, final int endAddress, final int flags,
+ final int[] characters, final int frequency, final int childrenAddress,
+ final ArrayList<WeightedString> shortcutTargets,
+ final ArrayList<PendingAttribute> bigrams) {
+ mOriginalAddress = originalAddress;
+ mEndAddress = endAddress;
+ mFlags = flags;
+ mCharacters = characters;
+ mFrequency = frequency;
+ mChildrenAddress = childrenAddress;
+ mShortcutTargets = shortcutTargets;
+ mBigrams = bigrams;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
new file mode 100644
index 000000000..8b53c9427
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -0,0 +1,767 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * A dictionary that can fusion heads and tails of words for more compression.
+ */
+public class FusionDictionary implements Iterable<Word> {
+
+ private static final boolean DBG = MakedictLog.DBG;
+
+ /**
+ * A node of the dictionary, containing several CharGroups.
+ *
+ * A node is but an ordered array of CharGroups, which essentially contain all the
+ * real information.
+ * This class also contains fields to cache size and address, to help with binary
+ * generation.
+ */
+ public static class Node {
+ ArrayList<CharGroup> mData;
+ // To help with binary generation
+ int mCachedSize;
+ int mCachedAddress;
+ public Node() {
+ mData = new ArrayList<CharGroup>();
+ mCachedSize = Integer.MIN_VALUE;
+ mCachedAddress = Integer.MIN_VALUE;
+ }
+ public Node(ArrayList<CharGroup> data) {
+ mData = data;
+ mCachedSize = Integer.MIN_VALUE;
+ mCachedAddress = Integer.MIN_VALUE;
+ }
+ }
+
+ /**
+ * A string with a frequency.
+ *
+ * This represents an "attribute", that is either a bigram or a shortcut.
+ */
+ public static class WeightedString {
+ final String mWord;
+ int mFrequency;
+ public WeightedString(String word, int frequency) {
+ mWord = word;
+ mFrequency = frequency;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(new Object[] { mWord, mFrequency });
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof WeightedString)) return false;
+ WeightedString w = (WeightedString)o;
+ return mWord.equals(w.mWord) && mFrequency == w.mFrequency;
+ }
+ }
+
+ /**
+ * A group of characters, with a frequency, shortcut targets, bigrams, and children.
+ *
+ * This is the central class of the in-memory representation. A CharGroup is what can
+ * be seen as a traditional "trie node", except it can hold several characters at the
+ * same time. A CharGroup essentially represents one or several characters in the middle
+ * of the trie trie; as such, it can be a terminal, and it can have children.
+ * In this in-memory representation, whether the CharGroup is a terminal or not is represented
+ * in the frequency, where NOT_A_TERMINAL (= -1) means this is not a terminal and any other
+ * value is the frequency of this terminal. A terminal may have non-null shortcuts and/or
+ * bigrams, but a non-terminal may not. Moreover, children, if present, are null.
+ */
+ public static class CharGroup {
+ public static final int NOT_A_TERMINAL = -1;
+ final int mChars[];
+ ArrayList<WeightedString> mShortcutTargets;
+ ArrayList<WeightedString> mBigrams;
+ int mFrequency; // NOT_A_TERMINAL == mFrequency indicates this is not a terminal.
+ Node mChildren;
+ // The two following members to help with binary generation
+ int mCachedSize;
+ int mCachedAddress;
+
+ public CharGroup(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
+ final ArrayList<WeightedString> bigrams, final int frequency) {
+ mChars = chars;
+ mFrequency = frequency;
+ mShortcutTargets = shortcutTargets;
+ mBigrams = bigrams;
+ mChildren = null;
+ }
+
+ public CharGroup(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
+ final ArrayList<WeightedString> bigrams, final int frequency, final Node children) {
+ mChars = chars;
+ mFrequency = frequency;
+ mShortcutTargets = shortcutTargets;
+ mBigrams = bigrams;
+ mChildren = children;
+ }
+
+ public void addChild(CharGroup n) {
+ if (null == mChildren) {
+ mChildren = new Node();
+ }
+ mChildren.mData.add(n);
+ }
+
+ public boolean isTerminal() {
+ return NOT_A_TERMINAL != mFrequency;
+ }
+
+ public boolean hasSeveralChars() {
+ assert(mChars.length > 0);
+ return 1 < mChars.length;
+ }
+
+ /**
+ * Adds a word to the bigram list. Updates the frequency if the word already
+ * exists.
+ */
+ public void addBigram(final String word, final int frequency) {
+ if (mBigrams == null) {
+ mBigrams = new ArrayList<WeightedString>();
+ }
+ WeightedString bigram = getBigram(word);
+ if (bigram != null) {
+ bigram.mFrequency = frequency;
+ } else {
+ bigram = new WeightedString(word, frequency);
+ mBigrams.add(bigram);
+ }
+ }
+
+ /**
+ * Gets the shortcut target for the given word. Returns null if the word is not in the
+ * shortcut list.
+ */
+ public WeightedString getShortcut(final String word) {
+ // TODO: Don't do a linear search
+ if (mShortcutTargets != null) {
+ final int size = mShortcutTargets.size();
+ for (int i = 0; i < size; ++i) {
+ WeightedString shortcut = mShortcutTargets.get(i);
+ if (shortcut.mWord.equals(word)) {
+ return shortcut;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the bigram for the given word.
+ * Returns null if the word is not in the bigrams list.
+ */
+ public WeightedString getBigram(final String word) {
+ // TODO: Don't do a linear search
+ if (mBigrams != null) {
+ final int size = mBigrams.size();
+ for (int i = 0; i < size; ++i) {
+ WeightedString bigram = mBigrams.get(i);
+ if (bigram.mWord.equals(word)) {
+ return bigram;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Updates the CharGroup with the given properties. Adds the shortcut and bigram lists to
+ * the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only
+ * updated if they are higher than the existing ones.
+ */
+ public void update(int frequency, ArrayList<WeightedString> shortcutTargets,
+ ArrayList<WeightedString> bigrams) {
+ if (frequency > mFrequency) {
+ mFrequency = frequency;
+ }
+ if (shortcutTargets != null) {
+ if (mShortcutTargets == null) {
+ mShortcutTargets = shortcutTargets;
+ } else {
+ final int size = shortcutTargets.size();
+ for (int i = 0; i < size; ++i) {
+ final WeightedString shortcut = shortcutTargets.get(i);
+ final WeightedString existingShortcut = getShortcut(shortcut.mWord);
+ if (existingShortcut == null) {
+ mShortcutTargets.add(shortcut);
+ } else if (existingShortcut.mFrequency < shortcut.mFrequency) {
+ existingShortcut.mFrequency = shortcut.mFrequency;
+ }
+ }
+ }
+ }
+ if (bigrams != null) {
+ if (mBigrams == null) {
+ mBigrams = bigrams;
+ } else {
+ final int size = bigrams.size();
+ for (int i = 0; i < size; ++i) {
+ final WeightedString bigram = bigrams.get(i);
+ final WeightedString existingBigram = getBigram(bigram.mWord);
+ if (existingBigram == null) {
+ mBigrams.add(bigram);
+ } else if (existingBigram.mFrequency < bigram.mFrequency) {
+ existingBigram.mFrequency = bigram.mFrequency;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Options global to the dictionary.
+ *
+ * There are no options at the moment, so this class is empty.
+ */
+ public static class DictionaryOptions {
+ public final boolean mGermanUmlautProcessing;
+ public final boolean mFrenchLigatureProcessing;
+ public final HashMap<String, String> mAttributes;
+ public DictionaryOptions(final HashMap<String, String> attributes,
+ final boolean germanUmlautProcessing, final boolean frenchLigatureProcessing) {
+ mAttributes = attributes;
+ mGermanUmlautProcessing = germanUmlautProcessing;
+ mFrenchLigatureProcessing = frenchLigatureProcessing;
+ }
+ }
+
+ public final DictionaryOptions mOptions;
+ public final Node mRoot;
+
+ public FusionDictionary(final Node root, final DictionaryOptions options) {
+ mRoot = root;
+ mOptions = options;
+ }
+
+ public void addOptionAttribute(final String key, final String value) {
+ mOptions.mAttributes.put(key, value);
+ }
+
+ /**
+ * Helper method to convert a String to an int array.
+ */
+ static private int[] getCodePoints(final String word) {
+ // TODO: this is a copy-paste of the contents of StringUtils.toCodePointArray,
+ // which is not visible from the makedict package. Factor this code.
+ final char[] characters = word.toCharArray();
+ final int length = characters.length;
+ final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
+ int codePoint = Character.codePointAt(characters, 0);
+ int dsti = 0;
+ for (int srci = Character.charCount(codePoint);
+ srci < length; srci += Character.charCount(codePoint), ++dsti) {
+ codePoints[dsti] = codePoint;
+ codePoint = Character.codePointAt(characters, srci);
+ }
+ codePoints[dsti] = codePoint;
+ return codePoints;
+ }
+
+ /**
+ * Helper method to add a word as a string.
+ *
+ * This method adds a word to the dictionary with the given frequency. Optional
+ * lists of bigrams and shortcuts can be passed here. For each word inside,
+ * they will be added to the dictionary as necessary.
+ *
+ * @param word the word to add.
+ * @param frequency the frequency of the word, in the range [0..255].
+ * @param shortcutTargets a list of shortcut targets for this word, or null.
+ */
+ public void add(final String word, final int frequency,
+ final ArrayList<WeightedString> shortcutTargets) {
+ add(getCodePoints(word), frequency, shortcutTargets);
+ }
+
+ /**
+ * Sanity check for a node.
+ *
+ * This method checks that all CharGroups in a node are ordered as expected.
+ * If they are, nothing happens. If they aren't, an exception is thrown.
+ */
+ private void checkStack(Node node) {
+ ArrayList<CharGroup> stack = node.mData;
+ int lastValue = -1;
+ for (int i = 0; i < stack.size(); ++i) {
+ int currentValue = stack.get(i).mChars[0];
+ if (currentValue <= lastValue)
+ throw new RuntimeException("Invalid stack");
+ else
+ lastValue = currentValue;
+ }
+ }
+
+ /**
+ * Helper method to add a new bigram to the dictionary.
+ *
+ * @param word1 the previous word of the context
+ * @param word2 the next word of the context
+ * @param frequency the bigram frequency
+ */
+ public void setBigram(final String word1, final String word2, final int frequency) {
+ CharGroup charGroup = findWordInTree(mRoot, word1);
+ if (charGroup != null) {
+ final CharGroup charGroup2 = findWordInTree(mRoot, word2);
+ if (charGroup2 == null) {
+ add(getCodePoints(word2), 0, null);
+ }
+ charGroup.addBigram(word2, frequency);
+ } else {
+ throw new RuntimeException("First word of bigram not found");
+ }
+ }
+
+ /**
+ * Add a word to this dictionary.
+ *
+ * The shortcuts, if any, have to be in the dictionary already. If they aren't,
+ * an exception is thrown.
+ *
+ * @param word the word, as an int array.
+ * @param frequency the frequency of the word, in the range [0..255].
+ * @param shortcutTargets an optional list of shortcut targets for this word (null if none).
+ */
+ private void add(final int[] word, final int frequency,
+ final ArrayList<WeightedString> shortcutTargets) {
+ assert(frequency >= 0 && frequency <= 255);
+ Node currentNode = mRoot;
+ int charIndex = 0;
+
+ CharGroup currentGroup = null;
+ int differentCharIndex = 0; // Set by the loop to the index of the char that differs
+ int nodeIndex = findIndexOfChar(mRoot, word[charIndex]);
+ while (CHARACTER_NOT_FOUND != nodeIndex) {
+ currentGroup = currentNode.mData.get(nodeIndex);
+ differentCharIndex = compareArrays(currentGroup.mChars, word, charIndex);
+ if (ARRAYS_ARE_EQUAL != differentCharIndex
+ && differentCharIndex < currentGroup.mChars.length) break;
+ if (null == currentGroup.mChildren) break;
+ charIndex += currentGroup.mChars.length;
+ if (charIndex >= word.length) break;
+ currentNode = currentGroup.mChildren;
+ nodeIndex = findIndexOfChar(currentNode, word[charIndex]);
+ }
+
+ if (-1 == nodeIndex) {
+ // No node at this point to accept the word. Create one.
+ final int insertionIndex = findInsertionIndex(currentNode, word[charIndex]);
+ final CharGroup newGroup = new CharGroup(
+ Arrays.copyOfRange(word, charIndex, word.length),
+ shortcutTargets, null /* bigrams */, frequency);
+ currentNode.mData.add(insertionIndex, newGroup);
+ if (DBG) checkStack(currentNode);
+ } else {
+ // There is a word with a common prefix.
+ if (differentCharIndex == currentGroup.mChars.length) {
+ if (charIndex + differentCharIndex >= word.length) {
+ // The new word is a prefix of an existing word, but the node on which it
+ // should end already exists as is. Since the old CharNode was not a terminal,
+ // make it one by filling in its frequency and other attributes
+ currentGroup.update(frequency, shortcutTargets, null);
+ } else {
+ // The new word matches the full old word and extends past it.
+ // We only have to create a new node and add it to the end of this.
+ final CharGroup newNode = new CharGroup(
+ Arrays.copyOfRange(word, charIndex + differentCharIndex, word.length),
+ shortcutTargets, null /* bigrams */, frequency);
+ currentGroup.mChildren = new Node();
+ currentGroup.mChildren.mData.add(newNode);
+ }
+ } else {
+ if (0 == differentCharIndex) {
+ // Exact same word. Update the frequency if higher. This will also add the
+ // new shortcuts to the existing shortcut list if it already exists.
+ currentGroup.update(frequency, shortcutTargets, null);
+ } else {
+ // Partial prefix match only. We have to replace the current node with a node
+ // containing the current prefix and create two new ones for the tails.
+ Node newChildren = new Node();
+ final CharGroup newOldWord = new CharGroup(
+ Arrays.copyOfRange(currentGroup.mChars, differentCharIndex,
+ currentGroup.mChars.length), currentGroup.mShortcutTargets,
+ currentGroup.mBigrams, currentGroup.mFrequency, currentGroup.mChildren);
+ newChildren.mData.add(newOldWord);
+
+ final CharGroup newParent;
+ if (charIndex + differentCharIndex >= word.length) {
+ newParent = new CharGroup(
+ Arrays.copyOfRange(currentGroup.mChars, 0, differentCharIndex),
+ shortcutTargets, null /* bigrams */, frequency, newChildren);
+ } else {
+ newParent = new CharGroup(
+ Arrays.copyOfRange(currentGroup.mChars, 0, differentCharIndex),
+ null /* shortcutTargets */, null /* bigrams */, -1, newChildren);
+ final CharGroup newWord = new CharGroup(Arrays.copyOfRange(word,
+ charIndex + differentCharIndex, word.length),
+ shortcutTargets, null /* bigrams */, frequency);
+ final int addIndex = word[charIndex + differentCharIndex]
+ > currentGroup.mChars[differentCharIndex] ? 1 : 0;
+ newChildren.mData.add(addIndex, newWord);
+ }
+ currentNode.mData.set(nodeIndex, newParent);
+ }
+ if (DBG) checkStack(currentNode);
+ }
+ }
+ }
+
+ private static int ARRAYS_ARE_EQUAL = 0;
+
+ /**
+ * Custom comparison of two int arrays taken to contain character codes.
+ *
+ * This method compares the two arrays passed as an argument in a lexicographic way,
+ * with an offset in the dst string.
+ * This method does NOT test for the first character. It is taken to be equal.
+ * I repeat: this method starts the comparison at 1 <> dstOffset + 1.
+ * The index where the strings differ is returned. ARRAYS_ARE_EQUAL = 0 is returned if the
+ * strings are equal. This works BECAUSE we don't look at the first character.
+ *
+ * @param src the left-hand side string of the comparison.
+ * @param dst the right-hand side string of the comparison.
+ * @param dstOffset the offset in the right-hand side string.
+ * @return the index at which the strings differ, or ARRAYS_ARE_EQUAL = 0 if they don't.
+ */
+ private static int compareArrays(final int[] src, final int[] dst, int dstOffset) {
+ // We do NOT test the first char, because we come from a method that already
+ // tested it.
+ for (int i = 1; i < src.length; ++i) {
+ if (dstOffset + i >= dst.length) return i;
+ if (src[i] != dst[dstOffset + i]) return i;
+ }
+ if (dst.length > src.length) return src.length;
+ return ARRAYS_ARE_EQUAL;
+ }
+
+ /**
+ * Helper class that compares and sorts two chargroups according to their
+ * first element only. I repeat: ONLY the first element is considered, the rest
+ * is ignored.
+ * This comparator imposes orderings that are inconsistent with equals.
+ */
+ static private class CharGroupComparator implements java.util.Comparator<CharGroup> {
+ @Override
+ public int compare(CharGroup c1, CharGroup c2) {
+ if (c1.mChars[0] == c2.mChars[0]) return 0;
+ return c1.mChars[0] < c2.mChars[0] ? -1 : 1;
+ }
+ }
+ final static private CharGroupComparator CHARGROUP_COMPARATOR = new CharGroupComparator();
+
+ /**
+ * Finds the insertion index of a character within a node.
+ */
+ private static int findInsertionIndex(final Node node, int character) {
+ final ArrayList<CharGroup> data = node.mData;
+ final CharGroup reference = new CharGroup(new int[] { character },
+ null /* shortcutTargets */, null /* bigrams */, 0);
+ int result = Collections.binarySearch(data, reference, CHARGROUP_COMPARATOR);
+ return result >= 0 ? result : -result - 1;
+ }
+
+ private static int CHARACTER_NOT_FOUND = -1;
+
+ /**
+ * Find the index of a char in a node, if it exists.
+ *
+ * @param node the node to search in.
+ * @param character the character to search for.
+ * @return the position of the character if it's there, or CHARACTER_NOT_FOUND = -1 else.
+ */
+ private static int findIndexOfChar(final Node node, int character) {
+ final int insertionIndex = findInsertionIndex(node, character);
+ if (node.mData.size() <= insertionIndex) return CHARACTER_NOT_FOUND;
+ return character == node.mData.get(insertionIndex).mChars[0] ? insertionIndex
+ : CHARACTER_NOT_FOUND;
+ }
+
+ /**
+ * Helper method to find a word in a given branch.
+ */
+ public static CharGroup findWordInTree(Node node, final String s) {
+ int index = 0;
+ final StringBuilder checker = DBG ? new StringBuilder() : null;
+
+ CharGroup currentGroup;
+ do {
+ int indexOfGroup = findIndexOfChar(node, s.codePointAt(index));
+ if (CHARACTER_NOT_FOUND == indexOfGroup) return null;
+ currentGroup = node.mData.get(indexOfGroup);
+ if (DBG) checker.append(new String(currentGroup.mChars, 0, currentGroup.mChars.length));
+ index += currentGroup.mChars.length;
+ if (index < s.length()) {
+ node = currentGroup.mChildren;
+ }
+ } while (null != node && index < s.length());
+
+ if (DBG && !s.equals(checker.toString())) return null;
+ return currentGroup;
+ }
+
+ /**
+ * Helper method to find out whether a word is in the dict or not.
+ */
+ public boolean hasWord(final String s) {
+ if (null == s || "".equals(s)) {
+ throw new RuntimeException("Can't search for a null or empty string");
+ }
+ return null != findWordInTree(mRoot, s);
+ }
+
+ /**
+ * Recursively count the number of character groups in a given branch of the trie.
+ *
+ * @param node the parent node.
+ * @return the number of char groups in all the branch under this node.
+ */
+ public static int countCharGroups(final Node node) {
+ final int nodeSize = node.mData.size();
+ int size = nodeSize;
+ for (int i = nodeSize - 1; i >= 0; --i) {
+ CharGroup group = node.mData.get(i);
+ if (null != group.mChildren)
+ size += countCharGroups(group.mChildren);
+ }
+ return size;
+ }
+
+ /**
+ * Recursively count the number of nodes in a given branch of the trie.
+ *
+ * @param node the node to count.
+ * @return the number of nodes in this branch.
+ */
+ public static int countNodes(final Node node) {
+ int size = 1;
+ for (int i = node.mData.size() - 1; i >= 0; --i) {
+ CharGroup group = node.mData.get(i);
+ if (null != group.mChildren)
+ size += countNodes(group.mChildren);
+ }
+ return size;
+ }
+
+ // Recursively find out whether there are any bigrams.
+ // This can be pretty expensive especially if there aren't any (we return as soon
+ // as we find one, so it's much cheaper if there are bigrams)
+ private static boolean hasBigramsInternal(final Node node) {
+ if (null == node) return false;
+ for (int i = node.mData.size() - 1; i >= 0; --i) {
+ CharGroup group = node.mData.get(i);
+ if (null != group.mBigrams) return true;
+ if (hasBigramsInternal(group.mChildren)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Finds out whether there are any bigrams in this dictionary.
+ *
+ * @return true if there is any bigram, false otherwise.
+ */
+ // TODO: this is expensive especially for large dictionaries without any bigram.
+ // The up side is, this is always accurate and correct and uses no memory. We should
+ // find a more efficient way of doing this, without compromising too much on memory
+ // and ease of use.
+ public boolean hasBigrams() {
+ return hasBigramsInternal(mRoot);
+ }
+
+ // Historically, the tails of the words were going to be merged to save space.
+ // However, that would prevent the code to search for a specific address in log(n)
+ // time so this was abandoned.
+ // The code is still of interest as it does add some compression to any dictionary
+ // that has no need for attributes. Implementations that does not read attributes should be
+ // able to read a dictionary with merged tails.
+ // Also, the following code does support frequencies, as in, it will only merges
+ // tails that share the same frequency. Though it would result in the above loss of
+ // performance while searching by address, it is still technically possible to merge
+ // tails that contain attributes, but this code does not take that into account - it does
+ // not compare attributes and will merge terminals with different attributes regardless.
+ public void mergeTails() {
+ MakedictLog.i("Do not merge tails");
+ return;
+
+// MakedictLog.i("Merging nodes. Number of nodes : " + countNodes(root));
+// MakedictLog.i("Number of groups : " + countCharGroups(root));
+//
+// final HashMap<String, ArrayList<Node>> repository =
+// new HashMap<String, ArrayList<Node>>();
+// mergeTailsInner(repository, root);
+//
+// MakedictLog.i("Number of different pseudohashes : " + repository.size());
+// int size = 0;
+// for (ArrayList<Node> a : repository.values()) {
+// size += a.size();
+// }
+// MakedictLog.i("Number of nodes after merge : " + (1 + size));
+// MakedictLog.i("Recursively seen nodes : " + countNodes(root));
+ }
+
+ // The following methods are used by the deactivated mergeTails()
+// private static boolean isEqual(Node a, Node b) {
+// if (null == a && null == b) return true;
+// if (null == a || null == b) return false;
+// if (a.data.size() != b.data.size()) return false;
+// final int size = a.data.size();
+// for (int i = size - 1; i >= 0; --i) {
+// CharGroup aGroup = a.data.get(i);
+// CharGroup bGroup = b.data.get(i);
+// if (aGroup.frequency != bGroup.frequency) return false;
+// if (aGroup.alternates == null && bGroup.alternates != null) return false;
+// if (aGroup.alternates != null && !aGroup.equals(bGroup.alternates)) return false;
+// if (!Arrays.equals(aGroup.chars, bGroup.chars)) return false;
+// if (!isEqual(aGroup.children, bGroup.children)) return false;
+// }
+// return true;
+// }
+
+// static private HashMap<String, ArrayList<Node>> mergeTailsInner(
+// final HashMap<String, ArrayList<Node>> map, final Node node) {
+// final ArrayList<CharGroup> branches = node.data;
+// final int nodeSize = branches.size();
+// for (int i = 0; i < nodeSize; ++i) {
+// CharGroup group = branches.get(i);
+// if (null != group.children) {
+// String pseudoHash = getPseudoHash(group.children);
+// ArrayList<Node> similarList = map.get(pseudoHash);
+// if (null == similarList) {
+// similarList = new ArrayList<Node>();
+// map.put(pseudoHash, similarList);
+// }
+// boolean merged = false;
+// for (Node similar : similarList) {
+// if (isEqual(group.children, similar)) {
+// group.children = similar;
+// merged = true;
+// break;
+// }
+// }
+// if (!merged) {
+// similarList.add(group.children);
+// }
+// mergeTailsInner(map, group.children);
+// }
+// }
+// return map;
+// }
+
+// private static String getPseudoHash(final Node node) {
+// StringBuilder s = new StringBuilder();
+// for (CharGroup g : node.data) {
+// s.append(g.frequency);
+// for (int ch : g.chars){
+// s.append(Character.toChars(ch));
+// }
+// }
+// return s.toString();
+// }
+
+ /**
+ * Iterator to walk through a dictionary.
+ *
+ * This is purely for convenience.
+ */
+ public static class DictionaryIterator implements Iterator<Word> {
+
+ private static class Position {
+ public Iterator<CharGroup> pos;
+ public int length;
+ public Position(ArrayList<CharGroup> groups) {
+ pos = groups.iterator();
+ length = 0;
+ }
+ }
+ final StringBuilder mCurrentString;
+ final LinkedList<Position> mPositions;
+
+ public DictionaryIterator(ArrayList<CharGroup> root) {
+ mCurrentString = new StringBuilder();
+ mPositions = new LinkedList<Position>();
+ final Position rootPos = new Position(root);
+ mPositions.add(rootPos);
+ }
+
+ @Override
+ public boolean hasNext() {
+ for (Position p : mPositions) {
+ if (p.pos.hasNext()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Word next() {
+ Position currentPos = mPositions.getLast();
+ mCurrentString.setLength(mCurrentString.length() - currentPos.length);
+
+ do {
+ if (currentPos.pos.hasNext()) {
+ final CharGroup currentGroup = currentPos.pos.next();
+ currentPos.length = currentGroup.mChars.length;
+ for (int i : currentGroup.mChars)
+ mCurrentString.append(Character.toChars(i));
+ if (null != currentGroup.mChildren) {
+ currentPos = new Position(currentGroup.mChildren.mData);
+ mPositions.addLast(currentPos);
+ }
+ if (currentGroup.mFrequency >= 0)
+ return new Word(mCurrentString.toString(), currentGroup.mFrequency,
+ currentGroup.mShortcutTargets, currentGroup.mBigrams);
+ } else {
+ mPositions.removeLast();
+ currentPos = mPositions.getLast();
+ mCurrentString.setLength(mCurrentString.length() - mPositions.getLast().length);
+ }
+ } while(true);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Unsupported yet");
+ }
+
+ }
+
+ /**
+ * Method to return an iterator.
+ *
+ * This method enables Java's enhanced for loop. With this you can have a FusionDictionary x
+ * and say : for (Word w : x) {}
+ */
+ @Override
+ public Iterator<Word> iterator() {
+ return new DictionaryIterator(mRoot.mData);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java
new file mode 100644
index 000000000..3f0cd0796
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import android.util.Log;
+
+/**
+ * Wrapper to redirect log events to the right output medium.
+ */
+public class MakedictLog {
+ public static final boolean DBG = false;
+ private static final String TAG = MakedictLog.class.getSimpleName();
+
+ public static void d(String message) {
+ if (DBG) {
+ Log.d(TAG, message);
+ }
+ }
+
+ public static void i(String message) {
+ if (DBG) {
+ Log.i(TAG, message);
+ }
+ }
+
+ public static void w(String message) {
+ Log.w(TAG, message);
+ }
+
+ public static void e(String message) {
+ Log.e(TAG, message);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java b/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java
new file mode 100644
index 000000000..5b41d27f2
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+/**
+ * A not-yet-resolved attribute.
+ *
+ * An attribute is either a bigram or a shortcut.
+ * All instances of this class are always immutable.
+ */
+public class PendingAttribute {
+ public final int mFrequency;
+ public final int mAddress;
+ public PendingAttribute(final int frequency, final int address) {
+ mFrequency = frequency;
+ mAddress = address;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java b/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java
new file mode 100644
index 000000000..bd42fb8fa
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+/**
+ * Simple exception thrown when a file format is not recognized.
+ */
+public class UnsupportedFormatException extends Exception {
+ public UnsupportedFormatException(String description) {
+ super(description);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/Word.java b/java/src/com/android/inputmethod/latin/makedict/Word.java
new file mode 100644
index 000000000..d07826757
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/Word.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Utility class for a word with a frequency.
+ *
+ * This is chiefly used to iterate a dictionary.
+ */
+public class Word implements Comparable<Word> {
+ final String mWord;
+ final int mFrequency;
+ final ArrayList<WeightedString> mShortcutTargets;
+ final ArrayList<WeightedString> mBigrams;
+
+ private int mHashCode = 0;
+
+ public Word(final String word, final int frequency,
+ final ArrayList<WeightedString> shortcutTargets,
+ final ArrayList<WeightedString> bigrams) {
+ mWord = word;
+ mFrequency = frequency;
+ mShortcutTargets = shortcutTargets;
+ mBigrams = bigrams;
+ }
+
+ private static int computeHashCode(Word word) {
+ return Arrays.hashCode(new Object[] {
+ word.mWord,
+ word.mFrequency,
+ word.mShortcutTargets.hashCode(),
+ word.mBigrams.hashCode()
+ });
+ }
+
+ /**
+ * Three-way comparison.
+ *
+ * A Word x is greater than a word y if x has a higher frequency. If they have the same
+ * frequency, they are sorted in lexicographic order.
+ */
+ @Override
+ public int compareTo(Word w) {
+ if (mFrequency < w.mFrequency) return 1;
+ if (mFrequency > w.mFrequency) return -1;
+ return mWord.compareTo(w.mWord);
+ }
+
+ /**
+ * Equality test.
+ *
+ * Words are equal if they have the same frequency, the same spellings, and the same
+ * attributes.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof Word)) return false;
+ Word w = (Word)o;
+ return mFrequency == w.mFrequency && mWord.equals(w.mWord)
+ && mShortcutTargets.equals(w.mShortcutTargets)
+ && mBigrams.equals(w.mBigrams);
+ }
+
+ @Override
+ public int hashCode() {
+ if (mHashCode == 0) {
+ mHashCode = computeHashCode(this);
+ }
+ return mHashCode;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
new file mode 100644
index 000000000..7fffc31c0
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -0,0 +1,837 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.spellcheck;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.service.textservice.SpellCheckerService;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.LruCache;
+import android.view.textservice.SentenceSuggestionsInfo;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+
+import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
+import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.ContactsBinaryDictionary;
+import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.latin.Dictionary.WordCallback;
+import com.android.inputmethod.latin.DictionaryCollection;
+import com.android.inputmethod.latin.DictionaryFactory;
+import com.android.inputmethod.latin.LocaleUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SynchronouslyLoadedContactsBinaryDictionary;
+import com.android.inputmethod.latin.SynchronouslyLoadedUserBinaryDictionary;
+import com.android.inputmethod.latin.UserBinaryDictionary;
+import com.android.inputmethod.latin.WhitelistDictionary;
+import com.android.inputmethod.latin.WordComposer;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Service for spell checking, using LatinIME's dictionaries and mechanisms.
+ */
+public class AndroidSpellCheckerService extends SpellCheckerService
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
+ private static final boolean DBG = false;
+ private static final int POOL_SIZE = 2;
+
+ public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
+
+ private static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
+ private static final int CAPITALIZE_FIRST = 1; // First only
+ private static final int CAPITALIZE_ALL = 2; // All caps
+
+ private final static String[] EMPTY_STRING_ARRAY = new String[0];
+ private Map<String, DictionaryPool> mDictionaryPools =
+ Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
+ private Map<String, UserBinaryDictionary> mUserDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, UserBinaryDictionary>());
+ private Map<String, Dictionary> mWhitelistDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ private ContactsBinaryDictionary mContactsDictionary;
+
+ // The threshold for a candidate to be offered as a suggestion.
+ private float mSuggestionThreshold;
+ // The threshold for a suggestion to be considered "recommended".
+ private float mRecommendedThreshold;
+ // Whether to use the contacts dictionary
+ private boolean mUseContactsDictionary;
+ private final Object mUseContactsLock = new Object();
+
+ private final HashSet<WeakReference<DictionaryCollection>> mDictionaryCollectionsList =
+ new HashSet<WeakReference<DictionaryCollection>>();
+
+ public static final int SCRIPT_LATIN = 0;
+ public static final int SCRIPT_CYRILLIC = 1;
+ private static final String SINGLE_QUOTE = "\u0027";
+ private static final String APOSTROPHE = "\u2019";
+ private static final TreeMap<String, Integer> mLanguageToScript;
+ static {
+ // List of the supported languages and their associated script. We won't check
+ // words written in another script than the selected script, because we know we
+ // don't have those in our dictionary so we will underline everything and we
+ // will never have any suggestions, so it makes no sense checking them, and this
+ // is done in {@link #shouldFilterOut}. Also, the script is used to choose which
+ // proximity to pass to the dictionary descent algorithm.
+ // IMPORTANT: this only contains languages - do not write countries in there.
+ // Only the language is searched from the map.
+ mLanguageToScript = new TreeMap<String, Integer>();
+ mLanguageToScript.put("en", SCRIPT_LATIN);
+ mLanguageToScript.put("fr", SCRIPT_LATIN);
+ mLanguageToScript.put("de", SCRIPT_LATIN);
+ mLanguageToScript.put("nl", SCRIPT_LATIN);
+ mLanguageToScript.put("cs", SCRIPT_LATIN);
+ mLanguageToScript.put("es", SCRIPT_LATIN);
+ mLanguageToScript.put("it", SCRIPT_LATIN);
+ mLanguageToScript.put("hr", SCRIPT_LATIN);
+ mLanguageToScript.put("pt", SCRIPT_LATIN);
+ mLanguageToScript.put("ru", SCRIPT_CYRILLIC);
+ // TODO: Make a persian proximity, and activate the Farsi subtype.
+ // mLanguageToScript.put("fa", SCRIPT_PERSIAN);
+ }
+
+ @Override public void onCreate() {
+ super.onCreate();
+ mSuggestionThreshold =
+ Float.parseFloat(getString(R.string.spellchecker_suggestion_threshold_value));
+ mRecommendedThreshold =
+ Float.parseFloat(getString(R.string.spellchecker_recommended_threshold_value));
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY);
+ }
+
+ private static int getScriptFromLocale(final Locale locale) {
+ final Integer script = mLanguageToScript.get(locale.getLanguage());
+ if (null == script) {
+ throw new RuntimeException("We have been called with an unsupported language: \""
+ + locale.getLanguage() + "\". Framework bug?");
+ }
+ return script;
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+ if (!PREF_USE_CONTACTS_KEY.equals(key)) return;
+ synchronized(mUseContactsLock) {
+ mUseContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true);
+ if (mUseContactsDictionary) {
+ startUsingContactsDictionaryLocked();
+ } else {
+ stopUsingContactsDictionaryLocked();
+ }
+ }
+ }
+
+ private void startUsingContactsDictionaryLocked() {
+ if (null == mContactsDictionary) {
+ // TODO: use the right locale for each session
+ mContactsDictionary =
+ new SynchronouslyLoadedContactsBinaryDictionary(this, Locale.getDefault());
+ }
+ final Iterator<WeakReference<DictionaryCollection>> iterator =
+ mDictionaryCollectionsList.iterator();
+ while (iterator.hasNext()) {
+ final WeakReference<DictionaryCollection> dictRef = iterator.next();
+ final DictionaryCollection dict = dictRef.get();
+ if (null == dict) {
+ iterator.remove();
+ } else {
+ dict.addDictionary(mContactsDictionary);
+ }
+ }
+ }
+
+ private void stopUsingContactsDictionaryLocked() {
+ if (null == mContactsDictionary) return;
+ final Dictionary contactsDict = mContactsDictionary;
+ // TODO: revert to the concrete type when USE_BINARY_CONTACTS_DICTIONARY is no longer needed
+ mContactsDictionary = null;
+ final Iterator<WeakReference<DictionaryCollection>> iterator =
+ mDictionaryCollectionsList.iterator();
+ while (iterator.hasNext()) {
+ final WeakReference<DictionaryCollection> dictRef = iterator.next();
+ final DictionaryCollection dict = dictRef.get();
+ if (null == dict) {
+ iterator.remove();
+ } else {
+ dict.removeDictionary(contactsDict);
+ }
+ }
+ contactsDict.close();
+ }
+
+ @Override
+ public Session createSession() {
+ return new AndroidSpellCheckerSession(this);
+ }
+
+ private static SuggestionsInfo getNotInDictEmptySuggestions() {
+ return new SuggestionsInfo(0, EMPTY_STRING_ARRAY);
+ }
+
+ private static SuggestionsInfo getInDictEmptySuggestions() {
+ return new SuggestionsInfo(SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY,
+ EMPTY_STRING_ARRAY);
+ }
+
+ private static class SuggestionsGatherer implements WordCallback {
+ public static class Result {
+ public final String[] mSuggestions;
+ public final boolean mHasRecommendedSuggestions;
+ public Result(final String[] gatheredSuggestions,
+ final boolean hasRecommendedSuggestions) {
+ mSuggestions = gatheredSuggestions;
+ mHasRecommendedSuggestions = hasRecommendedSuggestions;
+ }
+ }
+
+ private final ArrayList<CharSequence> mSuggestions;
+ private final int[] mScores;
+ private final String mOriginalText;
+ private final float mSuggestionThreshold;
+ private final float mRecommendedThreshold;
+ private final int mMaxLength;
+ private int mLength = 0;
+
+ // The two following attributes are only ever filled if the requested max length
+ // is 0 (or less, which is treated the same).
+ private String mBestSuggestion = null;
+ private int mBestScore = Integer.MIN_VALUE; // As small as possible
+
+ SuggestionsGatherer(final String originalText, final float suggestionThreshold,
+ final float recommendedThreshold, final int maxLength) {
+ mOriginalText = originalText;
+ mSuggestionThreshold = suggestionThreshold;
+ mRecommendedThreshold = recommendedThreshold;
+ mMaxLength = maxLength;
+ mSuggestions = new ArrayList<CharSequence>(maxLength + 1);
+ mScores = new int[mMaxLength];
+ }
+
+ @Override
+ synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score,
+ int dicTypeId, int dataType) {
+ final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score);
+ // binarySearch returns the index if the element exists, and -<insertion index> - 1
+ // if it doesn't. See documentation for binarySearch.
+ final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1;
+
+ if (insertIndex == 0 && mLength >= mMaxLength) {
+ // In the future, we may want to keep track of the best suggestion score even if
+ // we are asked for 0 suggestions. In this case, we can use the following
+ // (tested) code to keep it:
+ // If the maxLength is 0 (should never be less, but if it is, it's treated as 0)
+ // then we need to keep track of the best suggestion in mBestScore and
+ // mBestSuggestion. This is so that we know whether the best suggestion makes
+ // the score cutoff, since we need to know that to return a meaningful
+ // looksLikeTypo.
+ // if (0 >= mMaxLength) {
+ // if (score > mBestScore) {
+ // mBestScore = score;
+ // mBestSuggestion = new String(word, wordOffset, wordLength);
+ // }
+ // }
+ return true;
+ }
+ if (insertIndex >= mMaxLength) {
+ // We found a suggestion, but its score is too weak to be kept considering
+ // the suggestion limit.
+ return true;
+ }
+
+ // Compute the normalized score and skip this word if it's normalized score does not
+ // make the threshold.
+ final String wordString = new String(word, wordOffset, wordLength);
+ final float normalizedScore =
+ BinaryDictionary.calcNormalizedScore(mOriginalText, wordString, score);
+ if (normalizedScore < mSuggestionThreshold) {
+ if (DBG) Log.i(TAG, wordString + " does not make the score threshold");
+ return true;
+ }
+
+ if (mLength < mMaxLength) {
+ final int copyLen = mLength - insertIndex;
+ ++mLength;
+ System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen);
+ mSuggestions.add(insertIndex, wordString);
+ } else {
+ System.arraycopy(mScores, 1, mScores, 0, insertIndex);
+ mSuggestions.add(insertIndex, wordString);
+ mSuggestions.remove(0);
+ }
+ mScores[insertIndex] = score;
+
+ return true;
+ }
+
+ public Result getResults(final int capitalizeType, final Locale locale) {
+ final String[] gatheredSuggestions;
+ final boolean hasRecommendedSuggestions;
+ if (0 == mLength) {
+ // Either we found no suggestions, or we found some BUT the max length was 0.
+ // If we found some mBestSuggestion will not be null. If it is null, then
+ // we found none, regardless of the max length.
+ if (null == mBestSuggestion) {
+ gatheredSuggestions = null;
+ hasRecommendedSuggestions = false;
+ } else {
+ gatheredSuggestions = EMPTY_STRING_ARRAY;
+ final float normalizedScore = BinaryDictionary.calcNormalizedScore(
+ mOriginalText, mBestSuggestion, mBestScore);
+ hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold);
+ }
+ } else {
+ if (DBG) {
+ if (mLength != mSuggestions.size()) {
+ Log.e(TAG, "Suggestion size is not the same as stored mLength");
+ }
+ for (int i = mLength - 1; i >= 0; --i) {
+ Log.i(TAG, "" + mScores[i] + " " + mSuggestions.get(i));
+ }
+ }
+ Collections.reverse(mSuggestions);
+ StringUtils.removeDupes(mSuggestions);
+ if (CAPITALIZE_ALL == capitalizeType) {
+ for (int i = 0; i < mSuggestions.size(); ++i) {
+ // get(i) returns a CharSequence which is actually a String so .toString()
+ // should return the same object.
+ mSuggestions.set(i, mSuggestions.get(i).toString().toUpperCase(locale));
+ }
+ } else if (CAPITALIZE_FIRST == capitalizeType) {
+ for (int i = 0; i < mSuggestions.size(); ++i) {
+ // Likewise
+ mSuggestions.set(i, StringUtils.toTitleCase(
+ mSuggestions.get(i).toString(), locale));
+ }
+ }
+ // This returns a String[], while toArray() returns an Object[] which cannot be cast
+ // into a String[].
+ gatheredSuggestions = mSuggestions.toArray(EMPTY_STRING_ARRAY);
+
+ final int bestScore = mScores[mLength - 1];
+ final CharSequence bestSuggestion = mSuggestions.get(0);
+ final float normalizedScore =
+ BinaryDictionary.calcNormalizedScore(
+ mOriginalText, bestSuggestion.toString(), bestScore);
+ hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold);
+ if (DBG) {
+ Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
+ Log.i(TAG, "Normalized score = " + normalizedScore
+ + " (threshold " + mRecommendedThreshold
+ + ") => hasRecommendedSuggestions = " + hasRecommendedSuggestions);
+ }
+ }
+ return new Result(gatheredSuggestions, hasRecommendedSuggestions);
+ }
+ }
+
+ @Override
+ public boolean onUnbind(final Intent intent) {
+ closeAllDictionaries();
+ return false;
+ }
+
+ private void closeAllDictionaries() {
+ final Map<String, DictionaryPool> oldPools = mDictionaryPools;
+ mDictionaryPools = Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
+ final Map<String, UserBinaryDictionary> oldUserDictionaries = mUserDictionaries;
+ mUserDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, UserBinaryDictionary>());
+ final Map<String, Dictionary> oldWhitelistDictionaries = mWhitelistDictionaries;
+ mWhitelistDictionaries = Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ new Thread("spellchecker_close_dicts") {
+ @Override
+ public void run() {
+ for (DictionaryPool pool : oldPools.values()) {
+ pool.close();
+ }
+ for (Dictionary dict : oldUserDictionaries.values()) {
+ dict.close();
+ }
+ for (Dictionary dict : oldWhitelistDictionaries.values()) {
+ dict.close();
+ }
+ synchronized (mUseContactsLock) {
+ if (null != mContactsDictionary) {
+ // The synchronously loaded contacts dictionary should have been in one
+ // or several pools, but it is shielded against multiple closing and it's
+ // safe to call it several times.
+ final ContactsBinaryDictionary dictToClose = mContactsDictionary;
+ // TODO: revert to the concrete type when USE_BINARY_CONTACTS_DICTIONARY
+ // is no longer needed
+ mContactsDictionary = null;
+ dictToClose.close();
+ }
+ }
+ }
+ }.start();
+ }
+
+ private DictionaryPool getDictionaryPool(final String locale) {
+ DictionaryPool pool = mDictionaryPools.get(locale);
+ if (null == pool) {
+ final Locale localeObject = LocaleUtils.constructLocaleFromString(locale);
+ pool = new DictionaryPool(POOL_SIZE, this, localeObject);
+ mDictionaryPools.put(locale, pool);
+ }
+ return pool;
+ }
+
+ public DictAndProximity createDictAndProximity(final Locale locale) {
+ final int script = getScriptFromLocale(locale);
+ final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo(
+ SpellCheckerProximityInfo.getProximityForScript(script),
+ SpellCheckerProximityInfo.ROW_SIZE,
+ SpellCheckerProximityInfo.PROXIMITY_GRID_WIDTH,
+ SpellCheckerProximityInfo.PROXIMITY_GRID_HEIGHT);
+ final DictionaryCollection dictionaryCollection =
+ DictionaryFactory.createMainDictionaryFromManager(this, locale,
+ true /* useFullEditDistance */);
+ final String localeStr = locale.toString();
+ UserBinaryDictionary userDictionary = mUserDictionaries.get(localeStr);
+ if (null == userDictionary) {
+ userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, localeStr, true);
+ mUserDictionaries.put(localeStr, userDictionary);
+ }
+ dictionaryCollection.addDictionary(userDictionary);
+ Dictionary whitelistDictionary = mWhitelistDictionaries.get(localeStr);
+ if (null == whitelistDictionary) {
+ whitelistDictionary = new WhitelistDictionary(this, locale);
+ mWhitelistDictionaries.put(localeStr, whitelistDictionary);
+ }
+ dictionaryCollection.addDictionary(whitelistDictionary);
+ synchronized (mUseContactsLock) {
+ if (mUseContactsDictionary) {
+ if (null == mContactsDictionary) {
+ // TODO: use the right locale. We can't do it right now because the
+ // spell checker is reusing the contacts dictionary across sessions
+ // without regard for their locale, so we need to fix that first.
+ mContactsDictionary = new SynchronouslyLoadedContactsBinaryDictionary(this,
+ Locale.getDefault());
+ }
+ }
+ dictionaryCollection.addDictionary(mContactsDictionary);
+ mDictionaryCollectionsList.add(
+ new WeakReference<DictionaryCollection>(dictionaryCollection));
+ }
+ return new DictAndProximity(dictionaryCollection, proximityInfo);
+ }
+
+ // This method assumes the text is not empty or null.
+ private static int getCapitalizationType(String text) {
+ // If the first char is not uppercase, then the word is either all lower case,
+ // and in either case we return CAPITALIZE_NONE.
+ if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
+ final int len = text.length();
+ int capsCount = 1;
+ for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
+ if (1 != capsCount && i != capsCount) break;
+ if (Character.isUpperCase(text.codePointAt(i))) ++capsCount;
+ }
+ // We know the first char is upper case. So we want to test if either everything
+ // else is lower case, or if everything else is upper case. If the string is
+ // exactly one char long, then we will arrive here with capsCount 1, and this is
+ // correct, too.
+ if (1 == capsCount) return CAPITALIZE_FIRST;
+ return (len == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
+ }
+
+ private static class AndroidSpellCheckerSession extends Session {
+ // Immutable, but need the locale which is not available in the constructor yet
+ private DictionaryPool mDictionaryPool;
+ // Likewise
+ private Locale mLocale;
+ // Cache this for performance
+ private int mScript; // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now.
+
+ private final AndroidSpellCheckerService mService;
+
+ private final SuggestionsCache mSuggestionsCache = new SuggestionsCache();
+
+ private static class SuggestionsParams {
+ public final String[] mSuggestions;
+ public final int mFlags;
+ public SuggestionsParams(String[] suggestions, int flags) {
+ mSuggestions = suggestions;
+ mFlags = flags;
+ }
+ }
+
+ private static class SuggestionsCache {
+ private static final char CHAR_DELIMITER = '\uFFFC';
+ private static final int MAX_CACHE_SIZE = 50;
+ private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache =
+ new LruCache<String, SuggestionsParams>(MAX_CACHE_SIZE);
+
+ // TODO: Support n-gram input
+ private static String generateKey(String query, String prevWord) {
+ if (TextUtils.isEmpty(query) || TextUtils.isEmpty(prevWord)) {
+ return query;
+ }
+ return query + CHAR_DELIMITER + prevWord;
+ }
+
+ // TODO: Support n-gram input
+ public SuggestionsParams getSuggestionsFromCache(String query, String prevWord) {
+ return mUnigramSuggestionsInfoCache.get(generateKey(query, prevWord));
+ }
+
+ // TODO: Support n-gram input
+ public void putSuggestionsToCache(
+ String query, String prevWord, String[] suggestions, int flags) {
+ if (suggestions == null || TextUtils.isEmpty(query)) {
+ return;
+ }
+ mUnigramSuggestionsInfoCache.put(
+ generateKey(query, prevWord), new SuggestionsParams(suggestions, flags));
+ }
+ }
+
+ AndroidSpellCheckerSession(final AndroidSpellCheckerService service) {
+ mService = service;
+ }
+
+ @Override
+ public void onCreate() {
+ final String localeString = getLocale();
+ mDictionaryPool = mService.getDictionaryPool(localeString);
+ mLocale = LocaleUtils.constructLocaleFromString(localeString);
+ mScript = getScriptFromLocale(mLocale);
+ }
+
+ /*
+ * Returns whether the code point is a letter that makes sense for the specified
+ * locale for this spell checker.
+ * The dictionaries supported by Latin IME are described in res/xml/spellchecker.xml
+ * and is limited to EFIGS languages and Russian.
+ * Hence at the moment this explicitly tests for Cyrillic characters or Latin characters
+ * as appropriate, and explicitly excludes CJK, Arabic and Hebrew characters.
+ */
+ private static boolean isLetterCheckableByLanguage(final int codePoint,
+ final int script) {
+ switch (script) {
+ case SCRIPT_LATIN:
+ // Our supported latin script dictionaries (EFIGS) at the moment only include
+ // characters in the C0, C1, Latin Extended A and B, IPA extensions unicode
+ // blocks. As it happens, those are back-to-back in the code range 0x40 to 0x2AF,
+ // so the below is a very efficient way to test for it. As for the 0-0x3F, it's
+ // excluded from isLetter anyway.
+ return codePoint <= 0x2AF && Character.isLetter(codePoint);
+ case SCRIPT_CYRILLIC:
+ // All Cyrillic characters are in the 400~52F block. There are some in the upper
+ // Unicode range, but they are archaic characters that are not used in modern
+ // russian and are not used by our dictionary.
+ return codePoint >= 0x400 && codePoint <= 0x52F && Character.isLetter(codePoint);
+ default:
+ // Should never come here
+ throw new RuntimeException("Impossible value of script: " + script);
+ }
+ }
+
+ /**
+ * Finds out whether a particular string should be filtered out of spell checking.
+ *
+ * This will loosely match URLs, numbers, symbols. To avoid always underlining words that
+ * we know we will never recognize, this accepts a script identifier that should be one
+ * of the SCRIPT_* constants defined above, to rule out quickly characters from very
+ * different languages.
+ *
+ * @param text the string to evaluate.
+ * @param script the identifier for the script this spell checker recognizes
+ * @return true if we should filter this text out, false otherwise
+ */
+ private static boolean shouldFilterOut(final String text, final int script) {
+ if (TextUtils.isEmpty(text) || text.length() <= 1) return true;
+
+ // TODO: check if an equivalent processing can't be done more quickly with a
+ // compiled regexp.
+ // Filter by first letter
+ final int firstCodePoint = text.codePointAt(0);
+ // Filter out words that don't start with a letter or an apostrophe
+ if (!isLetterCheckableByLanguage(firstCodePoint, script)
+ && '\'' != firstCodePoint) return true;
+
+ // Filter contents
+ final int length = text.length();
+ int letterCount = 0;
+ for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
+ final int codePoint = text.codePointAt(i);
+ // Any word containing a '@' is probably an e-mail address
+ // Any word containing a '/' is probably either an ad-hoc combination of two
+ // words or a URI - in either case we don't want to spell check that
+ if ('@' == codePoint || '/' == codePoint) return true;
+ if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount;
+ }
+ // Guestimate heuristic: perform spell checking if at least 3/4 of the characters
+ // in this word are letters
+ return (letterCount * 4 < length * 3);
+ }
+
+ private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(
+ TextInfo ti, SentenceSuggestionsInfo ssi) {
+ final String typedText = ti.getText();
+ if (!typedText.contains(SINGLE_QUOTE)) {
+ return null;
+ }
+ final int N = ssi.getSuggestionsCount();
+ final ArrayList<Integer> additionalOffsets = new ArrayList<Integer>();
+ final ArrayList<Integer> additionalLengths = new ArrayList<Integer>();
+ final ArrayList<SuggestionsInfo> additionalSuggestionsInfos =
+ new ArrayList<SuggestionsInfo>();
+ String currentWord = null;
+ for (int i = 0; i < N; ++i) {
+ final SuggestionsInfo si = ssi.getSuggestionsInfoAt(i);
+ final int flags = si.getSuggestionsAttributes();
+ if ((flags & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) == 0) {
+ continue;
+ }
+ final int offset = ssi.getOffsetAt(i);
+ final int length = ssi.getLengthAt(i);
+ final String subText = typedText.substring(offset, offset + length);
+ final String prevWord = currentWord;
+ currentWord = subText;
+ if (!subText.contains(SINGLE_QUOTE)) {
+ continue;
+ }
+ final String[] splitTexts = subText.split(SINGLE_QUOTE, -1);
+ if (splitTexts == null || splitTexts.length <= 1) {
+ continue;
+ }
+ final int splitNum = splitTexts.length;
+ for (int j = 0; j < splitNum; ++j) {
+ final String splitText = splitTexts[j];
+ if (TextUtils.isEmpty(splitText)) {
+ continue;
+ }
+ if (mSuggestionsCache.getSuggestionsFromCache(
+ splitText, prevWord) == null) {
+ continue;
+ }
+ final int newLength = splitText.length();
+ // Neither RESULT_ATTR_IN_THE_DICTIONARY nor RESULT_ATTR_LOOKS_LIKE_TYPO
+ final int newFlags = 0;
+ final SuggestionsInfo newSi = new SuggestionsInfo(newFlags, EMPTY_STRING_ARRAY);
+ newSi.setCookieAndSequence(si.getCookie(), si.getSequence());
+ if (DBG) {
+ Log.d(TAG, "Override and remove old span over: "
+ + splitText + ", " + offset + "," + newLength);
+ }
+ additionalOffsets.add(offset);
+ additionalLengths.add(newLength);
+ additionalSuggestionsInfos.add(newSi);
+ }
+ }
+ final int additionalSize = additionalOffsets.size();
+ if (additionalSize <= 0) {
+ return null;
+ }
+ final int suggestionsSize = N + additionalSize;
+ final int[] newOffsets = new int[suggestionsSize];
+ final int[] newLengths = new int[suggestionsSize];
+ final SuggestionsInfo[] newSuggestionsInfos = new SuggestionsInfo[suggestionsSize];
+ int i;
+ for (i = 0; i < N; ++i) {
+ newOffsets[i] = ssi.getOffsetAt(i);
+ newLengths[i] = ssi.getLengthAt(i);
+ newSuggestionsInfos[i] = ssi.getSuggestionsInfoAt(i);
+ }
+ for (; i < suggestionsSize; ++i) {
+ newOffsets[i] = additionalOffsets.get(i - N);
+ newLengths[i] = additionalLengths.get(i - N);
+ newSuggestionsInfos[i] = additionalSuggestionsInfos.get(i - N);
+ }
+ return new SentenceSuggestionsInfo(newSuggestionsInfos, newOffsets, newLengths);
+ }
+
+ @Override
+ public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(
+ TextInfo[] textInfos, int suggestionsLimit) {
+ final SentenceSuggestionsInfo[] retval = super.onGetSentenceSuggestionsMultiple(
+ textInfos, suggestionsLimit);
+ if (retval == null || retval.length != textInfos.length) {
+ return retval;
+ }
+ for (int i = 0; i < retval.length; ++i) {
+ final SentenceSuggestionsInfo tempSsi =
+ fixWronglyInvalidatedWordWithSingleQuote(textInfos[i], retval[i]);
+ if (tempSsi != null) {
+ retval[i] = tempSsi;
+ }
+ }
+ return retval;
+ }
+
+ @Override
+ public SuggestionsInfo[] onGetSuggestionsMultiple(TextInfo[] textInfos,
+ int suggestionsLimit, boolean sequentialWords) {
+ final int length = textInfos.length;
+ final SuggestionsInfo[] retval = new SuggestionsInfo[length];
+ for (int i = 0; i < length; ++i) {
+ final String prevWord;
+ if (sequentialWords && i > 0) {
+ final String prevWordCandidate = textInfos[i - 1].getText();
+ // Note that an empty string would be used to indicate the initial word
+ // in the future.
+ prevWord = TextUtils.isEmpty(prevWordCandidate) ? null : prevWordCandidate;
+ } else {
+ prevWord = null;
+ }
+ retval[i] = onGetSuggestions(textInfos[i], prevWord, suggestionsLimit);
+ retval[i].setCookieAndSequence(
+ textInfos[i].getCookie(), textInfos[i].getSequence());
+ }
+ return retval;
+ }
+
+ // Note : this must be reentrant
+ /**
+ * Gets a list of suggestions for a specific string. This returns a list of possible
+ * corrections for the text passed as an argument. It may split or group words, and
+ * even perform grammatical analysis.
+ */
+ @Override
+ public SuggestionsInfo onGetSuggestions(final TextInfo textInfo,
+ final int suggestionsLimit) {
+ return onGetSuggestions(textInfo, null, suggestionsLimit);
+ }
+
+ private SuggestionsInfo onGetSuggestions(
+ final TextInfo textInfo, final String prevWord, final int suggestionsLimit) {
+ try {
+ final String inText = textInfo.getText();
+ final SuggestionsParams cachedSuggestionsParams =
+ mSuggestionsCache.getSuggestionsFromCache(inText, prevWord);
+ if (cachedSuggestionsParams != null) {
+ if (DBG) {
+ Log.d(TAG, "Cache hit: " + inText + ", " + cachedSuggestionsParams.mFlags);
+ }
+ return new SuggestionsInfo(
+ cachedSuggestionsParams.mFlags, cachedSuggestionsParams.mSuggestions);
+ }
+
+ if (shouldFilterOut(inText, mScript)) {
+ DictAndProximity dictInfo = null;
+ try {
+ dictInfo = mDictionaryPool.takeOrGetNull();
+ if (null == dictInfo) return getNotInDictEmptySuggestions();
+ return dictInfo.mDictionary.isValidWord(inText) ?
+ getInDictEmptySuggestions() : getNotInDictEmptySuggestions();
+ } finally {
+ if (null != dictInfo) {
+ if (!mDictionaryPool.offer(dictInfo)) {
+ Log.e(TAG, "Can't re-insert a dictionary into its pool");
+ }
+ }
+ }
+ }
+ final String text = inText.replaceAll(APOSTROPHE, SINGLE_QUOTE);
+
+ // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
+ final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(text,
+ mService.mSuggestionThreshold, mService.mRecommendedThreshold,
+ suggestionsLimit);
+ final WordComposer composer = new WordComposer();
+ final int length = text.length();
+ for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
+ final int codePoint = text.codePointAt(i);
+ // The getXYForCodePointAndScript method returns (Y << 16) + X
+ final int xy = SpellCheckerProximityInfo.getXYForCodePointAndScript(
+ codePoint, mScript);
+ if (SpellCheckerProximityInfo.NOT_A_COORDINATE_PAIR == xy) {
+ composer.add(codePoint, WordComposer.NOT_A_COORDINATE,
+ WordComposer.NOT_A_COORDINATE, null);
+ } else {
+ composer.add(codePoint, xy & 0xFFFF, xy >> 16, null);
+ }
+ }
+
+ final int capitalizeType = getCapitalizationType(text);
+ boolean isInDict = true;
+ DictAndProximity dictInfo = null;
+ try {
+ dictInfo = mDictionaryPool.takeOrGetNull();
+ if (null == dictInfo) return getNotInDictEmptySuggestions();
+ dictInfo.mDictionary.getWords(composer, prevWord, suggestionsGatherer,
+ dictInfo.mProximityInfo);
+ isInDict = dictInfo.mDictionary.isValidWord(text);
+ if (!isInDict && CAPITALIZE_NONE != capitalizeType) {
+ // We want to test the word again if it's all caps or first caps only.
+ // If it's fully down, we already tested it, if it's mixed case, we don't
+ // want to test a lowercase version of it.
+ isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
+ }
+ } finally {
+ if (null != dictInfo) {
+ if (!mDictionaryPool.offer(dictInfo)) {
+ Log.e(TAG, "Can't re-insert a dictionary into its pool");
+ }
+ }
+ }
+
+ final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(
+ capitalizeType, mLocale);
+
+ if (DBG) {
+ Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
+ + suggestionsLimit);
+ Log.i(TAG, "IsInDict = " + isInDict);
+ Log.i(TAG, "LooksLikeTypo = " + (!isInDict));
+ Log.i(TAG, "HasRecommendedSuggestions = " + result.mHasRecommendedSuggestions);
+ if (null != result.mSuggestions) {
+ for (String suggestion : result.mSuggestions) {
+ Log.i(TAG, suggestion);
+ }
+ }
+ }
+
+ final int flags =
+ (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
+ : SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO)
+ | (result.mHasRecommendedSuggestions
+ ? SuggestionsInfoCompatUtils
+ .getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS()
+ : 0);
+ final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
+ mSuggestionsCache.putSuggestionsToCache(text, prevWord, result.mSuggestions, flags);
+ return retval;
+ } catch (RuntimeException e) {
+ // Don't kill the keyboard if there is a bug in the spell checker
+ if (DBG) {
+ throw e;
+ } else {
+ Log.e(TAG, "Exception while spellcheking: " + e);
+ return getNotInDictEmptySuggestions();
+ }
+ }
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java b/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java
new file mode 100644
index 000000000..3dbbd40cd
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictAndProximity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.spellcheck;
+
+import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+/**
+ * A simple container for both a Dictionary and a ProximityInfo.
+ */
+public class DictAndProximity {
+ public final Dictionary mDictionary;
+ public final ProximityInfo mProximityInfo;
+ public DictAndProximity(final Dictionary dictionary, final ProximityInfo proximityInfo) {
+ mDictionary = dictionary;
+ mProximityInfo = proximityInfo;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
new file mode 100644
index 000000000..8fc632ee7
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.spellcheck;
+
+import java.util.Locale;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * A blocking queue that creates dictionaries up to a certain limit as necessary.
+ */
+@SuppressWarnings("serial")
+public class DictionaryPool extends LinkedBlockingQueue<DictAndProximity> {
+ private final AndroidSpellCheckerService mService;
+ private final int mMaxSize;
+ private final Locale mLocale;
+ private int mSize;
+ private volatile boolean mClosed;
+
+ public DictionaryPool(final int maxSize, final AndroidSpellCheckerService service,
+ final Locale locale) {
+ super();
+ mMaxSize = maxSize;
+ mService = service;
+ mLocale = locale;
+ mSize = 0;
+ mClosed = false;
+ }
+
+ @Override
+ public DictAndProximity take() throws InterruptedException {
+ final DictAndProximity dict = poll();
+ if (null != dict) return dict;
+ synchronized(this) {
+ if (mSize >= mMaxSize) {
+ // Our pool is already full. Wait until some dictionary is ready.
+ return super.take();
+ } else {
+ ++mSize;
+ return mService.createDictAndProximity(mLocale);
+ }
+ }
+ }
+
+ // Convenience method
+ public DictAndProximity takeOrGetNull() {
+ try {
+ return take();
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+
+ public void close() {
+ synchronized(this) {
+ mClosed = true;
+ for (DictAndProximity dict : this) {
+ dict.mDictionary.close();
+ }
+ clear();
+ }
+ }
+
+ @Override
+ public boolean offer(final DictAndProximity dict) {
+ if (mClosed) {
+ dict.mDictionary.close();
+ return false;
+ } else {
+ return super.offer(dict);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java
deleted file mode 100644
index 63c6d69d7..000000000
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellChecker.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin.spellcheck;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import com.android.inputmethod.compat.ArraysCompatUtils;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.Dictionary.DataType;
-import com.android.inputmethod.latin.Dictionary.WordCallback;
-import com.android.inputmethod.latin.DictionaryFactory;
-import com.android.inputmethod.latin.Utils;
-import com.android.inputmethod.latin.WordComposer;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Implements spell checking methods.
- */
-public class SpellChecker {
-
- public final Dictionary mDictionary;
-
- public SpellChecker(final Context context, final Locale locale) {
- final Resources resources = context.getResources();
- final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources);
- mDictionary = DictionaryFactory.createDictionaryFromManager(context, locale,
- fallbackResourceId);
- }
-
- // Note : this must be reentrant
- /**
- * Finds out whether a word is in the dictionary or not.
- *
- * @param text the sequence containing the word to check for.
- * @param start the index of the first character of the word in text.
- * @param end the index of the next-to-last character in text.
- * @return true if the word is in the dictionary, false otherwise.
- */
- public boolean isCorrect(final CharSequence text, final int start, final int end) {
- return mDictionary.isValidWord(text.subSequence(start, end));
- }
-
- private static class SuggestionsGatherer implements WordCallback {
- private final int DEFAULT_SUGGESTION_LENGTH = 16;
- private final List<String> mSuggestions = new LinkedList<String>();
- private int[] mScores = new int[DEFAULT_SUGGESTION_LENGTH];
- private int mLength = 0;
-
- @Override
- synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score,
- int dicTypeId, DataType dataType) {
- if (mLength >= mScores.length) {
- final int newLength = mScores.length * 2;
- mScores = new int[newLength];
- }
- final int positionIndex = ArraysCompatUtils.binarySearch(mScores, 0, mLength, score);
- // binarySearch returns the index if the element exists, and -<insertion index> - 1
- // if it doesn't. See documentation for binarySearch.
- final int insertionIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1;
- System.arraycopy(mScores, insertionIndex, mScores, insertionIndex + 1,
- mLength - insertionIndex);
- mLength += 1;
- mScores[insertionIndex] = score;
- mSuggestions.add(insertionIndex, new String(word, wordOffset, wordLength));
- return true;
- }
-
- public List<String> getGatheredSuggestions() {
- return mSuggestions;
- }
- }
-
- // Note : this must be reentrant
- /**
- * Gets a list of suggestions for a specific string.
- *
- * This returns a list of possible corrections for the text passed as an
- * arguments. It may split or group words, and even perform grammatical
- * analysis.
- *
- * @param text the sequence containing the word to check for.
- * @param start the index of the first character of the word in text.
- * @param end the index of the next-to-last character in text.
- * @return a list of possible suggestions to replace the text.
- */
- public List<String> getSuggestions(final CharSequence text, final int start, final int end) {
- final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer();
- final WordComposer composer = new WordComposer();
- for (int i = start; i < end; ++i) {
- int character = text.charAt(i);
- composer.add(character, new int[] { character },
- WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
- }
- mDictionary.getWords(composer, suggestionsGatherer);
- return suggestionsGatherer.getGatheredSuggestions();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
new file mode 100644
index 000000000..0103e8423
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.spellcheck;
+
+import com.android.inputmethod.keyboard.KeyDetector;
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+import java.util.TreeMap;
+
+public class SpellCheckerProximityInfo {
+ /* public for test */
+ final public static int NUL = KeyDetector.NOT_A_CODE;
+
+ // This must be the same as MAX_PROXIMITY_CHARS_SIZE else it will not work inside
+ // native code - this value is passed at creation of the binary object and reused
+ // as the size of the passed array afterwards so they can't be different.
+ final public static int ROW_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE;
+
+ // The number of keys in a row of the grid used by the spell checker.
+ final public static int PROXIMITY_GRID_WIDTH = 11;
+ // The number of rows in the grid used by the spell checker.
+ final public static int PROXIMITY_GRID_HEIGHT = 3;
+
+ final private static int NOT_AN_INDEX = -1;
+ final public static int NOT_A_COORDINATE_PAIR = -1;
+
+ // Helper methods
+ final protected static void buildProximityIndices(final int[] proximity,
+ final TreeMap<Integer, Integer> indices) {
+ for (int i = 0; i < proximity.length; i += ROW_SIZE) {
+ if (NUL != proximity[i]) indices.put(proximity[i], i / ROW_SIZE);
+ }
+ }
+ final protected static int computeIndex(final int characterCode,
+ final TreeMap<Integer, Integer> indices) {
+ final Integer result = indices.get(characterCode);
+ if (null == result) return NOT_AN_INDEX;
+ return result;
+ }
+
+ private static class Latin {
+ // This is a map from the code point to the index in the PROXIMITY array.
+ // At the time the native code to read the binary dictionary needs the proximity info be
+ // passed as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input
+ // character.
+ // Since we need to build such an array, we want to be able to search in our big proximity
+ // data quickly by character, and a map is probably the best way to do this.
+ final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>();
+
+ // The proximity here is the union of
+ // - the proximity for a QWERTY keyboard.
+ // - the proximity for an AZERTY keyboard.
+ // - the proximity for a QWERTZ keyboard.
+ // ...plus, add all characters in the ('a', 'e', 'i', 'o', 'u') set to each other.
+ //
+ // The reasoning behind this construction is, almost any alphabetic text we may want
+ // to spell check has been entered with one of the keyboards above. Also, specifically
+ // to English, many spelling errors consist of the last vowel of the word being wrong
+ // because in English vowels tend to merge with each other in pronunciation.
+ final static int[] PROXIMITY = {
+ // Proximity for row 1. This must have exactly ROW_SIZE entries for each letter,
+ // and exactly PROXIMITY_GRID_WIDTH letters for a row. Pad with NUL's.
+ // The number of rows must be exactly PROXIMITY_GRID_HEIGHT.
+ 'q', 'w', 's', 'a', 'z', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'w', 'q', 'a', 's', 'd', 'e', 'x', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'e', 'w', 's', 'd', 'f', 'r', 'a', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
+ 'r', 'e', 'd', 'f', 'g', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 't', 'r', 'f', 'g', 'h', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'y', 't', 'g', 'h', 'j', 'u', 'a', 's', 'd', 'x', NUL, NUL, NUL, NUL, NUL, NUL,
+ 'u', 'y', 'h', 'j', 'k', 'i', 'a', 'e', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'i', 'u', 'j', 'k', 'l', 'o', 'a', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'o', 'i', 'k', 'l', 'p', 'a', 'e', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'p', 'o', 'l', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ // Proximity for row 2. See comment above about size.
+ 'a', 'z', 'x', 's', 'w', 'q', 'e', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL,
+ 's', 'q', 'a', 'z', 'x', 'c', 'd', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'd', 'w', 's', 'x', 'c', 'v', 'f', 'r', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'f', 'e', 'd', 'c', 'v', 'b', 'g', 't', 'r', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'g', 'r', 'f', 'v', 'b', 'n', 'h', 'y', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'h', 't', 'g', 'b', 'n', 'm', 'j', 'u', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'j', 'y', 'h', 'n', 'm', 'k', 'i', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'k', 'u', 'j', 'm', 'l', 'o', 'i', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'l', 'i', 'k', 'p', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ // Proximity for row 3. See comment above about size.
+ 'z', 'a', 's', 'd', 'x', 't', 'g', 'h', 'j', 'u', 'q', 'e', NUL, NUL, NUL, NUL,
+ 'x', 'z', 'a', 's', 'd', 'c', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'c', 'x', 's', 'd', 'f', 'v', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'v', 'c', 'd', 'f', 'g', 'b', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'b', 'v', 'f', 'g', 'h', 'n', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'n', 'b', 'g', 'h', 'j', 'm', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'm', 'n', 'h', 'j', 'k', 'l', 'o', 'p', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ };
+ static {
+ buildProximityIndices(PROXIMITY, INDICES);
+ }
+ static int getIndexOf(int characterCode) {
+ return computeIndex(characterCode, INDICES);
+ }
+ }
+
+ private static class Cyrillic {
+ final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>();
+ // TODO: The following table is solely based on the keyboard layout. Consult with Russian
+ // speakers on commonly misspelled words/letters.
+ final static int[] PROXIMITY = {
+ // Proximity for row 1. This must have exactly ROW_SIZE entries for each letter,
+ // and exactly PROXIMITY_GRID_WIDTH letters for a row. Pad with NUL's.
+ // The number of rows must be exactly PROXIMITY_GRID_HEIGHT.
+ 'й', 'ц', 'ф', 'ы', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ц', 'й', 'ф', 'ы', 'в', 'у', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'у', 'ц', 'ы', 'в', 'а', 'к', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'к', 'у', 'в', 'а', 'п', 'е', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'е', 'к', 'а', 'п', 'р', 'н', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'н', 'е', 'п', 'р', 'о', 'г', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'г', 'н', 'р', 'о', 'л', 'ш', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ш', 'г', 'о', 'л', 'д', 'щ', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'щ', 'ш', 'л', 'д', 'ж', 'з', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'з', 'щ', 'д', 'ж', 'э', 'х', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'х', 'з', 'ж', 'э', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ // Proximity for row 2. See comment above about size.
+ 'ф', 'й', 'ц', 'ы', 'я', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ы', 'й', 'ц', 'у', 'ф', 'в', 'я', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'в', 'ц', 'у', 'к', 'ы', 'а', 'я', 'ч', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'а', 'у', 'к', 'е', 'в', 'п', 'ч', 'с', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'п', 'к', 'е', 'н', 'а', 'р', 'с', 'м', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'р', 'е', 'н', 'г', 'п', 'о', 'м', 'и', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'о', 'н', 'г', 'ш', 'р', 'л', 'и', 'т', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'л', 'г', 'ш', 'щ', 'о', 'д', 'т', 'ь', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'д', 'ш', 'щ', 'з', 'л', 'ж', 'ь', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ж', 'щ', 'з', 'х', 'д', 'э', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'э', 'з', 'х', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+
+ // Proximity for row 3. See comment above about size.
+ 'я', 'ф', 'ы', 'в', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ч', 'ы', 'в', 'а', 'я', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'с', 'в', 'а', 'п', 'ч', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'м', 'а', 'п', 'р', 'с', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'и', 'п', 'р', 'о', 'м', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'т', 'р', 'о', 'л', 'и', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ь', 'о', 'л', 'д', 'т', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'б', 'л', 'д', 'ж', 'ь', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ 'ю', 'д', 'ж', 'э', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL,
+ };
+ static {
+ buildProximityIndices(PROXIMITY, INDICES);
+ }
+ static int getIndexOf(int characterCode) {
+ return computeIndex(characterCode, INDICES);
+ }
+ }
+
+ public static int[] getProximityForScript(final int script) {
+ switch (script) {
+ case AndroidSpellCheckerService.SCRIPT_LATIN:
+ return Latin.PROXIMITY;
+ case AndroidSpellCheckerService.SCRIPT_CYRILLIC:
+ return Cyrillic.PROXIMITY;
+ default:
+ throw new RuntimeException("Wrong script supplied: " + script);
+ }
+ }
+
+ private static int getIndexOfCodeForScript(final int codePoint, final int script) {
+ switch (script) {
+ case AndroidSpellCheckerService.SCRIPT_LATIN:
+ return Latin.getIndexOf(codePoint);
+ case AndroidSpellCheckerService.SCRIPT_CYRILLIC:
+ return Cyrillic.getIndexOf(codePoint);
+ default:
+ throw new RuntimeException("Wrong script supplied: " + script);
+ }
+ }
+
+ // Returns (Y << 16) + X to avoid creating a temporary object. This is okay because
+ // X and Y are limited to PROXIMITY_GRID_WIDTH resp. PROXIMITY_GRID_HEIGHT which is very
+ // inferior to 1 << 16
+ // As an exception, this returns NOT_A_COORDINATE_PAIR if the key is not on the grid
+ public static int getXYForCodePointAndScript(final int codePoint, final int script) {
+ final int index = getIndexOfCodeForScript(codePoint, script);
+ if (NOT_AN_INDEX == index) return NOT_A_COORDINATE_PAIR;
+ final int y = index / PROXIMITY_GRID_WIDTH;
+ final int x = index % PROXIMITY_GRID_WIDTH;
+ if (y > PROXIMITY_GRID_HEIGHT) {
+ // Safety check, should be entirely useless
+ throw new RuntimeException("Wrong y coordinate in spell checker proximity");
+ }
+ return (y << 16) + x;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
new file mode 100644
index 000000000..e14db8797
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.android.inputmethod.latin.spellcheck;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+/**
+ * Spell checker preference screen.
+ */
+public class SpellCheckerSettingsActivity extends PreferenceActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public Intent getIntent() {
+ final Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, SpellCheckerSettingsFragment.class.getName());
+ modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ return modIntent;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
new file mode 100644
index 000000000..7056874a1
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.android.inputmethod.latin.spellcheck;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+import com.android.inputmethod.latin.R;
+
+/**
+ * Preference screen.
+ */
+public class SpellCheckerSettingsFragment extends PreferenceFragment {
+ /**
+ * Empty constructor for fragment generation.
+ */
+ public SpellCheckerSettingsFragment() {
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ addPreferencesFromResource(R.xml.spell_checker_settings);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
new file mode 100644
index 000000000..c6fe43b69
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.suggestions;
+
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.Utils;
+
+public class MoreSuggestions extends Keyboard {
+ public static final int SUGGESTION_CODE_BASE = 1024;
+
+ MoreSuggestions(Builder.MoreSuggestionsParam params) {
+ super(params);
+ }
+
+ public static class Builder extends Keyboard.Builder<Builder.MoreSuggestionsParam> {
+ private final MoreSuggestionsView mPaneView;
+ private SuggestedWords mSuggestions;
+ private int mFromPos;
+ private int mToPos;
+
+ public static class MoreSuggestionsParam extends Keyboard.Params {
+ private final int[] mWidths = new int[SuggestionsView.MAX_SUGGESTIONS];
+ private final int[] mRowNumbers = new int[SuggestionsView.MAX_SUGGESTIONS];
+ private final int[] mColumnOrders = new int[SuggestionsView.MAX_SUGGESTIONS];
+ private final int[] mNumColumnsInRow = new int[SuggestionsView.MAX_SUGGESTIONS];
+ private static final int MAX_COLUMNS_IN_ROW = 3;
+ private int mNumRows;
+ public Drawable mDivider;
+ public int mDividerWidth;
+
+ public int layout(SuggestedWords suggestions, int fromPos, int maxWidth, int minWidth,
+ int maxRow, MoreSuggestionsView view) {
+ clearKeys();
+ final Resources res = view.getContext().getResources();
+ mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
+ mDividerWidth = mDivider.getIntrinsicWidth();
+ final int padding = (int) res.getDimension(
+ R.dimen.more_suggestions_key_horizontal_padding);
+ final Paint paint = view.newDefaultLabelPaint();
+
+ int row = 0;
+ int pos = fromPos, rowStartPos = fromPos;
+ final int size = Math.min(suggestions.size(), SuggestionsView.MAX_SUGGESTIONS);
+ while (pos < size) {
+ final String word = suggestions.getWord(pos).toString();
+ // TODO: Should take care of text x-scaling.
+ mWidths[pos] = (int)view.getLabelWidth(word, paint) + padding;
+ final int numColumn = pos - rowStartPos + 1;
+ final int columnWidth =
+ (maxWidth - mDividerWidth * (numColumn - 1)) / numColumn;
+ if (numColumn > MAX_COLUMNS_IN_ROW
+ || !fitInWidth(rowStartPos, pos + 1, columnWidth)) {
+ if ((row + 1) >= maxRow) {
+ break;
+ }
+ mNumColumnsInRow[row] = pos - rowStartPos;
+ rowStartPos = pos;
+ row++;
+ }
+ mColumnOrders[pos] = pos - rowStartPos;
+ mRowNumbers[pos] = row;
+ pos++;
+ }
+ mNumColumnsInRow[row] = pos - rowStartPos;
+ mNumRows = row + 1;
+ mBaseWidth = mOccupiedWidth = Math.max(
+ minWidth, calcurateMaxRowWidth(fromPos, pos));
+ mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
+ return pos - fromPos;
+ }
+
+ private boolean fitInWidth(int startPos, int endPos, int width) {
+ for (int pos = startPos; pos < endPos; pos++) {
+ if (mWidths[pos] > width)
+ return false;
+ }
+ return true;
+ }
+
+ private int calcurateMaxRowWidth(int startPos, int endPos) {
+ int maxRowWidth = 0;
+ int pos = startPos;
+ for (int row = 0; row < mNumRows; row++) {
+ final int numColumnInRow = mNumColumnsInRow[row];
+ int maxKeyWidth = 0;
+ while (pos < endPos && mRowNumbers[pos] == row) {
+ maxKeyWidth = Math.max(maxKeyWidth, mWidths[pos]);
+ pos++;
+ }
+ maxRowWidth = Math.max(maxRowWidth,
+ maxKeyWidth * numColumnInRow + mDividerWidth * (numColumnInRow - 1));
+ }
+ return maxRowWidth;
+ }
+
+ private static final int[][] COLUMN_ORDER_TO_NUMBER = {
+ { 0, },
+ { 1, 0, },
+ { 2, 0, 1},
+ };
+
+ public int getNumColumnInRow(int pos) {
+ return mNumColumnsInRow[mRowNumbers[pos]];
+ }
+
+ public int getColumnNumber(int pos) {
+ final int columnOrder = mColumnOrders[pos];
+ final int numColumn = getNumColumnInRow(pos);
+ return COLUMN_ORDER_TO_NUMBER[numColumn - 1][columnOrder];
+ }
+
+ public int getX(int pos) {
+ final int columnNumber = getColumnNumber(pos);
+ return columnNumber * (getWidth(pos) + mDividerWidth);
+ }
+
+ public int getY(int pos) {
+ final int row = mRowNumbers[pos];
+ return (mNumRows -1 - row) * mDefaultRowHeight + mTopPadding;
+ }
+
+ public int getWidth(int pos) {
+ final int numColumnInRow = getNumColumnInRow(pos);
+ return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
+ }
+
+ public void markAsEdgeKey(Key key, int pos) {
+ final int row = mRowNumbers[pos];
+ if (row == 0)
+ key.markAsBottomEdge(this);
+ if (row == mNumRows - 1)
+ key.markAsTopEdge(this);
+
+ final int numColumnInRow = mNumColumnsInRow[row];
+ final int column = getColumnNumber(pos);
+ if (column == 0)
+ key.markAsLeftEdge(this);
+ if (column == numColumnInRow - 1)
+ key.markAsRightEdge(this);
+ }
+ }
+
+ public Builder(MoreSuggestionsView paneView) {
+ super(paneView.getContext(), new MoreSuggestionsParam());
+ mPaneView = paneView;
+ }
+
+ public Builder layout(SuggestedWords suggestions, int fromPos, int maxWidth,
+ int minWidth, int maxRow) {
+ final Keyboard keyboard = KeyboardSwitcher.getInstance().getKeyboard();
+ final int xmlId = R.xml.kbd_suggestions_pane_template;
+ load(xmlId, keyboard.mId);
+ mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2;
+
+ final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
+ mPaneView);
+ mFromPos = fromPos;
+ mToPos = fromPos + count;
+ mSuggestions = suggestions;
+ return this;
+ }
+
+ private static class Divider extends Key.Spacer {
+ private final Drawable mIcon;
+
+ public Divider(Keyboard.Params params, Drawable icon, int x, int y, int width,
+ int height) {
+ super(params, x, y, width, height);
+ mIcon = icon;
+ }
+
+ @Override
+ public Drawable getIcon(KeyboardIconsSet iconSet, int alpha) {
+ // KeyboardIconsSet and alpha are unused. Use the icon that has been passed to the
+ // constructor.
+ // TODO: Drawable itself should have an alpha value.
+ mIcon.setAlpha(128);
+ return mIcon;
+ }
+ }
+
+ @Override
+ public MoreSuggestions build() {
+ final MoreSuggestionsParam params = mParams;
+ for (int pos = mFromPos; pos < mToPos; pos++) {
+ final int x = params.getX(pos);
+ final int y = params.getY(pos);
+ final int width = params.getWidth(pos);
+ final String word = mSuggestions.getWord(pos).toString();
+ final String info = Utils.getDebugInfo(mSuggestions, pos);
+ final int index = pos + SUGGESTION_CODE_BASE;
+ final Key key = new Key(
+ params, word, info, KeyboardIconsSet.ICON_UNDEFINED, index, null, x, y,
+ width, params.mDefaultRowHeight, 0);
+ params.markAsEdgeKey(key, pos);
+ params.onAddKey(key);
+ final int columnNumber = params.getColumnNumber(pos);
+ final int numColumnInRow = params.getNumColumnInRow(pos);
+ if (columnNumber < numColumnInRow - 1) {
+ final Divider divider = new Divider(params, params.mDivider, x + width, y,
+ params.mDividerWidth, params.mDefaultRowHeight);
+ params.onAddKey(divider);
+ }
+ }
+ return new MoreSuggestions(params);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
new file mode 100644
index 000000000..19287e3f3
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.suggestions;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.PopupWindow;
+
+import com.android.inputmethod.keyboard.KeyDetector;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardActionListener;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.MoreKeysDetector;
+import com.android.inputmethod.keyboard.MoreKeysPanel;
+import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
+import com.android.inputmethod.keyboard.PointerTracker.KeyEventHandler;
+import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.latin.R;
+
+/**
+ * A view that renders a virtual {@link MoreSuggestions}. It handles rendering of keys and detecting
+ * key presses and touch movements.
+ */
+public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
+ private final int[] mCoordinates = new int[2];
+
+ final KeyDetector mModalPanelKeyDetector;
+ private final KeyDetector mSlidingPanelKeyDetector;
+
+ private Controller mController;
+ KeyboardActionListener mListener;
+ private int mOriginX;
+ private int mOriginY;
+
+ static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter();
+
+ final KeyboardActionListener mSuggestionsPaneListener =
+ new KeyboardActionListener.Adapter() {
+ @Override
+ public void onPressKey(int primaryCode) {
+ mListener.onPressKey(primaryCode);
+ }
+
+ @Override
+ public void onReleaseKey(int primaryCode, boolean withSliding) {
+ mListener.onReleaseKey(primaryCode, withSliding);
+ }
+
+ @Override
+ public void onCodeInput(int primaryCode, int x, int y) {
+ final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE;
+ if (index >= 0 && index < SuggestionsView.MAX_SUGGESTIONS) {
+ mListener.onCustomRequest(index);
+ }
+ }
+
+ @Override
+ public void onCancelInput() {
+ mListener.onCancelInput();
+ }
+ };
+
+ public MoreSuggestionsView(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.moreSuggestionsViewStyle);
+ }
+
+ public MoreSuggestionsView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final Resources res = context.getResources();
+ mModalPanelKeyDetector = new KeyDetector(/* keyHysteresisDistance */ 0);
+ mSlidingPanelKeyDetector = new MoreKeysDetector(
+ res.getDimension(R.dimen.more_suggestions_slide_allowance));
+ setKeyPreviewPopupEnabled(false, 0);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final Keyboard keyboard = getKeyboard();
+ if (keyboard != null) {
+ final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
+ final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
+ setMeasuredDimension(width, height);
+ } else {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ @Override
+ public void setKeyboard(Keyboard keyboard) {
+ super.setKeyboard(keyboard);
+ mModalPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), -getPaddingTop());
+ mSlidingPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
+ -getPaddingTop() + mVerticalCorrection);
+ }
+
+ @Override
+ public KeyDetector getKeyDetector() {
+ return mSlidingPanelKeyDetector;
+ }
+
+ @Override
+ public KeyboardActionListener getKeyboardActionListener() {
+ return mSuggestionsPaneListener;
+ }
+
+ @Override
+ public DrawingProxy getDrawingProxy() {
+ return this;
+ }
+
+ @Override
+ public TimerProxy getTimerProxy() {
+ return EMPTY_TIMER_PROXY;
+ }
+
+ @Override
+ public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
+ // Suggestions pane needs no pop-up key preview displayed, so we pass always false with a
+ // delay of 0. The delay does not matter actually since the popup is not shown anyway.
+ super.setKeyPreviewPopupEnabled(false, 0);
+ }
+
+ @Override
+ public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
+ PopupWindow window, KeyboardActionListener listener) {
+ mController = controller;
+ mListener = listener;
+ final View container = (View)getParent();
+ final MoreSuggestions pane = (MoreSuggestions)getKeyboard();
+ final int defaultCoordX = pane.mOccupiedWidth / 2;
+ // The coordinates of panel's left-top corner in parentView's coordinate system.
+ final int x = pointX - defaultCoordX - container.getPaddingLeft();
+ final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom();
+
+ window.setContentView(container);
+ window.setWidth(container.getMeasuredWidth());
+ window.setHeight(container.getMeasuredHeight());
+ parentView.getLocationInWindow(mCoordinates);
+ window.showAtLocation(parentView, Gravity.NO_GRAVITY,
+ x + mCoordinates[0], y + mCoordinates[1]);
+
+ mOriginX = x + container.getPaddingLeft();
+ mOriginY = y + container.getPaddingTop();
+ }
+
+ private boolean mIsDismissing;
+
+ @Override
+ public boolean dismissMoreKeysPanel() {
+ if (mIsDismissing || mController == null) return false;
+ mIsDismissing = true;
+ final boolean dismissed = mController.dismissMoreKeysPanel();
+ mIsDismissing = false;
+ return dismissed;
+ }
+
+ @Override
+ public int translateX(int x) {
+ return x - mOriginX;
+ }
+
+ @Override
+ public int translateY(int y) {
+ return y - mOriginY;
+ }
+
+ private final KeyEventHandler mModalPanelKeyEventHandler = new KeyEventHandler() {
+ @Override
+ public KeyDetector getKeyDetector() {
+ return mModalPanelKeyDetector;
+ }
+
+ @Override
+ public KeyboardActionListener getKeyboardActionListener() {
+ return mSuggestionsPaneListener;
+ }
+
+ @Override
+ public DrawingProxy getDrawingProxy() {
+ return MoreSuggestionsView.this;
+ }
+
+ @Override
+ public TimerProxy getTimerProxy() {
+ return EMPTY_TIMER_PROXY;
+ }
+ };
+
+ @Override
+ public boolean onTouchEvent(MotionEvent me) {
+ final int action = me.getAction();
+ final long eventTime = me.getEventTime();
+ final int index = me.getActionIndex();
+ final int id = me.getPointerId(index);
+ final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
+ final int x = (int)me.getX(index);
+ final int y = (int)me.getY(index);
+ tracker.processMotionEvent(action, x, y, eventTime, mModalPanelKeyEventHandler);
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
new file mode 100644
index 000000000..e86390b11
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin.suggestions;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Message;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.CharacterStyle;
+import android.text.style.StyleSpan;
+import android.text.style.UnderlineSpan;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.inputmethod.keyboard.KeyboardActionListener;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.MoreKeysPanel;
+import com.android.inputmethod.keyboard.PointerTracker;
+import com.android.inputmethod.keyboard.ViewLayoutUtils;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.ResearchLogger;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+import com.android.inputmethod.latin.Suggest;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.Utils;
+import com.android.inputmethod.latin.define.ProductionFlag;
+
+import java.util.ArrayList;
+
+public class SuggestionsView extends RelativeLayout implements OnClickListener,
+ OnLongClickListener {
+ public interface Listener {
+ public boolean addWordToDictionary(String word);
+ public void pickSuggestionManually(int index, CharSequence word, int x, int y);
+ }
+
+ // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
+ public static final int MAX_SUGGESTIONS = 18;
+
+ static final boolean DBG = LatinImeLogger.sDBG;
+
+ private final ViewGroup mSuggestionsStrip;
+ private KeyboardView mKeyboardView;
+
+ private final View mMoreSuggestionsContainer;
+ private final MoreSuggestionsView mMoreSuggestionsView;
+ private final MoreSuggestions.Builder mMoreSuggestionsBuilder;
+ private final PopupWindow mMoreSuggestionsWindow;
+
+ private final ArrayList<TextView> mWords = new ArrayList<TextView>();
+ private final ArrayList<TextView> mInfos = new ArrayList<TextView>();
+ private final ArrayList<View> mDividers = new ArrayList<View>();
+
+ private final PopupWindow mPreviewPopup;
+ private final TextView mPreviewText;
+
+ private Listener mListener;
+ private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
+
+ private final SuggestionsViewParams mParams;
+ private static final float MIN_TEXT_XSCALE = 0.70f;
+
+ private final UiHandler mHandler = new UiHandler(this);
+
+ private static class UiHandler extends StaticInnerHandlerWrapper<SuggestionsView> {
+ private static final int MSG_HIDE_PREVIEW = 0;
+
+ public UiHandler(SuggestionsView outerInstance) {
+ super(outerInstance);
+ }
+
+ @Override
+ public void dispatchMessage(Message msg) {
+ final SuggestionsView suggestionsView = getOuterInstance();
+ switch (msg.what) {
+ case MSG_HIDE_PREVIEW:
+ suggestionsView.hidePreview();
+ break;
+ }
+ }
+
+ public void cancelHidePreview() {
+ removeMessages(MSG_HIDE_PREVIEW);
+ }
+
+ public void cancelAllMessages() {
+ cancelHidePreview();
+ }
+ }
+
+ private static class SuggestionsViewParams {
+ private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3;
+ private static final int DEFAULT_CENTER_SUGGESTION_PERCENTILE = 40;
+ private static final int DEFAULT_MAX_MORE_SUGGESTIONS_ROW = 2;
+ private static final int PUNCTUATIONS_IN_STRIP = 5;
+
+ public final int mPadding;
+ public final int mDividerWidth;
+ public final int mSuggestionsStripHeight;
+ public final int mSuggestionsCountInStrip;
+ public final int mMoreSuggestionsRowHeight;
+ private int mMaxMoreSuggestionsRow;
+ public final float mMinMoreSuggestionsWidth;
+ public final int mMoreSuggestionsBottomGap;
+
+ private final ArrayList<TextView> mWords;
+ private final ArrayList<View> mDividers;
+ private final ArrayList<TextView> mInfos;
+
+ private final int mColorValidTypedWord;
+ private final int mColorTypedWord;
+ private final int mColorAutoCorrect;
+ private final int mColorSuggested;
+ private final float mAlphaObsoleted;
+ private final float mCenterSuggestionWeight;
+ private final int mCenterSuggestionIndex;
+ private final Drawable mMoreSuggestionsHint;
+ private static final String MORE_SUGGESTIONS_HINT = "\u2026";
+ private static final String LEFTWARDS_ARROW = "\u2190";
+
+ private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
+ private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
+ private static final int AUTO_CORRECT_BOLD = 0x01;
+ private static final int AUTO_CORRECT_UNDERLINE = 0x02;
+ private static final int VALID_TYPED_WORD_BOLD = 0x04;
+
+ private final int mSuggestionStripOption;
+
+ private final ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
+
+ public boolean mMoreSuggestionsAvailable;
+
+ private final TextView mWordToSaveView;
+ private final TextView mLeftwardsArrowView;
+ private final TextView mHintToSaveView;
+
+ public SuggestionsViewParams(Context context, AttributeSet attrs, int defStyle,
+ ArrayList<TextView> words, ArrayList<View> dividers, ArrayList<TextView> infos) {
+ mWords = words;
+ mDividers = dividers;
+ mInfos = infos;
+
+ final TextView word = words.get(0);
+ final View divider = dividers.get(0);
+ mPadding = word.getCompoundPaddingLeft() + word.getCompoundPaddingRight();
+ divider.measure(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ mDividerWidth = divider.getMeasuredWidth();
+
+ final Resources res = word.getResources();
+ mSuggestionsStripHeight = res.getDimensionPixelSize(R.dimen.suggestions_strip_height);
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.SuggestionsView, defStyle, R.style.SuggestionsViewStyle);
+ mSuggestionStripOption = a.getInt(R.styleable.SuggestionsView_suggestionStripOption, 0);
+ final float alphaValidTypedWord = getPercent(a,
+ R.styleable.SuggestionsView_alphaValidTypedWord, 100);
+ final float alphaTypedWord = getPercent(a,
+ R.styleable.SuggestionsView_alphaTypedWord, 100);
+ final float alphaAutoCorrect = getPercent(a,
+ R.styleable.SuggestionsView_alphaAutoCorrect, 100);
+ final float alphaSuggested = getPercent(a,
+ R.styleable.SuggestionsView_alphaSuggested, 100);
+ mAlphaObsoleted = getPercent(a, R.styleable.SuggestionsView_alphaSuggested, 100);
+ mColorValidTypedWord = applyAlpha(
+ a.getColor(R.styleable.SuggestionsView_colorValidTypedWord, 0),
+ alphaValidTypedWord);
+ mColorTypedWord = applyAlpha(
+ a.getColor(R.styleable.SuggestionsView_colorTypedWord, 0), alphaTypedWord);
+ mColorAutoCorrect = applyAlpha(
+ a.getColor(R.styleable.SuggestionsView_colorAutoCorrect, 0), alphaAutoCorrect);
+ mColorSuggested = applyAlpha(
+ a.getColor(R.styleable.SuggestionsView_colorSuggested, 0), alphaSuggested);
+ mSuggestionsCountInStrip = a.getInt(
+ R.styleable.SuggestionsView_suggestionsCountInStrip,
+ DEFAULT_SUGGESTIONS_COUNT_IN_STRIP);
+ mCenterSuggestionWeight = getPercent(a,
+ R.styleable.SuggestionsView_centerSuggestionPercentile,
+ DEFAULT_CENTER_SUGGESTION_PERCENTILE);
+ mMaxMoreSuggestionsRow = a.getInt(
+ R.styleable.SuggestionsView_maxMoreSuggestionsRow,
+ DEFAULT_MAX_MORE_SUGGESTIONS_ROW);
+ mMinMoreSuggestionsWidth = getRatio(a,
+ R.styleable.SuggestionsView_minMoreSuggestionsWidth);
+ a.recycle();
+
+ mMoreSuggestionsHint = getMoreSuggestionsHint(res,
+ res.getDimension(R.dimen.more_suggestions_hint_text_size), mColorAutoCorrect);
+ mCenterSuggestionIndex = mSuggestionsCountInStrip / 2;
+ mMoreSuggestionsBottomGap = res.getDimensionPixelOffset(
+ R.dimen.more_suggestions_bottom_gap);
+ mMoreSuggestionsRowHeight = res.getDimensionPixelSize(
+ R.dimen.more_suggestions_row_height);
+
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
+ mLeftwardsArrowView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
+ mHintToSaveView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
+ }
+
+ public int getMaxMoreSuggestionsRow() {
+ return mMaxMoreSuggestionsRow;
+ }
+
+ private int getMoreSuggestionsHeight() {
+ return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap;
+ }
+
+ public int setMoreSuggestionsHeight(int remainingHeight) {
+ final int currentHeight = getMoreSuggestionsHeight();
+ if (currentHeight <= remainingHeight) {
+ return currentHeight;
+ }
+
+ mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap)
+ / mMoreSuggestionsRowHeight;
+ final int newHeight = getMoreSuggestionsHeight();
+ return newHeight;
+ }
+
+ private static Drawable getMoreSuggestionsHint(Resources res, float textSize, int color) {
+ final Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTextAlign(Align.CENTER);
+ paint.setTextSize(textSize);
+ paint.setColor(color);
+ final Rect bounds = new Rect();
+ paint.getTextBounds(MORE_SUGGESTIONS_HINT, 0, MORE_SUGGESTIONS_HINT.length(), bounds);
+ final int width = Math.round(bounds.width() + 0.5f);
+ final int height = Math.round(bounds.height() + 0.5f);
+ final Bitmap buffer = Bitmap.createBitmap(
+ width, (height * 3 / 2), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(buffer);
+ canvas.drawText(MORE_SUGGESTIONS_HINT, width / 2, height, paint);
+ return new BitmapDrawable(res, buffer);
+ }
+
+ // Read integer value in TypedArray as percent.
+ private static float getPercent(TypedArray a, int index, int defValue) {
+ return a.getInt(index, defValue) / 100.0f;
+ }
+
+ // Read fraction value in TypedArray as float.
+ private static float getRatio(TypedArray a, int index) {
+ return a.getFraction(index, 1000, 1000, 1) / 1000.0f;
+ }
+
+ private CharSequence getStyledSuggestionWord(SuggestedWords suggestedWords, int pos) {
+ final CharSequence word = suggestedWords.getWord(pos);
+ final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect();
+ final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid;
+ if (!isAutoCorrect && !isTypedWordValid)
+ return word;
+
+ final int len = word.length();
+ final Spannable spannedWord = new SpannableString(word);
+ final int option = mSuggestionStripOption;
+ if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0)
+ || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) {
+ spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+ if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) {
+ spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+ return spannedWord;
+ }
+
+ private int getWordPosition(int index, SuggestedWords suggestedWords) {
+ // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
+ // suggestions.
+ final int centerPos = suggestedWords.willAutoCorrect() ? 1 : 0;
+ if (index == mCenterSuggestionIndex) {
+ return centerPos;
+ } else if (index == centerPos) {
+ return mCenterSuggestionIndex;
+ } else {
+ return index;
+ }
+ }
+
+ private int getSuggestionTextColor(int index, SuggestedWords suggestedWords, int pos) {
+ // TODO: Need to revisit this logic with bigram suggestions
+ final boolean isSuggested = (pos != 0);
+
+ final int color;
+ if (index == mCenterSuggestionIndex && suggestedWords.willAutoCorrect()) {
+ color = mColorAutoCorrect;
+ } else if (index == mCenterSuggestionIndex && suggestedWords.mTypedWordValid) {
+ color = mColorValidTypedWord;
+ } else if (isSuggested) {
+ color = mColorSuggested;
+ } else {
+ color = mColorTypedWord;
+ }
+ if (LatinImeLogger.sDBG && suggestedWords.size() > 1) {
+ // If we auto-correct, then the autocorrection is in slot 0 and the typed word
+ // is in slot 1.
+ if (index == mCenterSuggestionIndex && suggestedWords.mHasAutoCorrectionCandidate
+ && Suggest.shouldBlockAutoCorrectionBySafetyNet(
+ suggestedWords.getWord(1).toString(), suggestedWords.getWord(0))) {
+ return 0xFFFF0000;
+ }
+ }
+
+ if (suggestedWords.mIsObsoleteSuggestions && isSuggested) {
+ return applyAlpha(color, mAlphaObsoleted);
+ } else {
+ return color;
+ }
+ }
+
+ private static int applyAlpha(final int color, final float alpha) {
+ final int newAlpha = (int)(Color.alpha(color) * alpha);
+ return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
+ }
+
+ private static void addDivider(final ViewGroup stripView, final View divider) {
+ stripView.addView(divider);
+ final LinearLayout.LayoutParams params =
+ (LinearLayout.LayoutParams)divider.getLayoutParams();
+ params.gravity = Gravity.CENTER;
+ }
+
+ public void layout(SuggestedWords suggestedWords, ViewGroup stripView, ViewGroup placer,
+ int stripWidth) {
+ if (suggestedWords.mIsPunctuationSuggestions) {
+ layoutPunctuationSuggestions(suggestedWords, stripView);
+ return;
+ }
+
+ final int countInStrip = mSuggestionsCountInStrip;
+ setupTexts(suggestedWords, countInStrip);
+ mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
+ int x = 0;
+ for (int index = 0; index < countInStrip; index++) {
+ final int pos = getWordPosition(index, suggestedWords);
+
+ if (index != 0) {
+ final View divider = mDividers.get(pos);
+ // Add divider if this isn't the left most suggestion in suggestions strip.
+ addDivider(stripView, divider);
+ x += divider.getMeasuredWidth();
+ }
+
+ final CharSequence styled = mTexts.get(pos);
+ final TextView word = mWords.get(pos);
+ if (index == mCenterSuggestionIndex && mMoreSuggestionsAvailable) {
+ // TODO: This "more suggestions hint" should have nicely designed icon.
+ word.setCompoundDrawablesWithIntrinsicBounds(
+ null, null, null, mMoreSuggestionsHint);
+ // HACK: To align with other TextView that has no compound drawables.
+ word.setCompoundDrawablePadding(-mMoreSuggestionsHint.getIntrinsicHeight());
+ } else {
+ word.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+ }
+
+ // Disable this suggestion if the suggestion is null or empty.
+ word.setEnabled(!TextUtils.isEmpty(styled));
+ word.setTextColor(getSuggestionTextColor(index, suggestedWords, pos));
+ final int width = getSuggestionWidth(index, stripWidth);
+ final CharSequence text = getEllipsizedText(styled, width, word.getPaint());
+ final float scaleX = word.getTextScaleX();
+ word.setText(text); // TextView.setText() resets text scale x to 1.0.
+ word.setTextScaleX(scaleX);
+ stripView.addView(word);
+ setLayoutWeight(
+ word, getSuggestionWeight(index), ViewGroup.LayoutParams.MATCH_PARENT);
+ x += word.getMeasuredWidth();
+
+ if (DBG && pos < suggestedWords.size()) {
+ final CharSequence debugInfo = Utils.getDebugInfo(suggestedWords, pos);
+ if (debugInfo != null) {
+ final TextView info = mInfos.get(pos);
+ info.setText(debugInfo);
+ placer.addView(info);
+ info.measure(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ final int infoWidth = info.getMeasuredWidth();
+ final int y = info.getMeasuredHeight();
+ ViewLayoutUtils.placeViewAt(
+ info, x - infoWidth, y, infoWidth, info.getMeasuredHeight());
+ }
+ }
+ }
+ }
+
+ private int getSuggestionWidth(int index, int maxWidth) {
+ final int paddings = mPadding * mSuggestionsCountInStrip;
+ final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1);
+ final int availableWidth = maxWidth - paddings - dividers;
+ return (int)(availableWidth * getSuggestionWeight(index));
+ }
+
+ private float getSuggestionWeight(int index) {
+ if (index == mCenterSuggestionIndex) {
+ return mCenterSuggestionWeight;
+ } else {
+ // TODO: Revisit this for cases of 5 or more suggestions
+ return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1);
+ }
+ }
+
+ private void setupTexts(SuggestedWords suggestedWords, int countInStrip) {
+ mTexts.clear();
+ final int count = Math.min(suggestedWords.size(), countInStrip);
+ for (int pos = 0; pos < count; pos++) {
+ final CharSequence styled = getStyledSuggestionWord(suggestedWords, pos);
+ mTexts.add(styled);
+ }
+ for (int pos = count; pos < countInStrip; pos++) {
+ // Make this inactive for touches in layout().
+ mTexts.add(null);
+ }
+ }
+
+ private void layoutPunctuationSuggestions(SuggestedWords suggestedWords,
+ ViewGroup stripView) {
+ final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP);
+ for (int index = 0; index < countInStrip; index++) {
+ if (index != 0) {
+ // Add divider if this isn't the left most suggestion in suggestions strip.
+ addDivider(stripView, mDividers.get(index));
+ }
+
+ final TextView word = mWords.get(index);
+ word.setEnabled(true);
+ word.setTextColor(mColorAutoCorrect);
+ final CharSequence text = suggestedWords.getWord(index);
+ word.setText(text);
+ word.setTextScaleX(1.0f);
+ word.setCompoundDrawables(null, null, null, null);
+ stripView.addView(word);
+ setLayoutWeight(word, 1.0f, mSuggestionsStripHeight);
+ }
+ mMoreSuggestionsAvailable = false;
+ }
+
+ public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView,
+ int stripWidth, CharSequence hintText, OnClickListener listener) {
+ final int width = stripWidth - mDividerWidth - mPadding * 2;
+
+ final TextView wordView = mWordToSaveView;
+ wordView.setTextColor(mColorTypedWord);
+ final int wordWidth = (int)(width * mCenterSuggestionWeight);
+ final CharSequence text = getEllipsizedText(word, wordWidth, wordView.getPaint());
+ final float wordScaleX = wordView.getTextScaleX();
+ wordView.setTag(word);
+ wordView.setText(text);
+ wordView.setTextScaleX(wordScaleX);
+ stripView.addView(wordView);
+ setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
+
+ stripView.addView(mDividers.get(0));
+
+ final TextView leftArrowView = mLeftwardsArrowView;
+ leftArrowView.setTextColor(mColorAutoCorrect);
+ leftArrowView.setText(LEFTWARDS_ARROW);
+ stripView.addView(leftArrowView);
+
+ final TextView hintView = mHintToSaveView;
+ hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+ hintView.setTextColor(mColorAutoCorrect);
+ final int hintWidth = width - wordWidth - leftArrowView.getWidth();
+ final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
+ hintView.setText(hintText);
+ hintView.setTextScaleX(hintScaleX);
+ stripView.addView(hintView);
+ setLayoutWeight(
+ hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
+
+ wordView.setOnClickListener(listener);
+ leftArrowView.setOnClickListener(listener);
+ hintView.setOnClickListener(listener);
+ }
+
+ public CharSequence getAddToDictionaryWord() {
+ return (CharSequence)mWordToSaveView.getTag();
+ }
+
+ public boolean isAddToDictionaryShowing(View v) {
+ return v == mWordToSaveView || v == mHintToSaveView || v == mLeftwardsArrowView;
+ }
+
+ private static void setLayoutWeight(View v, float weight, int height) {
+ final ViewGroup.LayoutParams lp = v.getLayoutParams();
+ if (lp instanceof LinearLayout.LayoutParams) {
+ final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
+ llp.weight = weight;
+ llp.width = 0;
+ llp.height = height;
+ }
+ }
+
+ private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) {
+ paint.setTextScaleX(1.0f);
+ final int width = getTextWidth(text, paint);
+ if (width <= maxWidth) {
+ return 1.0f;
+ }
+ return maxWidth / (float)width;
+ }
+
+ private static CharSequence getEllipsizedText(CharSequence text, int maxWidth,
+ TextPaint paint) {
+ if (text == null) return null;
+ paint.setTextScaleX(1.0f);
+ final int width = getTextWidth(text, paint);
+ if (width <= maxWidth) {
+ return text;
+ }
+ final float scaleX = maxWidth / (float)width;
+ if (scaleX >= MIN_TEXT_XSCALE) {
+ paint.setTextScaleX(scaleX);
+ return text;
+ }
+
+ // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
+ // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
+ final CharSequence ellipsized = TextUtils.ellipsize(
+ text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
+ paint.setTextScaleX(MIN_TEXT_XSCALE);
+ return ellipsized;
+ }
+
+ private static int getTextWidth(CharSequence text, TextPaint paint) {
+ if (TextUtils.isEmpty(text)) return 0;
+ final Typeface savedTypeface = paint.getTypeface();
+ paint.setTypeface(getTextTypeface(text));
+ final int len = text.length();
+ final float[] widths = new float[len];
+ final int count = paint.getTextWidths(text, 0, len, widths);
+ int width = 0;
+ for (int i = 0; i < count; i++) {
+ width += Math.round(widths[i] + 0.5f);
+ }
+ paint.setTypeface(savedTypeface);
+ return width;
+ }
+
+ private static Typeface getTextTypeface(CharSequence text) {
+ if (!(text instanceof SpannableString))
+ return Typeface.DEFAULT;
+
+ final SpannableString ss = (SpannableString)text;
+ final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
+ if (styles.length == 0)
+ return Typeface.DEFAULT;
+
+ switch (styles[0].getStyle()) {
+ case Typeface.BOLD: return Typeface.DEFAULT_BOLD;
+ // TODO: BOLD_ITALIC, ITALIC case?
+ default: return Typeface.DEFAULT;
+ }
+ }
+ }
+
+ /**
+ * Construct a {@link SuggestionsView} for showing suggestions to be picked by the user.
+ * @param context
+ * @param attrs
+ */
+ public SuggestionsView(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.suggestionsViewStyle);
+ }
+
+ public SuggestionsView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ inflater.inflate(R.layout.suggestions_strip, this);
+
+ mPreviewPopup = new PopupWindow(context);
+ mPreviewText = (TextView) inflater.inflate(R.layout.suggestion_preview, null);
+ mPreviewPopup.setWindowLayoutMode(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ mPreviewPopup.setContentView(mPreviewText);
+ mPreviewPopup.setBackgroundDrawable(null);
+
+ mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
+ for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) {
+ final TextView word = (TextView)inflater.inflate(R.layout.suggestion_word, null);
+ word.setTag(pos);
+ word.setOnClickListener(this);
+ word.setOnLongClickListener(this);
+ mWords.add(word);
+ final View divider = inflater.inflate(R.layout.suggestion_divider, null);
+ divider.setTag(pos);
+ divider.setOnClickListener(this);
+ mDividers.add(divider);
+ mInfos.add((TextView)inflater.inflate(R.layout.suggestion_info, null));
+ }
+
+ mParams = new SuggestionsViewParams(context, attrs, defStyle, mWords, mDividers, mInfos);
+
+ mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
+ mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
+ .findViewById(R.id.more_suggestions_view);
+ mMoreSuggestionsBuilder = new MoreSuggestions.Builder(mMoreSuggestionsView);
+
+ final PopupWindow moreWindow = new PopupWindow(context);
+ moreWindow.setWindowLayoutMode(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ moreWindow.setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));
+ moreWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+ moreWindow.setFocusable(true);
+ moreWindow.setOutsideTouchable(true);
+ moreWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
+ @Override
+ public void onDismiss() {
+ mKeyboardView.dimEntireKeyboard(false);
+ }
+ });
+ mMoreSuggestionsWindow = moreWindow;
+
+ final Resources res = context.getResources();
+ mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
+ R.dimen.more_suggestions_modal_tolerance);
+ mMoreSuggestionsSlidingDetector = new GestureDetector(
+ context, mMoreSuggestionsSlidingListener);
+ }
+
+ /**
+ * A connection back to the input method.
+ * @param listener
+ */
+ public void setListener(Listener listener, View inputView) {
+ mListener = listener;
+ mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view);
+ }
+
+ public void setSuggestions(SuggestedWords suggestedWords) {
+ if (suggestedWords == null)
+ return;
+
+ clear();
+ mSuggestedWords = suggestedWords;
+ mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth());
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.suggestionsView_setSuggestions(mSuggestedWords);
+ }
+ }
+
+ public int setMoreSuggestionsHeight(int remainingHeight) {
+ return mParams.setMoreSuggestionsHeight(remainingHeight);
+ }
+
+ public boolean isShowingAddToDictionaryHint() {
+ return mSuggestionsStrip.getChildCount() > 0
+ && mParams.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0));
+ }
+
+ public void showAddToDictionaryHint(CharSequence word, CharSequence hintText) {
+ clear();
+ mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText, this);
+ }
+
+ public boolean dismissAddToDictionaryHint() {
+ if (isShowingAddToDictionaryHint()) {
+ clear();
+ return true;
+ }
+ return false;
+ }
+
+ public SuggestedWords getSuggestions() {
+ return mSuggestedWords;
+ }
+
+ public void clear() {
+ mSuggestionsStrip.removeAllViews();
+ removeAllViews();
+ addView(mSuggestionsStrip);
+ dismissMoreSuggestions();
+ }
+
+ private void hidePreview() {
+ mPreviewPopup.dismiss();
+ }
+
+ private void addToDictionary(CharSequence word) {
+ mListener.addWordToDictionary(word.toString());
+ }
+
+ private final KeyboardActionListener mMoreSuggestionsListener =
+ new KeyboardActionListener.Adapter() {
+ @Override
+ public boolean onCustomRequest(int requestCode) {
+ final int index = requestCode;
+ final CharSequence word = mSuggestedWords.getWord(index);
+ // TODO: change caller path so coordinates are passed through here
+ mListener.pickSuggestionManually(index, word, NOT_A_TOUCH_COORDINATE,
+ NOT_A_TOUCH_COORDINATE);
+ dismissMoreSuggestions();
+ return true;
+ }
+
+ @Override
+ public void onCancelInput() {
+ dismissMoreSuggestions();
+ }
+ };
+
+ private final MoreKeysPanel.Controller mMoreSuggestionsController =
+ new MoreKeysPanel.Controller() {
+ @Override
+ public boolean dismissMoreKeysPanel() {
+ return dismissMoreSuggestions();
+ }
+ };
+
+ private boolean dismissMoreSuggestions() {
+ if (mMoreSuggestionsWindow.isShowing()) {
+ mMoreSuggestionsWindow.dismiss();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ return showMoreSuggestions();
+ }
+
+ private boolean showMoreSuggestions() {
+ final SuggestionsViewParams params = mParams;
+ if (params.mMoreSuggestionsAvailable) {
+ final int stripWidth = getWidth();
+ final View container = mMoreSuggestionsContainer;
+ final int maxWidth = stripWidth - container.getPaddingLeft()
+ - container.getPaddingRight();
+ final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
+ builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth,
+ (int)(maxWidth * params.mMinMoreSuggestionsWidth),
+ params.getMaxMoreSuggestionsRow());
+ mMoreSuggestionsView.setKeyboard(builder.build());
+ container.measure(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
+ final int pointX = stripWidth / 2;
+ final int pointY = -params.mMoreSuggestionsBottomGap;
+ moreKeysPanel.showMoreKeysPanel(
+ this, mMoreSuggestionsController, pointX, pointY,
+ mMoreSuggestionsWindow, mMoreSuggestionsListener);
+ mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING;
+ mOriginX = mLastX;
+ mOriginY = mLastY;
+ mKeyboardView.dimEntireKeyboard(true);
+ for (int i = 0; i < params.mSuggestionsCountInStrip; i++) {
+ mWords.get(i).setPressed(false);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // Working variables for onLongClick and dispatchTouchEvent.
+ private int mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;
+ private static final int MORE_SUGGESTIONS_IN_MODAL_MODE = 0;
+ private static final int MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING = 1;
+ private static final int MORE_SUGGESTIONS_IN_SLIDING_MODE = 2;
+ private int mLastX;
+ private int mLastY;
+ private int mOriginX;
+ private int mOriginY;
+ private final int mMoreSuggestionsModalTolerance;
+ private final GestureDetector mMoreSuggestionsSlidingDetector;
+ private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
+ new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) {
+ final float dy = me.getY() - down.getY();
+ if (deltaY > 0 && dy < 0) {
+ return showMoreSuggestions();
+ }
+ return false;
+ }
+ };
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent me) {
+ if (!mMoreSuggestionsWindow.isShowing()
+ || mMoreSuggestionsMode == MORE_SUGGESTIONS_IN_MODAL_MODE) {
+ mLastX = (int)me.getX();
+ mLastY = (int)me.getY();
+ if (mMoreSuggestionsSlidingDetector.onTouchEvent(me)) {
+ return true;
+ }
+ return super.dispatchTouchEvent(me);
+ }
+
+ final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
+ final int action = me.getAction();
+ final long eventTime = me.getEventTime();
+ final int index = me.getActionIndex();
+ final int id = me.getPointerId(index);
+ final PointerTracker tracker = PointerTracker.getPointerTracker(id, moreKeysPanel);
+ final int x = (int)me.getX(index);
+ final int y = (int)me.getY(index);
+ final int translatedX = moreKeysPanel.translateX(x);
+ final int translatedY = moreKeysPanel.translateY(y);
+
+ if (mMoreSuggestionsMode == MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING) {
+ if (Math.abs(x - mOriginX) >= mMoreSuggestionsModalTolerance
+ || mOriginY - y >= mMoreSuggestionsModalTolerance) {
+ // Decided to be in the sliding input mode only when the touch point has been moved
+ // upward.
+ mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_SLIDING_MODE;
+ tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel);
+ } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
+ // Decided to be in the modal input mode
+ mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE;
+ }
+ return true;
+ }
+
+ // MORE_SUGGESTIONS_IN_SLIDING_MODE
+ tracker.processMotionEvent(action, translatedX, translatedY, eventTime, moreKeysPanel);
+ return true;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mParams.isAddToDictionaryShowing(view)) {
+ addToDictionary(mParams.getAddToDictionaryWord());
+ clear();
+ return;
+ }
+
+ final Object tag = view.getTag();
+ if (!(tag instanceof Integer))
+ return;
+ final int index = (Integer) tag;
+ if (index >= mSuggestedWords.size())
+ return;
+
+ final CharSequence word = mSuggestedWords.getWord(index);
+ mListener.pickSuggestionManually(index, word, mLastX, mLastY);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mHandler.cancelAllMessages();
+ hidePreview();
+ dismissMoreSuggestions();
+ }
+}