Background
As a native Cantonese speaker, I found it inconvenient to repeat all the time when I have to teach others how to speak my language. I acquired Jyutping (粵拼) a couple of years ago. It’s a popular phonetic system for the Cantonese language. However, some of my fellow countrymen aren’t fond of this romanization scheme.
A soft “introduction” to “Introduction to Jyutcitzi”
Recently, I’ve heard of another phonetic system called Jyutcit (粵切). It’s basically a “cutting sound method” (切音法). Each syllable is “initial + final”. To compose a sound, we take two syllables, from which we keep
- the “initial initial” (i.e. the initial of the first syllable)
- the “final final” (i.e. the final of the second syllable)
To do so, we need to “cut” both syllables—that’s how we got the name “切音法”. Thus, the application of this “cutting sound method” to the Cantonese language is “Cantonese cutting sound method” (粵語切音法), which we call “Jyutcit” (粵切) for short. Instead of using latin alphabets to denote the sounds, a specific set of characters or character components representing the sounds has been chosen. They would be the building blocks to be combined with other blocks to form a character (i.e. zi 字).
Problem
The jyutcitzi (粵切字), which are the characters formed when combining two (possibly three in case of compound initials, which are used for transcribing sounds from foreign languages, say “skill”), can’t be easily input from keyboard.
Solution
I’ve published a typst package called jyutcitzi to provide support for that.
To call this package on my local machine, I would need a heading like this.
#import "../jyutcitzi/lib.typ": *
#set page(height: auto, width: auto, margin: 5pt)
#set text(font: "Noto Serif CJK TC")
#jyutcitzi("keu")#jyutcitzi("leu")#jyutcitzi("liu")#jyutcitzi("leng")粵字
"Skill"#jyutcitzi("ge")#jyutcitzi("jyut")#jyutcitzi("zi")係「#combine-parts(
combine-parts(beginnings-dict.s.at(0), beginnings-dict.k.at(0), "-"),
"么",
"|"
)」。

Lessons learnt
typst package creation
The official way is typst init, which I didn’t know. I relied on Google
Gemini, which also generated the project structure and tests.
The exclude field is for everything that is neither the necessary for the
package to work nor linked in the README nor LICENSE.
smoke test vs unit tests
The later is to test if each unit (i.e. function) works as expected. The former is about how those units work together with the background.
upload the package to the typst universe
- The GitHub repo
typst/packageshas to be forked. - In
preview/pakcages/,package_name/version/(i.e.jyutcitzi/0.1.0) in my case has to be added. We cannot add it as a submodule.
- In principle, forking to a local machine using command prompt would work. However, that would copy all packages on the typst universe with all versions—that’s is very inefficient because I won’t need most of the functionalities there—about 600 MB of data would be downloaded. When the network is slow, that can take a few minutes!
- I think a more reasonable approach would be to utilize the github.dev editor. From my OS’s GUI file explorer, I select, drag and drop necessary files and/or folders into the left side pane for files. In this way, only the necessary files for the package would be transmitted.
My initial attemtpt didn’t succeed because the omission of the license field
had triggerred an error from GitHub Actions.
TODO
It’s a nightly build, and looking back, there’re several rooms of improvement.
I’m gonna make the main function (jyutcitzi()) more like a Swiss knife.
- support space-delimited jyutping sequence (
jyutcitzi("jyut cit zi")), so that it’s more usable then the current solution - support jyutping with digits (
jyutcitzi("jyut6")) (without breaking current behavior)- need rewriting
split-jyutping()method to capture the digit - refactor this method so that the input is an expanded tuple
- expose this utility method to entrypoint to that it can be used by others
- need rewriting
- accept space-delimited jyutcitzi alphabet group (initial + final) sequence
(
jyutcitzi("央乙 此子 止子"))- refactor
beginning→jc-initial - refactor
ending→jc-final(finalis a typst function name)
- refactor
- simplify the syntax for compound initial (
jyutcitzi("厶臼么"))