2026-08-11 19:35:11 +09:00
2026-08-13 21:25:12 +09:00
2026-08-13 21:25:12 +09:00
2026-08-12 21:23:59 +09:00
2026-08-12 17:33:14 +09:00
2026-08-11 19:35:11 +09:00
2026-08-14 02:43:42 +09:00
2026-08-12 15:54:16 +09:00
2026-05-28 23:38:23 +09:00
2026-08-14 02:43:42 +09:00
2026-08-12 15:54:16 +09:00
2026-08-11 19:34:14 +09:00

strans

strans is a small, single-user input method for Korean, Japanese, English, and emoji. It provides one engine shared by IBus, XIM, and GTK 3 frontends. The existing Vietnamese Telex mode remains available for compatibility, but is not an actively developed language mode.

Input behavior

English is direct passthrough. Korean uses 2-beolsik composition. Japanese Hiragana keeps the complete kana reading until it is committed, so kanji forms かんじ and offers whole-reading candidates such as 漢字 and 幹事. An apostrophe resolves an ambiguous n without forwarding the apostrophe: for example, n'ya forms んや. Katakana is direct Katakana composition and does not perform Kanji dictionary conversion.

A Japanese composition is committed by Enter, candidate selection, a real input boundary, or an explicit mode change. Backspace first removes pending romaji, then accumulated kana. The Japanese modes support doubled consonants and combinations such as nya, nnya, and matcha.

Modes and temporary searches use Ctrl and one letter:

Ctrl+N  Japanese Hiragana and Kanji conversion
Ctrl+K  Japanese Katakana
Ctrl+S  Korean Hangul
Ctrl+T  English passthrough
Ctrl+V  Vietnamese Telex compatibility mode
Ctrl+E  Emoji and symbol search
Ctrl+H  One-shot Hanja search
Ctrl+P  Toggle popup preedit

While candidates are visible, Up and Down move the selection, Enter accepts the selected candidate, and an unmodified 1-9 selects the corresponding visible row. Tab cycles temporary search results. 0 commits an unconverted language reading. Escape cancels the current composition. Ctrl, Alt, or Super combined with a number does not select a candidate.

Emoji search is temporary and returns to the previous mode. Queries may use English aliases or the active language's input rules, including Japanese egao becoming えがお or エガオ:

Ctrl+E → smile → Enter → 😀

Hanja search is temporary and returns to the active language after one conversion. Press Ctrl+H and type with that language's normal input rules, then select with Up, Down, Tab, Enter, or 1-9. The bundled dictionary currently indexes exactly one modern Hangul syllable. Incomplete jamo, multiple syllables, and other languages therefore have no candidates; Enter commits the displayed reading unchanged. Escape cancels the search. It does not convert words or text already surrounding the cursor.

Build and test

The supported build uses Docker so host and container toolchains are not mixed. Only Docker and Make are needed on the host:

git submodule update --init
make docker-image
make docker-build
make docker-check

docker-image creates the Arch Linux dependency image, docker-build compiles the runtime components, and docker-check runs the map verifiers and test suites. Docker targets force their own compilation, so newer host objects cannot be reused. docker is a convenience alias for the image and build steps. The resulting runtime artifacts are:

strans              daemon and IBus frontend
xim/strans-xim      XIM frontend
gtk/im-strans.so    GTK 3 frontend

Use make docker-check TESTARGS=hangul to filter the C unit tests. A native build is still possible with the dependencies and Plan 9 setup recorded in Dockerfile; use make all, make check, and make bench inside that environment.

After editing an input source, regenerate and verify its dictionary with:

map/mkemoji >map/emoji.dict
map/mkhanja >map/hanja.dict
make verify-map

Hanja import and Japanese dictionary regeneration are documented in map/README. The converter output is deterministic UTF-8, tab-separated data consumable by the runtime dictionary reader.

Run and install

