YanHuiIME: A Chinese Input Method That Learns How I Write—and Helps Me Learn New Characters

Inspiration

I use a 9-key T9 keyboard on my phone every day, but I have never been satisfied with existing Chinese input methods.

Most mainstream keyboards are optimized for the average user. They often struggle with the words that matter most to me: character names from my fiction, historical vocabulary, classical Chinese expressions, plant biology terms, gene names, and mixed Chinese-English scientific phrases. Even after repeatedly typing the same uncommon word, I may still have to search through several pages of candidates.

I am also interested in classical Chinese, but there is a simple obstacle to learning unfamiliar characters:

If I do not know a character, I will not use it. If I never use it, I may never think to search for it.

That led to the central idea behind YanHuiIME: an input method should not only predict what I already know. It can also create small, low-friction opportunities to discover something new.

For example, when I enter 934, corresponding to wei on a T9 keyboard, the keyboard still shows ordinary candidates such as “为”, “位”, and “未”. But it can also mark less familiar characters such as:

  • 渭 — wèi, the Wei River
  • 闱 — wéi, an inner palace gate; an examination hall
  • 隈 — wēi, a bend or sheltered corner of a mountain or river

A normal tap enters the character. A long press opens a compact pronunciation and definition card. The learning experience happens inside an action I already perform every day.

What I Built

YanHuiIME is a local-first Android Chinese input method centered on 9-key T9 input.

I began with the open-source Aegis input method because it already had a strong Kotlin foundation, offline decoding, local user learning, clipboard tools, emoji, symbols, and both 9-key and 26-key layouts. I then adapted it around my own workflow.

The current prototype includes:

  • Chinese T9 as the primary Chinese input layout
  • Offline candidate decoding
  • Local user-frequency learning
  • A separate character metadata dictionary
  • Reverse lookup by character, pinyin, and T9 digit sequence
  • Dictionary-aware candidate markers
  • Long-press pronunciation and definition previews
  • A dense expanded candidate grid that does not sacrifice browsing space
  • Separation between ordinary candidate ranking and dictionary annotations
  • Unihan data import tooling
  • Automated tests and reproducible APK builds

For example, entering 934 can retrieve wei candidates while the metadata layer separately provides tone-marked pinyin and definitions. The dictionary data does not artificially push obscure characters above common ones. It adds knowledge without damaging normal typing behavior.

How I Built It

I used Codex as an engineering collaborator throughout the project.

The process was highly iterative:

  1. I described the actual typing problem rather than prescribing an implementation.
  2. Codex inspected the existing architecture and identified reusable components.
  3. We compared continuing a clean-room prototype with adapting an established open-source project.
  4. After choosing Aegis, Codex migrated the project, preserved its existing features, and made Chinese T9 the default.
  5. I installed each APK on a real Android phone and tested the interaction manually.
  6. I returned screenshots and exact failure cases.
  7. Codex revised the implementation, added regression tests, ran lint, and rebuilt the APK.

This loop was especially important for the dictionary interface. An early version displayed every dictionary candidate as a large card. It worked technically, but one pronunciation could have dozens of matching characters, so the interface became too tall and difficult to browse.

We redesigned it as:

  • a dense grid for ordinary browsing;
  • a small indicator on characters with metadata;
  • one shared preview card;
  • a long press to pin the preview;
  • a tap on the preview to open the full entry.

This was not something I could have specified perfectly before using it. The design emerged from real-device testing.

Dictionary Data

The first implementation uses Unicode Unihan data for character readings, variants, and metadata. I also found a large MDX/MDD dictionary collection oriented toward classical Chinese, rare characters, proper names, historical dictionaries, and character origins.

The next data pipeline will extract only the information appropriate for quick input-method use:

Character + modern pronunciation + first useful definition

For example:

渭  wèi
水名。源出今甘肃省鸟鼠山,经陕西中部,至潼关入黄河。

Traditional phonological data such as fanqie, rhyme groups, and Middle Chinese classifications can remain available in the full entry, but they should not overwhelm the compact preview.

The input method will never read a huge PDF or dictionary file during typing. Source dictionaries are converted into indexed binary or database formats for fast offline lookup.

Personalization

The larger goal is to make the keyboard learn from my own writing.

