Thomas Verhave

Writing · Build Notes

I wrote a transliterator for Afrikaans in Japanese hiragana — then made it a Linux locale

Afrikaans has a shallow, phonetic spelling system.

Afrikaans has a shallow, phonetic spelling system. Hiragana is a syllabary built for a completely different language. I wondered what would happen if I forced one through the other — so I built Afurigana: a rule-based transliterator that writes Afrikaans phonetically in hiragana.

$ python3 afurigana.py "Goeie more, hoe gaan dit?"
ふいー もれ, ふ はーん でぃと?

The name is a pun — Afrikaans + furigana (振り仮名), the little hiragana reading-aids Japanese prints above kanji. Then I took it too far and installed it as a system locale, so my whole Linux desktop renders its Afrikaans UI in kana. More on that at the end.

The core problem: a syllabary can't spell an alphabet

Hiragana's units are vowels (あいうえお) and consonant+vowel pairs (か き く…). Afrikaans is alphabetic, with heavy consonant clusters and more vowel qualities than hiragana has sounds. You can't map letter-to-letter.

So Afurigana borrows the exact strategy Japanese already uses for foreign loanwords:

  1. Break each word into consonant–vowel syllables.
  2. Insert a default vowel to split consonant clusters (linguists call this epenthesis — it's why "strike" becomes ストライク, su-to-ra-i-ku).
  3. Approximate sounds hiragana lacks with the nearest row.

It maps spelling, not perfect pronunciation. It's a "sample system," not IPA — and being honest about that shaped every rule.

The fun part: the sounds hiragana doesn't have

This is where a phonology becomes a lookup table of small, opinionated decisions:

Afrikaans sound hiragana why
g, ch raspy [x] は-row(は ひ ふ へ ほ) no velar fricative — the same trick that makes Bach → バッハ
v, f [f] ふ + small vowel(ふぁ ふぃ ふぇ ふぉ) there's no f-row, so build one from ふ
w [v]/[w] わ-row(わ うぃ う うぇ うぉ)
l and r [l], [r] both → ら-row hiragana has no L at all; L and R must share
sj [ʃ] し / しゃ しゅ…
tj [tʃ] ち / ちゃ ちゅ…
ng [ŋ]

That l and r collapsing into the same row is the kind of lossy, one-way decision that makes transliteration fascinating — かける could map back to several Afrikaans spellings, so the transform is deliberately not reversible.

The syllable rules that make it read right

A handful of rules do most of the work:

A few from the phrasebook, to show the feel of it:

Afrikaans Afurigana English
Baie dankie ばいー だんきー Thank you very much
Ek het jou lief えく へと やう りーふ I love you
Lekker れっける Nice / great
Vis en tjips ふぃす えん ちぷす Fish and chips
Suid-Afrika さいど-あふりか South Africa

Then I made it a locale

A transliterator is a script you run. I wanted the operating system to speak it. So I built af_JP — "Afrikaans (Japan)" — a real installed locale whose message catalogue is the Afrikaans desktop UI run through Afurigana.

The install has one non-obvious gotcha worth sharing. You can drop a compiled locale into /usr/share/locale/, but the next time locale-gen runs (an apt upgrade, say), it rebuilds the archive from source definitions and silently drops your locale because there's no source for it. The fix is to give it one:

# give locale-gen a source file named af_JP (a copy of af_ZA) so the
# locale survives future locale-gen runs (apt upgrades, etc.)
sudo cp -n /usr/share/i18n/locales/af_ZA /usr/share/i18n/locales/af_JP
sudo localedef -i af_JP -f UTF-8 af_JP.UTF-8
echo "af_JP.UTF-8 UTF-8" | sudo tee -a /etc/locale.gen
sudo locale-gen

Set it as your language and menus, buttons, and dialogs come back in Afrikaans-in-hiragana. It is gloriously impractical and I love it.

What I learned

A build-story · see the live project → · more writing →