Create Python version of the make-keyboard-text tool

The Python version uses json files, separate from the xml files. Comments haven't been migrated still.

I'm still not very happy with the way the keyboard texts are managed and that it requires running a separate tool to generate a .java file. It's at least better than manually editing an autogenerated file as before, and python3 is more widely available than the archaic Android build system
This commit is contained in:
Aleksandras Kostarevas 2024-06-25 12:55:24 +03:00
parent c29f609a0f
commit 6bf523010d
83 changed files with 8477 additions and 4839 deletions

View File

@ -0,0 +1,319 @@
{
"locale": "DEFAULT",
"morekeys": {
"a": [],
"e": [],
"i": [],
"o": [],
"u": [],
"s": [],
"n": [],
"c": [],
"y": [],
"d": [],
"r": [],
"t": [],
"z": [],
"k": [],
"l": [],
"g": [],
"v": [],
"h": [],
"j": [],
"w": [],
"q": [],
"x": [],
"nordic_row2_10": [],
"nordic_row2_11": [],
"east_slavic_row2_2": [],
"east_slavic_row2_11": [],
"cyrillic_u": [],
"cyrillic_ka": [],
"cyrillic_en": [],
"cyrillic_ghe": [],
"cyrillic_a": [],
"cyrillic_o": [],
"cyrillic_i": [],
"cyrillic_ie": [],
"cyrillic_soft_sign": [],
"swiss_row1_11": [],
"swiss_row2_10": [],
"swiss_row2_11": [],
"currency_dollar": [
"¢",
"£",
"€",
"¥",
"₱"
],
"currency_generic": [
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
"punctuation": [
"?",
"!",
"\u203d",
"\u2026",
"_",
"\\\\",
"|",
"="
],
"tablet_punctuation": [
"?",
"!",
"\u203d",
"\u2026",
"_",
"\\\\",
"|",
"="
],
"star": [
"†",
"‡",
"★"
],
"bullet": [
"♪",
"♥",
"♠",
"♦",
"♣"
],
"plus": [
"±"
],
"left_parenthesis": [
"!fixedColumnOrder!3",
"!text/keyspecs_left_parenthesis_more_keys"
],
"right_parenthesis": [
"!fixedColumnOrder!3",
"!text/keyspecs_right_parenthesis_more_keys"
],
"less_than": [
"!fixedColumnOrder!3",
"!text/keyspec_left_single_angle_quote",
"!text/keyspec_less_than_equal",
"!text/keyspec_left_double_angle_quote"
],
"greater_than": [
"!fixedColumnOrder!3",
"!text/keyspec_right_single_angle_quote",
"!text/keyspec_greater_than_equal",
"!text/keyspec_right_double_angle_quote"
],
"arabic_diacritics": [],
"symbols_1": [
"¹",
"½",
"⅓",
"¼",
"⅛"
],
"symbols_2": [
"²",
"⅔"
],
"symbols_3": [
"³",
"¾",
"⅜"
],
"symbols_4": [
"⁴"
],
"symbols_5": [
"⅝"
],
"symbols_6": [],
"symbols_7": [
"⅞"
],
"symbols_8": [],
"symbols_9": [],
"symbols_0": [
"ⁿ",
"∅"
],
"tablet_comma": [],
"period": [
"!text/morekeys_punctuation"
],
"tablet_period": [
"!text/morekeys_tablet_punctuation"
],
"exclamation": [
"¡",
"‽"
],
"question": [
"¿"
],
"symbols_semicolon": [],
"symbols_percent": [
"‰"
],
"am_pm": [
"!fixedColumnOrder!2",
"!hasLabels!",
"!text/keylabel_time_am",
"!text/keylabel_time_pm"
],
"popular_domain": [
"!hasLabels!",
".net",
".org",
".gov",
".edu"
],
"single_quote": [
"!fixedColumnOrder!5",
"!text/single_quotes",
"!text/single_angle_quotes"
],
"double_quote": [
"!fixedColumnOrder!5",
"!text/double_quotes",
"!text/double_angle_quotes"
],
"tablet_double_quote": [
"!fixedColumnOrder!6",
"!text/double_quotes",
"!text/single_quotes",
"!text/double_angle_quotes",
"!text/single_angle_quotes"
]
},
"keyspec": {
"q": "q",
"w": "w",
"y": "y",
"x": "x",
"nordic_row1_11": "",
"nordic_row2_10": "",
"nordic_row2_11": "",
"east_slavic_row1_9": "",
"east_slavic_row2_2": "",
"east_slavic_row2_11": "",
"east_slavic_row3_5": "",
"south_slavic_row1_6": "",
"south_slavic_row2_11": "",
"south_slavic_row3_1": "",
"south_slavic_row3_8": "",
"swiss_row1_11": "",
"swiss_row2_10": "",
"swiss_row2_11": "",
"currency": "$",
"spanish_row2_10": "ñ",
"symbols_1": "1",
"symbols_2": "2",
"symbols_3": "3",
"symbols_4": "4",
"symbols_5": "5",
"symbols_6": "6",
"symbols_7": "7",
"symbols_8": "8",
"symbols_9": "9",
"symbols_0": "0",
"left_parenthesis": "(",
"right_parenthesis": ")",
"left_square_bracket": "[",
"right_square_bracket": "]",
"left_curly_bracket": "{",
"right_curly_bracket": "}",
"less_than": "<",
"greater_than": ">",
"less_than_equal": "≤",
"greater_than_equal": "≥",
"left_double_angle_quote": "«",
"right_double_angle_quote": "»",
"left_single_angle_quote": "",
"right_single_angle_quote": "",
"comma": ",",
"tablet_comma": ",",
"period": ".",
"tablet_period": ".",
"symbols_question": "?",
"symbols_semicolon": ";",
"symbols_percent": "%",
"settings": "!icon/settings_key|!code/key_settings",
"shortcut": "!icon/shortcut_key|!code/key_shortcut",
"action_next": "!hasLabels!,!text/label_next_key|!code/key_action_next",
"action_previous": "!hasLabels!,!text/label_previous_key|!code/key_action_previous",
"popular_domain": ".com",
"emoji_action_key": [
"!fixedColumnOrder!4",
"!needsDividers!",
"!icon/action_switch_language|!code/action_switch_language",
"!icon/action_text_edit|!code/action_text_edit",
"!icon/action_clipboard_history|!code/action_clipboard_history",
"!icon/action_emoji|!code/action_emoji",
"!icon/action_undo|!code/action_undo",
"!icon/action_redo|!code/action_redo"
]
},
"label": {
"go_key": "!string/label_go_key",
"send_key": "!string/label_send_key",
"next_key": "!string/label_next_key",
"done_key": "!string/label_done_key",
"search_key": "!string/label_search_key",
"previous_key": "!string/label_previous_key",
"pause_key": "!string/label_pause_key",
"wait_key": "!string/label_wait_key"
},
"keylabel": {
"to_alpha": "ABC",
"to_symbol": "?123",
"to_more_symbol": "= \\\\ <",
"tablet_to_more_symbol": "~ [ <",
"to_phone_numeric": "123",
"to_phone_symbols": "",
"time_am": "AM",
"time_pm": "PM"
},
"keyhintlabel": {
"tablet_comma": "",
"period": "",
"tablet_period": ""
},
"additional_morekeys": {
"symbols_1": [],
"symbols_2": [],
"symbols_3": [],
"symbols_4": [],
"symbols_5": [],
"symbols_6": [],
"symbols_7": [],
"symbols_8": [],
"symbols_9": [],
"symbols_0": []
},
"other": {
"single_quotes": "!text/single_lqm_rqm",
"double_quotes": "!text/double_lqm_rqm",
"single_angle_quotes": "!text/single_laqm_raqm",
"double_angle_quotes": "!text/double_laqm_raqm",
"keyspecs_left_parenthesis_more_keys": "!text/keyspec_less_than,!text/keyspec_left_curly_bracket,!text/keyspec_left_square_bracket",
"keyspecs_right_parenthesis_more_keys": "!text/keyspec_greater_than,!text/keyspec_right_curly_bracket,!text/keyspec_right_square_bracket",
"single_laqm_raqm": "!text/keyspec_left_single_angle_quote,!text/keyspec_right_single_angle_quote",
"single_raqm_laqm": "!text/keyspec_right_single_angle_quote,!text/keyspec_left_single_angle_quote",
"double_laqm_raqm": "!text/keyspec_left_double_angle_quote,!text/keyspec_right_double_angle_quote",
"double_raqm_laqm": "!text/keyspec_right_double_angle_quote,!text/keyspec_left_double_angle_quote",
"single_lqm_rqm": ",,",
"single_9qm_lqm": ",,",
"single_9qm_rqm": ",,",
"single_rqm_9qm": ",,",
"double_lqm_rqm": "„,“,”",
"double_9qm_lqm": "”,„,“",
"double_9qm_rqm": "“,„,”",
"double_rqm_9qm": "“,”,„"
}
}

View File

@ -0,0 +1,64 @@
{
"locale": "af",
"morekeys": {
"a": [
"á",
"â",
"ä",
"à",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ì",
"ï",
"î",
"į",
"ī",
"ij"
],
"o": [
"ó",
"ô",
"ö",
"ò",
"õ",
"œ",
"ø",
"ō"
],
"u": [
"ú",
"û",
"ü",
"ù",
"ū"
],
"n": [
"ñ",
"ń"
],
"y": [
"ý",
"ij"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,142 @@
{
"locale": "ar",
"morekeys": {
"period": [
"!text/morekeys_arabic_diacritics"
],
"tablet_period": [
"!text/morekeys_arabic_diacritics"
],
"question": [
"?",
"¿"
],
"symbols_semicolon": [
";"
],
"symbols_percent": [
"\\%",
"‰"
],
"tablet_comma": [
"!fixedColumnOrder!4",
":",
"!",
"؟",
"؛",
"-",
"\\\"",
"\\'"
],
"bullet": [
"♪"
],
"star": [
"★",
"٭"
],
"left_parenthesis": [
"!fixedColumnOrder!4",
"|﴿",
"!text/keyspecs_left_parenthesis_more_keys"
],
"right_parenthesis": [
"!fixedColumnOrder!4",
"﴿|",
"!text/keyspecs_right_parenthesis_more_keys"
],
"arabic_diacritics": [
"!fixedColumnOrder!7",
" ٕ|ٕ",
" ٔ|ٔ",
" ْ|ْ",
" ٍ|ٍ",
" ٌ|ٌ",
" ً|ً",
" ّ|ّ",
" ٖ|ٖ",
" ٰ|ٰ",
" ٓ|ٓ",
" ِ|ِ",
" ُ|ُ",
" َ|َ",
"ـــ|ـ"
]
},
"keyspec": {
"symbols_1": "١",
"symbols_2": "٢",
"symbols_3": "٣",
"symbols_4": "٤",
"symbols_5": "٥",
"symbols_6": "٦",
"symbols_7": "٧",
"symbols_8": "٨",
"symbols_9": "٩",
"symbols_0": "٠",
"comma": "،",
"symbols_question": "؟",
"symbols_semicolon": "؛",
"symbols_percent": "٪",
"tablet_comma": "،",
"left_parenthesis": "(|)",
"right_parenthesis": ")|(",
"left_square_bracket": "[|]",
"right_square_bracket": "]|[",
"left_curly_bracket": "{|}",
"right_curly_bracket": "}|{",
"less_than": "<|>",
"greater_than": ">|<",
"less_than_equal": "≤|≥",
"greater_than_equal": "≥|≤",
"left_double_angle_quote": "«|»",
"right_double_angle_quote": "»|«",
"left_single_angle_quote": "|",
"right_single_angle_quote": "|"
},
"label": {},
"keylabel": {
"to_alpha": "أ‌ب‌ج",
"to_symbol": "٣٢١؟"
},
"keyhintlabel": {
"period": "ّ",
"tablet_period": "ّ",
"tablet_comma": "؟"
},
"additional_morekeys": {
"symbols_1": [
"1"
],
"symbols_2": [
"2"
],
"symbols_3": [
"3"
],
"symbols_4": [
"4"
],
"symbols_5": [
"5"
],
"symbols_6": [
"6"
],
"symbols_7": [
"7"
],
"symbols_8": [
"8"
],
"symbols_9": [
"9"
],
"symbols_0": [
"0",
"٫",
"٬"
]
},
"other": {}
}

View File

@ -0,0 +1,70 @@
{
"locale": "az",
"morekeys": {
"a": [
"â",
"ä",
"á"
],
"e": [
"ə",
"é"
],
"i": [
"ı",
"î",
"ï",
"ì",
"í",
"į",
"ī"
],
"o": [
"ö",
"ô",
"œ",
"ò",
"ó",
"õ",
"ø",
"ō"
],
"u": [
"ü",
"û",
"ù",
"ú",
"ū"
],
"s": [
"ş",
"ß",
"ś",
"š"
],
"g": [
"ğ"
],
"n": [
"ň",
"ñ"
],
"c": [
"ç",
"ć",
"č"
],
"y": [
"ý"
],
"z": [
"ž"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,27 @@
{
"locale": "be",
"morekeys": {
"cyrillic_ie": [
"ё"
],
"cyrillic_soft_sign": [
"ъ"
]
},
"keyspec": {
"east_slavic_row1_9": "ў",
"east_slavic_row2_2": "ы",
"east_slavic_row2_11": "э",
"east_slavic_row3_5": "і"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,14 @@
{
"locale": "bg",
"morekeys": {},
"keyspec": {},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,14 @@
{
"locale": "bn_BD",
"morekeys": {},
"keyspec": {
"currency": "৳"
},
"label": {},
"keylabel": {
"to_alpha": "কখগ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "bn_IN",
"morekeys": {},
"keyspec": {
"currency": "₹"
},
"label": {},
"keylabel": {
"to_alpha": "কখগ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,111 @@
{
"locale": "ca",
"morekeys": {
"a": [
"à",
"á",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
"e": [
"è",
"é",
"ë",
"ê",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
"o": [
"ò",
"ó",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
"u": [
"ú",
"ü",
"ù",
"û",
"ū"
],
"n": [
"ñ",
"ń"
],
"c": [
"ç",
"ć",
"č"
],
"l": [
"l·l",
"ł"
],
"punctuation": [
"!autoColumnOrder!9",
"\\",
"?",
"!",
"·",
"#",
")",
"(",
"/",
";",
"'",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
],
"tablet_punctuation": [
"!autoColumnOrder!8",
"\\",
"'",
"·",
"#",
")",
"(",
"/",
";",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
]
},
"keyspec": {
"spanish_row2_10": "ç"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,95 @@
{
"locale": "cs",
"morekeys": {
"a": [
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"ě",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
"i": [
"í",
"î",
"ï",
"ì",
"į",
"ī"
],
"o": [
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
"u": [
"ú",
"ů",
"û",
"ü",
"ù",
"ū"
],
"s": [
"š",
"ß",
"ś"
],
"n": [
"ň",
"ñ",
"ń"
],
"c": [
"č",
"ç",
"ć"
],
"y": [
"ý",
"ÿ"
],
"d": [
"ď"
],
"r": [
"ř"
],
"t": [
"ť"
],
"z": [
"ž",
"ź",
"ż"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,80 @@
{
"locale": "da",
"morekeys": {
"a": [
"å",
"æ",
"á",
"ä",
"à",
"â",
"ã",
"ā"
],
"e": [
"é",
"ë"
],
"i": [
"í",
"ï"
],
"o": [
"ø",
"ö",
"ó",
"ô",
"ò",
"õ",
"œ",
"ō"
],
"u": [
"ú",
"ü",
"û",
"ù",
"ū"
],
"s": [
"ß",
"ś",
"š"
],
"n": [
"ñ",
"ń"
],
"y": [
"ý",
"ÿ"
],
"d": [
"ð"
],
"l": [
"ł"
],
"nordic_row2_10": [
"ä"
],
"nordic_row2_11": [
"ö"
]
},
"keyspec": {
"nordic_row1_11": "å",
"nordic_row2_10": "æ",
"nordic_row2_11": "ø"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,75 @@
{
"locale": "de",
"morekeys": {
"a": [
"ä",
"%",
"â",
"à",
"á",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"è",
"ê",
"ë",
"ė"
],
"o": [
"ö",
"%",
"ô",
"ò",
"ó",
"õ",
"œ",
"ø",
"ō"
],
"u": [
"ü",
"%",
"û",
"ù",
"ú",
"ū"
],
"s": [
"ß",
"ś",
"š"
],
"n": [
"ñ",
"ń"
],
"swiss_row1_11": [
"è"
],
"swiss_row2_10": [
"é"
],
"swiss_row2_11": [
"à"
]
},
"keyspec": {
"swiss_row1_11": "ü",
"swiss_row2_10": "ö",
"swiss_row2_11": "ä"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,12 @@
{
"locale": "el",
"morekeys": {},
"keyspec": {},
"label": {},
"keylabel": {
"to_alpha": "ΑΒΓ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,61 @@
{
"locale": "en",
"morekeys": {
"a": [
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"è",
"ê",
"ë",
"ē"
],
"i": [
"í",
"î",
"ï",
"ī",
"ì"
],
"o": [
"ó",
"ô",
"ö",
"ò",
"œ",
"ø",
"ō",
"õ"
],
"u": [
"ú",
"û",
"ü",
"ù",
"ū"
],
"s": [
"ß"
],
"n": [
"ñ"
],
"c": [
"ç"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,158 @@
{
"locale": "eo",
"morekeys": {
"a": [
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā",
"ă",
"ą",
"ª"
],
"e": [
"é",
"ě",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
"i": [
"í",
"î",
"ï",
"ĩ",
"ì",
"į",
"ī",
"ı",
"ij"
],
"o": [
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō",
"ő",
"º"
],
"u": [
"ú",
"ů",
"û",
"ü",
"ù",
"ū",
"ũ",
"ű",
"ų",
"µ"
],
"s": [
"ß",
"š",
"ś",
"ș",
"ş"
],
"n": [
"ñ",
"ń",
"ņ",
"ň",
"ʼn",
"ŋ"
],
"c": [
"ć",
"č",
"ç",
"ċ"
],
"y": [
"y",
"ý",
"ŷ",
"ÿ",
"þ"
],
"d": [
"ð",
"ď",
"đ"
],
"r": [
"ř",
"ŕ",
"ŗ"
],
"t": [
"ť",
"ț",
"ţ",
"ŧ"
],
"z": [
"ź",
"ż",
"ž"
],
"k": [
"ķ",
"ĸ"
],
"l": [
"ĺ",
"ļ",
"ľ",
"ŀ",
"ł"
],
"g": [
"ğ",
"ġ",
"ģ"
],
"v": [
"w",
"ŵ"
],
"h": [
"ĥ",
"ħ"
],
"w": [
"w",
"ŵ"
],
"q": [
"q"
],
"x": [
"x"
]
},
"keyspec": {
"q": "ŝ",
"w": "ĝ",
"y": "ŭ",
"x": "ĉ",
"spanish_row2_10": "ĵ"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,88 @@
{
"locale": "es",
"morekeys": {
"a": [
"á",
"à",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
"e": [
"é",
"è",
"ë",
"ê",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
"o": [
"ó",
"ò",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
"u": [
"ú",
"ü",
"ù",
"û",
"ū"
],
"n": [
"ñ",
"ń"
],
"c": [
"ç",
"ć",
"č"
],
"punctuation": [
"!autoColumnOrder!9",
"\\",
"?",
"!",
"#",
")",
"(",
"/",
";",
"¡",
"'",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&",
"¿"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,121 @@
{
"locale": "et",
"morekeys": {
"a": [
"ä",
"ā",
"à",
"á",
"â",
"ã",
"å",
"æ",
"ą"
],
"e": [
"ē",
"è",
"ė",
"é",
"ê",
"ë",
"ę",
"ě"
],
"i": [
"ī",
"ì",
"į",
"í",
"î",
"ï",
"ı"
],
"o": [
"ö",
"õ",
"ò",
"ó",
"ô",
"œ",
"ő",
"ø"
],
"u": [
"ü",
"ū",
"ų",
"ù",
"ú",
"û",
"ů",
"ű"
],
"s": [
"š",
"ß",
"ś",
"ş"
],
"n": [
"ņ",
"ñ",
"ń"
],
"c": [
"č",
"ç",
"ć"
],
"y": [
"ý",
"ÿ"
],
"d": [
"ď"
],
"r": [
"ŗ",
"ř",
"ŕ"
],
"t": [
"ţ",
"ť"
],
"z": [
"ž",
"ż",
"ź"
],
"k": [
"ķ"
],
"l": [
"ļ",
"ł",
"ĺ",
"ľ"
],
"g": [
"ģ",
"ğ"
],
"nordic_row2_10": [
"õ"
]
},
"keyspec": {
"nordic_row1_11": "ü",
"nordic_row2_10": "ö",
"nordic_row2_11": "ä"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,67 @@
{
"locale": "eu",
"morekeys": {
"a": [
"á",
"à",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
"e": [
"é",
"è",
"ë",
"ê",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
"o": [
"ó",
"ò",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
"u": [
"ú",
"ü",
"ù",
"û",
"ū"
],
"n": [
"ñ",
"ń"
],
"c": [
"ç",
"ć",
"č"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,155 @@
{
"locale": "fa",
"morekeys": {
"period": [
"!text/morekeys_arabic_diacritics"
],
"tablet_period": [
"!text/morekeys_arabic_diacritics"
],
"question": [
"?",
"¿"
],
"symbols_semicolon": [
";"
],
"symbols_percent": [
"\\%",
"‰"
],
"tablet_comma": [
"!fixedColumnOrder!4",
":",
"!",
"؟",
"؛",
"-",
"!text/keyspec_left_double_angle_quote",
"!text/keyspec_right_double_angle_quote"
],
"bullet": [
"♪"
],
"star": [
"★",
"٭"
],
"left_parenthesis": [
"!fixedColumnOrder!4",
"|﴿",
"!text/keyspecs_left_parenthesis_more_keys"
],
"right_parenthesis": [
"!fixedColumnOrder!4",
"﴿|",
"!text/keyspecs_right_parenthesis_more_keys"
],
"less_than": [
"!fixedColumnOrder!3",
"!text/keyspec_left_single_angle_quote",
"!text/keyspec_less_than_equal",
"!text/keyspec_less_than"
],
"greater_than": [
"!fixedColumnOrder!3",
"!text/keyspec_right_single_angle_quote",
"!text/keyspec_greater_than_equal",
"!text/keyspec_greater_than"
],
"arabic_diacritics": [
"!fixedColumnOrder!7",
" ٕ|ٕ",
" ْ|ْ",
" ّ|ّ",
" ٌ|ٌ",
" ٍ|ٍ",
" ً|ً",
" ٔ|ٔ",
" ٖ|ٖ",
" ٰ|ٰ",
" ٓ|ٓ",
" ُ|ُ",
" ِ|ِ",
" َ|َ",
"ـــ|ـ"
]
},
"keyspec": {
"symbols_1": "۱",
"symbols_2": "۲",
"symbols_3": "۳",
"symbols_4": "۴",
"symbols_5": "۵",
"symbols_6": "۶",
"symbols_7": "۷",
"symbols_8": "۸",
"symbols_9": "۹",
"symbols_0": "۰",
"comma": "،",
"symbols_question": "؟",
"symbols_semicolon": "؛",
"symbols_percent": "٪",
"tablet_comma": "،",
"currency": "﷼",
"left_parenthesis": "(|)",
"right_parenthesis": ")|(",
"left_square_bracket": "[|]",
"right_square_bracket": "]|[",
"left_curly_bracket": "{|}",
"right_curly_bracket": "}|{",
"less_than": "<|>",
"greater_than": ">|<",
"less_than_equal": "≤|≥",
"greater_than_equal": "≥|≤",
"left_double_angle_quote": "«|»",
"right_double_angle_quote": "»|«",
"left_single_angle_quote": "|",
"right_single_angle_quote": "|"
},
"label": {},
"keylabel": {
"to_alpha": "ا‌ب‌پ",
"to_symbol": "۳۲۱؟"
},
"keyhintlabel": {
"period": "ً",
"tablet_period": "ً",
"tablet_comma": "؟"
},
"additional_morekeys": {
"symbols_1": [
"1"
],
"symbols_2": [
"2"
],
"symbols_3": [
"3"
],
"symbols_4": [
"4"
],
"symbols_5": [
"5"
],
"symbols_6": [
"6"
],
"symbols_7": [
"7"
],
"symbols_8": [
"8"
],
"symbols_9": [
"9"
],
"symbols_0": [
"0",
"٫",
"٬"
]
},
"other": {}
}

View File

@ -0,0 +1,54 @@
{
"locale": "fi",
"morekeys": {
"a": [
"ä",
"å",
"æ",
"à",
"á",
"â",
"ã",
"ā"
],
"o": [
"ö",
"ø",
"ô",
"ò",
"ó",
"õ",
"œ",
"ō"
],
"u": [
"ü"
],
"s": [
"š",
"ß",
"ś"
],
"z": [
"ž",
"ź",
"ż"
],
"nordic_row2_10": [
"ø"
],
"nordic_row2_11": [
"æ"
]
},
"keyspec": {
"nordic_row1_11": "å",
"nordic_row2_10": "ö",
"nordic_row2_11": "ä"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,85 @@
{
"locale": "fr",
"morekeys": {
"a": [
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
],
"e": [
"é",
"è",
"ê",
"ë",
"%",
"ę",
"ė",
"ē"
],
"i": [
"î",
"%",
"ï",
"ì",
"í",
"į",
"ī"
],
"o": [
"ô",
"œ",
"%",
"ö",
"ò",
"ó",
"õ",
"ø",
"ō",
"º"
],
"u": [
"ù",
"û",
"%",
"ü",
"ú",
"ū"
],
"c": [
"ç",
"%",
"ć",
"č"
],
"y": [
"%",
"ÿ"
],
"swiss_row1_11": [
"ü"
],
"swiss_row2_10": [
"ö"
],
"swiss_row2_11": [
"ä"
]
},
"keyspec": {
"swiss_row1_11": "è",
"swiss_row2_10": "é",
"swiss_row2_11": "à"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,67 @@
{
"locale": "gl",
"morekeys": {
"a": [
"á",
"à",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
"e": [
"é",
"è",
"ë",
"ê",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
"o": [
"ó",
"ò",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
"u": [
"ú",
"ü",
"ù",
"û",
"ū"
],
"n": [
"ñ",
"ń"
],
"c": [
"ç",
"ć",
"č"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,97 @@
{
"locale": "hi",
"morekeys": {
"period": [
"!autoColumnOrder!9",
"\\",
".",
"?",
"!",
"#",
")",
"(",
"/",
";",
"'",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
],
"tablet_period": [
"!autoColumnOrder!8",
"\\",
".",
"'",
"#",
")",
"(",
"/",
";",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
]
},
"keyspec": {
"symbols_1": "१",
"symbols_2": "२",
"symbols_3": "३",
"symbols_4": "४",
"symbols_5": "५",
"symbols_6": "६",
"symbols_7": "७",
"symbols_8": "८",
"symbols_9": "९",
"symbols_0": "",
"currency": "₹",
"period": "।",
"tablet_period": "।"
},
"label": {},
"keylabel": {
"to_alpha": "कखग",
"to_symbol": "?१२३"
},
"keyhintlabel": {},
"additional_morekeys": {
"symbols_1": [
"1"
],
"symbols_2": [
"2"
],
"symbols_3": [
"3"
],
"symbols_4": [
"4"
],
"symbols_5": [
"5"
],
"symbols_6": [
"6"
],
"symbols_7": [
"7"
],
"symbols_8": [
"8"
],
"symbols_9": [
"9"
],
"symbols_0": [
"0"
]
},
"other": {}
}

View File

@ -0,0 +1,21 @@
{
"locale": "hi_ZZ",
"morekeys": {},
"keyspec": {
"currency": "₹"
},
"label": {
"go_key": "Go",
"send_key": "Send",
"next_key": "Next",
"done_key": "Done",
"search_key": "Search",
"previous_key": "Prev",
"pause_key": "Pause",
"wait_key": "Wait"
},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,38 @@
{
"locale": "hr",
"morekeys": {
"s": [
"š",
"ś",
"ß"
],
"n": [
"ñ",
"ń"
],
"z": [
"ž",
"ź",
"ż"
],
"c": [
"č",
"ć",
"ç"
],
"d": [
"đ"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_rqm",
"double_quotes": "!text/double_9qm_rqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,62 @@
{
"locale": "hu",
"morekeys": {
"a": [
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
"i": [
"í",
"î",
"ï",
"ì",
"į",
"ī"
],
"o": [
"ó",
"ö",
"ő",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
"u": [
"ú",
"ü",
"ű",
"û",
"ù",
"ū"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_rqm",
"double_quotes": "!text/double_9qm_rqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,48 @@
{
"locale": "hy",
"morekeys": {
"punctuation": [
"!autoColumnOrder!8",
"\\",
"՞",
"՜",
".",
"՚",
"ՙ",
"?",
"!",
"՝",
"՛",
"֊",
"»",
"«",
"՟",
";",
":"
],
"question": [
"՞",
"¿"
],
"exclamation": [
"՜",
"¡"
],
"tablet_period": [
"!text/morekeys_punctuation"
]
},
"keyspec": {
"comma": "՝",
"tablet_comma": "՝",
"period": "։",
"tablet_period": "։"
},
"label": {},
"keylabel": {
"to_alpha": "ԱԲԳ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,68 @@
{
"locale": "is",
"morekeys": {
"a": [
"á",
"ä",
"æ",
"å",
"à",
"â",
"ã",
"ā"
],
"e": [
"é",
"ë",
"è",
"ê",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"î",
"ì",
"į",
"ī"
],
"o": [
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
"u": [
"ú",
"ü",
"û",
"ù",
"ū"
],
"y": [
"ý",
"ÿ"
],
"d": [
"ð"
],
"t": [
"þ"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,70 @@
{
"locale": "it",
"morekeys": {
"a": [
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā",
"ª"
],
"e": [
"è",
"é",
"ê",
"ë",
"ę",
"ė",
"ē"
],
"i": [
"ì",
"í",
"î",
"ï",
"į",
"ī"
],
"o": [
"ò",
"ó",
"ô",
"ö",
"õ",
"œ",
"ø",
"ō",
"º"
],
"u": [
"ù",
"ú",
"û",
"ü",
"ū"
],
"swiss_row1_11": [
"è"
],
"swiss_row2_10": [
"é"
],
"swiss_row2_11": [
"à"
]
},
"keyspec": {
"swiss_row1_11": "ü",
"swiss_row2_10": "ö",
"swiss_row2_11": "ä"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,39 @@
{
"locale": "iw",
"morekeys": {
"star": [
"★"
],
"plus": [
"±",
"﬩"
]
},
"keyspec": {
"left_parenthesis": "(|)",
"right_parenthesis": ")|(",
"left_square_bracket": "[|]",
"right_square_bracket": "]|[",
"left_curly_bracket": "{|}",
"right_curly_bracket": "}|{",
"less_than": "<|>",
"greater_than": ">|<",
"less_than_equal": "≤|≥",
"greater_than_equal": "≥|≤",
"left_double_angle_quote": "«|»",
"right_double_angle_quote": "»|«",
"left_single_angle_quote": "|",
"right_single_angle_quote": "|",
"currency": "₪"
},
"label": {},
"keylabel": {
"to_alpha": "אבג"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_rqm_9qm",
"double_quotes": "!text/double_rqm_9qm"
}
}

View File

@ -0,0 +1,15 @@
{
"locale": "ka",
"morekeys": {},
"keyspec": {},
"label": {},
"keylabel": {
"to_alpha": "აბგ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,49 @@
{
"locale": "kk",
"morekeys": {
"cyrillic_u": [
"ү",
"ұ"
],
"cyrillic_ka": [
"қ"
],
"cyrillic_ie": [
"ё"
],
"cyrillic_en": [
"ң"
],
"cyrillic_ghe": [
"ғ"
],
"east_slavic_row2_2": [
"і"
],
"cyrillic_a": [
"ә"
],
"cyrillic_o": [
"ө"
],
"east_slavic_row2_11": [
"һ"
],
"cyrillic_soft_sign": [
"ъ"
]
},
"keyspec": {
"east_slavic_row1_9": "щ",
"east_slavic_row2_2": "ы",
"east_slavic_row2_11": "э",
"east_slavic_row3_5": "и"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,21 @@
{
"locale": "km",
"morekeys": {
"currency_dollar": [
"៛",
"¢",
"£",
"€",
"¥",
"₱"
]
},
"keyspec": {},
"label": {},
"keylabel": {
"to_alpha": "កខគ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "kn",
"morekeys": {},
"keyspec": {
"currency": "₹"
},
"label": {},
"keylabel": {
"to_alpha": "ಅಆಇ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,33 @@
{
"locale": "ky",
"morekeys": {
"cyrillic_u": [
"ү"
],
"cyrillic_ie": [
"ё"
],
"cyrillic_en": [
"ң"
],
"cyrillic_o": [
"ө"
],
"cyrillic_soft_sign": [
"ъ"
]
},
"keyspec": {
"east_slavic_row1_9": "щ",
"east_slavic_row2_2": "ы",
"east_slavic_row2_11": "э",
"east_slavic_row3_5": "и"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "lo",
"morekeys": {},
"keyspec": {
"currency": "₭"
},
"label": {},
"keylabel": {
"to_alpha": "ກຂຄ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,21 @@
{
"locale": "lt",
"morekeys": {
"a": "ą",
"e": ["ė", "ę"],
"i": "į",
"u": ["ū", "ų"],
"s": "š",
"c": "č",
"z": "ž"
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": ["", "", ""],
"double_quotes": ["”", "„", "“"]
}
}

View File

@ -0,0 +1,114 @@
{
"locale": "lv",
"morekeys": {
"a": [
"ā",
"à",
"á",
"â",
"ã",
"ä",
"å",
"æ",
"ą"
],
"e": [
"ē",
"ė",
"è",
"é",
"ê",
"ë",
"ę",
"ě"
],
"i": [
"ī",
"į",
"ì",
"í",
"î",
"ï",
"ı"
],
"o": [
"ò",
"ó",
"ô",
"õ",
"ö",
"œ",
"ő",
"ø"
],
"u": [
"ū",
"ų",
"ù",
"ú",
"û",
"ü",
"ů",
"ű"
],
"s": [
"š",
"ß",
"ś",
"ş"
],
"n": [
"ņ",
"ñ",
"ń"
],
"c": [
"č",
"ç",
"ć"
],
"y": [
"ý",
"ÿ"
],
"d": [
"ď"
],
"r": [
"ŗ",
"ř",
"ŕ"
],
"t": [
"ţ",
"ť"
],
"z": [
"ž",
"ż",
"ź"
],
"k": [
"ķ"
],
"l": [
"ļ",
"ł",
"ĺ",
"ľ"
],
"g": [
"ģ",
"ğ"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,27 @@
{
"locale": "mk",
"morekeys": {
"cyrillic_ie": [
"ѐ"
],
"cyrillic_i": [
"ѝ"
]
},
"keyspec": {
"south_slavic_row1_6": "ѕ",
"south_slavic_row2_11": "ќ",
"south_slavic_row3_1": "з",
"south_slavic_row3_8": "ѓ"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,14 @@
{
"locale": "ml",
"morekeys": {},
"keyspec": {
"currency": "₹"
},
"label": {},
"keylabel": {
"to_alpha": "അ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "mn",
"morekeys": {},
"keyspec": {
"currency": "₮"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,56 @@
{
"locale": "mr",
"morekeys": {},
"keyspec": {
"symbols_1": "१",
"symbols_2": "२",
"symbols_3": "३",
"symbols_4": "४",
"symbols_5": "५",
"symbols_6": "६",
"symbols_7": "७",
"symbols_8": "८",
"symbols_9": "९",
"symbols_0": "",
"currency": "₹"
},
"label": {},
"keylabel": {
"to_alpha": "कखग",
"to_symbol": "?१२३"
},
"keyhintlabel": {},
"additional_morekeys": {
"symbols_1": [
"1"
],
"symbols_2": [
"2"
],
"symbols_3": [
"3"
],
"symbols_4": [
"4"
],
"symbols_5": [
"5"
],
"symbols_6": [
"6"
],
"symbols_7": [
"7"
],
"symbols_8": [
"8"
],
"symbols_9": [
"9"
],
"symbols_0": [
"0"
]
},
"other": {}
}

View File

@ -0,0 +1,61 @@
{
"locale": "my",
"morekeys": {
"tablet_comma": [
"\\"
],
"punctuation": [
"!autoColumnOrder!9",
"၊",
".",
"?",
"!",
"#",
")",
"(",
"/",
";",
"...",
"'",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
],
"tablet_punctuation": [
"!autoColumnOrder!8",
".",
"'",
"#",
")",
"(",
"/",
";",
"@",
"...",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
]
},
"keyspec": {
"tablet_comma": "၊",
"tablet_period": "။",
"period": "။"
},
"label": {},
"keylabel": {
"to_alpha": "ကခဂ"
},
"keyhintlabel": {
"period": "၊"
},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,60 @@
{
"locale": "nb",
"morekeys": {
"a": [
"å",
"æ",
"ä",
"à",
"á",
"â",
"ã",
"ā"
],
"e": [
"é",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
"o": [
"ø",
"ö",
"ô",
"ò",
"ó",
"õ",
"œ",
"ō"
],
"u": [
"ü",
"û",
"ù",
"ú",
"ū"
],
"nordic_row2_10": [
"ö"
],
"nordic_row2_11": [
"ä"
]
},
"keyspec": {
"nordic_row1_11": "å",
"nordic_row2_10": "ø",
"nordic_row2_11": "æ"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_rqm",
"double_quotes": "!text/double_9qm_rqm"
}
}

View File

@ -0,0 +1,97 @@
{
"locale": "ne",
"morekeys": {
"period": [
"!autoColumnOrder!9",
".",
"\\",
"?",
"!",
"#",
")",
"(",
"/",
";",
"'",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
],
"tablet_period": [
"!autoColumnOrder!8",
".",
"\\",
"'",
"#",
")",
"(",
"/",
";",
"@",
":",
"-",
"\\\"",
"+",
"\\%",
"&"
]
},
"keyspec": {
"symbols_1": "१",
"symbols_2": "२",
"symbols_3": "३",
"symbols_4": "४",
"symbols_5": "५",
"symbols_6": "६",
"symbols_7": "७",
"symbols_8": "८",
"symbols_9": "९",
"symbols_0": "",
"currency": "रु.",
"period": "।",
"tablet_period": "।"
},
"label": {},
"keylabel": {
"to_alpha": "कखग",
"to_symbol": "?१२३"
},
"keyhintlabel": {},
"additional_morekeys": {
"symbols_1": [
"1"
],
"symbols_2": [
"2"
],
"symbols_3": [
"3"
],
"symbols_4": [
"4"
],
"symbols_5": [
"5"
],
"symbols_6": [
"6"
],
"symbols_7": [
"7"
],
"symbols_8": [
"8"
],
"symbols_9": [
"9"
],
"symbols_0": [
"0"
]
},
"other": {}
}

View File

@ -0,0 +1,66 @@
{
"locale": "nl",
"morekeys": {
"a": [
"á",
"ä",
"â",
"à",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"ë",
"ê",
"è",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"ì",
"î",
"į",
"ī",
"ij"
],
"o": [
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
"u": [
"ú",
"ü",
"û",
"ù",
"ū"
],
"n": [
"ñ",
"ń"
],
"y": [
"ij"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_rqm",
"double_quotes": "!text/double_9qm_rqm"
}
}

View File

@ -0,0 +1,66 @@
{
"locale": "pl",
"morekeys": {
"a": [
"ą",
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
"e": [
"ę",
"è",
"é",
"ê",
"ë",
"ė",
"ē"
],
"o": [
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
"s": [
"ś",
"ß",
"š"
],
"n": [
"ń",
"ñ"
],
"c": [
"ć",
"ç",
"č"
],
"z": [
"ż",
"ź",
"ž"
],
"l": [
"ł"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_rqm",
"double_quotes": "!text/double_9qm_rqm"
}
}

View File

@ -0,0 +1,63 @@
{
"locale": "pt",
"morekeys": {
"a": [
"á",
"ã",
"à",
"â",
"ä",
"å",
"æ",
"ª"
],
"e": [
"é",
"ê",
"è",
"ę",
"ė",
"ē",
"ë"
],
"i": [
"í",
"î",
"ì",
"ï",
"į",
"ī"
],
"o": [
"ó",
"õ",
"ô",
"ò",
"ö",
"œ",
"ø",
"ō",
"º"
],
"u": [
"ú",
"ü",
"ù",
"û",
"ū"
],
"c": [
"ç",
"č",
"ć"
]
},
"keyspec": {
"spanish_row2_10": "ç"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,20 @@
{
"locale": "rm",
"morekeys": {
"o": [
"ò",
"ó",
"ö",
"ô",
"õ",
"œ",
"ø"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,42 @@
{
"locale": "ro",
"morekeys": {
"a": [
"ă",
"â",
"ã",
"à",
"á",
"ä",
"æ",
"å",
"ā"
],
"i": [
"î",
"ï",
"ì",
"í",
"į",
"ī"
],
"s": [
"ș",
"ß",
"ś",
"š"
],
"t": [
"ț"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_rqm",
"double_quotes": "!text/double_9qm_rqm"
}
}

View File

@ -0,0 +1,27 @@
{
"locale": "ru",
"morekeys": {
"cyrillic_ie": [
"ё"
],
"cyrillic_soft_sign": [
"ъ"
]
},
"keyspec": {
"east_slavic_row1_9": "щ",
"east_slavic_row2_2": "ы",
"east_slavic_row2_11": "э",
"east_slavic_row3_5": "и"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,14 @@
{
"locale": "si",
"morekeys": {},
"keyspec": {
"currency": "රු"
},
"label": {},
"keylabel": {
"to_alpha": "අ,ආ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,117 @@
{
"locale": "sk",
"morekeys": {
"a": [
"á",
"ä",
"ā",
"à",
"â",
"ã",
"å",
"æ",
"ą"
],
"e": [
"é",
"ě",
"ē",
"ė",
"è",
"ê",
"ë",
"ę"
],
"i": [
"í",
"ī",
"į",
"ì",
"î",
"ï",
"ı"
],
"o": [
"ô",
"ó",
"ö",
"ò",
"õ",
"œ",
"ő",
"ø"
],
"u": [
"ú",
"ů",
"ü",
"ū",
"ų",
"ù",
"û",
"ű"
],
"s": [
"š",
"ß",
"ś",
"ş"
],
"n": [
"ň",
"ņ",
"ñ",
"ń"
],
"c": [
"č",
"ç",
"ć"
],
"y": [
"ý",
"ÿ"
],
"d": [
"ď"
],
"r": [
"ŕ",
"ř",
"ŗ"
],
"t": [
"ť",
"ţ"
],
"z": [
"ž",
"ż",
"ź"
],
"k": [
"ķ"
],
"l": [
"ľ",
"ĺ",
"ļ",
"ł"
],
"g": [
"ģ",
"ğ"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,29 @@
{
"locale": "sl",
"morekeys": {
"s": [
"š"
],
"c": [
"č",
"ć"
],
"d": [
"đ"
],
"z": [
"ž"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,29 @@
{
"locale": "sr",
"morekeys": {
"cyrillic_ie": [
"ѐ"
],
"cyrillic_i": [
"ѝ"
]
},
"keyspec": {
"south_slavic_row1_6": "з",
"south_slavic_row2_11": "ћ",
"south_slavic_row3_1": "ѕ",
"south_slavic_row3_8": "ђ"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm",
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,43 @@
{
"locale": "sr_ZZ",
"morekeys": {
"e": [
"è"
],
"i": [
"ì"
],
"s": [
"š",
"%"
],
"c": [
"č",
"ć",
"%"
],
"d": [
"đ",
"%"
],
"z": [
"ž",
"%"
]
},
"keyspec": {},
"label": {
"go_key": "Idi",
"send_key": "Šalji",
"next_key": "Sled",
"done_key": "Gotov",
"search_key": "Traži",
"previous_key": "Preth",
"pause_key": "Pauza",
"wait_key": "Čekaj"
},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,104 @@
{
"locale": "sv",
"morekeys": {
"a": [
"ä",
"å",
"æ",
"á",
"à",
"â",
"ą",
"ã"
],
"c": [
"ç",
"ć",
"č"
],
"d": [
"ð",
"ď"
],
"e": [
"é",
"è",
"ê",
"ë",
"ę"
],
"i": [
"í",
"ì",
"î",
"ï"
],
"l": [
"ł"
],
"n": [
"ń",
"ñ",
"ň"
],
"o": [
"ö",
"ø",
"œ",
"ó",
"ò",
"ô",
"õ",
"ō"
],
"r": [
"ř"
],
"s": [
"ś",
"š",
"ş",
"ß"
],
"t": [
"ť",
"þ"
],
"u": [
"ü",
"ú",
"ù",
"û",
"ū"
],
"y": [
"ý",
"ÿ"
],
"z": [
"ź",
"ž",
"ż"
],
"nordic_row2_11": [
"æ"
],
"nordic_row2_10": [
"ø",
"œ"
]
},
"keyspec": {
"nordic_row1_11": "å",
"nordic_row2_11": "ä",
"nordic_row2_10": "ö"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_angle_quotes": "!text/single_raqm_laqm",
"double_angle_quotes": "!text/double_raqm_laqm"
}
}

View File

@ -0,0 +1,64 @@
{
"locale": "sw",
"morekeys": {
"a": [
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
"e": [
"è",
"é",
"ê",
"ë",
"ē"
],
"i": [
"î",
"ï",
"í",
"ī",
"ì"
],
"o": [
"ô",
"ö",
"ò",
"ó",
"œ",
"ø",
"ō",
"õ"
],
"u": [
"û",
"ü",
"ù",
"ú",
"ū"
],
"s": [
"ß"
],
"n": [
"ñ"
],
"c": [
"ç"
],
"g": [
"g\\'"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "ta_IN",
"morekeys": {},
"keyspec": {
"currency": "௹"
},
"label": {},
"keylabel": {
"to_alpha": "தமிழ்"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "ta_LK",
"morekeys": {},
"keyspec": {
"currency": "රු"
},
"label": {},
"keylabel": {
"to_alpha": "தமிழ்"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,12 @@
{
"locale": "ta_SG",
"morekeys": {},
"keyspec": {},
"label": {},
"keylabel": {
"to_alpha": "தமிழ்"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "te",
"morekeys": {},
"keyspec": {
"currency": "₹"
},
"label": {},
"keylabel": {
"to_alpha": "అఆఇ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,14 @@
{
"locale": "th",
"morekeys": {},
"keyspec": {
"currency": "฿"
},
"label": {},
"keylabel": {
"to_alpha": "กขค"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,67 @@
{
"locale": "tl",
"morekeys": {
"a": [
"á",
"à",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
"e": [
"é",
"è",
"ë",
"ê",
"ę",
"ė",
"ē"
],
"i": [
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
"o": [
"ó",
"ò",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
"u": [
"ú",
"ü",
"ù",
"û",
"ū"
],
"n": [
"ñ",
"ń"
],
"c": [
"ç",
"ć",
"č"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,70 @@
{
"locale": "tr",
"morekeys": {
"a": [
"â",
"ä",
"á"
],
"e": [
"ə",
"é"
],
"i": [
"ı",
"î",
"ï",
"ì",
"í",
"į",
"ī"
],
"o": [
"ö",
"ô",
"œ",
"ò",
"ó",
"õ",
"ø",
"ō"
],
"u": [
"ü",
"û",
"ù",
"ú",
"ū"
],
"s": [
"ş",
"ß",
"ś",
"š"
],
"g": [
"ğ"
],
"n": [
"ň",
"ñ"
],
"c": [
"ç",
"ć",
"č"
],
"y": [
"ý"
],
"z": [
"ž"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,31 @@
{
"locale": "uk",
"morekeys": {
"cyrillic_ghe": [
"ґ"
],
"east_slavic_row2_2": [
"ї"
],
"cyrillic_soft_sign": [
"ъ"
]
},
"keyspec": {
"east_slavic_row1_9": "щ",
"east_slavic_row2_2": "і",
"east_slavic_row2_11": "є",
"east_slavic_row3_5": "и",
"currency": "₴"
},
"label": {},
"keylabel": {
"to_alpha": "АБВ"
},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {
"single_quotes": "!text/single_9qm_lqm",
"double_quotes": "!text/double_9qm_lqm"
}
}

View File

@ -0,0 +1,70 @@
{
"locale": "uz",
"morekeys": {
"a": [
"â",
"ä",
"á"
],
"e": [
"ə",
"é"
],
"i": [
"ı",
"î",
"ï",
"ì",
"í",
"į",
"ī"
],
"o": [
"ö",
"ô",
"œ",
"ò",
"ó",
"õ",
"ø",
"ō"
],
"u": [
"ü",
"û",
"ù",
"ú",
"ū"
],
"s": [
"ş",
"ß",
"ś",
"š"
],
"g": [
"ğ"
],
"n": [
"ň",
"ñ"
],
"c": [
"ç",
"ć",
"č"
],
"y": [
"ý"
],
"z": [
"ž"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,94 @@
{
"locale": "vi",
"morekeys": {
"a": [
"à",
"á",
"ả",
"ã",
"ạ",
"ă",
"ằ",
"ắ",
"ẳ",
"ẵ",
"ặ",
"â",
"ầ",
"ấ",
"ẩ",
"ẫ",
"ậ"
],
"e": [
"è",
"é",
"ẻ",
"ẽ",
"ẹ",
"ê",
"ề",
"ế",
"ể",
"ễ",
"ệ"
],
"i": [
"ì",
"í",
"ỉ",
"ĩ",
"ị"
],
"o": [
"ò",
"ó",
"ỏ",
"õ",
"ọ",
"ô",
"ồ",
"ố",
"ổ",
"ỗ",
"ộ",
"ơ",
"ờ",
"ớ",
"ở",
"ỡ",
"ợ"
],
"u": [
"ù",
"ú",
"ủ",
"ũ",
"ụ",
"ư",
"ừ",
"ứ",
"ử",
"ữ",
"ự"
],
"y": [
"ỳ",
"ý",
"ỷ",
"ỹ",
"ỵ"
],
"d": [
"đ"
]
},
"keyspec": {
"currency": "₫"
},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,61 @@
{
"locale": "zu",
"morekeys": {
"a": [
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
"e": [
"é",
"è",
"ê",
"ë",
"ē"
],
"i": [
"í",
"î",
"ï",
"ī",
"ì"
],
"o": [
"ó",
"ô",
"ö",
"ò",
"œ",
"ø",
"ō",
"õ"
],
"u": [
"ú",
"û",
"ü",
"ù",
"ū"
],
"s": [
"ß"
],
"n": [
"ñ"
],
"c": [
"ç"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,148 @@
{
"locale": "zz",
"morekeys": {
"a": [
"à",
"á",
"â",
"ã",
"ä",
"å",
"æ",
"ā",
"ă",
"ą",
"ª"
],
"e": [
"è",
"é",
"ê",
"ë",
"ē",
"ĕ",
"ė",
"ę",
"ě"
],
"i": [
"ì",
"í",
"î",
"ï",
"ĩ",
"ī",
"ĭ",
"į",
"ı",
"ij"
],
"o": [
"ò",
"ó",
"ô",
"õ",
"ö",
"ø",
"ō",
"ŏ",
"ő",
"œ",
"º"
],
"u": [
"ù",
"ú",
"û",
"ü",
"ũ",
"ū",
"ŭ",
"ů",
"ű",
"ų"
],
"s": [
"ß",
"ś",
"ŝ",
"ş",
"š",
"ſ"
],
"n": [
"ñ",
"ń",
"ņ",
"ň",
"ʼn",
"ŋ"
],
"c": [
"ç",
"ć",
"ĉ",
"ċ",
"č"
],
"y": [
"ý",
"ŷ",
"ÿ",
"ij"
],
"d": [
"ď",
"đ",
"ð"
],
"r": [
"ŕ",
"ŗ",
"ř"
],
"t": [
"þ",
"ţ",
"ť",
"ŧ"
],
"z": [
"ź",
"ż",
"ž"
],
"k": [
"ķ",
"ĸ"
],
"l": [
"ĺ",
"ļ",
"ľ",
"ŀ",
"ł"
],
"g": [
"ĝ",
"ğ",
"ġ",
"ģ"
],
"h": [
"ĥ"
],
"j": [
"ĵ"
],
"w": [
"ŵ"
]
},
"keyspec": {},
"label": {},
"keylabel": {},
"keyhintlabel": {},
"additional_morekeys": {},
"other": {}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.futo.inputmethod.keyboard.internal;
import java.util.HashMap;
import java.util.Locale;
/**
* !!!!! DO NOT EDIT THIS FILE !!!!!
*
* This file is generated by tools/make-keyboard-text. The base template file is
* tools/make-keyboard-text/res/src/org/futo/inputmethod/keyboard/internal/
* KeyboardTextsTable.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/make-keyboard-text/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/make-keyboard-text
* $ make-keyboard-text -java packages/inputmethods/LatinIME/java
*
* The updated source file will be generated to the following path (this file).
* packages/inputmethods/LatinIME/java/src/org/futo/inputmethod/keyboard/internal/
* KeyboardTextsTable.java
*/
public final class KeyboardTextsTable {
// Name to index map.
private static final HashMap<String, Integer> sNameToIndexesMap = new HashMap<>();
// Locale to texts table map.
private static final HashMap<String, String[]> sLocaleToTextsTableMap = new HashMap<>();
// TODO: Remove this variable after debugging.
// Texts table to locale maps.
private static final HashMap<String[], String> sTextsTableToLocaleMap = new HashMap<>();
public static String getText(final String name, final String[] textsTable) {
final Integer indexObj = sNameToIndexesMap.get(name);
if (indexObj == null) {
throw new RuntimeException("Unknown text name=" + name + " locale="
+ sTextsTableToLocaleMap.get(textsTable));
}
final int index = indexObj;
final String text = (index < textsTable.length) ? textsTable[index] : null;
if (text != null) {
return text;
}
// Validity check.
if (index >= 0 && index < TEXTS_DEFAULT.length) {
return TEXTS_DEFAULT[index];
}
// Throw exception for debugging purpose.
throw new RuntimeException("Illegal index=" + index + " for name=" + name
+ " locale=" + sTextsTableToLocaleMap.get(textsTable));
}
public static String[] getTextsTable(final Locale locale) {
final String localeKey = locale.toString();
if (sLocaleToTextsTableMap.containsKey(localeKey)) {
return sLocaleToTextsTableMap.get(localeKey);
}
final String languageKey = locale.getLanguage();
if (sLocaleToTextsTableMap.containsKey(languageKey)) {
return sLocaleToTextsTableMap.get(languageKey);
}
return TEXTS_DEFAULT;
}
private static final String[] NAMES = {
// /* index:histogram */ "name",
/* @NAMES@ */
};
private static final String EMPTY = "";
/* @TEXTS@ */
private static final Object[] LOCALES_AND_TEXTS = {
// "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */
/* @LOCALES_AND_TEXTS@ */
};
static {
for (int index = 0; index < NAMES.length; index++) {
sNameToIndexesMap.put(NAMES[index], index);
}
for (int i = 0; i < LOCALES_AND_TEXTS.length; i += 2) {
final String locale = (String)LOCALES_AND_TEXTS[i];
final String[] textsTable = (String[])LOCALES_AND_TEXTS[i + 1];
sLocaleToTextsTableMap.put(locale, textsTable);
sTextsTableToLocaleMap.put(textsTable, locale);
}
}
}

View File

@ -0,0 +1,117 @@
# Note: Run this tool in the make-keyboard-text-py directory
import json
import glob
def load_data():
all_data = []
for fname in glob.glob("locales/*.json"):
with open(fname, "r") as f:
all_data.append(json.loads(f.read()))
return all_data
def transform_to_texts(locale_data):
texts = { }
texts["locale"] = locale_data["locale"]
prefixes = ['morekeys_', 'keyspec_', 'label_', 'keylabel_', 'keyhintlabel_', 'additional_morekeys_']
for prefix in prefixes:
for k, v in locale_data[prefix.rstrip("_")].items():
if isinstance(v, list):
texts[prefix + k] = ",".join(v)
else:
texts[prefix + k] = v
for k, v in locale_data["other"].items():
if isinstance(v, list):
texts[k] = ",".join(v)
else:
texts[k] = v
return texts
def transform_texts_dict_to_array(texts_dict, names):
texts = []
last_idx = 0
for name in names:
if name in texts_dict:
texts.append(texts_dict[name])
last_idx = len(texts)
else:
texts.append(None)
return texts[:last_idx]
def dump_names(names):
out = ""
for name in names:
out += " " + json.dumps(name) + ",\n"
return out[:-2]
def dump_texts(texts_by_locale):
out = ""
for locale, texts in texts_by_locale.items():
out += " private static final String[] TEXTS_" + locale + " = {\n"
for item in texts:
if item == "":
out += " EMPTY,\n"
else:
out += " " + json.dumps(item) + ",\n"
out = out[:-2] + "\n };\n\n"
return out
def dump_locales_and_texts(texts_by_locale):
out = ""
for locale in texts_by_locale.keys():
out += " " + json.dumps(locale) + ", " + "TEXTS_" + locale + ",\n"
return out[:-2]
def generate_templated_code(names, texts_by_locale):
out = ""
with open("src/KeyboardTextsTable.tmpl", "r") as f:
for line in f:
if "@NAMES@" in line:
out += dump_names(names) + "\n"
elif "@TEXTS@" in line:
out += dump_texts(texts_by_locale) + "\n"
elif "@LOCALES_AND_TEXTS@" in line:
out += dump_locales_and_texts(texts_by_locale) + "\n"
else:
out += line
return out
if __name__ == "__main__":
data = load_data()
data = list(map(transform_to_texts, data))
all_names = set([k for texts in data for k in texts.keys()])
names_and_uses = [
(name, sum([
1 if name in texts else 0
for texts in data
]))
for name in all_names
]
names_and_uses.sort(key=lambda x: -x[1])
names = [x[0] for x in names_and_uses]
texts_by_locale = {}
for texts in data:
texts_by_locale[texts["locale"]] = transform_texts_dict_to_array(texts, names)
code = generate_templated_code(names, texts_by_locale)
with open("../../java/src/org/futo/inputmethod/keyboard/internal/KeyboardTextsTable.java", "w") as f:
f.write(code)

View File

@ -0,0 +1,66 @@
import os
import json
import xml.etree.ElementTree as ET
# Base directory containing the XML files
base_dir = '../make-keyboard-text/res'
# List of known prefixes
prefixes = ['morekeys_', 'keyspec_', 'label_', 'keylabel_', 'keyhintlabel_', 'additional_morekeys_']
# Function to convert XML to a dictionary
def xml_to_dict(xml_file):
tree = ET.parse(xml_file)
root = tree.getroot()
locale_data = {prefix.rstrip('_'): {} for prefix in prefixes}
locale_data['other'] = {}
for string in root.findall('string'):
name = string.get('name')
value = string.text or ""
value = value.replace("\\\\", "\\")
if value.startswith('"') and value.endswith('"'):
value = value.lstrip('"').rstrip('"')
# Categorize based on prefixes
categorized = False
for prefix in prefixes:
if name.startswith(prefix):
if "morekeys" in prefix:
locale_data[prefix.rstrip('_')][name.replace(prefix, '')] = list(filter(lambda x: x, value.split(",")))
else:
locale_data[prefix.rstrip('_')][name.replace(prefix, '')] = value
categorized = True
break
# If no known prefix matches, categorize as "other"
if not categorized:
locale_data['other'][name] = value
return locale_data
# Function to process all XML files and convert them to JSON
def process_locale_files(base_dir):
for root, _, files in os.walk(base_dir):
for file in files:
if file.endswith('.xml'):
xml_file_path = os.path.join(root, file)
locale_code = root.split(os.sep)[-1].replace('values-', '')
if locale_code == "values":
locale_code = "DEFAULT"
if "-r" in locale_code:
locale_code = locale_code.replace("-r", "_")
json_data = {"locale": locale_code} | xml_to_dict(xml_file_path)
json_file_path = (f"locales/{locale_code}.json")
with open(json_file_path, 'w', encoding='utf-8') as json_file:
json.dump(json_data, json_file, ensure_ascii=False, indent=4)
print(f"Converted {xml_file_path} to {json_file_path}")
# Run the process
process_locale_files(base_dir)

View File

@ -1,31 +0,0 @@
//
// 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 {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "packages_inputmethods_LatinIME_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["packages_inputmethods_LatinIME_license"],
}
java_binary_host {
name: "make-keyboard-text",
srcs: ["src/**/*.java"],
main_class: "org.futo.inputmethod.keyboard.tools.MakeKeyboardText",
java_resource_dirs: ["res"],
}

View File

@ -62,4 +62,6 @@
U+010D: "č" LATIN SMALL LETTER C WITH CARON
U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
<string name="morekeys_c">&#x00E7;,&#x010D;,&#x0107;</string>
<string name="keyspec_spanish_row2_10">&#x00E7;</string>
</resources>

View File

@ -1,104 +0,0 @@
/*
* 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 org.futo.inputmethod.keyboard.tools;
import java.io.PrintStream;
public class ArrayInitializerFormatter {
private final PrintStream mOut;
private final int mMaxWidth;
private final String mIndent;
// String resource names array; indexed by {@link #CurrentIndex} and
// {@link #mStartIndexOfBuffer}.
private final String[] mResourceNames;
private int mCurrentIndex = 0;
private String mLastElement;
private final StringBuilder mBuffer = new StringBuilder();
private int mBufferedLen;
private int mStartIndexOfBuffer = Integer.MIN_VALUE;
public ArrayInitializerFormatter(final PrintStream out, final int width, final String indent,
final String[] resourceNames) {
mOut = out;
mMaxWidth = width - indent.length();
mIndent = indent;
mResourceNames = resourceNames;
}
public int getCurrentIndex() {
return mCurrentIndex;
}
public void flush() {
if (mBuffer.length() == 0) {
return;
}
final int lastIndex = mCurrentIndex - 1;
if (mStartIndexOfBuffer == lastIndex) {
mOut.format("%s/* %s */ %s\n",
mIndent, mResourceNames[mStartIndexOfBuffer], mBuffer);
} else if (mStartIndexOfBuffer == lastIndex - 1) {
final String startElement = mBuffer.toString()
.substring(0, mBuffer.length() - mLastElement.length())
.trim();
mOut.format("%s/* %s */ %s\n"
+ "%s/* %s */ %s\n",
mIndent, mResourceNames[mStartIndexOfBuffer], startElement,
mIndent, mResourceNames[lastIndex], mLastElement);
} else {
mOut.format("%s/* %s ~ */\n"
+ "%s%s\n"
+ "%s/* ~ %s */\n",
mIndent, mResourceNames[mStartIndexOfBuffer],
mIndent, mBuffer,
mIndent, mResourceNames[lastIndex]);
}
mBuffer.setLength(0);
mBufferedLen = 0;
}
public void outCommentLines(final String lines) {
flush();
mOut.print(lines);
mLastElement = null;
}
public void outElement(final String element) {
if (!element.equals(mLastElement)) {
flush();
mStartIndexOfBuffer = mCurrentIndex;
}
final int nextLen = mBufferedLen + " ".length() + element.length();
if (mBufferedLen != 0 && nextLen < mMaxWidth) {
// Element can fit in the current line.
mBuffer.append(' ');
mBuffer.append(element);
mBufferedLen = nextLen;
} else {
// Element should be on the next line.
if (mBufferedLen != 0) {
mBuffer.append('\n');
mBuffer.append(mIndent);
}
mBuffer.append(element);
mBufferedLen = element.length();
}
mCurrentIndex++;
mLastElement = element;
}
}

View File

@ -1,117 +0,0 @@
/*
* 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 org.futo.inputmethod.keyboard.tools;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Locale;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public final class JarUtils {
private JarUtils() {
// This utility class is not publicly instantiable.
}
public static JarFile getJarFile(final Class<?> mainClass) {
final String mainClassPath = "/" + mainClass.getName().replace('.', '/') + ".class";
final URL resUrl = mainClass.getResource(mainClassPath);
if (!resUrl.getProtocol().equals("jar")) {
throw new RuntimeException("Should run as jar");
}
final String path = resUrl.getPath();
if (!path.startsWith("file:")) {
throw new RuntimeException("Unknown jar path: " + path);
}
final String jarPath = path.substring("file:".length(), path.indexOf('!'));
try {
return new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
} catch (UnsupportedEncodingException e) {
} catch (IOException e) {
}
return null;
}
public static InputStream openResource(final String name) {
return JarUtils.class.getResourceAsStream("/" + name);
}
public interface JarFilter {
public boolean accept(String dirName, String name);
}
public static ArrayList<String> getEntryNameListing(final JarFile jar, final JarFilter filter) {
final ArrayList<String> result = new ArrayList<>();
final Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
final String path = entry.getName();
final int pos = path.lastIndexOf('/');
final String dirName = (pos >= 0) ? path.substring(0, pos) : "";
final String name = (pos >= 0) ? path.substring(pos + 1) : path;
if (filter.accept(dirName, name)) {
result.add(path);
}
}
return result;
}
public static ArrayList<String> getEntryNameListing(final JarFile jar,
final String filterName) {
return getEntryNameListing(jar, new JarFilter() {
@Override
public boolean accept(final String dirName, final String name) {
return name.equals(filterName);
}
});
}
// The locale is taken from string resource jar entry name (values-<locale>/)
// or {@link LocaleUtils#DEFAULT_LOCALE} for the default string resource
// directory (values/).
public static Locale getLocaleFromEntryName(final String jarEntryName) {
final String dirName = jarEntryName.substring(0, jarEntryName.lastIndexOf('/'));
final int pos = dirName.lastIndexOf('/');
final String parentName = (pos >= 0) ? dirName.substring(pos + 1) : dirName;
final int localePos = parentName.indexOf('-');
if (localePos < 0) {
// Default resource name.
return LocaleUtils.DEFAULT_LOCALE;
}
final String localeStr = parentName.substring(localePos + 1);
final int regionPos = localeStr.indexOf("-r");
if (regionPos < 0) {
return LocaleUtils.constructLocaleFromString(localeStr);
}
return LocaleUtils.constructLocaleFromString(localeStr.replace("-r", "_"));
}
public static void close(final Closeable stream) {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
}
}
}

View File

@ -1,167 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.futo.inputmethod.keyboard.tools;
import java.util.HashMap;
import java.util.Locale;
/**
* A class to help with handling Locales in string form.
*
* This is a subset of org/futo/inputmethod/latin/utils/LocaleUtils.java in order to use
* for the make-keyboard-text tool.
*/
public final class LocaleUtils {
public static final Locale DEFAULT_LOCALE = Locale.ROOT;
private static final String DEFAULT_LOCALE_CODE = "DEFAULT";
public static final String NO_LANGUAGE_LOCALE_CODE = "zz";
public static final String NO_LANGUAGE_LOCALE_DISPLAY_NAME = "Alphabet";
private LocaleUtils() {
// Intentional empty constructor for utility class.
}
private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
private static final int INDEX_LANGUAGE = 0;
private static final int INDEX_SCRIPT = 1;
private static final int INDEX_REGION = 2;
private static final int ELEMENT_LIMIT = INDEX_REGION + 1;
/**
* Creates a locale from a string specification.
*
* Locale string is: language(_script)?(_region)?
* where: language := [a-zA-Z]{2,3}
* script := [a-zA-Z]{4}
* region := [a-zA-Z]{2,3}|[0-9]{3}
*/
public static Locale constructLocaleFromString(final String localeStr) {
if (localeStr == null) {
return null;
}
synchronized (sLocaleCache) {
if (sLocaleCache.containsKey(localeStr)) {
return sLocaleCache.get(localeStr);
}
boolean hasRegion = false;
final Locale.Builder builder = new Locale.Builder();
final String[] localeElements = localeStr.split("_", ELEMENT_LIMIT);
if (localeElements.length > INDEX_LANGUAGE) {
final String text = localeElements[INDEX_LANGUAGE];
if (isValidLanguage(text)) {
builder.setLanguage(text);
} else {
throw new RuntimeException("Unknown locale format: " + localeStr);
}
}
if (localeElements.length > INDEX_SCRIPT) {
final String text = localeElements[INDEX_SCRIPT];
if (isValidScript(text)) {
builder.setScript(text);
} else if (isValidRegion(text)) {
builder.setRegion(text);
hasRegion = true;
} else {
throw new RuntimeException("Unknown locale format: " + localeStr);
}
}
if (localeElements.length > INDEX_REGION) {
final String text = localeElements[INDEX_REGION];
if (!hasRegion && isValidRegion(text)) {
builder.setRegion(text);
} else {
throw new RuntimeException("Unknown locale format: " + localeStr);
}
}
final Locale locale = builder.build();
sLocaleCache.put(localeStr, locale);
return locale;
}
}
private static final int MIN_LENGTH_OF_LANGUAGE = 2;
private static final int MAX_LENGTH_OF_LANGUAGE = 2;
private static final int LENGTH_OF_SCRIPT = 4;
private static final int MIN_LENGTH_OF_REGION = 2;
private static final int MAX_LENGTH_OF_REGION = 2;
private static final int LENGTH_OF_AREA_CODE = 3;
private static boolean isValidLanguage(final String text) {
return isAlphabetSequence(text, MIN_LENGTH_OF_LANGUAGE, MAX_LENGTH_OF_LANGUAGE);
}
private static boolean isValidScript(final String text) {
return isAlphabetSequence(text, LENGTH_OF_SCRIPT, LENGTH_OF_SCRIPT);
}
private static boolean isValidRegion(final String text) {
return isAlphabetSequence(text, MIN_LENGTH_OF_REGION, MAX_LENGTH_OF_REGION)
|| isDigitSequence(text, LENGTH_OF_AREA_CODE, LENGTH_OF_AREA_CODE);
}
private static boolean isAlphabetSequence(final String text, final int lower, final int upper) {
final int length = text.length();
if (length < lower || length > upper) {
return false;
}
for (int index = 0; index < length; index++) {
if (!isAsciiAlphabet(text.charAt(index))) {
return false;
}
}
return true;
}
private static boolean isDigitSequence(final String text, final int lower, final int upper) {
final int length = text.length();
if (length < lower || length > upper) {
return false;
}
for (int index = 0; index < length; ++index) {
if (!isAsciiDigit(text.charAt(index))) {
return false;
}
}
return true;
}
private static boolean isAsciiAlphabet(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
private static boolean isAsciiDigit(char c) {
return c >= '0' && c <= '9';
}
public static String getLocaleCode(final Locale locale) {
if (locale == DEFAULT_LOCALE) {
return DEFAULT_LOCALE_CODE;
}
return locale.toString();
}
public static String getLocaleDisplayName(final Locale locale) {
if (locale == DEFAULT_LOCALE) {
return DEFAULT_LOCALE_CODE;
}
if (locale.getLanguage().equals(NO_LANGUAGE_LOCALE_CODE)) {
return NO_LANGUAGE_LOCALE_DISPLAY_NAME;
}
return locale.getDisplayName(Locale.ENGLISH);
}
}

View File

@ -1,65 +0,0 @@
/*
* 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 org.futo.inputmethod.keyboard.tools;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.jar.JarFile;
public class MakeKeyboardText {
static class Options {
private static final String OPTION_JAVA = "-java";
public final String mJava;
public static void usage(String message) {
if (message != null) {
System.err.println(message);
}
System.err.println("usage: make-keyboard-text " + OPTION_JAVA + " <java_output_dir>");
System.exit(1);
}
public Options(final String[] argsArray) {
final LinkedList<String> args = new LinkedList<>(Arrays.asList(argsArray));
String arg = null;
String java = null;
try {
while (!args.isEmpty()) {
arg = args.removeFirst();
if (arg.equals(OPTION_JAVA)) {
java = args.removeFirst();
} else {
usage("Unknown option: " + arg);
}
}
} catch (NoSuchElementException e) {
usage("Option " + arg + " needs argument");
}
mJava = java;
}
}
public static void main(final String[] args) {
final Options options = new Options(args);
final JarFile jar = JarUtils.getJarFile(MakeKeyboardText.class);
final MoreKeysResources resources = new MoreKeysResources(jar);
resources.writeToJava(options.mJava);
}
}

View File

@ -1,255 +0,0 @@
/*
* 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 org.futo.inputmethod.keyboard.tools;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.TreeMap;
import java.util.jar.JarFile;
public class MoreKeysResources {
private static final String TEXT_RESOURCE_NAME = "donottranslate-more-keys.xml";
private static final String JAVA_TEMPLATE = "KeyboardTextsTable.tmpl";
private static final String MARK_NAMES = "@NAMES@";
private static final String MARK_DEFAULT_TEXTS = "@DEFAULT_TEXTS@";
private static final String MARK_TEXTS = "@TEXTS@";
private static final String TEXTS_ARRAY_NAME_PREFIX = "TEXTS_";
private static final String MARK_LOCALES_AND_TEXTS = "@LOCALES_AND_TEXTS@";
private static final String EMPTY_STRING_VAR = "EMPTY";
private final JarFile mJar;
// String resources maps sorted by its language. The language is determined from the jar entry
// name by calling {@link JarUtils#getLocaleFromEntryName(String)}.
private final TreeMap<String, StringResourceMap> mResourcesMap = new TreeMap<>();
// Default string resources map.
private final StringResourceMap mDefaultResourceMap;
// Histogram of string resource names. This is used to sort {@link #mSortedResourceNames}.
private final HashMap<String, Integer> mNameHistogram = new HashMap<>();
// Sorted string resource names array; Descending order of histogram count.
// The string resource name is specified as an attribute "name" in string resource files.
// The string resource can be accessed by specifying name "!text/<name>"
// via {@link KeyboardTextsSet#getText(String)}.
private final String[] mSortedResourceNames;
public MoreKeysResources(final JarFile jar) {
mJar = jar;
final ArrayList<String> resourceEntryNames = JarUtils.getEntryNameListing(
jar, TEXT_RESOURCE_NAME);
for (final String entryName : resourceEntryNames) {
final StringResourceMap resMap = new StringResourceMap(entryName);
mResourcesMap.put(LocaleUtils.getLocaleCode(resMap.mLocale), resMap);
}
mDefaultResourceMap = mResourcesMap.get(
LocaleUtils.getLocaleCode(LocaleUtils.DEFAULT_LOCALE));
// Initialize name histogram and names list.
final HashMap<String, Integer> nameHistogram = mNameHistogram;
final ArrayList<String> resourceNamesList = new ArrayList<>();
for (final StringResource res : mDefaultResourceMap.getResources()) {
nameHistogram.put(res.mName, 0); // Initialize histogram value.
resourceNamesList.add(res.mName);
}
// Make name histogram.
for (final String locale : mResourcesMap.keySet()) {
final StringResourceMap resMap = mResourcesMap.get(locale);
if (resMap == mDefaultResourceMap) continue;
for (final StringResource res : resMap.getResources()) {
if (!mDefaultResourceMap.contains(res.mName)) {
throw new RuntimeException(res.mName + " in " + locale
+ " doesn't have default resource");
}
final int histogramValue = nameHistogram.get(res.mName);
nameHistogram.put(res.mName, histogramValue + 1);
}
}
// Sort names list.
Collections.sort(resourceNamesList, new Comparator<String>() {
@Override
public int compare(final String leftName, final String rightName) {
final int leftCount = nameHistogram.get(leftName);
final int rightCount = nameHistogram.get(rightName);
// Descending order of histogram count.
if (leftCount > rightCount) return -1;
if (leftCount < rightCount) return 1;
// TODO: Add further criteria to order the same histogram value names to be able to
// minimize footprints of string resources arrays.
return 0;
}
});
mSortedResourceNames = resourceNamesList.toArray(new String[resourceNamesList.size()]);
}
public void writeToJava(final String outDir) {
final ArrayList<String> list = JarUtils.getEntryNameListing(mJar, JAVA_TEMPLATE);
if (list.isEmpty()) {
throw new RuntimeException("Can't find java template " + JAVA_TEMPLATE);
}
if (list.size() > 1) {
throw new RuntimeException("Found multiple java template " + JAVA_TEMPLATE);
}
final String template = list.get(0);
final String javaPackage = template.substring(0, template.lastIndexOf('/'));
PrintStream ps = null;
LineNumberReader lnr = null;
try {
if (outDir == null) {
ps = System.out;
} else {
final File outPackage = new File(outDir, javaPackage);
final File outputFile = new File(outPackage,
JAVA_TEMPLATE.replace(".tmpl", ".java"));
outPackage.mkdirs();
ps = new PrintStream(outputFile, "UTF-8");
}
lnr = new LineNumberReader(new InputStreamReader(JarUtils.openResource(template)));
inflateTemplate(lnr, ps);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
JarUtils.close(lnr);
JarUtils.close(ps);
}
}
private void inflateTemplate(final LineNumberReader in, final PrintStream out)
throws IOException {
String line;
while ((line = in.readLine()) != null) {
if (line.contains(MARK_NAMES)) {
dumpNames(out);
} else if (line.contains(MARK_DEFAULT_TEXTS)) {
dumpDefaultTexts(out);
} else if (line.contains(MARK_TEXTS)) {
dumpTexts(out);
} else if (line.contains(MARK_LOCALES_AND_TEXTS)) {
dumpLocalesMap(out);
} else {
out.println(line);
}
}
}
private void dumpNames(final PrintStream out) {
final int namesCount = mSortedResourceNames.length;
for (int index = 0; index < namesCount; index++) {
final String name = mSortedResourceNames[index];
final int histogramValue = mNameHistogram.get(name);
out.format(" /* %3d:%2d */ \"%s\",\n", index, histogramValue, name);
}
}
private void dumpDefaultTexts(final PrintStream out) {
final int outputArraySize = dumpTextsInternal(out, mDefaultResourceMap);
mDefaultResourceMap.setOutputArraySize(outputArraySize);
}
private static String getArrayNameForLocale(final Locale locale) {
return TEXTS_ARRAY_NAME_PREFIX + LocaleUtils.getLocaleCode(locale);
}
private void dumpTexts(final PrintStream out) {
for (final StringResourceMap resMap : mResourcesMap.values()) {
final Locale locale = resMap.mLocale;
if (resMap == mDefaultResourceMap) continue;
out.format(" /* Locale %s: %s */\n",
locale, LocaleUtils.getLocaleDisplayName(locale));
out.format(" private static final String[] " + getArrayNameForLocale(locale)
+ " = {\n");
final int outputArraySize = dumpTextsInternal(out, resMap);
resMap.setOutputArraySize(outputArraySize);
out.format(" };\n\n");
}
}
private void dumpLocalesMap(final PrintStream out) {
for (final StringResourceMap resMap : mResourcesMap.values()) {
final Locale locale = resMap.mLocale;
final String localeStr = LocaleUtils.getLocaleCode(locale);
final String localeToDump = (locale == LocaleUtils.DEFAULT_LOCALE)
? String.format("\"%s\"", localeStr)
: String.format("\"%s\"%s", localeStr, " ".substring(localeStr.length()));
out.format(" %s, %-12s /* %3d/%3d %s */\n",
localeToDump, getArrayNameForLocale(locale) + ",",
resMap.getResources().size(), resMap.getOutputArraySize(),
LocaleUtils.getLocaleDisplayName(locale));
}
}
private int dumpTextsInternal(final PrintStream out, final StringResourceMap resMap) {
final ArrayInitializerFormatter formatter =
new ArrayInitializerFormatter(out, 100, " ", mSortedResourceNames);
int outputArraySize = 0;
boolean successiveNull = false;
final int namesCount = mSortedResourceNames.length;
for (int index = 0; index < namesCount; index++) {
final String name = mSortedResourceNames[index];
final StringResource res = resMap.get(name);
if (res != null) {
// TODO: Check whether the resource value is equal to the default.
if (res.mComment != null) {
formatter.outCommentLines(addPrefix(" // ", res. mComment));
}
final String escaped = escapeNonAscii(res.mValue);
if (escaped.length() == 0) {
formatter.outElement(EMPTY_STRING_VAR + ",");
} else {
formatter.outElement(String.format("\"%s\",", escaped));
}
successiveNull = false;
outputArraySize = formatter.getCurrentIndex();
} else {
formatter.outElement("null,");
successiveNull = true;
}
}
if (!successiveNull) {
formatter.flush();
}
return outputArraySize;
}
private static String addPrefix(final String prefix, final String lines) {
final StringBuilder sb = new StringBuilder();
for (final String line : lines.split("\n")) {
sb.append(prefix + line.trim() + "\n");
}
return sb.toString();
}
private static String escapeNonAscii(final String text) {
final StringBuilder sb = new StringBuilder();
final int length = text.length();
for (int i = 0; i < length; i++) {
final char c = text.charAt(i);
if (c >= ' ' && c < 0x7f) {
sb.append(c);
} else {
sb.append(String.format("\\u%04X", (int)c));
}
}
return sb.toString();
}
}

View File

@ -1,29 +0,0 @@
/*
* 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 org.futo.inputmethod.keyboard.tools;
public class StringResource {
public final String mName;
public final String mValue;
public final String mComment;
public StringResource(final String name, final String value, final String comment) {
mName = name;
mValue = value;
mComment = comment;
}
}

View File

@ -1,158 +0,0 @@
/*
* 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 org.futo.inputmethod.keyboard.tools;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.DefaultHandler2;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class StringResourceMap {
// Locale of this string resource map.
public final Locale mLocale;
// String resource list.
private final List<StringResource> mResources;
// Name to string resource map.
private final Map<String, StringResource> mResourcesMap;
// The length of String[] that is created from this {@link StringResourceMap}. The length is
// calculated in {@link MoreKeysResources#dumpTexts(OutputStream)} and recorded by
// {@link #setOutputArraySize(int)}. The recorded length is used as a part of comment by
// {@link MoreKeysResources#dumpLocaleMap(OutputStream)} via {@link #getOutputArraySize()}.
private int mOutputArraySize;
public StringResourceMap(final String jarEntryName) {
mLocale = JarUtils.getLocaleFromEntryName(jarEntryName);
final StringResourceHandler handler = new StringResourceHandler();
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
final InputStream stream = JarUtils.openResource(jarEntryName);
try {
final SAXParser parser = factory.newSAXParser();
// In order to get comment tag.
parser.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
parser.parse(stream, handler);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (SAXParseException e) {
throw new RuntimeException(e.getMessage() + " at line " + e.getLineNumber()
+ ", column " + e.getColumnNumber(), e);
} catch (SAXException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
JarUtils.close(stream);
}
mResources = Collections.unmodifiableList(handler.mResources);
final HashMap<String, StringResource> map = new HashMap<>();
for (final StringResource res : mResources) {
map.put(res.mName, res);
}
mResourcesMap = map;
}
public List<StringResource> getResources() {
return mResources;
}
public boolean contains(final String name) {
return mResourcesMap.containsKey(name);
}
public StringResource get(final String name) {
return mResourcesMap.get(name);
}
public void setOutputArraySize(final int arraySize) {
mOutputArraySize = arraySize;
}
public int getOutputArraySize() {
return mOutputArraySize;
}
static class StringResourceHandler extends DefaultHandler2 {
private static final String TAG_RESOURCES = "resources";
private static final String TAG_STRING = "string";
private static final String ATTR_NAME = "name";
final ArrayList<StringResource> mResources = new ArrayList<>();
private String mName;
private final StringBuilder mValue = new StringBuilder();
private final StringBuilder mComment = new StringBuilder();
private void init() {
mName = null;
mComment.setLength(0);
}
@Override
public void comment(char[] ch, int start, int length) {
mComment.append(ch, start, length);
if (ch[start + length - 1] != '\n') {
mComment.append('\n');
}
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attr) {
if (TAG_RESOURCES.equals(localName)) {
init();
} else if (TAG_STRING.equals(localName)) {
mName = attr.getValue(ATTR_NAME);
mValue.setLength(0);
}
}
@Override
public void characters(char[] ch, int start, int length) {
mValue.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (TAG_STRING.equals(localName)) {
if (mName == null)
throw new SAXException(TAG_STRING + " doesn't have name");
final String comment = mComment.length() > 0 ? mComment.toString() : null;
String value = mValue.toString();
if (value.startsWith("\"") && value.endsWith("\"")) {
// Trim surroundings double quote.
value = value.substring(1, value.length() - 1);
}
mResources.add(new StringResource(mName, value, comment));
init();
}
}
}
}