A Fcitx5 input method for Traditional Chinese that lets you type Bopomofo (注音)
and English together without switching modes. Every key first shows as itself;
keys only become Chinese once they form a complete, toned 注音 syllable
(e.g. su stays su until a tone arrives — su3 → 你). The whole pre-edit may
freely mix English and Chinese in any order (e.g. acer螢幕) and is only sent to
the application when you press Enter.
Built on libchewing for conversion, phrasing and per-user learning.
- Mixed input, no mode switching — type
acer螢幕in one go. - Out-of-order tolerant —
su3ands3uboth produce 你. - Result-based tone-one input — a pending key sequence plus Space converts
only when libchewing actually produces a Han character. There is no
per-key or per-word allow/deny list, so
astays literal whileu+ Space produces一on the default layout; the same rule applies to out-of-order sequences and every supported layout. - English-word friendly — a tone peels the shortest trailing syllable, so
brand names stay intact (
aceru/6→acer螢). - Live contextual ranking — as soon as a complete Chinese result is available, libchewing applies its surrounding-word model and learned habits to the inline result. Ari does not open a candidate panel automatically; press Down to enter normal candidate picking when you want alternatives.
- Candidate re-selection anywhere — press ↓/←/→ to open a cursor that walks
the whole pre-edit and re-pick any character or phrase; phrase recommendations
that contain the focused character remain available even at the end of a
word, and earlier picks stay pinned. Candidates can be picked by number key or
direct click/touch, and multi-page lists show their current page in the
auxiliary line. The labeled
原始鍵 ...candidate restores a converted character back to its raw keys. Literal punctuation cells use the same picker: ↓ exposes only the half-width, full-width, Chinese and paired variants associated with that key, with the current form first; for example,[can be changed to「,『,【,《and other nested brackets, without unrelated!candidates. If a punctuation-looking key such as.or,is also used in a 注音 syllable, its punctuation variants are added to that Chinese character's candidate list as well; the complete Chinese candidate list stays first, punctuation follows it, and the raw-key recovery entry remains last.Ctrl+Zrestores recent candidate choices until text is otherwise edited;Shift+Deleteforgets the highlighted personal candidate without removing the same word from the built-in dictionary. - Committed-text reconversion — select a short all-Chinese range that has
already been sent to the application and press
Ctrl+Alt+Rto reopen Ari's native candidate editor. The original text stays available, so a phrase can be corrected without deleting and retyping it. This uses Fcitx5's native surrounding-text capability, does nothing in unsupported or sensitive fields, and can be cleared or rebound through theReconversionKeyaddon setting. - Safe mixed-text editing — pasted common multi-codepoint Emoji (including variation-selector, flag and ZWJ sequences) behaves as one unit for the caret and Backspace instead of being split into broken fragments.
- Consistent phrasing — the character shown while typing matches the top candidate the selection window offers ("以選字候選為準").
- Explicit Chinese punctuation — ordinary punctuation stays literal and
half-width regardless of surrounding Chinese or English. Hold the configured
ChinesePunctuationShortcut(defaultCtrl+Shift) with a punctuation key to request its Chinese form temporarily: comma → ,, period → 。, slash → ?, apostrophe key (') → 、,(→ (,{→ 『, etc. In particular, the default Chinese enumeration comma is Ctrl+Shift+'. The native Fcitx5 setting can switch the gesture toAlt+Shift,Ctrl,Alt, or disable it when an application reserves the default shortcut. The dedicatedAlt+[andAlt+]shortcuts produce Chinese corner quotes「and」; modified forms such asCtrl+Alt+[remain available to the application. FullWidthPunctuation remains available for users who explicitly prefer full-width symbols without holding a modifier, including@→ @,%→ %,_→ _,`→ ` and"→ ". Ari IME reserves no punctuation toggle shortcut by default, so common application shortcuts such asCtrl+.remain available; FullWidthPunctuationToggle can optionally bind a modifier shortcut that flips the setting live and persists it. OtherAltpunctuation remains available to applications instead of being captured. - Forced English mode —
Ctrl+Spacetoggles it; a transient 中/英 hint pops up, and the mode persists until toggled again. - Optional traditional Space selection — enable the native
SpaceCandidateModesetting if you prefer Space to open candidates after a complete Chinese conversion. It is off by default, so Ari keeps its mixed input Space-as-tone-one/literal-space behavior and Enter-only commit contract. - Visible composition status — the auxiliary line shows current 中/英 mode, keyboard layout and punctuation mode while composing. This status line is off by default and can be re-enabled in the addon config.
- Weighted per-user learning — committing with Enter gives an unchanged conversion one weak positive learning pass. An explicitly selected character or phrase receives three extra passes (roughly 4:1), plus one short surrounding-context pass, so deliberate choices adapt faster without treating accepted defaults as mistakes. Explicitly selected or imported mappings, including entries added through Ari's dictionary API, are kept in a small Ari-owned preference sidecar for backup and forget bookkeeping. Live candidate order remains under libchewing's contextual scorer; Ari does not open a hidden candidate window on every completed syllable or force a static preference to the top. AutoLearn can be disabled in the addon's configuration when the personal dictionary should remain unchanged. Password and sensitive input fields never write learning data.
- Automatic offline context — libchewing's local phrase model uses
surrounding words to distinguish homophones such as
我的and跑得快. Personal weights feed the same model automatically; there is no external AI, network request, model download or setting to enable. - Portable personal dictionary —
ari-ime-dictcan inspect the active libchewing version and data directory, list or export personal phrase mappings, validate an import without changing anything, merge an import safely, and create a raw-data backup. The text format stores canonical Unicode Bopomofo readings such asㄋㄧˇ, so it is not tied to one keyboard layout. Package installation never imports or changes user data. - Punctuation-aware boundaries — a literal symbol can be followed directly
by Zhuyin (
(hk4g4->(測試) without trapping the following keys in an English token. - Reusable WebAssembly core —
wasm/packages the same headless input state machine as@ari-ime/wasm. Other applications can import it and own keyboard events, candidate rendering, clipboard handling and persistence; it has no Fcitx5 or UI runtime dependency.
The WebAssembly package ships its generated .js, .wasm and dictionary data
artifacts for direct npm use. See wasm/README.md for the
Emscripten build inputs and the native/API smoke tests.
| Key | Action |
|---|---|
| letters / digits | 注音 keys in the selected keyboard layout, or literal English |
| layout tone keys, space (一聲) | complete the pending syllable |
| ↓ / ← / → | open candidate re-selection over the pre-edit |
| Ctrl+Alt+R | reopen a selected short Chinese range for candidate correction (configurable) |
| ↑ | open/reinterpret the current pre-edit cell |
| Tab / Shift+Tab (in candidates) | move candidate highlight forward / backward |
| Home / End | jump to the beginning / end of the pre-edit |
| Ctrl+Left / Ctrl+Right | move by libchewing phrase boundaries or English words |
| Delete | delete the character right of the caret, or the focused candidate cell |
| Shift+Delete (in candidates) | forget the highlighted personal learning record |
| PageUp / PageDown | move between candidate pages |
number 1–9 |
pick a candidate |
| Backspace (in selection) | delete the focused character and leave selection |
| Esc | clear pre-edit, or close selection/candidates first |
| Enter | commit the whole pre-edit to the application |
| Ctrl+V / Shift+Insert | paste clipboard text at the current pre-edit caret, with control/newline-like separators folded into visible spaces and zero-width artifacts removed |
| Ctrl+Z | restore the most recent candidate choice while it is still the latest edit |
| Ctrl+Space | toggle forced English mode |
Numeric-keypad navigation keys are treated like their main-keyboard equivalents
when NumLock is off. Numeric-keypad digits remain literal digits when NumLock is
on, so they do not accidentally become tone keys. Shift+KP_Insert also pastes.
Currently supported layouts:
- 大千 (
KB_DEFAULT) —su3→ 你,su3cl3→ 你好 - 倚天 (
KB_ET) —ne3→ 你,ne3hz3→ 你好 - 許氏 (
KB_HSU) —nef→ 你,nefhwf→ 你好 - IBM (
KB_IBM) —7a,→ 你,7a,-;,→ 你好 - 精業 (
KB_GIN_YIEH) —d-a→ 你,d-avla→ 你好 - Dvorak (
KB_DVORAK) —og3→ 你,og3jn3→ 你好 - Carpalx (
KB_CARPALX) —su3→ 你,su3cl3→ 你好 - Colemak-DH ANSI (
KB_COLEMAK_DH_ANSI) —rl3→ 你,rl3di3→ 你好 - Colemak-DH Ortholinear (
KB_COLEMAK_DH_ORTH) —rl3→ 你,rl3ci3→ 你好 - Workman (
KB_WORKMAN) —sf3→ 你,sf3mo3→ 你好 - Colemak (
KB_COLEMAK) —rl3→ 你,rl3ci3→ 你好
The addon's config exposes the keyboard layout setting with these display names, and the key classification plus libchewing keyboard type share one layout layer, so other layouts can be added without changing the input state machine. Changing the layout clears the current uncommitted pre-edit and shows a transient keyboard-layout hint. Pinyin keyboard modes are intentionally not exposed here because this engine's state machine is built around one-key-per-Bopomofo-symbol layouts.
Choose one of the two AUR packages below. They conflict with each other because both install the same input-method module.
fcitx5-ari-ime-bin
downloads the tested GitHub Release binary. It does not install a compiler,
CMake or other build tools:
yay -S fcitx5-ari-ime-bin && ari-ime-enable --yes --make-default
# or: paru -S fcitx5-ari-ime-bin && ari-ime-enable --yes --make-defaultAfter a successful package installation, the command adds Ari to the current user's Fcitx5 profile and selects it as the default input method.
Binary archives and SHA-256 checksums are also available from GitHub Releases.
fcitx5-ari-ime downloads
the tagged source and builds it locally:
yay -S fcitx5-ari-ime && ari-ime-enable --yes --make-default
# or: paru -S fcitx5-ari-ime && ari-ime-enable --yes --make-defaultDevelopers can instead clone this repository and use the manual source-build instructions below.
The repository ships a Nix flake. Its module registers Ari as a Fcitx5 addon automatically whenever Fcitx5 is the configured input method framework, so installation is declarative — there is no install script to run.
-
Add the flake input and import the module:
# flake.nix inputs.ari-ime.url = "github:kaiyasi/Ari-IME";
# configuration.nix { inputs, ... }: { imports = [ inputs.ari-ime.nixosModules.default ]; i18n.inputMethod = { type = "fcitx5"; fcitx5.addons = [ ]; # Ari is appended by the imported module }; }
-
Rebuild and log out and back in:
sudo nixos-rebuild switch --flake .#your-host -
Add Ari IME (
ari-ime) throughfcitx5-configtool, or runari-ime-enable --yes --make-defaultif you prefer the same helper used on other distributions.
Home Manager users who manage only their home directory can import
homeManagerModules.default with the same i18n.inputMethod options.
To wire the package manually without any module:
i18n.inputMethod.fcitx5.addons =
[ inputs.ari-ime.packages.${pkgs.system}.default ];The flake also provides overlays.default (adds
pkgs.fcitx5-ari-ime) and a development shell via nix develop. The package
version is read from CMakeLists.txt, so it always matches the source tree.
Learned personal data lives under ~/.config/ari-ime/ exactly like on other
distributions; nixos-rebuild never removes it. Resetting it stays available
through ari-ime-reset-data.
- fcitx5 (and
Fcitx5Core/Fcitx5Config/Fcitx5Utils/Fcitx5ModuleClipboarddevelopment files) - libchewing (
chewing) - hicolor-icon-theme (for the installed
ari-imeicon) - extra-cmake-modules (ECM)
- a C++20 compiler, CMake ≥ 3.16
The automated tests are written to tolerate libchewing dictionary ranking changes where Ari IME does not own the exact candidate order. The release gate prints the resolved libchewing version so a distribution update can be correlated with candidate-order changes; the exact first candidate is not a cross-distro compatibility promise.
For a source build on Arch Linux:
sudo pacman -S fcitx5 hicolor-icon-theme libchewing extra-cmake-modules cmake gccOn Ubuntu / Debian:
sudo apt install \
cmake extra-cmake-modules g++ pkg-config \
fcitx5 libfcitx5core-dev libfcitx5config-dev libfcitx5utils-dev \
fcitx5-modules-dev libchewing3-dev hicolor-icon-themefcitx5-modules-dev provides the clipboard module headers (clipboard_public.h,
Fcitx5ModuleClipboard) that the Ctrl+V paste path links against. Ubuntu builds
against whatever libchewing the distribution ships (for example libchewing 0.8.x
on Ubuntu 24.04); candidate ordering can differ slightly between distributions —
see ISSUES.md. No source changes
are needed: the build uses GNUInstallDirs, so the module installs to the
distribution's multiarch fcitx5 directory (e.g.
/usr/lib/x86_64-linux-gnu/fcitx5) which fcitx5 scans automatically. Install with
-DCMAKE_INSTALL_PREFIX=/usr (see below) so the descriptors land under /usr/share.
If libchewing's system dictionary lives in a non-standard location, set
CHEWING_PATH to point at it; Ari IME otherwise falls back to a read-only chewing
context when its own user-dictionary directory is not writable, so composition
keeps working even without per-user learning.
Each GitHub release also includes a tested .deb for 64-bit Debian/Ubuntu:
sudo apt install ./fcitx5-ari-ime_<version>_amd64.debDownload the matching .deb and .sha256 files from the
GitHub Release, then continue
with the Fcitx5 setup steps below.
For a one-command installation that downloads the latest release, verifies the checksum, installs dependencies, adds Ari to the Fcitx5 profile, and selects it as the default input method in the current graphical session:
curl -fsSL https://raw.githubusercontent.com/kaiyasi/Ari-IME/main/scripts/install-ubuntu.sh | bashThe command installs the prebuilt release package; the build itself is already
performed and tested by GitHub Actions. Run it as the normal desktop user so
ari-ime-enable updates that user's Fcitx5 profile. The installer also falls
back to the existing versioned release assets while older releases do not yet
have the stable fcitx5-ari-ime_amd64.deb alias.
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
sudo cmake --install buildOn Ubuntu/Debian (and other distros where fcitx5 only scans /usr), add
-DCMAKE_INSTALL_PREFIX=/usr to the configure step so the addon and descriptors
install where fcitx5 looks for them. On Debian/Ubuntu you can also build a .deb
straight from the tree with dpkg-buildpackage -us -uc -b (see the debian/
directory).
Then restart fcitx5:
fcitx5 -rFor the shortest first-run setup, add Ari to the current Fcitx5 profile with the installed command:
ari-ime-enable --make-defaultThis is an explicit user command, not a package hook. It changes only the first
Fcitx5 input-method group, creates a timestamped backup before changing an
existing profile, and makes Ari the default only when --make-default is
given. Omit that option to keep the current default input method. When run in a
graphical session, it starts Fcitx5 if needed, reloads the profile, selects Ari,
and verifies that ari-ime is active; in a headless shell it updates the profile
but asks you to start Fcitx5 and run the command again.
Installing into ~/.local is useful for testing without sudo, but a normal
Fcitx5 desktop process does not necessarily search that directory for addons.
Use the helper below after building; it installs the module, restarts Fcitx5
with the local addon path, selects Ari IME, and verifies the loaded .so path:
bash scripts/install-local.shThe helper uses build-public-release by default. For the ordinary build
directory, use ARI_IME_BUILD_DIR=build bash scripts/install-local.sh. This is
intended for the current development session. For a persistent desktop install,
use the AUR package, a GitHub release package, or install under /usr as shown
above so Fcitx5 finds the addon through its normal search path.
The graphical alternative is to add Ari IME in fcitx5-configtool:
- Run
fcitx5-configtoolfrom a terminal or your application launcher — not your desktop environment's system input settings. - Go to the Input Method tab → click + → search Ari → select Ari IME → click OK.
Then select it once and verify the active name:
fcitx5-remote -s ari-ime
fcitx5-remote -n # should print: ari-imePer-addon options (keyboard layout, Chinese-punctuation shortcut, Space candidate mode, full-width punctuation and AutoLearn) appear under the addon's config page.
ctest --test-dir buildThe tests isolate chewing's learned dictionary in a temp directory, so they are
deterministic and do not touch your real ~/.config data.
Development/test safeguards around personalization:
- Automated tests set
ARI_IME_USER_DATA_DIRandXDG_CONFIG_HOMEto a fresh temp directory. - Automated tests also set
ARI_IME_DISABLE_AUTOLEARN=1, so no learned personalization is intentionally recorded during ordinary unit/integration/fuzz runs, and any libchewing-created artifacts stay inside the disposable temp directory. - Production usage keeps auto-learning enabled by default and writes only to
Ari IME's own user-data directory (
userdict.dat,chewing.datandchewing-deleted.dat), not libchewing's built-in dictionary resources.
For the full local verification pass:
scripts/check.shThis checks version consistency across CMake/PKGBUILD/.SRCINFO, then runs the
release build, CTest, install smoke check, PKGBUILD syntax check, and the
sanitizer test profile. The version check prints the validated Ari IME version,
libchewing version, CMake version, and active C++ compiler so CI failures can be
correlated with dependency changes. Add
ARI_IME_CHECK_PACKAGE=1 to also run an offline Arch package
build/check/package simulation.
Set ARI_IME_CHECK_MODE=release, sanitize, coverage, fuzz, or package
to run just one part of the check. GitHub Actions uses the release, sanitizer,
bounded-fuzz, and package modes as separate jobs in an Arch Linux container on
pushes and pull requests.
For memory/undefined-behavior checks:
cmake -B build-sanitize -DCMAKE_BUILD_TYPE=Debug -DARI_IME_ENABLE_SANITIZERS=ON
cmake --build build-sanitize
ctest --test-dir build-sanitize --output-on-failureLeak detection is disabled in this profile so the tests still run in ptrace-based
sandboxes. To include LeakSanitizer on a normal local/CI runner, add
-DARI_IME_SANITIZER_DETECT_LEAKS=ON.
For a local gcov coverage report:
ARI_IME_CHECK_MODE=coverage scripts/check.shThis builds the tests with -DARI_IME_ENABLE_COVERAGE=ON, runs CTest, and writes
.gcov reports for the main src/ state-machine files to
build-coverage/gcov/.
For bounded state-machine fuzzing with libFuzzer:
cmake -B build-fuzz -DCMAKE_CXX_COMPILER=clang++ -DARI_IME_ENABLE_FUZZING=ON
cmake --build build-fuzz --target fuzz_buffer
./build-fuzz/fuzz_buffer -runs=1000The fuzz target is opt-in and is not part of the normal release/package build.
It feeds mixed key, paste, candidate-selection, layout-switch, and punctuation
events into Buffer while checking UTF-8 and public caret/candidate invariants.
Use ARI_IME_CHECK_MODE=fuzz scripts/check.sh for the same bounded smoke run
that CI uses. It loads the seed corpus in test/corpus/fuzz_buffer when present;
the check script copies those seeds into a temporary corpus first so local fuzz
runs do not dirty the tracked seed directory. Printable ASCII bytes in those
seeds are interpreted as direct key presses. Set
ARI_IME_FUZZ_RUNS to adjust the run count, or ARI_IME_FUZZ_CORPUS_DIR to
point at another corpus directory. Set ARI_IME_FUZZ_ARTIFACT_DIR to make
libFuzzer write crash reproducers to a dedicated directory for CI artifact
upload.
GitHub also runs a separate scheduled/manual Nightly Fuzz workflow with a
larger default run count. Trigger it manually from Actions and set the runs
input when you want a longer one-off fuzz pass without slowing down normal
push/PR checks.
Real application behavior still needs manual validation because preedit, candidate windows, clipboard, and theme rendering depend on the desktop session. Use docs/manual-qa.md before releases.
Release-specific notes are tracked in CHANGELOG.md and docs/release-2.3.6.md.
Ari IME stores its learned per-user data in its own directory:
${ARI_IME_USER_DATA_DIR}, whenARI_IME_USER_DATA_DIRis set- otherwise
${XDG_CONFIG_HOME:-$HOME/.config}/ari-ime/
That directory holds userdict.dat, Ari's explicit preferences.tsv, plus
libchewing's learned files (chewing.dat, chewing-deleted.dat). Ari pins
CHEWING_USER_PATH to this directory so learning does not leak into the shared
$XDG_DATA_HOME/chewing used by other libchewing input methods. The sidecar
contains only phrases explicitly selected, imported, or added through Ari's
dictionary API for portable bookkeeping; the other files hold the learned
phrase/homophone frequencies that drive live ranking.
They are safe to reset without affecting libchewing's built-in/base dictionary.
Older Ari builds (before this pinning) may have left learned data in
~/.local/share/chewing; pass --include-shared to the reset script below to
clear that shared location too (it may be shared with other chewing IMEs).
Learning collected before the weighted scheme does not distinguish unchanged
output from explicit selections. It remains usable, but a one-time reset is a
useful diagnostic if old candidate ordering still feels inconsistent.
To reset learned data safely for development or local troubleshooting:
ari-ime-reset-dataThe same script is available as scripts/reset-user-data.sh from a source
checkout.
The package-installed ari-ime-dict command provides a no-UI way to inspect and
move Ari's personal phrase mappings:
ari-ime-dict info
ari-ime-dict candidates su3
ari-ime-dict export "$HOME/ari-ime-dictionary.tsv"
ari-ime-dict import --dry-run "$HOME/ari-ime-dictionary.tsv"
ari-ime-dict import "$HOME/ari-ime-dictionary.tsv"
ari-ime-dict backupImports are merges, are idempotent, and create a timestamped backup before any
existing libchewing data is changed. The portable text file contains a phrase
and libchewing's canonical Unicode Bopomofo reading separated by a tab; use a
reading such as ㄋㄧˇ, not layout-specific keys such as su3. The portable
format transfers personal phrase mappings, while exact frequency state can
still vary with the installed libchewing version; backup preserves the raw
files for same-engine recovery. candidates KEYS prints the current engine
result and candidate page for a raw 大千 key sequence such as su3 or hk4g4,
which makes candidate-order reports reproducible without changing the active
Fcitx5 session.
The script backs up the current userdict.dat to a timestamped .bak.* file
and removes the active learned dictionary so Ari IME starts relearning from a
clean state. Use --yes for non-interactive use, or --no-backup if you
explicitly want to discard the existing learned file.
For test/dev isolation, point Ari IME at a disposable user-data directory:
export ARI_IME_USER_DATA_DIR=/tmp/ari-ime-dev-userdataGPL-3.0-or-later. See LICENSE.