Install one or more scalable outline fonts, then pass their files in fallback order after the map directory. The daemon accepts at most four font files and does not search the system font database. For example, the Docker-tested Arch packages and paths are:

doas pacman -S ttf-dejavu ttf-jigmo
./strans map \
    /usr/share/fonts/TTF/DejaVuSans.ttf \
    /usr/share/fonts/TTF/Jigmo.ttf \
    /usr/share/fonts/TTF/Jigmo2.ttf &

These fonts are test fixtures, not runtime requirements. Any suitable scalable outline files may be supplied; their argument order is the glyph fallback order. A collection file uses its first face. If any named file is absent or invalid, the popup disables itself cleanly while input processing continues. run.sh and bench.sh accept the same font-file arguments. When run.sh is invoked without arguments, it uses the installed DejaVu, Jigmo, or Noto CJK font files from the standard Arch Linux paths. Explicit font-file arguments replace these defaults:

./run.sh
./run.sh /path/to/primary.ttf /path/to/fallback.ttc

run.sh remains in the foreground and owns only the daemon and XIM process that it starts. It waits for that daemon's IPC socket and IBus address file before reporting success. With DISPLAY set it then starts XIM; without a display it keeps the headless daemon in the foreground and does not start XIM. A signal or XIM exit stops and reaps the launcher's daemon. The launcher never replaces an existing daemon: an occupied per-user socket is a visible startup failure.

The IPC socket is placed at $XDG_RUNTIME_DIR/strans.sock when XDG_RUNTIME_DIR is an absolute path. Otherwise strans uses the per-user fallback /tmp/strans.<uid>. A second daemon will not replace a live daemon's socket.

For XIM applications:

./xim/strans-xim &
export XMODIFIERS=@im=strans
xterm

For GTK 3 applications, install the module built by Docker. Installation needs the GTK 3 runtime, but not its development package:

doas make -C gtk install

LIBDIR defaults to /usr/lib and may be overridden for another system. Normal DESTDIR semantics are supported, and a staged install does not update the host GTK module cache:

make -C gtk install DESTDIR="$pkgdir"

For IBus clients such as kitty:

GLFW_IM_MODULE=ibus kitty

strans provides its own IBus endpoint; neither ibus-daemon nor fcitx is required. Starting without DISPLAY is supported: input processing and IBus continue to run while the optional X popup is disabled.

Ownership and rendering constraints

There is one global composition, not one independent engine per frontend context. The first meaningful key from a new context resets the previous composition and transfers ownership. Reset, focus loss, context destruction, and disconnect affect the engine only when they come from its active owner; stale events cannot clear a newer owner's preedit.

The popup is an optional X window. It uses the explicit font-file order and fixed-width rune cells; U+FE0E and U+FE0F variation selectors use zero cells. It does not perform OpenType shaping, color-emoji rendering, or general grapheme clustering. Multi-rune emoji are committed intact but are drawn as their constituent rune cells under this boundary. A supplied caret rectangle is used when available, with the pointer as fallback. The X renderer accepts only a 24-depth, 32-bpp TrueColor root format and disables itself cleanly on other visuals.

Data, third-party code, and licensing

Data and third-party provenance is recorded in docs/PROVENANCE.md, with font-specific details in font/PROVENANCE. No font binaries are bundled; that file retains the provenance of the faces formerly kept in the repository. The historical SKK-derived Kanji dictionary is distributed under GPL version 2 or later; its license text is in LICENSES/GPL-2.0-or-later.txt. The single-character Hanja data derived from libhangul is distributed under the BSD 3-Clause license in LICENSES/BSD-3-Clause-libhangul-hanja.txt.

The repository does not currently declare a license for the strans project source as a whole. The licenses of bundled data, historical font assets, and third-party components do not by themselves license the original strans source.

Description
No description provided
Readme 59 MiB
Languages
C 91.1%
Python 5.8%
Makefile 2.2%
Shell 0.6%
Dockerfile 0.3%