abouttreesummaryrefslogcommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/make-apk.yml4
-rw-r--r--.gitmodules3
-rw-r--r--AndroidManifest.xml8
-rw-r--r--build.gradle.kts9
-rw-r--r--gen_method_xml.py63
-rw-r--r--res/drawable/ic_delete.xml2
-rw-r--r--res/drawable/ic_download.xml2
-rw-r--r--res/layout/candidates_status_no_dict.xml2
-rw-r--r--res/layout/dictionaries_activity.xml7
-rw-r--r--res/layout/dictionary_download_item.xml6
-rw-r--r--res/layout/launcher_activity.xml1
-rw-r--r--res/values/dictionaries.xml237
-rw-r--r--res/values/strings.xml4
-rw-r--r--res/values/styles.xml33
-rw-r--r--res/xml/method.xml134
-rw-r--r--shell.nix2
-rw-r--r--srcs/juloo.keyboard2/Config.java18
-rw-r--r--srcs/juloo.keyboard2/DeviceLocales.java2
-rw-r--r--srcs/juloo.keyboard2/KeyEventHandler.java4
-rw-r--r--srcs/juloo.keyboard2/Keyboard2.java45
-rw-r--r--srcs/juloo.keyboard2/LauncherActivity.java7
-rw-r--r--srcs/juloo.keyboard2/Utils.java12
-rw-r--r--srcs/juloo.keyboard2/dict/Dictionaries.java149
-rw-r--r--srcs/juloo.keyboard2/dict/DictionariesActivity.java15
-rw-r--r--srcs/juloo.keyboard2/dict/DictionaryListView.java191
-rw-r--r--srcs/juloo.keyboard2/dict/SupportedDictionaries.java33
-rw-r--r--srcs/juloo.keyboard2/suggestions/CandidatesView.java2
-rw-r--r--srcs/juloo.keyboard2/suggestions/Suggestions.java27
-rw-r--r--vendor/Android.mk12
m---------vendor/cdict0
30 files changed, 925 insertions, 109 deletions
diff --git a/.github/workflows/make-apk.yml b/.github/workflows/make-apk.yml
index c7c7c5b..26fd7fd 100644
--- a/.github/workflows/make-apk.yml
+++ b/.github/workflows/make-apk.yml
@@ -10,7 +10,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
+ with:
+ submodules: true
- name: Restore debug keystore from GitHub Secrets
run: |
# Check if exist and use the secret named DEBUG_KEYSTORE
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..364e005
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "vendor/cdict"]
+ path = vendor/cdict
+ url = https://github.com/Julow/cdict
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index fb47a5f..95d80b9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false">
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:label="@string/app_name" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:hardwareAccelerated="false">
<service android:name="juloo.keyboard2.Keyboard2" android:label="@string/app_name" android:permission="android.permission.BIND_INPUT_METHOD" android:exported="true" android:directBootAware="true">
@@ -23,6 +25,12 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
+
+ <activity android:name="juloo.keyboard2.dict.DictionariesActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ </intent-filter>
+ </activity>
</application>
<!-- To query enabled input methods for voice IME detection -->
diff --git a/build.gradle.kts b/build.gradle.kts
index e111ac8..782b8db 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -27,7 +27,7 @@ android {
sourceSets {
named("main") {
manifest.srcFile("AndroidManifest.xml")
- java.srcDirs("srcs/juloo.keyboard2")
+ java.srcDirs("srcs/juloo.keyboard2", "vendor/cdict/java/juloo.cdict")
res.srcDirs("res", "build/generated-resources")
assets.srcDirs("assets")
}
@@ -37,6 +37,12 @@ android {
}
}
+ externalNativeBuild {
+ ndkBuild {
+ path = file("vendor/Android.mk")
+ }
+ }
+
signingConfigs {
// Debug builds will always be signed. If no environment variables are set, a default
// keystore will be initialized by the task initDebugKeystore and used. This keystore
@@ -116,6 +122,7 @@ val genLayoutsList by tasks.registering(Exec::class) {
val genMethodXml by tasks.registering(Exec::class) {
val out = projectDir.resolve("res/xml/method.xml")
inputs.file(projectDir.resolve("gen_method_xml.py"))
+ inputs.file(projectDir.resolve("res/values/dictionaries.xml"))
outputs.file(out)
doFirst { println("\nGenerating res/xml/method.xml") }
doFirst { standardOutput = FileOutputStream(out) }
diff --git a/gen_method_xml.py b/gen_method_xml.py
index 3b1962f..c01f212 100644
--- a/gen_method_xml.py
+++ b/gen_method_xml.py
@@ -1,3 +1,4 @@
+import xml.etree.ElementTree as ET
import itertools as it
# This script generates res/xml/method.xml.
@@ -78,37 +79,69 @@ LOCALES = [
]
# The locale that is at the beginning of the list
-DEFAULT_LOCALE = loc("en", "latin", "latn_qwerty_us", tag="en")
+DEFAULT_LOCALE = loc("en", "latin", "latn_qwerty_us", tag="en", dictionary="en_US")
-def loc_to_subtype(loc):
+def parse_dictionaries():
+ tree = ET.parse("res/values/dictionaries.xml")
+ root = tree.getroot()
+ return set(( it.text for it in root.findall('*[@name="dictionaries_locale"]/item') ))
+
+# Available dictionares of the form "de" or "de_CH".
+available_dictionaries = parse_dictionaries()
+
+def subtype_elem(root, loc):
tag = loc["tag"].replace("_", "-")
extra_keys = ",extra_keys=" + loc["extra_keys"] if "extra_keys" in loc else ""
- return f'<subtype android:label="%s" android:languageTag="{tag}" android:imeSubtypeLocale="{loc["name"]}" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script={loc["script"]},default_layout={loc["default_layout"]}{extra_keys}"/>'
+ dictionaries = ",dictionary=" + loc["dictionary"] if loc["dictionary"] != None else ""
+ extra_value = f'script={loc["script"]},default_layout={loc["default_layout"]}{dictionaries}{extra_keys}'
+ ET.SubElement(root, "subtype", attrib={
+ "android:label": "%s",
+ "android:languageTag": tag,
+ "android:imeSubtypeLocale": loc["name"],
+ "android:imeSubtypeMode": "keyboard",
+ "android:isAsciiCapable": "true",
+ "android:imeSubtypeExtraValue": extra_value
+ })
-# Return locales in sorted order with the 'tag' item added.
-def compute_tags():
+# Return locales in sorted order with the "tag" and "dictionary" attributes
+# added.
+def compute_attrs():
+ locales_grouped = {} # Locales grouped by language tag
def lang(loc):
return loc["name"].split("_")[0]
- locales_grouped = { k: list(v) for k, v in it.groupby(sorted(LOCALES, key=lang), lang) }
+ for loc in LOCALES:
+ locales_grouped.setdefault(lang(loc), []).append(loc)
def tag(loc):
if "tag" in loc: return loc["tag"]
l = lang(loc)
if loc["name"] == f"{l}_{l.upper()}": return l # Locales like "fr_FR"
# Return a short tag when it's not shared between several locales
return l if len(locales_grouped[l]) == 1 else loc["name"]
- return [ dict(tag=tag(loc), **loc) for loc in LOCALES ]
+ def dictionary(loc):
+ if loc["name"] in available_dictionaries: return loc["name"]
+ l = lang(loc)
+ if l in available_dictionaries: return l
+ return None
+ def add_attrs(loc):
+ return dict(tag=tag(loc), dictionary=dictionary(loc), **loc)
+ return map(add_attrs, LOCALES)
def gen():
- locales = compute_tags()
- print(f"""<?xml version="1.0" encoding="utf-8"?>
-<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
- <!-- This file is automatically generated. DO NOT EDIT.
+ locales = compute_attrs()
+ root = ET.Element("input-method", attrib={
+ "xmlns:android": "http://schemas.android.com/apk/res/android",
+ "android:settingsActivity": "juloo.keyboard2.SettingsActivity",
+ "android:supportsSwitchingToNextInputMethod": "true",
+ })
+ root.append(ET.Comment(text=""" This file is automatically generated. DO NOT EDIT.
Locales definitions should go into 'gen_method_xml.py'.
Update this file with 'gradle test'.
- -->
- {loc_to_subtype(DEFAULT_LOCALE)}
- {"\n ".join(sorted(map(loc_to_subtype, locales)))}
-</input-method>""")
+ """))
+ subtype_elem(root, DEFAULT_LOCALE)
+ for loc in sorted(locales, key=lambda loc: loc["name"]):
+ subtype_elem(root, loc)
+ ET.indent(root)
+ print(ET.tostring(root, encoding="utf-8", xml_declaration=True).decode("UTF-8"))
gen()
diff --git a/res/drawable/ic_delete.xml b/res/drawable/ic_delete.xml
index 5b69d0b..08a5f71 100644
--- a/res/drawable/ic_delete.xml
+++ b/res/drawable/ic_delete.xml
@@ -1 +1 @@
-<!-- drawable/delete.xml --><vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"><path android:fillColor="#000000" android:pathData="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" /></vector> \ No newline at end of file
+<!-- drawable/delete.xml --><vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"><path android:fillColor="#000000" android:pathData="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" /></vector>
diff --git a/res/drawable/ic_download.xml b/res/drawable/ic_download.xml
new file mode 100644
index 0000000..1fb7e98
--- /dev/null
+++ b/res/drawable/ic_download.xml
@@ -0,0 +1,2 @@
+<!-- From https://pictogrammers.com/library/mdi/icon/download/ -->
+<!-- drawable/download.xml --><vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"><path android:fillColor="#000000" android:pathData="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /></vector>
diff --git a/res/layout/candidates_status_no_dict.xml b/res/layout/candidates_status_no_dict.xml
index 6ba20b9..8bd1e37 100644
--- a/res/layout/candidates_status_no_dict.xml
+++ b/res/layout/candidates_status_no_dict.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/candidates_status">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/candidates_status_no_dict"/>
- <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/candidates_status_install"/>
+ <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/candidates_status_install" android:onClick="launch_dictionaries_activity"/>
</LinearLayout>
diff --git a/res/layout/dictionaries_activity.xml b/res/layout/dictionaries_activity.xml
new file mode 100644
index 0000000..96b1bcb
--- /dev/null
+++ b/res/layout/dictionaries_activity.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:fitsSystemWindows="true">
+ <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
+ <TextView style="@style/paragraph" android:text="@string/dictionaries_from_internet"/>
+ <juloo.keyboard2.dict.DictionaryListView style="@style/dictionary_list_view"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/dictionary_download_item.xml b/res/layout/dictionary_download_item.xml
new file mode 100644
index 0000000..e6dd3c6
--- /dev/null
+++ b/res/layout/dictionary_download_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/dictionary_download_item">
+ <TextView android:id="@+id/dictionary_download_locale" style="@style/dictionary_download_locale"/>
+ <TextView android:id="@+id/dictionary_download_size" style="@style/dictionary_download_size"/>
+ <View android:id="@+id/dictionary_download_button" style="@style/dictionary_download_button" android:background="@drawable/ic_download"/>
+</LinearLayout>
diff --git a/res/layout/launcher_activity.xml b/res/layout/launcher_activity.xml
index 20df09a..b4c23ab 100644
--- a/res/layout/launcher_activity.xml
+++ b/res/layout/launcher_activity.xml
@@ -4,6 +4,7 @@
<TextView style="@style/paragraph" android:text="@string/launcher_description"/>
<Button style="@style/paragraph" android:text="@string/launcher_button_imesettings" android:onClick="launch_imesettings" android:layout_width="wrap_content"/>
<Button style="@style/paragraph" android:text="@string/launcher_button_imepicker" android:onClick="launch_imepicker" android:layout_width="wrap_content"/>
+ <Button style="@style/paragraph" android:text="@string/launcher_button_dictionaries" android:onClick="launch_dictionaries_activity" android:layout_width="wrap_content"/>
<LinearLayout style="@style/anim_box">
<ImageView style="@style/anim" android:id="@+id/launcher_anim_swipe" android:background="@drawable/doc_key_u" android:src="@drawable/doc_anim_swipe"/>
<TextView style="@style/anim_text" android:text="@string/launcher_anim_7"/>
diff --git a/res/values/dictionaries.xml b/res/values/dictionaries.xml
new file mode 100644
index 0000000..f3e73fd
--- /dev/null
+++ b/res/values/dictionaries.xml
@@ -0,0 +1,237 @@
+<?xml version='1.0' encoding='utf-8'?>
+<resources>
+ <string name="dict_name_ar">Arabic</string>
+ <string name="dict_name_as">Assamese</string>
+ <string name="dict_name_be">Belarusian</string>
+ <string name="dict_name_bg">Bulgarian</string>
+ <string name="dict_name_bn">Bangla</string>
+ <string name="dict_name_bs">Bosnian</string>
+ <string name="dict_name_ca">Catalan</string>
+ <string name="dict_name_cs">Czech</string>
+ <string name="dict_name_da">Danish</string>
+ <string name="dict_name_de">German</string>
+ <string name="dict_name_de_ch">German (Switzerland)</string>
+ <string name="dict_name_el">Greek</string>
+ <string name="dict_name_en_au">English (Australia)</string>
+ <string name="dict_name_en_gb">English (United Kingdom)</string>
+ <string name="dict_name_en_us">English (United States)</string>
+ <string name="dict_name_es">Spanish</string>
+ <string name="dict_name_eu">Basque</string>
+ <string name="dict_name_fi">Finnish</string>
+ <string name="dict_name_fr">French</string>
+ <string name="dict_name_gl">Galician</string>
+ <string name="dict_name_gu">Gujarati</string>
+ <string name="dict_name_hi">Hindi</string>
+ <string name="dict_name_hr">Croatian</string>
+ <string name="dict_name_hu">Hungarian</string>
+ <string name="dict_name_hy">Armenian</string>
+ <string name="dict_name_it">Italian</string>
+ <string name="dict_name_iw">Hebrew</string>
+ <string name="dict_name_ka">Georgian</string>
+ <string name="dict_name_km">Khmer</string>
+ <string name="dict_name_kn">Kannada</string>
+ <string name="dict_name_lb">Luxembourgish</string>
+ <string name="dict_name_lt">Lithuanian</string>
+ <string name="dict_name_lv">Latvian</string>
+ <string name="dict_name_mai">Maithili</string>
+ <string name="dict_name_ml">Malayalam</string>
+ <string name="dict_name_mr">Marathi</string>
+ <string name="dict_name_nb">Norwegian Bokmål</string>
+ <string name="dict_name_nl">Dutch</string>
+ <string name="dict_name_or">Odia</string>
+ <string name="dict_name_pa">Punjabi</string>
+ <string name="dict_name_pl">Polish</string>
+ <string name="dict_name_pt_br">Portuguese (Brazil)</string>
+ <string name="dict_name_pt_pt">Portuguese (Portugal)</string>
+ <string name="dict_name_ro">Romanian</string>
+ <string name="dict_name_ru">Russian</string>
+ <string name="dict_name_sa">Sanskrit</string>
+ <string name="dict_name_sat">Santali</string>
+ <string name="dict_name_sd">Sindhi</string>
+ <string name="dict_name_sl">Slovenian</string>
+ <string name="dict_name_sr">Serbian</string>
+ <string name="dict_name_sv">Swedish</string>
+ <string name="dict_name_ta">Tamil</string>
+ <string name="dict_name_te">Telugu</string>
+ <string name="dict_name_tr">Turkish</string>
+ <string name="dict_name_uk">Ukrainian</string>
+ <string name="dict_name_ur">Urdu</string>
+ <string name="dict_name_zgh">Standard Moroccan Tamazight</string>
+ <string-array name="dictionaries_locale">
+ <item>ar</item>
+ <item>as</item>
+ <item>be</item>
+ <item>bg</item>
+ <item>bn</item>
+ <item>bs</item>
+ <item>ca</item>
+ <item>cs</item>
+ <item>da</item>
+ <item>de</item>
+ <item>de_CH</item>
+ <item>el</item>
+ <item>en_AU</item>
+ <item>en_GB</item>
+ <item>en_US</item>
+ <item>es</item>
+ <item>eu</item>
+ <item>fi</item>
+ <item>fr</item>
+ <item>gl</item>
+ <item>gu</item>
+ <item>hi</item>
+ <item>hr</item>
+ <item>hu</item>
+ <item>hy</item>
+ <item>it</item>
+ <item>iw</item>
+ <item>ka</item>
+ <item>km</item>
+ <item>kn</item>
+ <item>lb</item>
+ <item>lt</item>
+ <item>lv</item>
+ <item>mai</item>
+ <item>ml</item>
+ <item>mr</item>
+ <item>nb</item>
+ <item>nl</item>
+ <item>or</item>
+ <item>pa</item>
+ <item>pl</item>
+ <item>pt_BR</item>
+ <item>pt_PT</item>
+ <item>ro</item>
+ <item>ru</item>
+ <item>sa</item>
+ <item>sat</item>
+ <item>sd</item>
+ <item>sl</item>
+ <item>sr</item>
+ <item>sv</item>
+ <item>ta</item>
+ <item>te</item>
+ <item>tr</item>
+ <item>uk</item>
+ <item>ur</item>
+ <item>zgh</item>
+ </string-array>
+ <string-array name="dictionaries_name">
+ <item>@string/dict_name_ar</item>
+ <item>@string/dict_name_as</item>
+ <item>@string/dict_name_be</item>
+ <item>@string/dict_name_bg</item>
+ <item>@string/dict_name_bn</item>
+ <item>@string/dict_name_bs</item>
+ <item>@string/dict_name_ca</item>
+ <item>@string/dict_name_cs</item>
+ <item>@string/dict_name_da</item>
+ <item>@string/dict_name_de</item>
+ <item>@string/dict_name_de_ch</item>
+ <item>@string/dict_name_el</item>
+ <item>@string/dict_name_en_au</item>
+ <item>@string/dict_name_en_gb</item>
+ <item>@string/dict_name_en_us</item>
+ <item>@string/dict_name_es</item>
+ <item>@string/dict_name_eu</item>
+ <item>@string/dict_name_fi</item>
+ <item>@string/dict_name_fr</item>
+ <item>@string/dict_name_gl</item>
+ <item>@string/dict_name_gu</item>
+ <item>@string/dict_name_hi</item>
+ <item>@string/dict_name_hr</item>
+ <item>@string/dict_name_hu</item>
+ <item>@string/dict_name_hy</item>
+ <item>@string/dict_name_it</item>
+ <item>@string/dict_name_iw</item>
+ <item>@string/dict_name_ka</item>
+ <item>@string/dict_name_km</item>
+ <item>@string/dict_name_kn</item>
+ <item>@string/dict_name_lb</item>
+ <item>@string/dict_name_lt</item>
+ <item>@string/dict_name_lv</item>
+ <item>@string/dict_name_mai</item>
+ <item>@string/dict_name_ml</item>
+ <item>@string/dict_name_mr</item>
+ <item>@string/dict_name_nb</item>
+ <item>@string/dict_name_nl</item>
+ <item>@string/dict_name_or</item>
+ <item>@string/dict_name_pa</item>
+ <item>@string/dict_name_pl</item>
+ <item>@string/dict_name_pt_br</item>
+ <item>@string/dict_name_pt_pt</item>
+ <item>@string/dict_name_ro</item>
+ <item>@string/dict_name_ru</item>
+ <item>@string/dict_name_sa</item>
+ <item>@string/dict_name_sat</item>
+ <item>@string/dict_name_sd</item>
+ <item>@string/dict_name_sl</item>
+ <item>@string/dict_name_sr</item>
+ <item>@string/dict_name_sv</item>
+ <item>@string/dict_name_ta</item>
+ <item>@string/dict_name_te</item>
+ <item>@string/dict_name_tr</item>
+ <item>@string/dict_name_uk</item>
+ <item>@string/dict_name_ur</item>
+ <item>@string/dict_name_zgh</item>
+ </string-array>
+ <integer-array name="dictionaries_size">
+ <item>455658</item>
+ <item>307451</item>
+ <item>1745968</item>
+ <item>347735</item>
+ <item>301586</item>
+ <item>481783</item>
+ <item>335099</item>
+ <item>657214</item>
+ <item>933060</item>
+ <item>1071580</item>
+ <item>1075177</item>
+ <item>964195</item>
+ <item>645068</item>
+ <item>644719</item>
+ <item>650605</item>
+ <item>635119</item>
+ <item>359849</item>
+ <item>1003794</item>
+ <item>871636</item>
+ <item>240926</item>
+ <item>279333</item>
+ <item>301928</item>
+ <item>727487</item>
+ <item>331818</item>
+ <item>948362</item>
+ <item>696974</item>
+ <item>352933</item>
+ <item>488139</item>
+ <item>263411</item>
+ <item>286588</item>
+ <item>331897</item>
+ <item>736799</item>
+ <item>854603</item>
+ <item>333644</item>
+ <item>354875</item>
+ <item>301259</item>
+ <item>776481</item>
+ <item>926933</item>
+ <item>357107</item>
+ <item>107120</item>
+ <item>740895</item>
+ <item>705536</item>
+ <item>996904</item>
+ <item>1421447</item>
+ <item>907625</item>
+ <item>342293</item>
+ <item>322250</item>
+ <item>256078</item>
+ <item>228729</item>
+ <item>740293</item>
+ <item>916845</item>
+ <item>297338</item>
+ <item>304295</item>
+ <item>690598</item>
+ <item>1179318</item>
+ <item>265324</item>
+ <item>628168</item>
+ </integer-array>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e01e98f..d46b828 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -108,6 +108,7 @@
<string name="key_action_send">Send</string>
<string name="launcher_button_imesettings">Enable keyboard</string>
<string name="launcher_button_imepicker">Select keyboard</string>
+ <string name="launcher_button_dictionaries">Install dictionaries</string>
<string name="launcher_description">This application is a virtual keyboard. Go to the system settings by clicking on the button below and enable Unexpected-Keyboard.</string>
<string name="launcher_sourcecode">This is a free and open source application. You can find the source code or report bugs on GitHub.</string>
<string name="launcher_tryhere">After enabling, you can try the keyboard here:</string>
@@ -154,6 +155,9 @@
<string name="pref_clipboard_history_duration_30">At most 30 minutes</string>
<string name="pref_clipboard_history_duration_stop">Until the app stops</string>
<string name="pref_dialog_edit_text">Custom definition</string>
+ <string name="dictionaries_from_internet">Download a dictionary from the Internet</string>
+ <string name="dictionaries_download_success">Dictionary installed</string>
+ <string name="dictionaries_download_failed">Download failed</string>
<string name="candidates_status_no_dict">No dictionary installed</string>
<string name="candidates_status_install">Install</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 5defb7b..6977e00 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -64,7 +64,7 @@
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginVertical">8dp</item>
- <item name="android:layout_marginHorizontal">16dp</item>
+ <item name="android:layout_marginHorizontal">24dp</item>
<item name="android:layout_gravity">center</item>
</style>
<style name="anim">
@@ -90,6 +90,37 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:orientation">horizontal</item>
</style>
+ <!-- Dictionaries activity -->
+ <style name="dictionary_list_view">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginVertical">24dp</item>
+ </style>
+ <style name="dictionary_download_item">
+ <item name="android:orientation">horizontal</item>
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginVertical">8dp</item>
+ <item name="android:gravity">center</item>
+ <item name="android:paddingHorizontal">48dp</item>
+ </style>
+ <style name="dictionary_download_locale">
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+ <style name="dictionary_download_size">
+ <item name="android:layout_weight">0</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginRight">8dp</item>
+ <item name="android:textSize">12sp</item>
+ </style>
+ <style name="dictionary_download_button">
+ <item name="android:layout_width">24dp</item>
+ <item name="android:layout_height">24dp</item>
+ </style>
<style name="appTheme" parent="@android:style/Theme.Material.Light"/>
<style name="settingsTheme" parent="appTheme">
<!-- Setting this in the activity theme so it propagate to nested
diff --git a/res/xml/method.xml b/res/xml/method.xml
index eb5b04b..4778722 100644
--- a/res/xml/method.xml
+++ b/res/xml/method.xml
@@ -1,74 +1,74 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version='1.0' encoding='utf-8'?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="juloo.keyboard2.SettingsActivity" android:supportsSwitchingToNextInputMethod="true">
<!-- This file is automatically generated. DO NOT EDIT.
Locales definitions should go into 'gen_method_xml.py'.
Update this file with 'gradle test'.
-->
- <subtype android:label="%s" android:languageTag="en" android:imeSubtypeLocale="en" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
- <subtype android:label="%s" android:languageTag="ar" android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc_hindu"/>
- <subtype android:label="%s" android:languageTag="ar-TN" android:imeSubtypeLocale="ar_TN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc"/>
- <subtype android:label="%s" android:languageTag="ay" android:imeSubtypeLocale="ay_AM" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=armenian,default_layout=armenian_ph_am"/>
- <subtype android:label="%s" android:languageTag="az" android:imeSubtypeLocale="az_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_az,extra_keys=accent_trema:ü:ö@w|accent_cedille:ç:ş@s|ğ@g|ı@k|ə@l"/>
- <subtype android:label="%s" android:languageTag="be" android:imeSubtypeLocale="be_BY" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_ru,extra_keys=ґ|є|і|ї|ў"/>
- <subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_ueishsht,extra_keys=€"/>
- <subtype android:label="%s" android:languageTag="bn" android:imeSubtypeLocale="bn_BD" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=৳"/>
- <subtype android:label="%s" android:languageTag="cs" android:imeSubtypeLocale="cs_CZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_cz,extra_keys=accent_aigu:á:é:í:ó:ú:ý@d|accent_ring:ů@s|accent_caron:č:ě:ň:ř:š:ž:ď:ť@f"/>
- <subtype android:label="%s" android:languageTag="cy" android:imeSubtypeLocale="cy_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_cy"/>
- <subtype android:label="%s" android:languageTag="da" android:imeSubtypeLocale="da_DK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_da,extra_keys=€|æ|å|ø"/>
- <subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_de,extra_keys=accent_trema:ä:ö:ü@u|ß|€"/>
- <subtype android:label="%s" android:languageTag="de-BE" android:imeSubtypeLocale="de_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€"/>
- <subtype android:label="%s" android:languageTag="el" android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=grek_qwerty,extra_keys=£@l|€"/>
- <subtype android:label="%s" android:languageTag="en-AU" android:imeSubtypeLocale="en_AU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
- <subtype android:label="%s" android:languageTag="en-CA" android:imeSubtypeLocale="en_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
- <subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_gb,extra_keys=£@l"/>
- <subtype android:label="%s" android:languageTag="en-IN" android:imeSubtypeLocale="en_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
- <subtype android:label="%s" android:languageTag="en-NG" android:imeSubtypeLocale="en_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦"/>
- <subtype android:label="%s" android:languageTag="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us"/>
- <subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_es,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_tilde:ñ@n|accent_grave@f|accent_trema@u|€"/>
- <subtype android:label="%s" android:languageTag="et" android:imeSubtypeLocale="et_EE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_et,extra_keys=accent_trema:ä:ö:ü@u|accent_tilde:õ@o|accent_caron:š:ž@s|€"/>
- <subtype android:label="%s" android:languageTag="fa" android:imeSubtypeLocale="fa_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=persian,default_layout=arab_pc_ir"/>
- <subtype android:label="%s" android:languageTag="fr" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è:ù@d|accent_aigu:é@d|accent_circonflexe:â:ê:ô:û@o|accent_cedille:ç@c|accent_trema:ë:ï:ü@l|€"/>
- <subtype android:label="%s" android:languageTag="fr-BE" android:imeSubtypeLocale="fr_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:ê:û@f|accent_cedille:ç@c|accent_trema@u|€"/>
- <subtype android:label="%s" android:languageTag="fr-CA" android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô:û@f|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u"/>
- <subtype android:label="%s" android:languageTag="fr-CH" android:imeSubtypeLocale="fr_CH" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_fr_ch,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô:û@o|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u|€"/>
- <subtype android:label="%s" android:languageTag="ga" android:imeSubtypeLocale="ga_IE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ga,extra_keys=accent_aigu:á:é:í:ó:ú@k|accent_dot_above@l"/>
- <subtype android:label="%s" android:languageTag="ha" android:imeSubtypeLocale="ha_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦|ɓ|ɗ|ƙ|’|ƴ|r̃"/>
- <subtype android:label="%s" android:languageTag="haw" android:imeSubtypeLocale="haw_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_haw,extra_keys=ʻ@l|accent_macron:ā:ē:ī:ō:ū@m"/>
- <subtype android:label="%s" android:languageTag="he" android:imeSubtypeLocale="he_IL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hebrew,default_layout=default_layout=hebr_1_il,extra_keys=₪@r|€"/>
- <subtype android:label="%s" android:languageTag="hi" android:imeSubtypeLocale="hi_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
- <subtype android:label="%s" android:languageTag="hu" android:imeSubtypeLocale="hu_HU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_hu,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_trema:ö:ü@u|accent_ogonek@s|accent_double_aigu:ő:ű@k|€"/>
- <subtype android:label="%s" android:languageTag="ig" android:imeSubtypeLocale="ig_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦|ṅ|ọ|ụ"/>
- <subtype android:label="%s" android:languageTag="is" android:imeSubtypeLocale="is_IS" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_is,extra_keys=ð|þ|æ|accent_trema:ö@o|accent_aigu:á:é:í:ó:ú:ý@d|accent_circonflexe|accent_ring|accent_grave"/>
- <subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=accent_grave:à:è:ì:ò:ù@f|accent_aigu:é:ó@d|accent_circonflexe:î@f|€|ə"/>
- <subtype android:label="%s" android:languageTag="ka" android:imeSubtypeLocale="ka_GE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=georgian_mes"/>
- <subtype android:label="%s" android:languageTag="kk" android:imeSubtypeLocale="kk_KZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_kk"/>
- <subtype android:label="%s" android:languageTag="kn" android:imeSubtypeLocale="kn_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=kannada,default_layout=kann_kannada"/>
- <subtype android:label="%s" android:languageTag="ko" android:imeSubtypeLocale="ko_KR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hangul,default_layout=latn_qwerty_us"/>
- <subtype android:label="%s" android:languageTag="lt" android:imeSubtypeLocale="lt_LT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lt,extra_keys=accent_ogonek:ą:ę:į:ų@s|accent_caron:č:š:ž@f|accent_dot_above:ė@s|accent_macron:ū@o|€"/>
- <subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lv,extra_keys=accent_macron:ā:ē:ī:ū@o|accent_caron:č:š:ž@f|accent_ogonek:ķ:ļ:ņ@s|accent_cedille:ģ@c|€"/>
- <subtype android:label="%s" android:languageTag="mk" android:imeSubtypeLocale="mk" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_lynyertdz_mk,extra_keys=ѕ|ѓ|ќ|ѝ|ѐ|љ|њ|џ|„|“|€"/>
- <subtype android:label="%s" android:languageTag="mn" android:imeSubtypeLocale="mn_MN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_fcuzhen_mn,extra_keys=ү|ө"/>
- <subtype android:label="%s" android:languageTag="mr" android:imeSubtypeLocale="mr_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
- <subtype android:label="%s" android:languageTag="mt" android:imeSubtypeLocale="mt_MT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_mt,extra_keys=accent_grave:à:è:ì:ò:ù|accent_dot_above:ċ:ż:ġ|ħ"/>
- <subtype android:label="%s" android:languageTag="ne" android:imeSubtypeLocale="ne_NE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
- <subtype android:label="%s" android:languageTag="nl" android:imeSubtypeLocale="nl_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€"/>
- <subtype android:label="%s" android:languageTag="no" android:imeSubtypeLocale="no_NO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=€|æ@a|å@a|ø@o|accent_aigu:é:ó@d|accent_grave:è:ò:ù@f|accent_circonflexe:ê:ô@f"/>
- <subtype android:label="%s" android:languageTag="pl" android:imeSubtypeLocale="pl_PL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pl"/>
- <subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pt,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_cedille:ç@c|accent_circonflexe:â:ê:ô@f|accent_grave:à:ò@f|accent_tilde:ã:õ@n|€|ª|º"/>
- <subtype android:label="%s" android:languageTag="ro" android:imeSubtypeLocale="ro_RO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ro,extra_keys=ă|â|î|ș|ț|€|$"/>
- <subtype android:label="%s" android:languageTag="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_ru"/>
- <subtype android:label="%s" android:languageTag="si" android:imeSubtypeLocale="si_LK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=sinhala,default_layout=sinhala_phonetic,extra_keys=₨"/>
- <subtype android:label="%s" android:languageTag="sk" android:imeSubtypeLocale="sk_SK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sk,extra_keys=accent_caron:ě:ř:ž:š:č:ň:ď:ľ:ť@f|accent_ring:ů@s|accent_circonflexe:ô@f|accent_trema:ä:ü:ö@u|accent_aigu:á:é:í:ó:ú:ŕ:ś:ĺ:ý@d"/>
- <subtype android:label="%s" android:languageTag="sq" android:imeSubtypeLocale="sq_AL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sq"/>
- <subtype android:label="%s" android:languageTag="sr" android:imeSubtypeLocale="sr_" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_lynyertz_sr"/>
- <subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_se,extra_keys=accent_aigu:á@d|accent_trema:ä:ö@o|accent_ring:å@s|€"/>
- <subtype android:label="%s" android:languageTag="ta" android:imeSubtypeLocale="ta_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=tamil,default_layout=tamil_default"/>
- <subtype android:label="%s" android:languageTag="tly-AZ" android:imeSubtypeLocale="tly_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tly,extra_keys=á|ú|â|ê|ı|š|ž"/>
- <subtype android:label="%s" android:languageTag="tly-IR" android:imeSubtypeLocale="tly_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=persian,default_layout=arab_hamvaj_tly"/>
- <subtype android:label="%s" android:languageTag="tr" android:imeSubtypeLocale="tr_TR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tr,extra_keys=accent_cedille:ç:ş@c|accent_trema:ö:ü@u|accent_circonflexe:â:î:û@f|₺|ı|ğ"/>
- <subtype android:label="%s" android:languageTag="uk" android:imeSubtypeLocale="uk_UA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_uk,extra_keys=ґ|є|і|ї|₴"/>
- <subtype android:label="%s" android:languageTag="uz" android:imeSubtypeLocale="uz_UZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_uz,extra_keys=ʻ|ʼ"/>
- <subtype android:label="%s" android:languageTag="vi" android:imeSubtypeLocale="vi_VN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_vi"/>
- <subtype android:label="%s" android:languageTag="yo" android:imeSubtypeLocale="yo_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦|ẹ|ọ|ṣ"/>
+ <subtype android:label="%s" android:languageTag="en" android:imeSubtypeLocale="en" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,dictionary=en_US" />
+ <subtype android:label="%s" android:languageTag="ar" android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc_hindu,dictionary=ar" />
+ <subtype android:label="%s" android:languageTag="ar-TN" android:imeSubtypeLocale="ar_TN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=arabic,default_layout=arab_pc,dictionary=ar" />
+ <subtype android:label="%s" android:languageTag="ay" android:imeSubtypeLocale="ay_AM" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=armenian,default_layout=armenian_ph_am" />
+ <subtype android:label="%s" android:languageTag="az" android:imeSubtypeLocale="az_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_az,extra_keys=accent_trema:ü:ö@w|accent_cedille:ç:ş@s|ğ@g|ı@k|ə@l" />
+ <subtype android:label="%s" android:languageTag="be" android:imeSubtypeLocale="be_BY" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_ru,dictionary=be,extra_keys=ґ|є|і|ї|ў" />
+ <subtype android:label="%s" android:languageTag="bg" android:imeSubtypeLocale="bg_BG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_ueishsht,dictionary=bg,extra_keys=€" />
+ <subtype android:label="%s" android:languageTag="bn" android:imeSubtypeLocale="bn_BD" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,dictionary=bn,extra_keys=৳" />
+ <subtype android:label="%s" android:languageTag="cs" android:imeSubtypeLocale="cs_CZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_cz,dictionary=cs,extra_keys=accent_aigu:á:é:í:ó:ú:ý@d|accent_ring:ů@s|accent_caron:č:ě:ň:ř:š:ž:ď:ť@f" />
+ <subtype android:label="%s" android:languageTag="cy" android:imeSubtypeLocale="cy_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_cy" />
+ <subtype android:label="%s" android:languageTag="da" android:imeSubtypeLocale="da_DK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_da,dictionary=da,extra_keys=€|æ|å|ø" />
+ <subtype android:label="%s" android:languageTag="de-BE" android:imeSubtypeLocale="de_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,dictionary=de,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€" />
+ <subtype android:label="%s" android:languageTag="de" android:imeSubtypeLocale="de_DE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_de,dictionary=de,extra_keys=accent_trema:ä:ö:ü@u|ß|€" />
+ <subtype android:label="%s" android:languageTag="el" android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=grek_qwerty,dictionary=el,extra_keys=£@l|€" />
+ <subtype android:label="%s" android:languageTag="en-AU" android:imeSubtypeLocale="en_AU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,dictionary=en_AU" />
+ <subtype android:label="%s" android:languageTag="en-CA" android:imeSubtypeLocale="en_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us" />
+ <subtype android:label="%s" android:languageTag="en-GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_gb,dictionary=en_GB,extra_keys=£@l" />
+ <subtype android:label="%s" android:languageTag="en-IN" android:imeSubtypeLocale="en_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us" />
+ <subtype android:label="%s" android:languageTag="en-NG" android:imeSubtypeLocale="en_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦" />
+ <subtype android:label="%s" android:languageTag="en-US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,dictionary=en_US" />
+ <subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_es,dictionary=es,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_tilde:ñ@n|accent_grave@f|accent_trema@u|€" />
+ <subtype android:label="%s" android:languageTag="et" android:imeSubtypeLocale="et_EE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_et,extra_keys=accent_trema:ä:ö:ü@u|accent_tilde:õ@o|accent_caron:š:ž@s|€" />
+ <subtype android:label="%s" android:languageTag="fa" android:imeSubtypeLocale="fa_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=persian,default_layout=arab_pc_ir" />
+ <subtype android:label="%s" android:languageTag="fr-BE" android:imeSubtypeLocale="fr_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,dictionary=fr,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:ê:û@f|accent_cedille:ç@c|accent_trema@u|€" />
+ <subtype android:label="%s" android:languageTag="fr-CA" android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,dictionary=fr,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô:û@f|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u" />
+ <subtype android:label="%s" android:languageTag="fr-CH" android:imeSubtypeLocale="fr_CH" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_fr_ch,dictionary=fr,extra_keys=accent_grave:à:è:ù@f|accent_aigu:é@d|accent_circonflexe:â:ê:ô:û@o|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@u|€" />
+ <subtype android:label="%s" android:languageTag="fr" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,dictionary=fr,extra_keys=accent_grave:à:è:ù@d|accent_aigu:é@d|accent_circonflexe:â:ê:ô:û@o|accent_cedille:ç@c|accent_trema:ë:ï:ü@l|€" />
+ <subtype android:label="%s" android:languageTag="ga" android:imeSubtypeLocale="ga_IE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ga,extra_keys=accent_aigu:á:é:í:ó:ú@k|accent_dot_above@l" />
+ <subtype android:label="%s" android:languageTag="ha" android:imeSubtypeLocale="ha_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦|ɓ|ɗ|ƙ|’|ƴ|r̃" />
+ <subtype android:label="%s" android:languageTag="haw" android:imeSubtypeLocale="haw_US" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_haw,extra_keys=ʻ@l|accent_macron:ā:ē:ī:ō:ū@m" />
+ <subtype android:label="%s" android:languageTag="he" android:imeSubtypeLocale="he_IL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hebrew,default_layout=default_layout=hebr_1_il,extra_keys=₪@r|€" />
+ <subtype android:label="%s" android:languageTag="hi" android:imeSubtypeLocale="hi_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,dictionary=hi,extra_keys=₹" />
+ <subtype android:label="%s" android:languageTag="hu" android:imeSubtypeLocale="hu_HU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_hu,dictionary=hu,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_trema:ö:ü@u|accent_ogonek@s|accent_double_aigu:ő:ű@k|€" />
+ <subtype android:label="%s" android:languageTag="ig" android:imeSubtypeLocale="ig_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦|ṅ|ọ|ụ" />
+ <subtype android:label="%s" android:languageTag="is" android:imeSubtypeLocale="is_IS" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_is,extra_keys=ð|þ|æ|accent_trema:ö@o|accent_aigu:á:é:í:ó:ú:ý@d|accent_circonflexe|accent_ring|accent_grave" />
+ <subtype android:label="%s" android:languageTag="it" android:imeSubtypeLocale="it_IT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,dictionary=it,extra_keys=accent_grave:à:è:ì:ò:ù@f|accent_aigu:é:ó@d|accent_circonflexe:î@f|€|ə" />
+ <subtype android:label="%s" android:languageTag="ka" android:imeSubtypeLocale="ka_GE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=georgian_mes,dictionary=ka" />
+ <subtype android:label="%s" android:languageTag="kk" android:imeSubtypeLocale="kk_KZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_kk" />
+ <subtype android:label="%s" android:languageTag="kn" android:imeSubtypeLocale="kn_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=kannada,default_layout=kann_kannada,dictionary=kn" />
+ <subtype android:label="%s" android:languageTag="ko" android:imeSubtypeLocale="ko_KR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hangul,default_layout=latn_qwerty_us" />
+ <subtype android:label="%s" android:languageTag="lt" android:imeSubtypeLocale="lt_LT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lt,dictionary=lt,extra_keys=accent_ogonek:ą:ę:į:ų@s|accent_caron:č:š:ž@f|accent_dot_above:ė@s|accent_macron:ū@o|€" />
+ <subtype android:label="%s" android:languageTag="lv" android:imeSubtypeLocale="lv_LV" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_lv,dictionary=lv,extra_keys=accent_macron:ā:ē:ī:ū@o|accent_caron:č:š:ž@f|accent_ogonek:ķ:ļ:ņ@s|accent_cedille:ģ@c|€" />
+ <subtype android:label="%s" android:languageTag="mk" android:imeSubtypeLocale="mk" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_lynyertdz_mk,extra_keys=ѕ|ѓ|ќ|ѝ|ѐ|љ|њ|џ|„|“|€" />
+ <subtype android:label="%s" android:languageTag="mn" android:imeSubtypeLocale="mn_MN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_fcuzhen_mn,extra_keys=ү|ө" />
+ <subtype android:label="%s" android:languageTag="mr" android:imeSubtypeLocale="mr_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,dictionary=mr,extra_keys=₹" />
+ <subtype android:label="%s" android:languageTag="mt" android:imeSubtypeLocale="mt_MT" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_mt,extra_keys=accent_grave:à:è:ì:ò:ù|accent_dot_above:ċ:ż:ġ|ħ" />
+ <subtype android:label="%s" android:languageTag="ne" android:imeSubtypeLocale="ne_NE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹" />
+ <subtype android:label="%s" android:languageTag="nl" android:imeSubtypeLocale="nl_BE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_be,dictionary=nl,extra_keys=accent_grave:è@f|accent_aigu:á:é:í:ó:ú:ý:j́@d|accent_circonflexe:ê@f|accent_cedille:ç@c|accent_trema@u|€" />
+ <subtype android:label="%s" android:languageTag="no" android:imeSubtypeLocale="no_NO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=€|æ@a|å@a|ø@o|accent_aigu:é:ó@d|accent_grave:è:ò:ù@f|accent_circonflexe:ê:ô@f" />
+ <subtype android:label="%s" android:languageTag="pl" android:imeSubtypeLocale="pl_PL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pl,dictionary=pl" />
+ <subtype android:label="%s" android:languageTag="pt" android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_pt,dictionary=pt_BR,extra_keys=accent_aigu:á:é:í:ó:ú@d|accent_cedille:ç@c|accent_circonflexe:â:ê:ô@f|accent_grave:à:ò@f|accent_tilde:ã:õ@n|€|ª|º" />
+ <subtype android:label="%s" android:languageTag="ro" android:imeSubtypeLocale="ro_RO" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_ro,dictionary=ro,extra_keys=ă|â|î|ș|ț|€|$" />
+ <subtype android:label="%s" android:languageTag="ru" android:imeSubtypeLocale="ru_RU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_jcuken_ru,dictionary=ru" />
+ <subtype android:label="%s" android:languageTag="si" android:imeSubtypeLocale="si_LK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=sinhala,default_layout=sinhala_phonetic,extra_keys=₨" />
+ <subtype android:label="%s" android:languageTag="sk" android:imeSubtypeLocale="sk_SK" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sk,extra_keys=accent_caron:ě:ř:ž:š:č:ň:ď:ľ:ť@f|accent_ring:ů@s|accent_circonflexe:ô@f|accent_trema:ä:ü:ö@u|accent_aigu:á:é:í:ó:ú:ŕ:ś:ĺ:ý@d" />
+ <subtype android:label="%s" android:languageTag="sq" android:imeSubtypeLocale="sq_AL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_sq" />
+ <subtype android:label="%s" android:languageTag="sr" android:imeSubtypeLocale="sr_" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=cyrl_lynyertz_sr,dictionary=sr" />
+ <subtype android:label="%s" android:languageTag="sv" android:imeSubtypeLocale="sv_SE" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_se,dictionary=sv,extra_keys=accent_aigu:á@d|accent_trema:ä:ö@o|accent_ring:å@s|€" />
+ <subtype android:label="%s" android:languageTag="ta" android:imeSubtypeLocale="ta_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=tamil,default_layout=tamil_default,dictionary=ta" />
+ <subtype android:label="%s" android:languageTag="tly-AZ" android:imeSubtypeLocale="tly_AZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tly,extra_keys=á|ú|â|ê|ı|š|ž" />
+ <subtype android:label="%s" android:languageTag="tly-IR" android:imeSubtypeLocale="tly_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=persian,default_layout=arab_hamvaj_tly" />
+ <subtype android:label="%s" android:languageTag="tr" android:imeSubtypeLocale="tr_TR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_tr,dictionary=tr,extra_keys=accent_cedille:ç:ş@c|accent_trema:ö:ü@u|accent_circonflexe:â:î:û@f|₺|ı|ğ" />
+ <subtype android:label="%s" android:languageTag="uk" android:imeSubtypeLocale="uk_UA" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=cyrillic,default_layout=cyrl_jcuken_uk,dictionary=uk,extra_keys=ґ|є|і|ї|₴" />
+ <subtype android:label="%s" android:languageTag="uz" android:imeSubtypeLocale="uz_UZ" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_uz,extra_keys=ʻ|ʼ" />
+ <subtype android:label="%s" android:languageTag="vi" android:imeSubtypeLocale="vi_VN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_vi" />
+ <subtype android:label="%s" android:languageTag="yo" android:imeSubtypeLocale="yo_NG" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_us,extra_keys=₦|ẹ|ọ|ṣ" />
</input-method>
diff --git a/shell.nix b/shell.nix
index e9f4156..e517d48 100644
--- a/shell.nix
+++ b/shell.nix
@@ -11,6 +11,8 @@ let
buildToolsVersions = [ build_tools_version ];
platformVersions = [ "35" ];
abiVersions = [ "armeabi-v7a" ];
+ includeNDK = true;
+ ndkVersion = "27.0.12077973";
};
emulators = let
diff --git a/srcs/juloo.keyboard2/Config.java b/srcs/juloo.keyboard2/Config.java
index 16a92ef..18e9fe7 100644
--- a/srcs/juloo.keyboard2/Config.java
+++ b/srcs/juloo.keyboard2/Config.java
@@ -8,6 +8,8 @@ import android.util.TypedValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import juloo.cdict.Cdict;
+import juloo.keyboard2.dict.Dictionaries;
import juloo.keyboard2.prefs.CustomExtraKeysPreference;
import juloo.keyboard2.prefs.ExtraKeysPreference;
import juloo.keyboard2.prefs.LayoutsPreference;
@@ -80,8 +82,8 @@ public final class Config
public ExtraKeys extra_keys_subtype;
public Map<KeyValue, KeyboardData.PreferredPos> extra_keys_param;
public Map<KeyValue, KeyboardData.PreferredPos> extra_keys_custom;
-
- public final IKeyEventHandler handler;
+ public Cdict current_dictionary = null; // Might be 'null'.
+ public IKeyEventHandler handler;
public boolean orientation_landscape = false;
public boolean foldable_unfolded = false;
public boolean wide_screen = false;
@@ -90,7 +92,8 @@ public final class Config
int current_layout_narrow;
int current_layout_wide;
- private Config(SharedPreferences prefs, Resources res, IKeyEventHandler h, Boolean foldableUnfolded)
+ private Config(SharedPreferences prefs, Resources res,
+ Boolean foldableUnfolded, Dictionaries dicts)
{
_prefs = prefs;
editor_config = new EditorConfig();
@@ -100,17 +103,16 @@ public final class Config
labelTextSize = 0.33f;
sublabelTextSize = 0.22f;
// from prefs
- refresh(res, foldableUnfolded);
+ refresh(res, foldableUnfolded, dicts);
// initialized later
shouldOfferVoiceTyping = false;
extra_keys_subtype = null;
- handler = h;
}
/*
** Reload prefs
*/
- public void refresh(Resources res, Boolean foldableUnfolded)
+ public void refresh(Resources res, Boolean foldableUnfolded, Dictionaries dicts)
{
DisplayMetrics dm = res.getDisplayMetrics();
orientation_landscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
@@ -289,10 +291,10 @@ public final class Config
private static Config _globalConfig = null;
public static void initGlobalConfig(SharedPreferences prefs, Resources res,
- IKeyEventHandler handler, Boolean foldableUnfolded)
+ Boolean foldableUnfolded, Dictionaries dicts)
{
migrate(prefs);
- _globalConfig = new Config(prefs, res, handler, foldableUnfolded);
+ _globalConfig = new Config(prefs, res, foldableUnfolded, dicts);
LayoutModifier.init(_globalConfig, res);
}
diff --git a/srcs/juloo.keyboard2/DeviceLocales.java b/srcs/juloo.keyboard2/DeviceLocales.java
index a6cfdaf..c0c489c 100644
--- a/srcs/juloo.keyboard2/DeviceLocales.java
+++ b/srcs/juloo.keyboard2/DeviceLocales.java
@@ -36,6 +36,7 @@ public final class DeviceLocales
public final String script;
public final String default_layout; // Might be [null]
public final ExtraKeys extra_keys;
+ public final String dictionary; // Might be [null]
public Loc(InputMethodSubtype st)
{
@@ -45,6 +46,7 @@ public final class DeviceLocales
String extra_keys_s = st.getExtraValueOf("extra_keys");
extra_keys = (extra_keys_s != null) ?
ExtraKeys.parse(script, extra_keys_s) : ExtraKeys.EMPTY;
+ dictionary = st.getExtraValueOf("dictionary");
}
}
diff --git a/srcs/juloo.keyboard2/KeyEventHandler.java b/srcs/juloo.keyboard2/KeyEventHandler.java
index 18e0592..2bda20c 100644
--- a/srcs/juloo.keyboard2/KeyEventHandler.java
+++ b/srcs/juloo.keyboard2/KeyEventHandler.java
@@ -31,14 +31,14 @@ public final class KeyEventHandler
[setSelection] could be used instead. */
boolean _move_cursor_force_fallback = false;
- public KeyEventHandler(IReceiver recv)
+ public KeyEventHandler(IReceiver recv, Config config)
{
_recv = recv;
Handler handler = recv.getHandler();
_autocap = new Autocapitalisation(handler,
this.new Autocapitalisation_callback());
_mods = Pointers.Modifiers.EMPTY;
- _suggestions = new Suggestions(recv);
+ _suggestions = new Suggestions(recv, config);
_typedword = new CurrentlyTypedWord(handler, this);
}
diff --git a/srcs/juloo.keyboard2/Keyboard2.java b/srcs/juloo.keyboard2/Keyboard2.java
index 25af0d0..ffe99ac 100644
--- a/srcs/juloo.keyboard2/Keyboard2.java
+++ b/srcs/juloo.keyboard2/Keyboard2.java
@@ -23,8 +23,11 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import juloo.keyboard2.dict.Dictionaries;
+import juloo.keyboard2.dict.DictionariesActivity;
import juloo.keyboard2.prefs.LayoutsPreference;
import juloo.keyboard2.suggestions.CandidatesView;
+import juloo.cdict.Cdict;
public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener
@@ -40,6 +43,7 @@ public class Keyboard2 extends InputMethodService
private KeyboardData _localeTextLayout;
/** Installed and current locales. */
private DeviceLocales _device_locales;
+ private Dictionaries _dictionaries;
private ViewGroup _emojiPane = null;
private ViewGroup _clipboard_pane = null;
private Handler _handler;
@@ -115,11 +119,14 @@ public class Keyboard2 extends InputMethodService
super.onCreate();
SharedPreferences prefs = DirectBootAwarePreferences.get_shared_preferences(this);
_handler = new Handler(getMainLooper());
- _keyeventhandler = new KeyEventHandler(this.new Receiver());
_foldStateTracker = new FoldStateTracker(this);
- Config.initGlobalConfig(prefs, getResources(), _keyeventhandler, _foldStateTracker.isUnfolded());
- prefs.registerOnSharedPreferenceChangeListener(this);
+ _dictionaries = Dictionaries.instance(this);
+ Config.initGlobalConfig(prefs, getResources(),
+ _foldStateTracker.isUnfolded(), _dictionaries);
_config = Config.globalConfig();
+ _keyeventhandler = new KeyEventHandler(this.new Receiver(), _config);
+ _config.handler = _keyeventhandler;
+ prefs.registerOnSharedPreferenceChangeListener(this);
Logs.set_debug_logs(getResources().getBoolean(R.bool.debug_logs));
refreshSubtypeImm();
create_keyboard_view();
@@ -163,6 +170,18 @@ public class Keyboard2 extends InputMethodService
_localeTextLayout = default_layout;
}
+ private void refresh_current_dictionary()
+ {
+ _config.current_dictionary = null;
+ String current = _device_locales.default_.dictionary;
+ if (current == null)
+ return;
+ Cdict[] dicts = _dictionaries.load(current);
+ if (dicts == null)
+ return;
+ _config.current_dictionary = Dictionaries.find_by_name(dicts, "main");
+ }
+
private void refresh_candidates_view()
{
boolean should_show =
@@ -178,7 +197,8 @@ public class Keyboard2 extends InputMethodService
private void refresh_config()
{
int prev_theme = _config.theme;
- _config.refresh(getResources(), _foldStateTracker.isUnfolded());
+ _config.refresh(getResources(), _foldStateTracker.isUnfolded(), _dictionaries);
+ refresh_current_dictionary();
// Refreshing the theme config requires re-creating the views
if (prev_theme != _config.theme)
{
@@ -331,6 +351,19 @@ public class Keyboard2 extends InputMethodService
return false;
}
+ /** Called from [onClick] attributes. */
+ public void launch_dictionaries_activity(View v)
+ {
+ start_activity(DictionariesActivity.class);
+ }
+
+ void start_activity(Class cls)
+ {
+ Intent intent = new Intent(this, cls);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+
/** Not static */
public class Receiver implements KeyEventHandler.IReceiver
{
@@ -339,9 +372,7 @@ public class Keyboard2 extends InputMethodService
switch (ev)
{
case CONFIG:
- Intent intent = new Intent(Keyboard2.this, SettingsActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+ start_activity(SettingsActivity.class);
break;
case SWITCH_TEXT:
diff --git a/srcs/juloo.keyboard2/LauncherActivity.java b/srcs/juloo.keyboard2/LauncherActivity.java
index ee769fb..d708619 100644
--- a/srcs/juloo.keyboard2/LauncherActivity.java
+++ b/srcs/juloo.keyboard2/LauncherActivity.java
@@ -21,6 +21,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
+import juloo.keyboard2.dict.DictionariesActivity;
+import juloo.keyboard2.R;
public class LauncherActivity extends Activity implements Handler.Callback
{
@@ -96,6 +98,11 @@ public class LauncherActivity extends Activity implements Handler.Callback
imm.showInputMethodPicker();
}
+ public void launch_dictionaries_activity(View v)
+ {
+ startActivity(new Intent(this, DictionariesActivity.class));
+ }
+
Animatable find_anim(int id)
{
ImageView img = (ImageView)findViewById(id);
diff --git a/srcs/juloo.keyboard2/Utils.java b/srcs/juloo.keyboard2/Utils.java
index 5cc1664..ae82474 100644
--- a/srcs/juloo.keyboard2/Utils.java
+++ b/srcs/juloo.keyboard2/Utils.java
@@ -9,6 +9,8 @@ import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;
@@ -49,4 +51,14 @@ public final class Utils
out.append(buff, 0, l);
return out.toString();
}
+
+ public static byte[] read_all_bytes(InputStream inp) throws IOException
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buff = new byte[128000];
+ int l;
+ while ((l = inp.read(buff)) != -1)
+ out.write(buff, 0, l);
+ return out.toByteArray();
+ }
}
diff --git a/srcs/juloo.keyboard2/dict/Dictionaries.java b/srcs/juloo.keyboard2/dict/Dictionaries.java
new file mode 100644
index 0000000..ac43c9b
--- /dev/null
+++ b/srcs/juloo.keyboard2/dict/Dictionaries.java
@@ -0,0 +1,149 @@
+package juloo.keyboard2.dict;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import juloo.cdict.Cdict;
+import juloo.keyboard2.Logs;
+import juloo.keyboard2.Utils;
+
+/** Manage and load installed dictionaries. */
+public final class Dictionaries
+{
+ public static Dictionaries instance(Context ctx)
+ {
+ if (_instance == null)
+ _instance = new Dictionaries(ctx);
+ return _instance;
+ }
+
+ /** Util for finding a dictionary by name. Returns [null] if not found. */
+ public static Cdict find_by_name(Cdict[] dicts, String name)
+ {
+ for (Cdict d : dicts)
+ if (d.name.equals(name))
+ return d;
+ return null;
+ }
+
+ /** Load an installed dictionary. Return [null] if the requested dictionary
+ is not installed or the dictionary couldn't be loaded. */
+ public Cdict[] load(String dict_name)
+ {
+ if (_loaded_dictionaries.containsKey(dict_name))
+ return _loaded_dictionaries.get(dict_name);
+ Cdict[] dict = load_uncached(dict_name);
+ _loaded_dictionaries.put(dict_name, dict);
+ return dict;
+ }
+
+ public Set<String> get_installed() { return _installed_dictionaries; }
+
+ public void install(String dict_name, byte[] data) throws IOException
+ {
+ FileOutputStream outp = _context.openFileOutput(dict_file_name(dict_name),
+ Context.MODE_PRIVATE);
+ outp.write(data);
+ outp.close();
+ set_installed(dict_name);
+ }
+
+ /** Return the absolute path used to store the dictionary with the given
+ name. Return the same result whether the dictionary is installed or not. */
+ public File get_install_location(String dict_name)
+ {
+ return _context.getFileStreamPath(dict_file_name(dict_name));
+ }
+
+ /** Declare a dictionary as installed. A dictionary file must exist at the
+ path returned by [get_install_location(dict_name)]. */
+ public void set_installed(String dict_name)
+ {
+ _installed_dictionaries.add(dict_name);
+ _loaded_dictionaries.remove(dict_name);
+ save();
+ }
+
+ public void uninstall(String dict_name)
+ {
+ _context.deleteFile(dict_file_name(dict_name));
+ _installed_dictionaries.remove(dict_name);
+ _loaded_dictionaries.remove(dict_name);
+ save();
+ }
+
+ /** Private */
+
+ Context _context;
+ Set<String> _installed_dictionaries;
+ /** Might be 'null' when safe storage is not available. */
+ SharedPreferences _shared_prefs;
+ Map<String, Cdict[]> _loaded_dictionaries;
+
+ static Dictionaries _instance = null;
+
+ static final String PREF_INSTALLED_DICTS = "installed";
+
+ Dictionaries(Context ctx)
+ {
+ _context = ctx;
+ _installed_dictionaries = new HashSet();
+ _loaded_dictionaries = new TreeMap<String, Cdict[]>();
+ load_prefs();
+ }
+
+ void load_prefs()
+ {
+ _shared_prefs = null;
+ try
+ {
+ _shared_prefs =
+ _context.getSharedPreferences("dictionaries", Context.MODE_PRIVATE);
+ Set<String> s = _shared_prefs.getStringSet(PREF_INSTALLED_DICTS, null);
+ if (s != null)
+ _installed_dictionaries.addAll(s);
+ }
+ catch (Exception e)
+ {
+ Logs.exn("", e);
+ }
+ }
+
+ Cdict[] load_uncached(String dict_name)
+ {
+ if (!_installed_dictionaries.contains(dict_name))
+ return null;
+ try
+ {
+ FileInputStream inp = _context.openFileInput(dict_file_name(dict_name));
+ byte[] data = Utils.read_all_bytes(inp);
+ inp.close();
+ return Cdict.of_bytes(data);
+ }
+ catch (IOException e) { return null; }
+ catch (Cdict.ConstructionError e) { return null; }
+ }
+
+ void save()
+ {
+ if (_shared_prefs == null)
+ return;
+ _shared_prefs.edit()
+ .putStringSet(PREF_INSTALLED_DICTS, _installed_dictionaries)
+ .commit();
+ }
+
+ static String dict_file_name(String dict_name)
+ {
+ return dict_name + ".dict";
+ }
+}
diff --git a/srcs/juloo.keyboard2/dict/DictionariesActivity.java b/srcs/juloo.keyboard2/dict/DictionariesActivity.java
new file mode 100644
index 0000000..4143107
--- /dev/null
+++ b/srcs/juloo.keyboard2/dict/DictionariesActivity.java
@@ -0,0 +1,15 @@
+package juloo.keyboard2.dict;
+
+import android.app.Activity;
+import android.os.Bundle;
+import juloo.keyboard2.R;
+
+public class DictionariesActivity extends Activity
+{
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.dictionaries_activity);
+ }
+}
diff --git a/srcs/juloo.keyboard2/dict/DictionaryListView.java b/srcs/juloo.keyboard2/dict/DictionaryListView.java
new file mode 100644
index 0000000..465d373
--- /dev/null
+++ b/srcs/juloo.keyboard2/dict/DictionaryListView.java
@@ -0,0 +1,191 @@
+package juloo.keyboard2.dict;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+import juloo.cdict.Cdict;
+import juloo.keyboard2.Config;
+import juloo.keyboard2.DeviceLocales;
+import juloo.keyboard2.Logs;
+import juloo.keyboard2.R;
+import juloo.keyboard2.Utils;
+
+public class DictionaryListView extends LinearLayout
+{
+ List<DictView> _dict_views;
+ Dictionaries _dictionaries;
+ Set<String> _pending = new HashSet();
+
+ public DictionaryListView(Context ctx, AttributeSet attrs)
+ {
+ super(ctx, attrs);
+ setOrientation(LinearLayout.VERTICAL);
+ _dictionaries = Dictionaries.instance(ctx);
+ inflate_views(ctx);
+ }
+
+ void inflate_views(Context ctx)
+ {
+ DeviceLocales locales = DeviceLocales.load(ctx);
+ SupportedDictionaries ds = new SupportedDictionaries(ctx.getResources());
+ DownloadBtnListener listener = this.new DownloadBtnListener();
+ _dict_views = new ArrayList<DictView>();
+ for (DeviceLocales.Loc loc : locales.installed)
+ {
+ int idx = (loc.dictionary != null) ? ds.find(loc.dictionary) : -1;
+ if (idx >= 0)
+ {
+ DictView dv = new DictView(ctx, ds, idx, listener);
+ addView(dv.view);
+ _dict_views.add(dv);
+ }
+ }
+ refresh();
+ }
+
+ /** Update the "installed" status of item views. Meaning whether the
+ "download" or "delete" button is shown. */
+ void refresh()
+ {
+ Set<String> installed = _dictionaries.get_installed();
+ for (DictView d : _dict_views)
+ d.refresh(installed, _pending);
+ }
+
+ void toggle_installed(String dict_name)
+ {
+ run_dictionary_action(dict_name, new Runnable()
+ {
+ public void run()
+ {
+ if (_dictionaries.get_installed().contains(dict_name))
+ _dictionaries.uninstall(dict_name);
+ else if (install_dictionary_from_internet(dict_name))
+ post_toast(R.string.dictionaries_download_success);
+ else
+ post_toast(R.string.dictionaries_download_failed);
+ }
+ });
+ }
+
+ /** Run action [r] for dictionary [name] if no action is already running for
+ that dictionary. Calls [refresh] after the action completed. */
+ void run_dictionary_action(String name, Runnable r)
+ {
+ if (_pending.contains(name))
+ return;
+ _pending.add(name);
+ (new Thread()
+ {
+ public void run()
+ {
+ r.run();
+ post(new Runnable()
+ {
+ public void run()
+ {
+ _pending.remove(name);
+ refresh();
+ }
+ });
+ }
+ }).start();
+ refresh();
+ }
+
+ final class DownloadBtnListener implements View.OnClickListener
+ {
+ @Override
+ public void onClick(View v)
+ {
+ for (DictView dv : _dict_views)
+ if (dv.download_button == v)
+ toggle_installed(dv.dict_name);
+ }
+ }
+
+ static final class DictView
+ {
+ public final View view;
+ public final String dict_name;
+ public final View download_button;
+
+ public DictView(Context ctx, SupportedDictionaries ds, int dict_index,
+ DownloadBtnListener on_click)
+ {
+ view = View.inflate(ctx, R.layout.dictionary_download_item, null);
+ dict_name = ds.dict_name(dict_index);
+ float size_mb = ds.size(dict_index) / 1048576.f;
+ ((TextView)view.findViewById(R.id.dictionary_download_locale))
+ .setText(ds.display_name(dict_index));
+ ((TextView)view.findViewById(R.id.dictionary_download_size))
+ .setText(NumberFormat.getInstance().format(size_mb) + "MB");
+ download_button = view.findViewById(R.id.dictionary_download_button);
+ download_button.setOnClickListener(on_click);
+ }
+
+ public void refresh(Set<String> installed, Set<String> pending)
+ {
+ download_button.setBackgroundResource(installed.contains(dict_name)
+ ? R.drawable.ic_delete : R.drawable.ic_download);
+ download_button.setVisibility(pending.contains(dict_name)
+ ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ static final String DICT_REPO_URL =
+ "https://github.com/Julow/Unexpected-Keyboard-dictionaries/raw/refs/heads/main";
+
+ static URL url_of_dictionary(String dict_name)
+ throws MalformedURLException
+ {
+ int format_version = 0;
+ return new URL(DICT_REPO_URL + "/v" + format_version + "/" + dict_name
+ + ".dict");
+ }
+
+ /** Returns [true] on success. */
+ boolean install_dictionary_from_internet(String dict_name)
+ {
+ try
+ {
+ // Remote files are compressed with gzip at rest. Do not use server side
+ // compression and force decompression.
+ URLConnection con = url_of_dictionary(dict_name).openConnection();
+ con.setRequestProperty("Accept-Encoding", "identity");
+ byte[] data = Utils.read_all_bytes(new GZIPInputStream(con.getInputStream()));
+ Cdict.of_bytes(data); // Check that the dictionary can load.
+ _dictionaries.install(dict_name, data);
+ return true;
+ }
+ catch (Exception e)
+ {
+ Logs.exn("", e);
+ return false;
+ }
+ }
+
+ void post_toast(int msg_id)
+ {
+ post(new Runnable()
+ {
+ public void run()
+ {
+ Toast.makeText(getContext(), msg_id, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+}
diff --git a/srcs/juloo.keyboard2/dict/SupportedDictionaries.java b/srcs/juloo.keyboard2/dict/SupportedDictionaries.java
new file mode 100644
index 0000000..879fccd
--- /dev/null
+++ b/srcs/juloo.keyboard2/dict/SupportedDictionaries.java
@@ -0,0 +1,33 @@
+package juloo.keyboard2.dict;
+
+import android.content.res.Resources;
+import java.util.Arrays;
+import juloo.keyboard2.R;
+
+/** Access arrays in [dictionaries.xml]. */
+public class SupportedDictionaries
+{
+ public String[] locales;
+ public String[] names;
+ public int[] sizes;
+
+ public SupportedDictionaries(Resources res)
+ {
+ locales = res.getStringArray(R.array.dictionaries_locale);
+ names = res.getStringArray(R.array.dictionaries_name);
+ sizes = res.getIntArray(R.array.dictionaries_size);
+ }
+
+ /** Find the index for a given dictionary name. Return [-1] if not found. */
+ public int find(String dict_name)
+ {
+ int i = Arrays.binarySearch(locales, dict_name);
+ return (i < 0) ? -1 : i;
+ }
+
+ public int length() { return locales.length; }
+
+ public String dict_name(int i) { return locales[i]; }
+ public String display_name(int i) { return names[i]; }
+ public int size(int i) { return sizes[i]; }
+}
diff --git a/srcs/juloo.keyboard2/suggestions/CandidatesView.java b/srcs/juloo.keyboard2/suggestions/CandidatesView.java
index 259db35..b41177f 100644
--- a/srcs/juloo.keyboard2/suggestions/CandidatesView.java
+++ b/srcs/juloo.keyboard2/suggestions/CandidatesView.java
@@ -74,7 +74,7 @@ public class CandidatesView extends LinearLayout
// The status message indicates whether the dictionaries should be
// installed.
_status_no_dict = inflate_and_show(_status_no_dict,
- true,
+ (config.current_dictionary == null),
R.layout.candidates_status_no_dict);
set_height(config);
}
diff --git a/srcs/juloo.keyboard2/suggestions/Suggestions.java b/srcs/juloo.keyboard2/suggestions/Suggestions.java
index 50c64e0..998d40d 100644
--- a/srcs/juloo.keyboard2/suggestions/Suggestions.java
+++ b/srcs/juloo.keyboard2/suggestions/Suggestions.java
@@ -2,28 +2,47 @@ package juloo.keyboard2.suggestions;
import java.util.Arrays;
import java.util.List;
+import juloo.cdict.Cdict;
+import juloo.keyboard2.dict.Dictionaries;
+import juloo.keyboard2.Config;
/** Keep track of the word being typed and provide suggestions for
[CandidatesView]. */
public final class Suggestions
{
Callback _callback;
+ Config _config;
- public Suggestions(Callback c)
+ public Suggestions(Callback c, Config conf)
{
_callback = c;
+ _config = conf;
}
public void currently_typed_word(String word)
{
- if (word.equals(""))
+ Cdict dict = _config.current_dictionary;
+ if (word.length() < 2 || dict == null)
{
_callback.set_suggestions(NO_SUGGESTIONS);
}
else
{
- // TODO
- _callback.set_suggestions(Arrays.asList(word));
+ Cdict.Result r = dict.find(word);
+ String[] suggestions = new String[3];
+ int i = 0;
+ if (r.found)
+ suggestions[i++] = word;
+ int[] suffixes = dict.suffixes(r, 3);
+ int[] dist = dict.distance(word, 1, 3);
+ for (int j = 0; j < 3 && i < 3; j++)
+ {
+ if (suffixes.length > j)
+ suggestions[i++] = dict.word(suffixes[j]);
+ if (dist.length > j && i < 3)
+ suggestions[i++] = dict.word(dist[j]);
+ }
+ _callback.set_suggestions(Arrays.asList(suggestions));
}
}
diff --git a/vendor/Android.mk b/vendor/Android.mk
new file mode 100644
index 0000000..8a54c3d
--- /dev/null
+++ b/vendor/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/cdict/libcdict
+LOCAL_CFLAGS +=
+# -Wall -Wextra -Werror
+LOCAL_SRC_FILES := cdict/libcdict/libcdict.c cdict/java/jni/juloo_cdict_Cdict.c
+LOCAL_MODULE := libcdict_java
+LOCAL_SDK_VERSION := 21
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/vendor/cdict b/vendor/cdict
new file mode 160000
+Subproject aa1c986e79a632dff0a81f92c75d720e80aa844