Files
Jules Aguillon 77c4a27c4c Spell checking (#1137)
This adds dictionary-based spell checking to the keyboard. The keyboard looks at the word being typed and matches it against a dictionary to either complete the rest of the word or find alternative spellings.

The core of this feature is implemented in cdict, which is included as a
submodule in vendor/cidct.

Cdict is developped at https://github.com/Julow/cdict
The dictionaries are hosted at https://github.com/Julow/Unexpected-Keyboard-dictionaries/
The wordlists used to build the dictionaries are the same ones used by
HeliBoard from https://codeberg.org/Helium314/aosp-dictionaries

- Add an activity accessible from the launcher app that lists available
  dictionaries with a download button.
  The DictionaryListView view shows the list of available dictionaries and
  handles downloading and installing them.

- The Dictionaries class manages installed dictionaries. Dictionaries are
  installed as individual files into the app's private directory.

- Available dictionaries are listed in dictionaries.xml, which is generated
  when building Unexpected-Keyboard-dictionaries.
  method.xml mentions the dictionary name for each locales.
2026-02-02 00:20:00 +01:00

86 lines
2.7 KiB
Java

package juloo.keyboard2;
import android.content.Context;
import android.os.Build.VERSION;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import java.util.ArrayList;
import java.util.List;
public final class DeviceLocales
{
public final List<Loc> installed;
public final Loc default_;
public static DeviceLocales load(Context ctx)
{
InputMethodManager imm =
(InputMethodManager)ctx.getSystemService(Context.INPUT_METHOD_SERVICE);
List<Loc> locs = get_installed_locales(ctx.getPackageName(), imm);
return new DeviceLocales(locs, current_locale(imm, locs));
}
/** Extra keys required by all the installed locales. */
public ExtraKeys extra_keys()
{
List<ExtraKeys> extra_keys = new ArrayList<ExtraKeys>();
for (Loc l : installed)
extra_keys.add(l.extra_keys);
return ExtraKeys.merge(extra_keys);
}
public static final class Loc
{
public final String lang_tag;
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)
{
lang_tag = st.getLanguageTag();
script = st.getExtraValueOf("script");
default_layout = st.getExtraValueOf("default_layout");
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");
}
}
private DeviceLocales(List<Loc> locs, Loc def)
{ installed = locs; default_ = def; }
private static List<Loc> get_installed_locales(String pkg, InputMethodManager imm)
{
List<Loc> locs = new ArrayList<Loc>();
for (InputMethodInfo imi : imm.getEnabledInputMethodList())
if (imi.getPackageName().equals(pkg))
{
for (InputMethodSubtype subtype :
imm.getEnabledInputMethodSubtypeList(imi, true))
locs.add(new Loc(subtype));
break;
}
return locs;
}
private static Loc current_locale(InputMethodManager imm, List<Loc> installed)
{
// Android might return a random subtype, for example, the first in the
// list alphabetically.
InputMethodSubtype current_subtype = imm.getCurrentInputMethodSubtype();
if (current_subtype == null)
return null;
if (VERSION.SDK_INT < 24)
return new Loc(current_subtype);
String default_lang_tag = current_subtype.getLanguageTag();
for (Loc l : installed)
if (l.lang_tag.equals(default_lang_tag))
return l;
return null;
}
}