Annotasi teks Mandarin langsung di halaman web dengan pinyin inline di atas hanzi dan definisi Bahasa Indonesia melalui popup atau panel.
CC-CIDICT Annotator menggunakan:
- Node.js untuk backend
- Express untuk HTTP API dan static file server
@node-rs/jiebauntuk segmentasi teks Mandarin- SQLite untuk database kamus
- JavaScript single-file untuk client/browser
- CC-CIDICT sebagai sumber data kamus dari cidict.org
Persyaratan: Node.js 22.5+
Anda tidak perlu deploy backend sendiri. Untuk menggunakan annotator di website, cukup muat client dari server CC-CIDICT:
<script src="//api.cidict.org/static/cidict-annotator.min.js" charset="UTF-8"></script>
<script>
cidict.annotate('.chinese-text', { theme: 'light' });
</script>Contoh:
<p class="chinese-text">
这个故事特别有意思。
</p>
<script src="//api.cidict.org/static/cidict-annotator.min.js" charset="UTF-8"></script>
<script>
cidict.annotate('.chinese-text');
</script>'.chinese-text' adalah selector CSS untuk elemen yang ingin dianotasi.
Secara default, client menggunakan origin tempat file JavaScript dimuat sebagai apiBase. Dengan contoh di atas, request API otomatis diarahkan ke api.cidict.org.
cidict.configure({
apiBase: 'https://api.example.org'
});
cidict.annotate('.chinese-text', {
theme: 'light',
displayMode: 'popup'
});Opsi yang tersedia:
| Opsi | Default | Keterangan |
|---|---|---|
theme |
'light' |
'light' atau 'dark' |
showInline |
true |
Tampilkan pinyin inline |
showPopups |
true |
Tampilkan popup/panel definisi |
displayMode |
'popup' |
'popup', 'docked', atau 'both' |
dockAlign |
'right' |
Posisi dock desktop: 'left' atau 'right' |
chunkSize |
2000 |
Ukuran chunk untuk teks panjang; 0 = nonaktif; min 200 |
maxConcurrency |
3 |
Jumlah request anotasi paralel; batas 1–6 |
loading |
null |
Selector atau { target, show } untuk indikator loading |
popup — mode default. Di desktop, hover menampilkan pinyin utama dan hingga 4 definisi; klik membuka informasi lengkap. Pada perangkat tanpa hover, interaksi dilakukan dengan tap.
docked — definisi ditampilkan dalam panel. Di desktop panel berada di kiri/kanan; di mobile menjadi bottom sheet.
both — popup dan dock tersedia bersama dengan perilaku yang menyesuaikan perangkat.
Preferensi pengunjung seperti tema, pinyin, hanzi tradisional, dan mode tampilan disimpan di localStorage menggunakan key cidict_prefs.
cidict.annotate('.artikel');
cidict.annotateText('这个故事特别有意思。');
cidict.lookup('喝');
cidict.health();
cidict.setDisplayMode('docked');
cidict.toggleDisplayMode();
cidict.togglePinyin();
cidict.toggleHanzi();
cidict.toggleTheme();
cidict.showInline(false);
cidict.showPopups(false);
cidict.unannotate('.artikel');
cidict.destroy();annotate() dan annotateText() mengembalikan Promise.
annotateText() mengembalikan HTML hasil anotasi tanpa langsung memasukkannya ke halaman:
const html = await cidict.annotateText('你好世界');
document.querySelector('#hasil').innerHTML = html;Backend dapat dijalankan sendiri pada VPS atau server Linux yang dapat menjalankan Node.js 22.5+.
Deployment serverless seperti Vercel belum menjadi target atau konfigurasi resmi project ini. README ini hanya mendokumentasikan deployment pada server/VPS dengan proses Node.js yang berjalan terus-menerus.
git clone https://github.com/pseudovin/cidict-annotator.git /opt/cidict
cd /opt/cidict
npm install
npm run buildDatabase tidak disertakan di repository.
Download database CC-CIDICT dan version.json terbaru dari halaman download resmi:
Setelah diunduh, letakkan kedua file tersebut di server, misalnya:
/opt/cidict-data/
├── cc-cidict.db
└── version.json
Nama file dapat disesuaikan dengan file yang tersedia pada halaman download.
Buat file .env di direktori project:
PORT=3100
CIDICT_DB=/opt/cidict-data/cc-cidict.db
CIDICT_DB_VERSION_FILE=/opt/cidict-data/version.json
CIDICT_DB_HASH_CHECK=true
CIDICT_MIN_FREQ=1000
CIDICT_HMM=false
CIDICT_CACHE_SIZE=1000
CIDICT_CACHE_FILE=/opt/cidict-data/annotate-cache.db
CIDICT_CACHE_DISK_SIZE=10000
CIDICT_RATE_LIMIT=120
CIDICT_RELOAD_TOKEN=TULIS_TOKEN_UNIK_DAN_PANJANG_DISINIVariabel utama:
| Variabel | Default | Keterangan |
|---|---|---|
PORT |
3100 |
Port HTTP server |
CIDICT_DB |
path database lokal | Path database SQLite |
CIDICT_DB_VERSION_FILE |
kosong | Path version.json; jika diaktifkan, versi database dapat dipantau untuk hot reload |
CIDICT_DB_HASH_CHECK |
true |
Verifikasi databaseMd5 dari version.json |
CIDICT_MIN_FREQ |
1000 |
Minimum frekuensi kata pada leksikon jieba |
CIDICT_HMM |
false |
Aktif/nonaktif model HMM jieba |
CIDICT_CACHE_SIZE |
1000 |
Cache memori LRU; 0 untuk menonaktifkan |
CIDICT_CACHE_FILE |
path cache lokal | Cache SQLite persisten; kosongkan untuk menonaktifkan |
CIDICT_CACHE_DISK_SIZE |
10000 |
Jumlah maksimum entri cache disk |
CIDICT_RATE_LIMIT |
120 |
Rate limit POST /api/annotate: maks request per IP per 60 detik; 0 = nonaktif |
CIDICT_RELOAD_TOKEN |
kosong | Token proteksi POST /api/seg-reload; koneksi langsung dari localhost bebas token |
npm startSecara default server menggunakan port 3100.
Untuk production, gunakan process manager seperti systemd dan reverse proxy seperti nginx atau Caddy untuk HTTPS.
Buat:
/etc/systemd/system/cidict.service
[Unit]
Description=CC-CIDICT Annotator
After=network.target
[Service]
WorkingDirectory=/opt/cidict
ExecStart=/usr/bin/node server.js
Restart=always
[Install]
WantedBy=multi-user.targetAktifkan:
systemctl daemon-reload
systemctl enable --now cidictPeriksa service:
systemctl status cidict
curl http://127.0.0.1:3100/api/healthKemudian arahkan reverse proxy ke:
http://127.0.0.1:3100
Disarankan menyimpan database dan cache di luar repository, misalnya:
/opt/cidict-data/
Dengan begitu, file data tidak ikut tertimpa ketika aplikasi di-update atau di-deploy ulang.
Self-hosting tidak mengunduh database baru secara otomatis dari repository GitHub.
Untuk memperoleh data terbaru, download kembali database CC-CIDICT dan version.json terbaru dari:
Backend mendukung hot reload ketika CIDICT_DB_VERSION_FILE digunakan. Saat versi pada version.json berubah, server dapat memuat ulang database dan membangun ulang artefak turunannya tanpa restart.
Untuk keamanan, database baru diverifikasi menggunakan databaseMd5. Jika database tidak cocok atau gagal dimuat, database yang sedang aktif tetap digunakan.
Urutan update yang disarankan:
download file terbaru
↓
upload database ke server
↓
pastikan upload selesai
↓
update version.json
↓
backend mendeteksi versi baru
↓
database di-reload
Pastikan nama file database (DB) sudah sesuai dengan nilai CIDICT_DB di file .env.
Jangan memperbarui version.json sebelum database baru tersedia sepenuhnya.
Backend menyediakan API untuk annotasi dan lookup:
| Endpoint | Keterangan |
|---|---|
GET /api/health |
Status service dan metadata database |
POST /api/annotate |
Segmentasi + pinyin + definisi (rate limit 120 req/menit/IP) |
GET /api/lookup?text=喝 |
Lookup satu kata |
POST /api/seg-reload |
Reload aturan segmentasi dan prioritas pinyin (dari localhost bebas token; dari luar wajib token) |
GET /static/cidict-annotator.min.js |
Client JavaScript |
GET / |
Halaman demo |
Request:
{
"text": "这个特别好"
}Response:
{
"tokens": ["这个", "特别", "好"],
"defs": {
"这个": {
"r": [
{ "y": "zhège", "d": ["ini"] }
],
"t": "這個"
},
"好": {
"r": [
{ "y": "hǎo", "d": ["bagus; baik"] },
{ "y": "hào", "d": ["suka"] }
],
"t": null
}
},
"v": "1791109522067.4575:0"
}Keterangan:
tokens— hasil segmentasi jieba.defs— data kamus yang ditemukan.r— daftar bacaan;y= pinyin bertanda nada,d= definisi.t— bentuk tradisional;nullbila sama dengan simplified.v— versi data yang digunakan sebagai bagian dari cache client.
Pinyin dinormalisasi ke bentuk ortografi yang lebih natural, misalnya:
kě yǐ → kěyǐ
píng ān → píng'ān
Běi jīng Dà xué → Běijīng Dàxué
Teks yang dikirim ke endpoint anotasi dibatasi hingga 20.000 karakter. Client dapat memecah teks panjang menjadi beberapa chunk dan menjalankan request secara paralel. Endpoint ini juga dilindungi rate limit 120 request/menit per IP (HTTP 429 + header Retry-After bila terlampaui).
Daftar kata yang perlu diperlakukan sebagai force-split oleh segmenter.
Satu kata per baris. Komentar dapat diawali # atau //.
Digunakan untuk memprioritaskan bacaan pinyin tertentu.
Format:
<kata> = <pinyin>
Contoh:
喝 = hē
Override ini berguna ketika sebuah kata memiliki beberapa kemungkinan bacaan dan urutan default tidak sesuai konteks yang diinginkan. Endpoint ini mengubah state server, jadi tidak terbuka bebas:
- Koneksi TCP langsung dari localhost (mis.
curlvia SSH kehttp://127.0.0.1:3100/api/seg-reload) → bebas token. - Dari luar → wajib token: header
Authorization: Bearer <token>atau query?token=<token>, dengan<token>= isiCIDICT_RELOAD_TOKEN. Tanpa token yang cocok →403. - Request via reverse proxy selalu membawa
X-Forwarded-Forsehingga tidak dihitung sebagai localhost — token tetap wajib walau nginx-nya sekota dengan Node. - Bila
CIDICT_RELOAD_TOKENkosong, non-localhost selalu403.
# via SSH (tanpa token)
curl -X POST http://127.0.0.1:3100/api/seg-reload
# dari luar (dengan token)
curl -X POST -H "Authorization: Bearer $TOKEN" https://api.cidict.org/api/seg-reload
# atau: curl -X POST "https://api.cidict.org/api/seg-reload?token=$TOKEN"
# via Console
fetch('https://api.cidict.org/api/seg-reload/?token=<TOKEN>', { method: 'POST' })
.then(r => r.json()).then(console.log)Source client:
src/cidict-annotator.js
Build client:
npm run buildOutput:
dist/cidict-annotator.min.js
Backend:
server.js
Normalisasi dan prioritas pinyin:
pinyin.js
Aturan segmentasi:
segment_overrides.txt
Prioritas bacaan:
pinyin_priority.txt
CC-CIDICT Annotator menggunakan database dari CC-CEDICT (© CC-CEDICT Contributors). Versi Bahasa Indonesia awal dikembangkan oleh Harmony Mandarin, dan diteruskan secara mandiri sebagai proyek CC-CIDICT. Didistribusikan di bawah lisensi Creative Commons Attribution–ShareAlike 4.0 International (CC BY-SA 4.0).