I plan to import two very different personal corpora:

  • fiction and fan writing, containing names, relationships, historical vocabulary, and stylistic phrases;
  • laboratory notes, containing plant biology terminology, Arabidopsis gene names, experimental conditions, and mixed Chinese-English expressions.

The dictionary answers:

What does this character mean?

My personal corpus answers:

What am I likely to type?

These responsibilities remain separate. A rich dictionary entry should not automatically receive a high typing frequency, and a frequently used personal term should not overwrite dictionary definitions.

Planned examples include:

曹丕
紫鸾
根尖再生
细胞壁感知
Arabidopsis
ARH1
FEI1
RNA-seq
Col-0

What I Learned

The biggest lesson was that an input method is not simply a keyboard UI connected to a word list.

It is a system of interacting layers:

  • digit-to-pinyin decoding;
  • pinyin segmentation;
  • candidate generation;
  • frequency ranking;
  • contextual prediction;
  • personal learning;
  • touch gestures;
  • privacy-sensitive fields;
  • dictionary metadata;
  • backup and migration;
  • device-specific behavior.

I also learned that automated tests and real-device testing solve different problems.

Tests can verify that:

  • 934 resolves to wei;
  • “渭” exists in the dictionary candidates;
  • tapping commits the correct character;
  • metadata lookup returns the expected reading;
  • ordinary candidate order remains unchanged.

But tests cannot fully answer:

  • Is the preview comfortable to trigger?
  • Does a swipe conflict with scrolling?
  • Is the candidate grid too crowded?
  • Does the card disappear at the wrong moment?
  • Does the interaction feel natural during actual conversation?

Codex could build and verify the system, but I still had to act as the human usability tester.

Another important lesson was to reuse mature infrastructure instead of rebuilding everything for ideological purity. My original plan was a completely independent T9 engine. After inspecting Aegis, I realized that adapting a tested offline-first foundation would let me focus on the distinctive parts of the project: personalized language learning and dictionary-assisted character discovery.

Challenges

1. Designing discovery without disrupting typing

Rare characters cannot simply be placed at the front of the candidate list. That would make the keyboard educational but frustrating.

The solution was to keep ordinary ranking intact and treat pronunciation and definitions as an additional metadata layer.

2. Showing definitions without making the keyboard enormous

Displaying a definition beneath every character quickly consumed the entire screen.

The current design keeps the grid dense and displays only one shared preview when the user deliberately long-presses a marked character.

3. Gesture conflicts

An early interaction required an upward swipe to pin the preview. Unfortunately, the same gesture also scrolled the candidate grid.

The revised model is simpler:

  • tap: enter the character;
  • long press: pin the preview;
  • tap the preview: open the full entry;
  • tap elsewhere: close it.

4. Processing dictionary sources

A scanned classical Chinese dictionary initially seemed promising, but OCR would be unreliable for complex, rare, traditional, and variant glyphs.

Finding structured MDX/MDD dictionary data changed the direction of the project. Instead of attempting large-scale OCR, the project can parse structured entries and preserve specialized fonts and glyph resources where needed.

5. Working without an Android emulator

The development computer did not have an Android emulator configured. Codex could run tests, lint, and builds, but it could not directly experience the final touch interaction.

I therefore transferred each APK to my phone, tested it manually, captured screenshots, and described the exact mismatch between the implementation and my intended behavior.

What Comes Next

The current roadmap is:

  1. Finalize and archive the stable dictionary-preview version.
  2. Integrate the larger classical Chinese dictionary.
  3. Build a reusable personal-corpus import pipeline.
  4. Learn Chinese vocabulary and contextual preferences from my writing.
  5. Add English completion, spelling correction, and scientific terminology.
  6. Support editing pinyin in the middle of an unfinished composition.
  7. Add in-keyboard speech recognition without switching input methods.
  8. Redesign the visual style and symbol panel after the functional layout is stable.

Why This Project Matters to Me

YanHuiIME began as a personal frustration: my keyboard did not know the language of my research, my writing, or my interests.

But it gradually became a broader experiment in what an input method could be.

A keyboard does not have to be a passive utility that waits for perfect instructions. It can adapt to a person’s vocabulary, preserve private learning locally, reduce the friction of specialized writing, and quietly introduce unfamiliar knowledge at the moment it becomes relevant.

I wanted a keyboard that recognizes how I write.

Now I am building one that may also change what I am able to write.

Built With

Share this project:

Updates

Submission history