basa 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- basa/__init__.py +33 -0
- basa/augment/__init__.py +0 -0
- basa/augment/noise.py +0 -0
- basa/augment/paraphrase.py +0 -0
- basa/augment/synthetic.py +0 -0
- basa/core/__init__.py +0 -0
- basa/core/normalize.py +240 -0
- basa/core/quick.py +48 -0
- basa/core/slang.py +2071 -0
- basa/core/typo.py +470 -0
- basa/dataset/__init__.py +0 -0
- basa/dataset/builder.py +0 -0
- basa/dataset/cleaner.py +0 -0
- basa/dataset/split.py +0 -0
- basa/dataset/validator.py +0 -0
- basa/evaluate/__init__.py +0 -0
- basa/evaluate/factual.py +0 -0
- basa/evaluate/metrics.py +0 -0
- basa/evaluate/similarity.py +0 -0
- basa/tokenize/__init__.py +0 -0
- basa/tokenize/lang_detect.py +0 -0
- basa/tokenize/sentence.py +0 -0
- basa/tokenize/word.py +0 -0
- basa/translate/__init__.py +0 -0
- basa/translate/jv_id.py +0 -0
- basa/translate/router.py +0 -0
- basa/translate/su_id.py +0 -0
- basa/utils/__init__.py +0 -0
- basa/utils/constants.py +0 -0
- basa/utils/regex.py +0 -0
- basa/utils/text_clean.py +0 -0
- basa-0.1.0.dist-info/METADATA +439 -0
- basa-0.1.0.dist-info/RECORD +35 -0
- basa-0.1.0.dist-info/WHEEL +4 -0
- basa-0.1.0.dist-info/licenses/LICENSE +21 -0
basa/core/slang.py
ADDED
|
@@ -0,0 +1,2071 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BASA - Slang Normalization Module
|
|
3
|
+
===================================
|
|
4
|
+
Converts informal/colloquial Indonesian text (including Javanese/Sundanese
|
|
5
|
+
particles) into standardized Indonesian.
|
|
6
|
+
|
|
7
|
+
Supported categories:
|
|
8
|
+
- Pronouns (aku/kamu shortcuts)
|
|
9
|
+
- Kinship & address terms (kk, bokap, nyokap, dll)
|
|
10
|
+
- Negation (ga/gak/nggak → tidak)
|
|
11
|
+
- Compound negation (gamau, gabisa, gatau → tidak mau, dll)
|
|
12
|
+
- Conjunctions & prepositions (abbreviations like yg, dgn, krn)
|
|
13
|
+
- Common verbs (udah, blm, mo, tau, liat, dll)
|
|
14
|
+
- Adjectives & adverbs (bgt, bener, lumayan, dll)
|
|
15
|
+
- Question words (knp, gmn, kmn, dll)
|
|
16
|
+
- Greetings & responses (makasih, ok, sip, tq, dll)
|
|
17
|
+
- Temporal & location (skrg, ntr, kmrn, sini, dll)
|
|
18
|
+
- Internet slang → Indonesian equivalent (btw, lol, omg, dll)
|
|
19
|
+
- E-commerce & finance (ongkir, rekber, tf, dll)
|
|
20
|
+
- Youth & Gen-Z slang (mager, baper, gabut, dll)
|
|
21
|
+
- Discourse markers (mksd, intinya, menurutku, dll)
|
|
22
|
+
- Javanese extended (mangan, turu, apik, dll)
|
|
23
|
+
- Sundanese extended (abdi, anjeun, geus, dll)
|
|
24
|
+
- Nouns (temen, hp, laptop, dll)
|
|
25
|
+
- Health terms (dmm, btk, opname, dll)
|
|
26
|
+
- Emotions & expressions (galau, baper, kesal, ghosting, dll)
|
|
27
|
+
- Food & drink (nasgor, kopsu, laper, kenyang, dll)
|
|
28
|
+
- Clothing & fashion (ootd, thrifting, hoodie, dll)
|
|
29
|
+
- Transportation (ojol, krl, macet, nebeng, dll)
|
|
30
|
+
- Religion & culture (alhamdulillah, bismillah, ultah, dll)
|
|
31
|
+
- Education extended (bimbel, ospek, maba, snbt, dll)
|
|
32
|
+
- Work & office (wfh, deadline, lembur, resign, dll)
|
|
33
|
+
- Numbers & quantity (1rb, 5jt, rata2, tiba2, dll)
|
|
34
|
+
- Compound expressions (ngapain, otw ke, kapan2, dll)
|
|
35
|
+
- Particles (lah, deh, nih, dong, kok, sih, lho, pun, dll)
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
from basa.core.slang import slang
|
|
39
|
+
|
|
40
|
+
# Basic usage (convenience singleton)
|
|
41
|
+
result = slang.normalize("gw gamau pergi krn lg baper bgt")
|
|
42
|
+
# → "saya tidak mau pergi karena sedang bawa perasaan banget"
|
|
43
|
+
|
|
44
|
+
# Inspect all supported slang words
|
|
45
|
+
words = slang.supported_words()
|
|
46
|
+
# → {"adek": "adik", "ak": "aku", "ane": "saya", ...}
|
|
47
|
+
|
|
48
|
+
# Count total entries
|
|
49
|
+
len(slang)
|
|
50
|
+
# → 120+
|
|
51
|
+
|
|
52
|
+
# With custom entries
|
|
53
|
+
from basa.core.slang import SlangNormalizer
|
|
54
|
+
normalizer = SlangNormalizer(custom_mapping={"jancok": "ekspresi"})
|
|
55
|
+
result = normalizer.normalize("gw jancok kaget")
|
|
56
|
+
|
|
57
|
+
# Batch processing
|
|
58
|
+
texts = ["gw udah makan", "km blm tidur?"]
|
|
59
|
+
results = slang.normalize_batch(texts)
|
|
60
|
+
|
|
61
|
+
Notes:
|
|
62
|
+
- All replacements are lowercased (standard for NLP preprocessing).
|
|
63
|
+
- Word boundaries (\\b) prevent partial-word substitution.
|
|
64
|
+
- Slang keys sorted longest-first to prevent premature partial matches.
|
|
65
|
+
- Repeated character normalization distinguishes vowels vs consonants
|
|
66
|
+
to avoid breaking abbreviations like "kk", "dll", "mm".
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
import re
|
|
70
|
+
|
|
71
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
# SLANG DICTIONARY (organized by category for easier maintenance)
|
|
73
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
# First & second person pronouns
|
|
76
|
+
_PRONOUNS: dict[str, str] = {
|
|
77
|
+
# First person singular
|
|
78
|
+
"aq": "aku",
|
|
79
|
+
"ak": "aku",
|
|
80
|
+
"akuh": "aku",
|
|
81
|
+
"q": "aku",
|
|
82
|
+
"sy": "saya",
|
|
83
|
+
"w": "saya",
|
|
84
|
+
"gw": "saya",
|
|
85
|
+
"gue": "saya",
|
|
86
|
+
"gua": "saya",
|
|
87
|
+
"ane": "saya", # Betawi/Jakartan slang
|
|
88
|
+
"ana": "saya", # Arabic-influenced
|
|
89
|
+
"wkwk": "tertawa", # common filler — override happens in internet
|
|
90
|
+
# First person possessive
|
|
91
|
+
"gw nya": "saya punya",
|
|
92
|
+
"gue nya": "saya punya",
|
|
93
|
+
# Second person
|
|
94
|
+
"u": "kamu",
|
|
95
|
+
"lu": "kamu",
|
|
96
|
+
"lo": "kamu",
|
|
97
|
+
"loe": "kamu",
|
|
98
|
+
"elo": "kamu",
|
|
99
|
+
"elu": "kamu",
|
|
100
|
+
"km": "kamu",
|
|
101
|
+
"ente": "kamu", # Betawi/Jakartan slang
|
|
102
|
+
"antum": "kamu", # Arabic-influenced (plural polite)
|
|
103
|
+
"sampeyan": "kamu", # Javanese polite
|
|
104
|
+
"sampean": "kamu", # Javanese casual
|
|
105
|
+
"sampyan": "kamu", # Javanese casual variant
|
|
106
|
+
# Third person
|
|
107
|
+
"dy": "dia",
|
|
108
|
+
"dya": "dia",
|
|
109
|
+
"doi": "dia", # Jakartan slang for girlfriend/boyfriend
|
|
110
|
+
# Plural
|
|
111
|
+
"mrk": "mereka",
|
|
112
|
+
"qt": "kita",
|
|
113
|
+
"kln": "kalian",
|
|
114
|
+
# Reflexive
|
|
115
|
+
"sndiri": "sendiri",
|
|
116
|
+
"sndr": "sendiri",
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# Kinship & address terms
|
|
120
|
+
_KINSHIP: dict[str, str] = {
|
|
121
|
+
"kk": "kakak",
|
|
122
|
+
"kak": "kakak",
|
|
123
|
+
"adk": "adik",
|
|
124
|
+
"adek": "adik",
|
|
125
|
+
"bpk": "bapak",
|
|
126
|
+
"bpak": "bapak",
|
|
127
|
+
"bapk": "bapak",
|
|
128
|
+
"ayh": "ayah",
|
|
129
|
+
"klg": "keluarga",
|
|
130
|
+
"klrg": "keluarga",
|
|
131
|
+
"kel": "keluarga",
|
|
132
|
+
"ortu": "orang tua",
|
|
133
|
+
"ortuku": "orang tuaku",
|
|
134
|
+
"bokap": "ayah",
|
|
135
|
+
"nyokap": "ibu",
|
|
136
|
+
"pakde": "paman",
|
|
137
|
+
"bude": "bibi",
|
|
138
|
+
"om": "paman",
|
|
139
|
+
"tante": "bibi",
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
# Standalone negation words
|
|
143
|
+
_NEGATION: dict[str, str] = {
|
|
144
|
+
"g": "tidak",
|
|
145
|
+
"ga": "tidak",
|
|
146
|
+
"gak": "tidak",
|
|
147
|
+
"gk": "tidak",
|
|
148
|
+
"ngga": "tidak",
|
|
149
|
+
"nggak": "tidak",
|
|
150
|
+
"engga": "tidak",
|
|
151
|
+
"enggak": "tidak",
|
|
152
|
+
"kagak": "tidak",
|
|
153
|
+
"nope": "tidak",
|
|
154
|
+
"nop": "tidak",
|
|
155
|
+
"gakk": "tidak",
|
|
156
|
+
"gaknya": "tidaknya",
|
|
157
|
+
"bkn": "bukan",
|
|
158
|
+
"bknnya": "bukannya",
|
|
159
|
+
"jgn": "jangan",
|
|
160
|
+
"jgnan": "jangan",
|
|
161
|
+
"belom": "belum",
|
|
162
|
+
"belom2": "belum-belum",
|
|
163
|
+
"blom": "belum",
|
|
164
|
+
"blm2": "belum-belum",
|
|
165
|
+
"masih blm": "masih belum",
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# Compound negation — written as one word without spaces (very common in chat)
|
|
169
|
+
# e.g. "gamau" = "ga" + "mau" = "tidak mau"
|
|
170
|
+
# NOTE: These MUST be registered before single-char negation in the dict so
|
|
171
|
+
# that the longest-first sort in _compile_pattern() handles them correctly.
|
|
172
|
+
_COMPOUND_NEGATION: dict[str, str] = {
|
|
173
|
+
"gamau": "tidak mau",
|
|
174
|
+
"gmau": "tidak mau",
|
|
175
|
+
"gabisa": "tidak bisa",
|
|
176
|
+
"gbisa": "tidak bisa",
|
|
177
|
+
"gakbisa": "tidak bisa",
|
|
178
|
+
"gapunya": "tidak punya",
|
|
179
|
+
"gpunya": "tidak punya",
|
|
180
|
+
"gasuka": "tidak suka",
|
|
181
|
+
"gsuka": "tidak suka",
|
|
182
|
+
"gaada": "tidak ada",
|
|
183
|
+
"gada": "tidak ada", # gaada → gada after vowel reduction
|
|
184
|
+
"gatau": "tidak tahu",
|
|
185
|
+
"gtau": "tidak tahu",
|
|
186
|
+
"gatahu": "tidak tahu",
|
|
187
|
+
"gaperlu": "tidak perlu",
|
|
188
|
+
"gperlu": "tidak perlu",
|
|
189
|
+
"gaboleh": "tidak boleh",
|
|
190
|
+
"gboleh": "tidak boleh",
|
|
191
|
+
"gamakan": "tidak makan",
|
|
192
|
+
"gaminum": "tidak minum",
|
|
193
|
+
"gadatang": "tidak datang",
|
|
194
|
+
"gamasuk": "tidak masuk",
|
|
195
|
+
"gasempet": "tidak sempat",
|
|
196
|
+
"gabawa": "tidak bawa",
|
|
197
|
+
"gabayar": "tidak bayar",
|
|
198
|
+
"gaberani": "tidak berani",
|
|
199
|
+
"gabalik": "tidak balik",
|
|
200
|
+
"gabener": "tidak benar",
|
|
201
|
+
"gakuat": "tidak kuat",
|
|
202
|
+
"gamungkin": "tidak mungkin",
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
# Conjunctions, prepositions, and formal abbreviations
|
|
206
|
+
_CONJUNCTIONS: dict[str, str] = {
|
|
207
|
+
"tp": "tapi",
|
|
208
|
+
"tpi": "tapi",
|
|
209
|
+
"trs": "terus",
|
|
210
|
+
"trus": "terus",
|
|
211
|
+
"dr": "dari",
|
|
212
|
+
"sm": "sama",
|
|
213
|
+
"ama": "sama",
|
|
214
|
+
"dpt": "dapat",
|
|
215
|
+
"tdk": "tidak",
|
|
216
|
+
"krn": "karena",
|
|
217
|
+
"krna": "karena",
|
|
218
|
+
"karna": "karena",
|
|
219
|
+
"utk": "untuk",
|
|
220
|
+
"bwt": "buat",
|
|
221
|
+
"spy": "supaya",
|
|
222
|
+
"klo": "kalau",
|
|
223
|
+
"kalo": "kalau",
|
|
224
|
+
"yg": "yang",
|
|
225
|
+
"dgn": "dengan",
|
|
226
|
+
"dg": "dengan",
|
|
227
|
+
"jg": "juga",
|
|
228
|
+
"bkn": "bukan",
|
|
229
|
+
"pd": "pada",
|
|
230
|
+
"dlm": "dalam",
|
|
231
|
+
# Formal abbreviations
|
|
232
|
+
"dll": "dan lain-lain",
|
|
233
|
+
"dsb": "dan sebagainya",
|
|
234
|
+
"dst": "dan seterusnya",
|
|
235
|
+
"tsb": "tersebut",
|
|
236
|
+
"yth": "yang terhormat",
|
|
237
|
+
"nb": "catatan",
|
|
238
|
+
# Time-relation conjunctions
|
|
239
|
+
"stlh": "setelah",
|
|
240
|
+
"sblm": "sebelum",
|
|
241
|
+
"slma": "selama",
|
|
242
|
+
"tntg": "tentang",
|
|
243
|
+
"ttng": "tentang",
|
|
244
|
+
"thd": "terhadap",
|
|
245
|
+
"antr": "antara",
|
|
246
|
+
"srt": "serta",
|
|
247
|
+
"kmdian": "kemudian",
|
|
248
|
+
"kmdn": "kemudian",
|
|
249
|
+
"lalu": "kemudian",
|
|
250
|
+
# Formal/business abbreviations
|
|
251
|
+
"ttd": "tanda tangan",
|
|
252
|
+
"an": "atas nama",
|
|
253
|
+
"up": "untuk perhatian",
|
|
254
|
+
"re": "balasan",
|
|
255
|
+
"fwd": "teruskan",
|
|
256
|
+
"fw": "teruskan",
|
|
257
|
+
"lmk": "beri tahu saya",
|
|
258
|
+
"etc": "dan lain-lain",
|
|
259
|
+
"ps": "catatan tambahan",
|
|
260
|
+
"no": "nomor",
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
# Verbs and auxiliary verbs
|
|
264
|
+
_VERBS: dict[str, str] = {
|
|
265
|
+
"udh": "sudah",
|
|
266
|
+
"sdh": "sudah",
|
|
267
|
+
"dah": "sudah",
|
|
268
|
+
"udah": "sudah",
|
|
269
|
+
"udeh": "sudah",
|
|
270
|
+
"blm": "belum",
|
|
271
|
+
"blum": "belum",
|
|
272
|
+
"lg": "sedang",
|
|
273
|
+
"lgi": "sedang",
|
|
274
|
+
"bs": "bisa",
|
|
275
|
+
"bsa": "bisa",
|
|
276
|
+
"jd": "jadi",
|
|
277
|
+
"mo": "mau",
|
|
278
|
+
"mw": "mau",
|
|
279
|
+
"tau": "tahu",
|
|
280
|
+
"taw": "tahu",
|
|
281
|
+
"pake": "pakai",
|
|
282
|
+
"make": "pakai",
|
|
283
|
+
"mkn": "makan",
|
|
284
|
+
"mkan": "makan",
|
|
285
|
+
"liat": "lihat",
|
|
286
|
+
"liad": "lihat",
|
|
287
|
+
"ngerti": "mengerti",
|
|
288
|
+
"ngarti": "mengerti",
|
|
289
|
+
"nanya": "bertanya",
|
|
290
|
+
"nany": "bertanya",
|
|
291
|
+
"nyari": "mencari",
|
|
292
|
+
"nyoba": "mencoba",
|
|
293
|
+
"ngomong": "berbicara",
|
|
294
|
+
"nunggu": "menunggu",
|
|
295
|
+
"lakuin": "lakukan",
|
|
296
|
+
"byr": "bayar",
|
|
297
|
+
"hrs": "harus",
|
|
298
|
+
"blh": "boleh",
|
|
299
|
+
"prlu": "perlu",
|
|
300
|
+
"blg": "bilang",
|
|
301
|
+
"bilng": "bilang",
|
|
302
|
+
"sk": "suka",
|
|
303
|
+
"dtg": "datang",
|
|
304
|
+
"dateng": "datang",
|
|
305
|
+
# Extended verbs
|
|
306
|
+
"bikin": "membuat",
|
|
307
|
+
"bkin": "membuat",
|
|
308
|
+
"ambl": "ambil",
|
|
309
|
+
"simpen": "simpan",
|
|
310
|
+
"smpen": "simpan",
|
|
311
|
+
"masukin": "masukkan",
|
|
312
|
+
"keluarin": "keluarkan",
|
|
313
|
+
"tambahin": "tambahkan",
|
|
314
|
+
"kurangin": "kurangi",
|
|
315
|
+
"hapusin": "hapuskan",
|
|
316
|
+
"benerin": "betulkan",
|
|
317
|
+
"gnti": "ganti",
|
|
318
|
+
"pndh": "pindah",
|
|
319
|
+
"plng": "pulang",
|
|
320
|
+
"brngkt": "berangkat",
|
|
321
|
+
"balik": "kembali",
|
|
322
|
+
"blk": "kembali",
|
|
323
|
+
"nyampe": "sampai",
|
|
324
|
+
"nyampek": "sampai",
|
|
325
|
+
"smpe": "sampai",
|
|
326
|
+
"sampe": "sampai",
|
|
327
|
+
"ketemu": "bertemu",
|
|
328
|
+
"ktmu": "bertemu",
|
|
329
|
+
"ngikut": "ikut",
|
|
330
|
+
"ikutin": "ikuti",
|
|
331
|
+
"dengerin": "dengarkan",
|
|
332
|
+
"denger": "dengar",
|
|
333
|
+
"dnger": "dengar",
|
|
334
|
+
"lpd": "lupa",
|
|
335
|
+
"inget": "ingat",
|
|
336
|
+
"ngelupain": "melupakan",
|
|
337
|
+
"ngebantu": "membantu",
|
|
338
|
+
"bntu": "bantu",
|
|
339
|
+
"cek": "periksa",
|
|
340
|
+
"ngecek": "memeriksa",
|
|
341
|
+
"cobaain": "coba",
|
|
342
|
+
"ngelakuin": "melakukan",
|
|
343
|
+
"mnta": "minta",
|
|
344
|
+
"mintain": "mintakan",
|
|
345
|
+
"krm": "kirim",
|
|
346
|
+
"kirimin": "kirimkan",
|
|
347
|
+
"bli": "beli",
|
|
348
|
+
"beliin": "belikan",
|
|
349
|
+
"jln": "jalan",
|
|
350
|
+
"maen": "main",
|
|
351
|
+
"nemenin": "menemani",
|
|
352
|
+
"temenin": "menemani",
|
|
353
|
+
"temenan": "berteman",
|
|
354
|
+
"kenalan": "berkenalan",
|
|
355
|
+
"ngobrol": "mengobrol",
|
|
356
|
+
"ngopi": "minum kopi",
|
|
357
|
+
"nitip": "titip",
|
|
358
|
+
"titipin": "titipkan",
|
|
359
|
+
"bayarin": "bayarkan",
|
|
360
|
+
"bljr": "belajar",
|
|
361
|
+
"bljar": "belajar",
|
|
362
|
+
"ngajar": "mengajar",
|
|
363
|
+
"ngjar": "mengajar",
|
|
364
|
+
"pegi": "pergi",
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
# Adjectives, adverbs, and discourse particles
|
|
368
|
+
_ADJECTIVES_ADVERBS: dict[str, str] = {
|
|
369
|
+
"bgt": "banget",
|
|
370
|
+
"bngt": "banget",
|
|
371
|
+
"bnget": "banget",
|
|
372
|
+
"bget": "banget",
|
|
373
|
+
"bet": "banget",
|
|
374
|
+
"amet": "amat",
|
|
375
|
+
"bener": "benar",
|
|
376
|
+
"bnr": "benar",
|
|
377
|
+
"bner": "benar",
|
|
378
|
+
"cepet": "cepat",
|
|
379
|
+
"cpet": "cepat",
|
|
380
|
+
"cpat": "cepat",
|
|
381
|
+
"ttp": "tetap",
|
|
382
|
+
"lbh": "lebih",
|
|
383
|
+
"krg": "kurang",
|
|
384
|
+
"sdkt": "sedikit",
|
|
385
|
+
"dikit": "sedikit",
|
|
386
|
+
"dkit": "sedikit",
|
|
387
|
+
"hny": "hanya",
|
|
388
|
+
"hnya": "hanya",
|
|
389
|
+
"bbrp": "beberapa",
|
|
390
|
+
"bbrpa": "beberapa",
|
|
391
|
+
"emg": "memang",
|
|
392
|
+
"emang": "memang",
|
|
393
|
+
"aja": "saja",
|
|
394
|
+
"doang": "saja",
|
|
395
|
+
"kek": "seperti",
|
|
396
|
+
"kayak": "seperti",
|
|
397
|
+
"kyk": "seperti",
|
|
398
|
+
"syg": "sayang",
|
|
399
|
+
"syng": "sayang",
|
|
400
|
+
"syang": "sayang",
|
|
401
|
+
"sayng": "sayang",
|
|
402
|
+
# Common informal particles mapped to nearest standard equivalent
|
|
403
|
+
"nih": "ini",
|
|
404
|
+
"tuh": "itu",
|
|
405
|
+
"ntu": "itu",
|
|
406
|
+
"yok": "ayo",
|
|
407
|
+
"yuk": "ayo",
|
|
408
|
+
"ae": "saja", # Sundanese/Javanese particle
|
|
409
|
+
"wae": "saja", # Sundanese: just/only
|
|
410
|
+
"tok": "saja", # Javanese: only
|
|
411
|
+
# Extended adjectives/adverbs
|
|
412
|
+
"abis": "habis",
|
|
413
|
+
"abish": "habis",
|
|
414
|
+
"hbs": "habis",
|
|
415
|
+
"pol": "sekali",
|
|
416
|
+
"beneran": "sungguhan",
|
|
417
|
+
"lm": "lama",
|
|
418
|
+
"lame": "lama",
|
|
419
|
+
"trllu": "terlalu",
|
|
420
|
+
"ckp": "cukup",
|
|
421
|
+
"smpt": "sempat",
|
|
422
|
+
"prnh": "pernah",
|
|
423
|
+
"pernh": "pernah",
|
|
424
|
+
"prnah": "pernah",
|
|
425
|
+
"srg": "sering",
|
|
426
|
+
"jrng": "jarang",
|
|
427
|
+
"jrang": "jarang",
|
|
428
|
+
"sllu": "selalu",
|
|
429
|
+
"slalu": "selalu",
|
|
430
|
+
"kdng": "kadang",
|
|
431
|
+
"mngkin": "mungkin",
|
|
432
|
+
"mngkn": "mungkin",
|
|
433
|
+
"mgkn": "mungkin",
|
|
434
|
+
"pst": "pasti",
|
|
435
|
+
"trnyta": "ternyata",
|
|
436
|
+
"trnyata": "ternyata",
|
|
437
|
+
"lgsg": "langsung",
|
|
438
|
+
"lngsng": "langsung",
|
|
439
|
+
"mlh": "malah",
|
|
440
|
+
"pdhl": "padahal",
|
|
441
|
+
"pdhal": "padahal",
|
|
442
|
+
"pdahl": "padahal",
|
|
443
|
+
"slnya": "soalnya",
|
|
444
|
+
"gitu": "begitu",
|
|
445
|
+
"gt": "begitu",
|
|
446
|
+
"gini": "begini",
|
|
447
|
+
"gn": "begini",
|
|
448
|
+
"segini": "sebanyak ini",
|
|
449
|
+
"sgini": "sebanyak ini",
|
|
450
|
+
"segitu": "sebanyak itu",
|
|
451
|
+
"sgitu": "sebanyak itu",
|
|
452
|
+
"bnyk": "banyak",
|
|
453
|
+
"byk": "banyak",
|
|
454
|
+
"bnyak": "banyak",
|
|
455
|
+
"sdkit": "sedikit",
|
|
456
|
+
"bgs": "bagus",
|
|
457
|
+
"bgus": "bagus",
|
|
458
|
+
"bagoes": "bagus",
|
|
459
|
+
"jlk": "jelek",
|
|
460
|
+
"jlek": "jelek",
|
|
461
|
+
"kcewa": "kecewa",
|
|
462
|
+
"mhl": "mahal",
|
|
463
|
+
"mhal": "mahal",
|
|
464
|
+
"mahl": "mahal",
|
|
465
|
+
"mrh": "murah",
|
|
466
|
+
"pinter": "pintar",
|
|
467
|
+
"pintr": "pintar",
|
|
468
|
+
"pntar": "pintar",
|
|
469
|
+
"pntr": "pintar",
|
|
470
|
+
"hbat": "hebat",
|
|
471
|
+
"hebt": "hebat",
|
|
472
|
+
"hbt": "hebat",
|
|
473
|
+
"lmyn": "lumayan",
|
|
474
|
+
"lumyn": "lumayan",
|
|
475
|
+
"lmyan": "lumayan",
|
|
476
|
+
"mayan": "lumayan",
|
|
477
|
+
"enk": "enak",
|
|
478
|
+
"mntap": "mantap",
|
|
479
|
+
"asik": "asyik",
|
|
480
|
+
"cpk": "capai",
|
|
481
|
+
"cape": "capai",
|
|
482
|
+
"lela": "lelah",
|
|
483
|
+
"ngantu": "mengantuk",
|
|
484
|
+
"laper": "lapar",
|
|
485
|
+
"lper": "lapar",
|
|
486
|
+
"skt": "sakit",
|
|
487
|
+
"skit": "sakit",
|
|
488
|
+
"smbh": "sembuh",
|
|
489
|
+
"smbuh": "sembuh",
|
|
490
|
+
"seneng": "senang",
|
|
491
|
+
"sneng": "senang",
|
|
492
|
+
"bhgia": "bahagia",
|
|
493
|
+
"tkt": "takut",
|
|
494
|
+
"tkut": "takut",
|
|
495
|
+
"bngun": "bingung",
|
|
496
|
+
"psng": "pusing",
|
|
497
|
+
"pusng": "pusing",
|
|
498
|
+
"pening": "pusing",
|
|
499
|
+
"pning": "pusing",
|
|
500
|
+
"mls": "malas",
|
|
501
|
+
"mlas": "malas",
|
|
502
|
+
"mles": "malas",
|
|
503
|
+
"males": "malas",
|
|
504
|
+
"rjn": "rajin",
|
|
505
|
+
"rjin": "rajin",
|
|
506
|
+
"sbnrnya": "sebenarnya",
|
|
507
|
+
"sbnr": "sebenarnya",
|
|
508
|
+
"mending": "lebih baik",
|
|
509
|
+
"mnding": "lebih baik",
|
|
510
|
+
"kyknya": "sepertinya",
|
|
511
|
+
"sptnya": "sepertinya",
|
|
512
|
+
"sprtnya": "sepertinya",
|
|
513
|
+
"gitu2": "begitu-begitu",
|
|
514
|
+
"pelan2": "pelan-pelan",
|
|
515
|
+
"lama2": "lama-lama",
|
|
516
|
+
"buru2": "terburu-buru",
|
|
517
|
+
"kwalitas": "kualitas",
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
# Question words
|
|
521
|
+
_QUESTION_WORDS: dict[str, str] = {
|
|
522
|
+
"knp": "kenapa",
|
|
523
|
+
"knpa": "kenapa",
|
|
524
|
+
"knapa": "kenapa",
|
|
525
|
+
"gmn": "bagaimana",
|
|
526
|
+
"gmna": "bagaimana",
|
|
527
|
+
"gimna": "bagaimana",
|
|
528
|
+
"gimana": "bagaimana",
|
|
529
|
+
"kmn": "kemana",
|
|
530
|
+
"kmna": "kemana",
|
|
531
|
+
"kmana": "kemana",
|
|
532
|
+
"kemna": "kemana",
|
|
533
|
+
"dmn": "di mana",
|
|
534
|
+
"dmna": "di mana",
|
|
535
|
+
"dmana": "di mana",
|
|
536
|
+
"dimna": "di mana",
|
|
537
|
+
"dimana": "di mana",
|
|
538
|
+
"drmn": "dari mana",
|
|
539
|
+
"drmna": "dari mana",
|
|
540
|
+
"drmana": "dari mana",
|
|
541
|
+
"kpn": "kapan",
|
|
542
|
+
"kpan": "kapan",
|
|
543
|
+
"manaa": "mana",
|
|
544
|
+
# Sundanese question words
|
|
545
|
+
"kumaha": "bagaimana",
|
|
546
|
+
"naon": "apa",
|
|
547
|
+
"saha": "siapa",
|
|
548
|
+
"iraha": "kapan",
|
|
549
|
+
"kamana": "kemana",
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
# Greetings, affirmations, and common social responses
|
|
553
|
+
_GREETINGS_RESPONSES: dict[str, str] = {
|
|
554
|
+
# Thanks
|
|
555
|
+
"makasih": "terima kasih",
|
|
556
|
+
"makasi": "terima kasih",
|
|
557
|
+
"mksh": "terima kasih",
|
|
558
|
+
"mksih": "terima kasih",
|
|
559
|
+
"trims": "terima kasih",
|
|
560
|
+
"thx": "terima kasih",
|
|
561
|
+
"tq": "terima kasih",
|
|
562
|
+
"ty": "terima kasih",
|
|
563
|
+
"trimakasih": "terima kasih",
|
|
564
|
+
"terimakasih": "terima kasih",
|
|
565
|
+
"mkch": "terima kasih",
|
|
566
|
+
"tengkyu": "terima kasih",
|
|
567
|
+
"tengkyuu": "terima kasih",
|
|
568
|
+
# Requests
|
|
569
|
+
"pls": "tolong",
|
|
570
|
+
"pliss": "tolong",
|
|
571
|
+
"plz": "tolong",
|
|
572
|
+
"plzz": "tolong",
|
|
573
|
+
"tlg": "tolong",
|
|
574
|
+
# Apology
|
|
575
|
+
"mf": "maaf",
|
|
576
|
+
"afwan": "maaf", # Arabic-Indonesian
|
|
577
|
+
"maap": "maaf",
|
|
578
|
+
"sori": "maaf",
|
|
579
|
+
"sory": "maaf",
|
|
580
|
+
"sorry": "maaf",
|
|
581
|
+
"sorri": "maaf",
|
|
582
|
+
"mnt maaf": "minta maaf",
|
|
583
|
+
# Agreement
|
|
584
|
+
"ok": "oke",
|
|
585
|
+
"okk": "oke",
|
|
586
|
+
"okee": "oke",
|
|
587
|
+
"okelah": "oke",
|
|
588
|
+
"sip": "baik",
|
|
589
|
+
"siapp": "siap",
|
|
590
|
+
"iy": "iya",
|
|
591
|
+
"iyap": "iya",
|
|
592
|
+
"yap": "ya",
|
|
593
|
+
"yep": "ya",
|
|
594
|
+
"yup": "ya",
|
|
595
|
+
"yupp": "ya",
|
|
596
|
+
"yeah": "ya",
|
|
597
|
+
"yoi": "iya", # Jakartan slang
|
|
598
|
+
"mantul": "mantap betul",
|
|
599
|
+
# Greetings
|
|
600
|
+
"hi": "hai",
|
|
601
|
+
"hey": "hei",
|
|
602
|
+
"met pagi": "selamat pagi",
|
|
603
|
+
"met siang": "selamat siang",
|
|
604
|
+
"met sore": "selamat sore",
|
|
605
|
+
"met malam": "selamat malam",
|
|
606
|
+
"slmt dtng": "selamat datang",
|
|
607
|
+
"smpai jumpa": "sampai jumpa",
|
|
608
|
+
"dadah": "sampai jumpa",
|
|
609
|
+
"dah": "sampai jumpa",
|
|
610
|
+
"bye": "selamat tinggal",
|
|
611
|
+
"byee": "selamat tinggal",
|
|
612
|
+
"byebye": "selamat tinggal",
|
|
613
|
+
"ciao": "selamat tinggal",
|
|
614
|
+
"papay": "selamat tinggal",
|
|
615
|
+
# Javanese / Sundanese particles (polite registers)
|
|
616
|
+
"nggih": "iya", # Javanese: yes (polite)
|
|
617
|
+
"inggih": "iya", # Javanese: yes (formal)
|
|
618
|
+
"mboten": "tidak", # Javanese: no/not
|
|
619
|
+
"monggo": "silakan", # Javanese: please go ahead
|
|
620
|
+
"suwun": "terima kasih", # Javanese: thank you
|
|
621
|
+
"matur suwun": "terima kasih", # Javanese: thank you (full form)
|
|
622
|
+
"nuwun": "terima kasih", # Javanese: thank you
|
|
623
|
+
# Sundanese
|
|
624
|
+
"muhun": "iya",
|
|
625
|
+
"hapunten": "maaf",
|
|
626
|
+
"punten": "permisi",
|
|
627
|
+
"hatur nuhun": "terima kasih",
|
|
628
|
+
# Arabic-Indonesian
|
|
629
|
+
"syukron": "terima kasih",
|
|
630
|
+
# Polite expressions
|
|
631
|
+
"prmisi": "permisi",
|
|
632
|
+
"silahkan": "silakan",
|
|
633
|
+
"samasama": "sama-sama",
|
|
634
|
+
"samsama": "sama-sama",
|
|
635
|
+
"sama sama": "sama-sama",
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
# Temporal expressions and locations
|
|
639
|
+
_TEMPORAL_LOCATION: dict[str, str] = {
|
|
640
|
+
"skrg": "sekarang",
|
|
641
|
+
"skrng": "sekarang",
|
|
642
|
+
"ntr": "nanti",
|
|
643
|
+
"ntar": "nanti",
|
|
644
|
+
"kmrn": "kemarin",
|
|
645
|
+
"kmren": "kemarin",
|
|
646
|
+
"bsk": "besok",
|
|
647
|
+
"td": "tadi",
|
|
648
|
+
"dlu": "dulu",
|
|
649
|
+
"dlo": "dulu",
|
|
650
|
+
"hr": "hari",
|
|
651
|
+
"hri": "hari",
|
|
652
|
+
"mlm": "malam",
|
|
653
|
+
"malem": "malam",
|
|
654
|
+
"pg": "pagi",
|
|
655
|
+
"sni": "sini",
|
|
656
|
+
"dsini": "di sini",
|
|
657
|
+
"dsni": "di sini",
|
|
658
|
+
"sono": "sana",
|
|
659
|
+
"mgg": "minggu",
|
|
660
|
+
"bln": "bulan",
|
|
661
|
+
"thn": "tahun",
|
|
662
|
+
"mnt": "menit",
|
|
663
|
+
"dtk": "detik",
|
|
664
|
+
"jdwl": "jadwal",
|
|
665
|
+
"wktu": "waktu",
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
# Internet slang — mapped to Indonesian equivalents (not English)
|
|
669
|
+
_INTERNET_SLANG: dict[str, str] = {
|
|
670
|
+
"otw": "dalam perjalanan",
|
|
671
|
+
"btw": "omong-omong",
|
|
672
|
+
"fyi": "sebagai informasi",
|
|
673
|
+
"imo": "menurut saya",
|
|
674
|
+
"imho": "menurut saya",
|
|
675
|
+
"cmiiw": "koreksi jika saya salah",
|
|
676
|
+
"lol": "tertawa",
|
|
677
|
+
"wkwk": "tertawa",
|
|
678
|
+
"wkwwk": "tertawa",
|
|
679
|
+
"wkwkwk": "tertawa",
|
|
680
|
+
"awokwok": "tertawa",
|
|
681
|
+
"xixi": "tertawa", # Chinese laughter, common in Indonesian social media
|
|
682
|
+
"lmao": "tertawa keras",
|
|
683
|
+
"omg": "astaga",
|
|
684
|
+
"idk": "saya tidak tahu",
|
|
685
|
+
"tbh": "sejujurnya",
|
|
686
|
+
"ngl": "sejujurnya",
|
|
687
|
+
"tbf": "sejujurnya",
|
|
688
|
+
"nvm": "lupakan saja",
|
|
689
|
+
"jk": "bercanda",
|
|
690
|
+
"np": "tidak masalah",
|
|
691
|
+
"afk": "pergi sebentar",
|
|
692
|
+
"brb": "segera kembali",
|
|
693
|
+
"dm": "pesan langsung",
|
|
694
|
+
"tldr": "ringkasnya",
|
|
695
|
+
"wdyt": "menurutmu",
|
|
696
|
+
"wdym": "apa maksudmu",
|
|
697
|
+
"ftr": "akhirnya",
|
|
698
|
+
# Platforms
|
|
699
|
+
"wa": "whatsapp",
|
|
700
|
+
"ig": "instagram",
|
|
701
|
+
"fb": "facebook",
|
|
702
|
+
"tt": "tiktok",
|
|
703
|
+
"yt": "youtube",
|
|
704
|
+
"twit": "twitter",
|
|
705
|
+
"linkin": "linkedin",
|
|
706
|
+
"gform": "google form",
|
|
707
|
+
"gdrive": "google drive",
|
|
708
|
+
"gmeet": "google meet",
|
|
709
|
+
# Social media terms
|
|
710
|
+
"wag": "grup whatsapp",
|
|
711
|
+
"gc": "grup chat",
|
|
712
|
+
"bc": "pesan siaran",
|
|
713
|
+
"nohp": "nomor handphone",
|
|
714
|
+
"ootd": "pakaian hari ini",
|
|
715
|
+
"vibe": "suasana",
|
|
716
|
+
"vibes": "suasana",
|
|
717
|
+
"mood": "suasana hati",
|
|
718
|
+
"hype": "heboh",
|
|
719
|
+
"trending": "sedang tren",
|
|
720
|
+
"lowkey": "diam-diam",
|
|
721
|
+
"highkey": "terang-terangan",
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
# E-commerce and finance terms
|
|
725
|
+
_ECOMMERCE_FINANCE: dict[str, str] = {
|
|
726
|
+
"gan": "saudara",
|
|
727
|
+
"sis": "saudari",
|
|
728
|
+
"rekber": "rekening bersama",
|
|
729
|
+
"cod": "bayar di tempat",
|
|
730
|
+
"ongkir": "ongkos kirim",
|
|
731
|
+
"tf": "transfer",
|
|
732
|
+
"dp": "uang muka",
|
|
733
|
+
"hrg": "harga",
|
|
734
|
+
"hrga": "harga",
|
|
735
|
+
"jastip": "jasa titip",
|
|
736
|
+
"pesen": "pesan",
|
|
737
|
+
"minat": "berminat",
|
|
738
|
+
"duit": "uang",
|
|
739
|
+
"duwit": "uang",
|
|
740
|
+
"fulus": "uang",
|
|
741
|
+
"rb": "ribu",
|
|
742
|
+
"jt": "juta",
|
|
743
|
+
"mlyr": "miliar",
|
|
744
|
+
"pcs": "buah",
|
|
745
|
+
"lbr": "lembar",
|
|
746
|
+
"btl": "botol",
|
|
747
|
+
"asap": "sesegera mungkin",
|
|
748
|
+
"acc": "disetujui",
|
|
749
|
+
"bkl": "bakal",
|
|
750
|
+
"bakal": "akan",
|
|
751
|
+
"mslh": "masalah",
|
|
752
|
+
"sls": "selesai",
|
|
753
|
+
"slsai": "selesai",
|
|
754
|
+
"mlai": "mulai",
|
|
755
|
+
"mulain": "mulai",
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
# Youth / Gen-Z Indonesian slang
|
|
759
|
+
_YOUTH_SLANG: dict[str, str] = {
|
|
760
|
+
"mager": "malas bergerak",
|
|
761
|
+
"baper": "bawa perasaan",
|
|
762
|
+
"gabut": "tidak ada kegiatan",
|
|
763
|
+
"kepo": "ingin tahu",
|
|
764
|
+
"santuy": "santai",
|
|
765
|
+
"woles": "santai",
|
|
766
|
+
"gercep": "gerak cepat",
|
|
767
|
+
"gass": "ayo",
|
|
768
|
+
"gaspol": "ayo semangat",
|
|
769
|
+
"gaskeun": "ayo lakukan", # Sundanese-influenced
|
|
770
|
+
"bucin": "budak cinta",
|
|
771
|
+
"julid": "iri hati",
|
|
772
|
+
"halu": "halusinasi",
|
|
773
|
+
"flexing": "pamer",
|
|
774
|
+
"pansos": "panjat sosial",
|
|
775
|
+
"curhat": "berbagi cerita",
|
|
776
|
+
"kekinian": "tren terkini",
|
|
777
|
+
"kekinan": "tren terkini",
|
|
778
|
+
"hits": "populer",
|
|
779
|
+
"relate": "relatable",
|
|
780
|
+
"selfie": "foto sendiri",
|
|
781
|
+
"caption": "keterangan foto",
|
|
782
|
+
"story": "cerita",
|
|
783
|
+
"feeds": "beranda",
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
# Discourse markers and meta-commentary
|
|
787
|
+
_DISCOURSE_MARKERS: dict[str, str] = {
|
|
788
|
+
"mksd": "maksud",
|
|
789
|
+
"mksdnya": "maksudnya",
|
|
790
|
+
"pkoknya": "pokoknya",
|
|
791
|
+
"pokonya": "pokoknya",
|
|
792
|
+
"jdinya": "jadinya",
|
|
793
|
+
"hslnya": "hasilnya",
|
|
794
|
+
"sngktnya": "singkatnya",
|
|
795
|
+
"menurutku": "menurut saya",
|
|
796
|
+
"mnrtku": "menurut saya",
|
|
797
|
+
"menurutgw": "menurut saya",
|
|
798
|
+
"akhirny": "akhirnya",
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
# Javanese extended vocabulary
|
|
802
|
+
_JAVANESE_EXTENDED: dict[str, str] = {
|
|
803
|
+
# Pronouns
|
|
804
|
+
"awakmu": "kamu",
|
|
805
|
+
"njenengan": "anda",
|
|
806
|
+
"kulo": "saya",
|
|
807
|
+
"kula": "saya",
|
|
808
|
+
"inyong": "saya",
|
|
809
|
+
"dewek": "sendiri",
|
|
810
|
+
# Adjectives
|
|
811
|
+
"apik": "bagus",
|
|
812
|
+
"elek": "jelek",
|
|
813
|
+
"okeh": "banyak",
|
|
814
|
+
"sithik": "sedikit",
|
|
815
|
+
"gedhe": "besar",
|
|
816
|
+
"cilik": "kecil",
|
|
817
|
+
"adoh": "jauh",
|
|
818
|
+
"cedhak": "dekat",
|
|
819
|
+
"alon": "pelan",
|
|
820
|
+
"anyar": "baru",
|
|
821
|
+
"lawas": "lama",
|
|
822
|
+
"sae": "baik",
|
|
823
|
+
# Verbs
|
|
824
|
+
"mangkat": "berangkat",
|
|
825
|
+
"kondur": "pulang",
|
|
826
|
+
"mangan": "makan",
|
|
827
|
+
"ngombe": "minum",
|
|
828
|
+
"turu": "tidur",
|
|
829
|
+
"tangi": "bangun",
|
|
830
|
+
"mlaku": "berjalan",
|
|
831
|
+
"mlayu": "berlari",
|
|
832
|
+
"lungguh": "duduk",
|
|
833
|
+
"ngadeg": "berdiri",
|
|
834
|
+
"weruh": "tahu",
|
|
835
|
+
"krungu": "dengar",
|
|
836
|
+
"ndelok": "lihat",
|
|
837
|
+
"takon": "bertanya",
|
|
838
|
+
"kandha": "berkata",
|
|
839
|
+
"tuku": "beli",
|
|
840
|
+
"adol": "jual",
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
# Sundanese extended vocabulary
|
|
844
|
+
_SUNDANESE_EXTENDED: dict[str, str] = {
|
|
845
|
+
# Pronouns
|
|
846
|
+
"abdi": "saya",
|
|
847
|
+
"anjeun": "kamu",
|
|
848
|
+
"maneh": "kamu",
|
|
849
|
+
# Particles
|
|
850
|
+
"atuh": "dong",
|
|
851
|
+
"euy": "ya",
|
|
852
|
+
"mah": "sih",
|
|
853
|
+
"teh": "itu",
|
|
854
|
+
"nya": "ya",
|
|
855
|
+
# Adjectives
|
|
856
|
+
"alus": "bagus",
|
|
857
|
+
"awon": "jelek",
|
|
858
|
+
"caket": "dekat",
|
|
859
|
+
"leueur": "lambat",
|
|
860
|
+
"sae pisan": "sangat bagus",
|
|
861
|
+
# Verbs/expressions
|
|
862
|
+
"geus": "sudah",
|
|
863
|
+
"keur": "sedang",
|
|
864
|
+
"bade": "akan",
|
|
865
|
+
"hoyong": "mau",
|
|
866
|
+
"daek": "mau",
|
|
867
|
+
"tiasa": "bisa",
|
|
868
|
+
"aya": "ada",
|
|
869
|
+
"teu": "tidak",
|
|
870
|
+
"acan": "belum",
|
|
871
|
+
"can": "belum",
|
|
872
|
+
# Quantity
|
|
873
|
+
"loba": "banyak",
|
|
874
|
+
"saeutik": "sedikit",
|
|
875
|
+
"ged\u00e9": "besar",
|
|
876
|
+
"leutik": "kecil",
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
# Common nouns (abbreviations and informal forms)
|
|
880
|
+
_NOUNS: dict[str, str] = {
|
|
881
|
+
# People & relationships
|
|
882
|
+
"tmn": "teman",
|
|
883
|
+
"temen": "teman",
|
|
884
|
+
"tmn2": "teman-teman",
|
|
885
|
+
"temen2": "teman-teman",
|
|
886
|
+
"shbt": "sahabat",
|
|
887
|
+
"pcr": "pacar",
|
|
888
|
+
"mntm": "mantan",
|
|
889
|
+
# Work & study
|
|
890
|
+
"krjn": "pekerjaan",
|
|
891
|
+
"kntr": "kantor",
|
|
892
|
+
"sklh": "sekolah",
|
|
893
|
+
"kmps": "kampus",
|
|
894
|
+
"kliah": "kuliah",
|
|
895
|
+
"tgs": "tugas",
|
|
896
|
+
"pr": "pekerjaan rumah",
|
|
897
|
+
"ujin": "ujian",
|
|
898
|
+
"ulngn": "ulangan",
|
|
899
|
+
"mhsw": "mahasiswa",
|
|
900
|
+
"mhs": "mahasiswa",
|
|
901
|
+
"mrd": "murid",
|
|
902
|
+
"kls": "kelas",
|
|
903
|
+
"mapel": "mata pelajaran",
|
|
904
|
+
"matkul": "mata kuliah",
|
|
905
|
+
"mtkl": "mata kuliah",
|
|
906
|
+
"skrpsi": "skripsi",
|
|
907
|
+
"wsd": "wisuda",
|
|
908
|
+
"nlai": "nilai",
|
|
909
|
+
"ipk": "indeks prestasi kumulatif",
|
|
910
|
+
"ip": "indeks prestasi",
|
|
911
|
+
"dl": "batas waktu",
|
|
912
|
+
"prsnts": "presentasi",
|
|
913
|
+
"lprn": "laporan",
|
|
914
|
+
"rvisi": "revisi",
|
|
915
|
+
# Things & gadgets
|
|
916
|
+
"hp": "handphone",
|
|
917
|
+
"hape": "handphone",
|
|
918
|
+
"ltop": "laptop",
|
|
919
|
+
"mtr": "motor",
|
|
920
|
+
"mbl": "mobil",
|
|
921
|
+
"rmh": "rumah",
|
|
922
|
+
"mkn": "makan",
|
|
923
|
+
"mnum": "minum",
|
|
924
|
+
# Places
|
|
925
|
+
"wrg": "warung",
|
|
926
|
+
"warteg": "warung tegal",
|
|
927
|
+
"psr": "pasar",
|
|
928
|
+
"gdg": "gedung",
|
|
929
|
+
"rs": "rumah sakit",
|
|
930
|
+
"pskms": "puskesmas",
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
# Health & wellness vocabulary
|
|
934
|
+
_HEALTH: dict[str, str] = {
|
|
935
|
+
# Symptoms
|
|
936
|
+
"dmm": "demam",
|
|
937
|
+
"dmam": "demam",
|
|
938
|
+
"btk": "batuk",
|
|
939
|
+
"btuk": "batuk",
|
|
940
|
+
"plk": "pilek",
|
|
941
|
+
"ml": "mual",
|
|
942
|
+
"mntah": "muntah",
|
|
943
|
+
"alrgi": "alergi",
|
|
944
|
+
"sesak": "sesak napas",
|
|
945
|
+
"sktkpl": "sakit kepala",
|
|
946
|
+
"mencret": "diare",
|
|
947
|
+
"mules": "mulas",
|
|
948
|
+
"lebam": "memar",
|
|
949
|
+
"kslng": "keseleo",
|
|
950
|
+
# Medical personnel & places
|
|
951
|
+
"obt": "obat",
|
|
952
|
+
"dkter": "dokter",
|
|
953
|
+
"dr": "dokter",
|
|
954
|
+
"prwt": "perawat",
|
|
955
|
+
"rwt": "rawat",
|
|
956
|
+
"opname": "rawat inap",
|
|
957
|
+
"ugd": "unit gawat darurat",
|
|
958
|
+
"igd": "instalasi gawat darurat",
|
|
959
|
+
"poli": "poliklinik",
|
|
960
|
+
"apotk": "apotek",
|
|
961
|
+
"resep": "resep dokter",
|
|
962
|
+
"rsep": "resep dokter",
|
|
963
|
+
"rapid test": "tes cepat",
|
|
964
|
+
# Wellness & fitness
|
|
965
|
+
"jalan2": "jalan-jalan",
|
|
966
|
+
"olrga": "olahraga",
|
|
967
|
+
"gym": "olahraga",
|
|
968
|
+
"lari": "berlari",
|
|
969
|
+
"jogging": "joging",
|
|
970
|
+
"tdr": "tidur",
|
|
971
|
+
"tdrsiang": "tidur siang",
|
|
972
|
+
"bgdng": "begadang",
|
|
973
|
+
"istrhat": "istirahat",
|
|
974
|
+
"istrht": "istirahat",
|
|
975
|
+
"shat": "sehat",
|
|
976
|
+
"smbh": "sembuh",
|
|
977
|
+
"lekas sembuh": "lekas sembuh",
|
|
978
|
+
"cpt smbh": "lekas sembuh",
|
|
979
|
+
"get well soon": "lekas sembuh",
|
|
980
|
+
"gws": "lekas sembuh",
|
|
981
|
+
"isoman": "isolasi mandiri",
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
# Emotions, feelings & expressions
|
|
985
|
+
_EMOTIONS_EXPRESSIONS: dict[str, str] = {
|
|
986
|
+
# Happiness / excitement
|
|
987
|
+
"happy": "bahagia",
|
|
988
|
+
"excited": "bersemangat",
|
|
989
|
+
"semngt": "semangat",
|
|
990
|
+
"smngat": "semangat",
|
|
991
|
+
"smgt": "semangat",
|
|
992
|
+
"bersemgt": "bersemangat",
|
|
993
|
+
"yey": "hore",
|
|
994
|
+
"yeay": "hore",
|
|
995
|
+
"yay": "hore",
|
|
996
|
+
"asoy": "asyik",
|
|
997
|
+
"krn2": "keren-keren",
|
|
998
|
+
"mantab": "mantap",
|
|
999
|
+
"yoi": "iya",
|
|
1000
|
+
"gokil": "luar biasa",
|
|
1001
|
+
"gila": "luar biasa",
|
|
1002
|
+
"gile": "luar biasa",
|
|
1003
|
+
"gilak": "luar biasa",
|
|
1004
|
+
"parah": "luar biasa",
|
|
1005
|
+
"lebay": "berlebihan",
|
|
1006
|
+
"lbay": "berlebihan",
|
|
1007
|
+
# Sadness / disappointment
|
|
1008
|
+
"sdh2": "sedih",
|
|
1009
|
+
"kcewa": "kecewa",
|
|
1010
|
+
"kzl": "kesal",
|
|
1011
|
+
"bete": "kesal",
|
|
1012
|
+
"bt": "kesal",
|
|
1013
|
+
"gondok": "kesal",
|
|
1014
|
+
"sewot": "kesal",
|
|
1015
|
+
"jutek": "judes",
|
|
1016
|
+
"nangis": "menangis",
|
|
1017
|
+
"nangiss": "menangis",
|
|
1018
|
+
"mewek": "menangis",
|
|
1019
|
+
"ngedumel": "mengeluh",
|
|
1020
|
+
"ngeluh": "mengeluh",
|
|
1021
|
+
"ngrundel": "mengeluh",
|
|
1022
|
+
"geregetan": "kesal",
|
|
1023
|
+
"gereget": "kesal",
|
|
1024
|
+
"dongkol": "kesal",
|
|
1025
|
+
"badmood": "suasana hati buruk",
|
|
1026
|
+
"bad mood": "suasana hati buruk",
|
|
1027
|
+
"overthink": "terlalu banyak pikiran",
|
|
1028
|
+
"otk": "terlalu banyak pikiran",
|
|
1029
|
+
"down": "sedang terpuruk",
|
|
1030
|
+
"ngedown": "sedang terpuruk",
|
|
1031
|
+
"insecure": "tidak percaya diri",
|
|
1032
|
+
"minder": "rendah diri",
|
|
1033
|
+
# Surprise / shock
|
|
1034
|
+
"shock": "syok",
|
|
1035
|
+
"bnggong": "bengong",
|
|
1036
|
+
"melongo": "terpana",
|
|
1037
|
+
"bnggung": "bingung",
|
|
1038
|
+
"mumet": "pusing",
|
|
1039
|
+
"mupeng": "sangat menginginkan",
|
|
1040
|
+
# Love / affection
|
|
1041
|
+
"syangku": "sayangku",
|
|
1042
|
+
"cintrong": "cinta",
|
|
1043
|
+
"gebetan2": "gebetan-gebetan",
|
|
1044
|
+
"pdkt": "pendekatan",
|
|
1045
|
+
"chat": "pesan",
|
|
1046
|
+
"dm2": "kirim pesan langsung",
|
|
1047
|
+
"ghosting": "menghilang tiba-tiba",
|
|
1048
|
+
"ghosted": "ditinggal tiba-tiba",
|
|
1049
|
+
"friendzone": "zona teman",
|
|
1050
|
+
"fz": "zona teman",
|
|
1051
|
+
"crush": "orang yang disukai",
|
|
1052
|
+
"clbk": "cinta lama bersemi kembali",
|
|
1053
|
+
"php": "pemberi harapan palsu",
|
|
1054
|
+
"playing": "mempermainkan",
|
|
1055
|
+
"dimainin": "dipermainkan",
|
|
1056
|
+
"selingkuh": "berselingkuh",
|
|
1057
|
+
"selingkuhi": "berselingkuhi",
|
|
1058
|
+
"selingkuhan": "perselingkuhan",
|
|
1059
|
+
"putusin": "memutuskan",
|
|
1060
|
+
"balikan": "bersama kembali",
|
|
1061
|
+
# Tired / lazy
|
|
1062
|
+
"capek": "lelah",
|
|
1063
|
+
"capai": "lelah",
|
|
1064
|
+
"kecapean": "kelelahan",
|
|
1065
|
+
"nganggur": "tidak bekerja",
|
|
1066
|
+
"males": "malas",
|
|
1067
|
+
"mager": "malas bergerak",
|
|
1068
|
+
"rebahan": "berbaring santai",
|
|
1069
|
+
"santey": "santai",
|
|
1070
|
+
"ndak": "tidak",
|
|
1071
|
+
"enggak": "tidak",
|
|
1072
|
+
"nyesel": "menyesal",
|
|
1073
|
+
"ngsyel": "menyesal",
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
# Food & drink vocabulary
|
|
1077
|
+
_FOOD_DRINK: dict[str, str] = {
|
|
1078
|
+
# General food terms
|
|
1079
|
+
"mkan": "makan",
|
|
1080
|
+
"mkanan": "makanan",
|
|
1081
|
+
"lauk": "lauk-pauk",
|
|
1082
|
+
"ns": "nasi",
|
|
1083
|
+
"sayur": "sayuran",
|
|
1084
|
+
"syr": "sayuran",
|
|
1085
|
+
"mie": "mi",
|
|
1086
|
+
"mie2": "mie-mie",
|
|
1087
|
+
"indomie": "mi instan",
|
|
1088
|
+
"indmie": "mi instan",
|
|
1089
|
+
"indomie goreng": "mi goreng instan",
|
|
1090
|
+
"migo": "mi goreng",
|
|
1091
|
+
"migor": "mi goreng",
|
|
1092
|
+
"nasgor": "nasi goreng",
|
|
1093
|
+
"nsgr": "nasi goreng",
|
|
1094
|
+
"molen": "kue molen",
|
|
1095
|
+
"grngn": "gorengan",
|
|
1096
|
+
"batagor": "bakso tahu goreng",
|
|
1097
|
+
"cireng": "aci goreng",
|
|
1098
|
+
"cilok": "aci dicolok",
|
|
1099
|
+
"baso": "bakso",
|
|
1100
|
+
"bks": "bakso",
|
|
1101
|
+
"gado2": "gado-gado",
|
|
1102
|
+
"blr": "bubur",
|
|
1103
|
+
"nsuduk": "nasi uduk",
|
|
1104
|
+
"warteg": "warung tegal",
|
|
1105
|
+
"wrtg": "warung tegal",
|
|
1106
|
+
# Drinks
|
|
1107
|
+
"mnum": "minum",
|
|
1108
|
+
"mnuman": "minuman",
|
|
1109
|
+
"kpi": "kopi",
|
|
1110
|
+
"tehmanis": "teh manis",
|
|
1111
|
+
"juice": "jus",
|
|
1112
|
+
"bubble tea": "boba teh",
|
|
1113
|
+
"kopsu": "kopi susu",
|
|
1114
|
+
"americano": "kopi americano",
|
|
1115
|
+
"minol": "minuman beralkohol",
|
|
1116
|
+
# Taste / quality
|
|
1117
|
+
"enakk": "enak",
|
|
1118
|
+
"mantul": "mantap betul",
|
|
1119
|
+
"kriuk": "renyah",
|
|
1120
|
+
"pedes": "pedas",
|
|
1121
|
+
"asem": "asam",
|
|
1122
|
+
"bukan enak": "tidak enak",
|
|
1123
|
+
"gaenak": "tidak enak",
|
|
1124
|
+
"ga enak": "tidak enak",
|
|
1125
|
+
"keabisan": "kehabisan",
|
|
1126
|
+
"khabisan": "kehabisan",
|
|
1127
|
+
# Meal times / hunger
|
|
1128
|
+
"makanmalam": "makan malam",
|
|
1129
|
+
"srpn": "sarapan",
|
|
1130
|
+
"malem": "malam",
|
|
1131
|
+
"laper": "lapar",
|
|
1132
|
+
"laperan": "sedang lapar",
|
|
1133
|
+
"kelaperan": "sangat lapar",
|
|
1134
|
+
"ngidam": "mengidam",
|
|
1135
|
+
"nagih": "ketagihan",
|
|
1136
|
+
"kenyangn": "kekenyangan",
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
# Clothing & fashion vocabulary
|
|
1140
|
+
_CLOTHING_FASHION: dict[str, str] = {
|
|
1141
|
+
# Garments
|
|
1142
|
+
"bj": "baju",
|
|
1143
|
+
"kaos": "kaus",
|
|
1144
|
+
"kos": "kaus",
|
|
1145
|
+
"kmja": "kemeja",
|
|
1146
|
+
"jket": "jaket",
|
|
1147
|
+
"cln": "celana",
|
|
1148
|
+
"dress": "gaun",
|
|
1149
|
+
"jlbb": "jilbab",
|
|
1150
|
+
"hijaber": "pengguna hijab",
|
|
1151
|
+
"krdng": "kerudung",
|
|
1152
|
+
"koko": "baju koko",
|
|
1153
|
+
"pjm": "piyama",
|
|
1154
|
+
"sweter": "sweater",
|
|
1155
|
+
"hudi": "hoodie",
|
|
1156
|
+
"cardigan": "kardigan",
|
|
1157
|
+
"outer": "jaket luar",
|
|
1158
|
+
"outher": "jaket luar",
|
|
1159
|
+
"vest": "rompi",
|
|
1160
|
+
# Footwear
|
|
1161
|
+
"spt2": "sepatu-sepatu",
|
|
1162
|
+
"sdl": "sandal",
|
|
1163
|
+
"sneakers": "sepatu kets",
|
|
1164
|
+
"snakers": "sepatu kets",
|
|
1165
|
+
"boots": "sepatu bot",
|
|
1166
|
+
"heels": "sepatu hak tinggi",
|
|
1167
|
+
"higheels": "sepatu hak tinggi",
|
|
1168
|
+
"flatshoes": "sepatu flat",
|
|
1169
|
+
"slippers": "sandal",
|
|
1170
|
+
# Accessories
|
|
1171
|
+
"tote bag": "tas tote",
|
|
1172
|
+
"totebag": "tas tote",
|
|
1173
|
+
"dmpt": "dompet",
|
|
1174
|
+
"jamtgn": "jam tangan",
|
|
1175
|
+
"kacmt": "kacamata",
|
|
1176
|
+
# Fashion terms
|
|
1177
|
+
"outfit": "pakaian",
|
|
1178
|
+
"ootd": "pakaian hari ini",
|
|
1179
|
+
"mix match": "padupadan",
|
|
1180
|
+
"mixmatch": "padupadan",
|
|
1181
|
+
"casual": "kasual",
|
|
1182
|
+
"stylish": "bergaya",
|
|
1183
|
+
"trendy": "trendi",
|
|
1184
|
+
"vintage": "jadul bergaya",
|
|
1185
|
+
"thrift": "beli baju bekas",
|
|
1186
|
+
"thrifting": "belanja baju bekas",
|
|
1187
|
+
"preloved": "bekas pakai",
|
|
1188
|
+
"ukrn": "ukuran",
|
|
1189
|
+
"size": "ukuran",
|
|
1190
|
+
"kebesaran": "terlalu besar",
|
|
1191
|
+
"kekecilan": "terlalu kecil",
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
# Transportation vocabulary
|
|
1195
|
+
_TRANSPORTATION: dict[str, str] = {
|
|
1196
|
+
# Vehicles
|
|
1197
|
+
"mtr": "motor",
|
|
1198
|
+
"mbl": "mobil",
|
|
1199
|
+
"spd": "sepeda",
|
|
1200
|
+
"angkot": "angkutan kota",
|
|
1201
|
+
"busway": "bus transjakarta",
|
|
1202
|
+
"tj": "transjakarta",
|
|
1203
|
+
"krl": "kereta rel listrik",
|
|
1204
|
+
"mrt": "mass rapid transit",
|
|
1205
|
+
"lrt": "light rail transit",
|
|
1206
|
+
"commuter": "kereta komuter",
|
|
1207
|
+
"komuter": "kereta komuter",
|
|
1208
|
+
"pswt": "pesawat",
|
|
1209
|
+
"bdr": "bandara",
|
|
1210
|
+
"kpl": "kapal",
|
|
1211
|
+
"ojol": "ojek online",
|
|
1212
|
+
"taxi": "taksi",
|
|
1213
|
+
"bentor": "becak motor",
|
|
1214
|
+
"bnsn": "bensin",
|
|
1215
|
+
"bbm": "bahan bakar minyak",
|
|
1216
|
+
# Navigation / travel
|
|
1217
|
+
"jln": "jalan",
|
|
1218
|
+
"mct": "macet",
|
|
1219
|
+
"plkmpng": "pulang kampung",
|
|
1220
|
+
"prjlnan": "perjalanan",
|
|
1221
|
+
"jrk": "jarak",
|
|
1222
|
+
"deket": "dekat",
|
|
1223
|
+
"prk": "parkir",
|
|
1224
|
+
"numpang": "menumpang",
|
|
1225
|
+
"nunut": "menumpang",
|
|
1226
|
+
"nebeng": "menumpang",
|
|
1227
|
+
"nyetir": "mengemudi",
|
|
1228
|
+
"nyupir": "mengemudikan",
|
|
1229
|
+
"setir": "kemudi",
|
|
1230
|
+
"spion": "kaca spion",
|
|
1231
|
+
"gps": "navigasi",
|
|
1232
|
+
"maps": "peta navigasi",
|
|
1233
|
+
"gmaps": "google maps",
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
# Religion, culture & social life
|
|
1237
|
+
_RELIGION_CULTURE: dict[str, str] = {
|
|
1238
|
+
# Islamic expressions (very common in Indonesian daily speech)
|
|
1239
|
+
"insyaallah": "insya allah",
|
|
1240
|
+
"inshallah": "insya allah",
|
|
1241
|
+
"ia": "insya allah",
|
|
1242
|
+
"alhdlh": "alhamdulillah",
|
|
1243
|
+
"alhdlll": "alhamdulillah",
|
|
1244
|
+
"amdlh": "alhamdulillah",
|
|
1245
|
+
"alhamdu": "alhamdulillah",
|
|
1246
|
+
"masyaallah": "masya allah",
|
|
1247
|
+
"subhankl": "subhanallah",
|
|
1248
|
+
"astagfirullah": "astaghfirullah",
|
|
1249
|
+
"astghfr": "astaghfirullah",
|
|
1250
|
+
"bsmllh": "bismillah",
|
|
1251
|
+
"bismillahirrahmanirrahim": "bismillah",
|
|
1252
|
+
"allahuakbar": "allahu akbar",
|
|
1253
|
+
"aamiin": "amin",
|
|
1254
|
+
"aminn": "amin",
|
|
1255
|
+
"jazakallah": "semoga Allah membalas kebaikanmu",
|
|
1256
|
+
"jazakallahu khair": "semoga Allah membalas kebaikanmu",
|
|
1257
|
+
"barakallah": "semoga Allah memberkahimu",
|
|
1258
|
+
"sholat": "salat",
|
|
1259
|
+
"solat": "salat",
|
|
1260
|
+
"shalat": "salat",
|
|
1261
|
+
"bukpus": "buka puasa",
|
|
1262
|
+
"bukber": "buka bersama",
|
|
1263
|
+
"ramadhan": "ramadan",
|
|
1264
|
+
"idulfitri": "idul fitri",
|
|
1265
|
+
"eid": "lebaran",
|
|
1266
|
+
"fitrah": "zakat fitrah",
|
|
1267
|
+
"msdjd": "masjid",
|
|
1268
|
+
"mushola": "musala",
|
|
1269
|
+
"musholla": "musala",
|
|
1270
|
+
"psntrn": "pesantren",
|
|
1271
|
+
"ustadz": "ustaz",
|
|
1272
|
+
"ustad": "ustaz",
|
|
1273
|
+
"kyai": "kiai",
|
|
1274
|
+
# National / cultural
|
|
1275
|
+
"bhineka": "bhinneka",
|
|
1276
|
+
"17an": "tujuh belasan",
|
|
1277
|
+
"hut ri": "hari ulang tahun republik indonesia",
|
|
1278
|
+
"hutri": "hari ulang tahun republik indonesia",
|
|
1279
|
+
# Events / celebrations
|
|
1280
|
+
"ultah": "ulang tahun",
|
|
1281
|
+
"ulangtahun": "ulang tahun",
|
|
1282
|
+
"ultahku": "ulang tahunku",
|
|
1283
|
+
"happy birthday": "selamat ulang tahun",
|
|
1284
|
+
"hbd": "selamat ulang tahun",
|
|
1285
|
+
"hbday": "selamat ulang tahun",
|
|
1286
|
+
"met ultah": "selamat ulang tahun",
|
|
1287
|
+
"met ulth": "selamat ulang tahun",
|
|
1288
|
+
"wedding": "pernikahan",
|
|
1289
|
+
"nikah": "menikah",
|
|
1290
|
+
"nikahin": "menikahkan",
|
|
1291
|
+
"tunang": "tunangan",
|
|
1292
|
+
"akad": "akad nikah",
|
|
1293
|
+
"undngn": "undangan",
|
|
1294
|
+
"kondangan": "menghadiri pernikahan",
|
|
1295
|
+
"kondngan": "kondangan",
|
|
1296
|
+
"ngaji": "mengaji",
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
# Education extended vocabulary
|
|
1300
|
+
_EDUCATION_EXTENDED: dict[str, str] = {
|
|
1301
|
+
# School levels
|
|
1302
|
+
"sd": "sekolah dasar",
|
|
1303
|
+
"smp": "sekolah menengah pertama",
|
|
1304
|
+
"sma": "sekolah menengah atas",
|
|
1305
|
+
"smk": "sekolah menengah kejuruan",
|
|
1306
|
+
"univ": "universitas",
|
|
1307
|
+
"univrsitas": "universitas",
|
|
1308
|
+
"kampus": "kampus",
|
|
1309
|
+
"kuliah": "kuliah",
|
|
1310
|
+
"mhsw": "mahasiswa",
|
|
1311
|
+
"dsn": "dosen",
|
|
1312
|
+
"gr": "guru",
|
|
1313
|
+
"kepsek": "kepala sekolah",
|
|
1314
|
+
"kpsek": "kepala sekolah",
|
|
1315
|
+
# Academic activities
|
|
1316
|
+
"bljar": "belajar",
|
|
1317
|
+
"bljr": "belajar",
|
|
1318
|
+
"ngajar": "mengajar",
|
|
1319
|
+
"ngjar": "mengajar",
|
|
1320
|
+
"ulngn": "ulangan",
|
|
1321
|
+
"tgs": "tugas",
|
|
1322
|
+
"pr": "pekerjaan rumah",
|
|
1323
|
+
"homework": "pekerjaan rumah",
|
|
1324
|
+
"hw": "pekerjaan rumah",
|
|
1325
|
+
"presntsi": "presentasi",
|
|
1326
|
+
"prsnts": "presentasi",
|
|
1327
|
+
"laporan": "laporan",
|
|
1328
|
+
"lprn": "laporan",
|
|
1329
|
+
"mklh": "makalah",
|
|
1330
|
+
"skrpsi": "skripsi",
|
|
1331
|
+
"thesis": "tesis",
|
|
1332
|
+
"wsuda": "wisuda",
|
|
1333
|
+
"wsda": "wisuda",
|
|
1334
|
+
"wsd": "wisuda",
|
|
1335
|
+
"yudisium": "yudisium",
|
|
1336
|
+
"ospek": "orientasi studi",
|
|
1337
|
+
"maba": "mahasiswa baru",
|
|
1338
|
+
"mhs baru": "mahasiswa baru",
|
|
1339
|
+
# Grades & results
|
|
1340
|
+
"nilai": "nilai",
|
|
1341
|
+
"nlai": "nilai",
|
|
1342
|
+
"rapor": "rapor",
|
|
1343
|
+
"raport": "rapor",
|
|
1344
|
+
"ipk": "indeks prestasi kumulatif",
|
|
1345
|
+
"ip": "indeks prestasi",
|
|
1346
|
+
"llus": "lulus",
|
|
1347
|
+
"lls": "lulus",
|
|
1348
|
+
"ggal": "gagal",
|
|
1349
|
+
"ggl": "gagal",
|
|
1350
|
+
"remedial": "remedial",
|
|
1351
|
+
"remidi": "remedial",
|
|
1352
|
+
"ngulang": "mengulang",
|
|
1353
|
+
"nunggak": "tidak naik kelas",
|
|
1354
|
+
"naikin": "menaikkan",
|
|
1355
|
+
"beasiwa": "beasiswa",
|
|
1356
|
+
"bsw": "beasiswa",
|
|
1357
|
+
"beasiswaku": "beasiswaku",
|
|
1358
|
+
"daftar": "daftar",
|
|
1359
|
+
"dft": "daftar",
|
|
1360
|
+
"pendaftran": "pendaftaran",
|
|
1361
|
+
"pendftran": "pendaftaran",
|
|
1362
|
+
"pndftran": "pendaftaran",
|
|
1363
|
+
"sleksi": "seleksi",
|
|
1364
|
+
"slksi": "seleksi",
|
|
1365
|
+
"snbt": "seleksi nasional berdasarkan tes",
|
|
1366
|
+
"utbk": "ujian tulis berbasis komputer",
|
|
1367
|
+
"sbmptn": "seleksi bersama masuk perguruan tinggi negeri",
|
|
1368
|
+
"ppdb": "penerimaan peserta didik baru",
|
|
1369
|
+
"bimbel": "bimbingan belajar",
|
|
1370
|
+
"bmbl": "bimbingan belajar",
|
|
1371
|
+
"tryout": "uji coba",
|
|
1372
|
+
"to": "uji coba",
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
# Work & office vocabulary
|
|
1376
|
+
_WORK_OFFICE: dict[str, str] = {
|
|
1377
|
+
# Job types & positions
|
|
1378
|
+
"krja": "kerja",
|
|
1379
|
+
"kerjaan": "pekerjaan",
|
|
1380
|
+
"krjaan": "pekerjaan",
|
|
1381
|
+
"kntr": "kantor",
|
|
1382
|
+
"prusahaan": "perusahaan",
|
|
1383
|
+
"prshn": "perusahaan",
|
|
1384
|
+
"bos": "atasan",
|
|
1385
|
+
"boss": "atasan",
|
|
1386
|
+
"rekan": "rekan kerja",
|
|
1387
|
+
"krywn": "karyawan",
|
|
1388
|
+
"pgwai": "pegawai",
|
|
1389
|
+
"pns": "pegawai negeri sipil",
|
|
1390
|
+
"asn": "aparatur sipil negara",
|
|
1391
|
+
"honorer": "tenaga honorer",
|
|
1392
|
+
"freelance": "pekerja lepas",
|
|
1393
|
+
"frilens": "pekerja lepas",
|
|
1394
|
+
"wfh": "kerja dari rumah",
|
|
1395
|
+
"wfo": "kerja dari kantor",
|
|
1396
|
+
"wfa": "kerja dari mana saja",
|
|
1397
|
+
"remote": "kerja jarak jauh",
|
|
1398
|
+
"hybrid": "kerja hibrida",
|
|
1399
|
+
"intern": "magang",
|
|
1400
|
+
"mgang": "magang",
|
|
1401
|
+
"kntrak": "kontrak",
|
|
1402
|
+
"resign": "mengundurkan diri",
|
|
1403
|
+
"resignasi": "pengunduran diri",
|
|
1404
|
+
"phk": "pemutusan hubungan kerja",
|
|
1405
|
+
# Work activities
|
|
1406
|
+
"rpt": "rapat",
|
|
1407
|
+
"meeting": "rapat",
|
|
1408
|
+
"mtg": "rapat",
|
|
1409
|
+
"zoom": "rapat video",
|
|
1410
|
+
"gmeet": "google meet",
|
|
1411
|
+
"deadline": "batas waktu",
|
|
1412
|
+
"dl": "batas waktu",
|
|
1413
|
+
"dl nya": "batas waktunya",
|
|
1414
|
+
"submit": "kirimkan",
|
|
1415
|
+
"sbmt": "kirimkan",
|
|
1416
|
+
"rvisi": "revisi",
|
|
1417
|
+
"approval": "persetujuan",
|
|
1418
|
+
"approved": "disetujui",
|
|
1419
|
+
"acc": "disetujui",
|
|
1420
|
+
"reject": "ditolak",
|
|
1421
|
+
"feedback": "masukan",
|
|
1422
|
+
"ftdbk": "masukan",
|
|
1423
|
+
"report": "laporan",
|
|
1424
|
+
"update": "perbarui",
|
|
1425
|
+
"followup": "tindak lanjut",
|
|
1426
|
+
"fu": "tindak lanjut",
|
|
1427
|
+
"asap": "sesegera mungkin",
|
|
1428
|
+
"urgent": "mendesak",
|
|
1429
|
+
"priority": "prioritas",
|
|
1430
|
+
"prio": "prioritas",
|
|
1431
|
+
"kpi": "indikator kinerja utama",
|
|
1432
|
+
"okr": "tujuan dan hasil kunci",
|
|
1433
|
+
"brainstorm": "curah gagasan",
|
|
1434
|
+
"brnstrm": "curah gagasan",
|
|
1435
|
+
# Finance / salary
|
|
1436
|
+
"gji": "gaji",
|
|
1437
|
+
"gajinya": "gajinya",
|
|
1438
|
+
"thr": "tunjangan hari raya",
|
|
1439
|
+
"lmbr": "lembur",
|
|
1440
|
+
"overtime": "lembur",
|
|
1441
|
+
"ot": "lembur",
|
|
1442
|
+
"ct": "cuti",
|
|
1443
|
+
"check in": "masuk kerja",
|
|
1444
|
+
"checkin": "masuk kerja",
|
|
1445
|
+
"check out": "keluar kerja",
|
|
1446
|
+
"checkout": "keluar kerja",
|
|
1447
|
+
# Tools / digital work
|
|
1448
|
+
"email": "surel",
|
|
1449
|
+
"mailing": "mengirim surel",
|
|
1450
|
+
"cc": "tembusan",
|
|
1451
|
+
"bcc": "tembusan tersembunyi",
|
|
1452
|
+
"forward": "teruskan",
|
|
1453
|
+
"teams": "microsoft teams",
|
|
1454
|
+
"ms teams": "microsoft teams",
|
|
1455
|
+
"excel": "microsoft excel",
|
|
1456
|
+
"word": "microsoft word",
|
|
1457
|
+
"ppt": "powerpoint",
|
|
1458
|
+
"powerpoint": "presentasi powerpoint",
|
|
1459
|
+
"drive": "google drive",
|
|
1460
|
+
"cloud": "komputasi awan",
|
|
1461
|
+
"database": "basis data",
|
|
1462
|
+
"app": "aplikasi",
|
|
1463
|
+
"apk": "aplikasi",
|
|
1464
|
+
"software": "perangkat lunak",
|
|
1465
|
+
"hardware": "perangkat keras",
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
# Numbers, measurements & quantity expressions
|
|
1469
|
+
_NUMBERS_QUANTITY: dict[str, str] = {
|
|
1470
|
+
# Informal prefix shortcuts (sejuta / semiliar are genuine contractions)
|
|
1471
|
+
"sejuta": "satu juta",
|
|
1472
|
+
"semiliar": "satu miliar",
|
|
1473
|
+
# Informal number abbreviations (rb = ribu, jt = juta)
|
|
1474
|
+
"1rb": "seribu",
|
|
1475
|
+
"2rb": "dua ribu",
|
|
1476
|
+
"5rb": "lima ribu",
|
|
1477
|
+
"10rb": "sepuluh ribu",
|
|
1478
|
+
"20rb": "dua puluh ribu",
|
|
1479
|
+
"50rb": "lima puluh ribu",
|
|
1480
|
+
"100rb": "seratus ribu",
|
|
1481
|
+
"200rb": "dua ratus ribu",
|
|
1482
|
+
"500rb": "lima ratus ribu",
|
|
1483
|
+
"1jt": "satu juta",
|
|
1484
|
+
"2jt": "dua juta",
|
|
1485
|
+
"5jt": "lima juta",
|
|
1486
|
+
"10jt": "sepuluh juta",
|
|
1487
|
+
# Quantity abbreviations (slang → standard)
|
|
1488
|
+
"slrh": "seluruh",
|
|
1489
|
+
"sktr": "sekitar",
|
|
1490
|
+
"hmpr": "hampir",
|
|
1491
|
+
"hmpir": "hampir",
|
|
1492
|
+
"plng2": "paling-paling",
|
|
1493
|
+
# Reduplications (written as X2 or concatenated)
|
|
1494
|
+
"rata2": "rata-rata",
|
|
1495
|
+
"ratarata": "rata-rata",
|
|
1496
|
+
"kira2": "kira-kira",
|
|
1497
|
+
"kirakira": "kira-kira",
|
|
1498
|
+
# Time quantities
|
|
1499
|
+
"sebentar": "sebentar",
|
|
1500
|
+
"sbntr": "sebentar",
|
|
1501
|
+
"sbntr lg": "sebentar lagi",
|
|
1502
|
+
"slmanya": "selamanya",
|
|
1503
|
+
"smntara": "sementara",
|
|
1504
|
+
"mndak": "mendadak",
|
|
1505
|
+
"dadakan": "mendadak",
|
|
1506
|
+
"ssgera": "segera",
|
|
1507
|
+
"sgera": "segera",
|
|
1508
|
+
"sgra": "segera",
|
|
1509
|
+
"cpat": "cepat",
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
# Common compound slang expressions & phrases
|
|
1513
|
+
# Only include entries where the COMBINED phrase produces a different result
|
|
1514
|
+
# than individual word lookups would give (e.g. slang fusion, negation compounds
|
|
1515
|
+
# with particles, or abbreviations that span multiple tokens).
|
|
1516
|
+
_COMPOUND_EXPRESSIONS: dict[str, str] = {
|
|
1517
|
+
# Slang word + particle/qualifier — transformation differs from individual lookups
|
|
1518
|
+
"eh iya": "oh iya", # discourse opener
|
|
1519
|
+
"gitu kan": "begitu kan",
|
|
1520
|
+
"gitu dong": "begitu dong",
|
|
1521
|
+
"beneran ga": "sungguh tidak",
|
|
1522
|
+
"beneran nih": "sungguh ini",
|
|
1523
|
+
"srius": "serius", # typo of standard word
|
|
1524
|
+
"serius nih": "serius ini",
|
|
1525
|
+
# Question compounds with negation particle
|
|
1526
|
+
"bisa ga": "bisa tidak",
|
|
1527
|
+
"bisa gak": "bisa tidak",
|
|
1528
|
+
"boleh ga": "boleh tidak",
|
|
1529
|
+
"boleh gak": "boleh tidak",
|
|
1530
|
+
"mau ga": "mau tidak",
|
|
1531
|
+
"mau gak": "mau tidak",
|
|
1532
|
+
"tau ga": "tahu tidak",
|
|
1533
|
+
"tau gak": "tahu tidak",
|
|
1534
|
+
# Multi-token slang phrases
|
|
1535
|
+
"gimana caranya": "bagaimana caranya",
|
|
1536
|
+
"gmn caranya": "bagaimana caranya",
|
|
1537
|
+
"gue juga": "saya juga",
|
|
1538
|
+
"gw juga": "saya juga",
|
|
1539
|
+
"kayaknya sih": "sepertinya",
|
|
1540
|
+
"kayaknya iya": "sepertinya iya",
|
|
1541
|
+
"buat apa": "untuk apa",
|
|
1542
|
+
"bwt apa": "untuk apa",
|
|
1543
|
+
"ngapain": "sedang apa",
|
|
1544
|
+
"ngapain aja": "sedang apa saja",
|
|
1545
|
+
"lagi ngapain": "sedang apa",
|
|
1546
|
+
"lagi dimana": "sedang di mana",
|
|
1547
|
+
"lg dmn": "sedang di mana",
|
|
1548
|
+
"otw ke": "dalam perjalanan ke",
|
|
1549
|
+
"nyampe blm": "sudah sampai belum",
|
|
1550
|
+
"sampai blm": "sudah sampai belum",
|
|
1551
|
+
# Compound slang where slang token fuses with standard word
|
|
1552
|
+
"udah mkan": "sudah makan", # mkan not split correctly if fused
|
|
1553
|
+
"blm makan": "belum makan",
|
|
1554
|
+
"udh lma": "sudah lama",
|
|
1555
|
+
"br aja": "baru saja",
|
|
1556
|
+
"bsk aja": "besok saja",
|
|
1557
|
+
"skrg juga": "sekarang juga",
|
|
1558
|
+
"dr tadi": "dari tadi",
|
|
1559
|
+
"dr dulu": "dari dulu",
|
|
1560
|
+
"tlg bantu": "tolong bantu",
|
|
1561
|
+
# Agreement / disagreement — particle changes meaning of phrase
|
|
1562
|
+
"emang bener": "memang benar",
|
|
1563
|
+
"bener juga": "benar juga",
|
|
1564
|
+
"iya bener": "iya benar",
|
|
1565
|
+
"nggak dong": "tidak dong",
|
|
1566
|
+
"nggak sih": "tidak sih",
|
|
1567
|
+
"ya ga": "ya tidak",
|
|
1568
|
+
"ga juga": "tidak juga",
|
|
1569
|
+
"gak juga": "tidak juga",
|
|
1570
|
+
"bukan gitu": "bukan begitu",
|
|
1571
|
+
"bukan disini": "bukan di sini",
|
|
1572
|
+
"maksudnya gimana": "maksudnya bagaimana",
|
|
1573
|
+
"mksdnya gmn": "maksudnya bagaimana",
|
|
1574
|
+
# Temporal compound abbreviations
|
|
1575
|
+
"kapan2": "kapan-kapan",
|
|
1576
|
+
"kapan2 ya": "kapan-kapan ya",
|
|
1577
|
+
"ntar aja": "nanti saja",
|
|
1578
|
+
"tar aja": "nanti saja",
|
|
1579
|
+
"makasih banyak": "terima kasih banyak",
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1583
|
+
# PARTICLES
|
|
1584
|
+
# Indonesian sentence-final / clause-final pragmatic particles.
|
|
1585
|
+
# The 6 canonical forms (lah, deh, nih, dong, kok, sih) are pass-through mapped
|
|
1586
|
+
# to prevent them from being stripped. Other particles rely on auto-reduction.
|
|
1587
|
+
#
|
|
1588
|
+
# Design: _reduce_repeated_chars automatically collapses:
|
|
1589
|
+
# - vowels: 2+ consecutive → 1 (laah → lah, yaa → ya)
|
|
1590
|
+
# - consonants: 3+ consecutive → 1 (lahhhh → lah, yukkk → yuk)
|
|
1591
|
+
# Note: 2-consonant repeats (lahh, dehh) are explicitly mapped here as they
|
|
1592
|
+
# are not auto-reduced.
|
|
1593
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1594
|
+
_PARTICLES: dict[str, str] = {
|
|
1595
|
+
# ── lah ──
|
|
1596
|
+
"lah": "lah",
|
|
1597
|
+
"lh": "lah",
|
|
1598
|
+
"lahh": "lah",
|
|
1599
|
+
"la": "lah",
|
|
1600
|
+
# ── deh ──
|
|
1601
|
+
"deh": "deh",
|
|
1602
|
+
"dh": "deh",
|
|
1603
|
+
"dehh": "deh",
|
|
1604
|
+
"de": "deh",
|
|
1605
|
+
# ── nih ──
|
|
1606
|
+
"nih": "nih",
|
|
1607
|
+
"ni": "nih",
|
|
1608
|
+
"nihh": "nih",
|
|
1609
|
+
"neh": "nih", # Betawi variant
|
|
1610
|
+
"nehh": "nih",
|
|
1611
|
+
# ── dong ──
|
|
1612
|
+
"dong": "dong",
|
|
1613
|
+
"dng": "dong",
|
|
1614
|
+
"dongg": "dong",
|
|
1615
|
+
"don": "dong",
|
|
1616
|
+
# ── kok ──
|
|
1617
|
+
"kok": "kok",
|
|
1618
|
+
"kokk": "kok",
|
|
1619
|
+
# ── sih ──
|
|
1620
|
+
"sih": "sih",
|
|
1621
|
+
"si": "sih",
|
|
1622
|
+
"sihh": "sih",
|
|
1623
|
+
"sich": "sih",
|
|
1624
|
+
# ── Other Particle Variants ──
|
|
1625
|
+
"loh": "lho",
|
|
1626
|
+
"lo": "lho",
|
|
1627
|
+
"punn": "pun",
|
|
1628
|
+
"tohh": "toh",
|
|
1629
|
+
"kahh": "kah",
|
|
1630
|
+
"tahh": "tah",
|
|
1631
|
+
"woy": "woi",
|
|
1632
|
+
"woyy": "woi",
|
|
1633
|
+
"hey": "hei",
|
|
1634
|
+
"yukk": "yuk",
|
|
1635
|
+
"yuk ah": "yuk",
|
|
1636
|
+
"ahh": "ah",
|
|
1637
|
+
"ihh": "ih",
|
|
1638
|
+
"idihh": "idih",
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1642
|
+
# MERGE ALL CATEGORIES INTO ONE MAPPING
|
|
1643
|
+
# Order matters: later dicts override earlier ones on key conflicts.
|
|
1644
|
+
# Compound negation must appear so that it sorts BEFORE single-char negation
|
|
1645
|
+
# (handled automatically by longest-first sort in _compile_pattern).
|
|
1646
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1647
|
+
_DEFAULT_SLANG: dict[str, str] = {}
|
|
1648
|
+
for _cat in (
|
|
1649
|
+
_PRONOUNS,
|
|
1650
|
+
_KINSHIP,
|
|
1651
|
+
_NEGATION,
|
|
1652
|
+
_COMPOUND_NEGATION,
|
|
1653
|
+
_CONJUNCTIONS,
|
|
1654
|
+
_VERBS,
|
|
1655
|
+
_ADJECTIVES_ADVERBS,
|
|
1656
|
+
_QUESTION_WORDS,
|
|
1657
|
+
_GREETINGS_RESPONSES,
|
|
1658
|
+
_TEMPORAL_LOCATION,
|
|
1659
|
+
_INTERNET_SLANG,
|
|
1660
|
+
_ECOMMERCE_FINANCE,
|
|
1661
|
+
_YOUTH_SLANG,
|
|
1662
|
+
_DISCOURSE_MARKERS,
|
|
1663
|
+
_JAVANESE_EXTENDED,
|
|
1664
|
+
_SUNDANESE_EXTENDED,
|
|
1665
|
+
_NOUNS,
|
|
1666
|
+
_HEALTH,
|
|
1667
|
+
_EMOTIONS_EXPRESSIONS,
|
|
1668
|
+
_FOOD_DRINK,
|
|
1669
|
+
_CLOTHING_FASHION,
|
|
1670
|
+
_TRANSPORTATION,
|
|
1671
|
+
_RELIGION_CULTURE,
|
|
1672
|
+
_EDUCATION_EXTENDED,
|
|
1673
|
+
_WORK_OFFICE,
|
|
1674
|
+
_NUMBERS_QUANTITY,
|
|
1675
|
+
_COMPOUND_EXPRESSIONS,
|
|
1676
|
+
_PARTICLES,
|
|
1677
|
+
):
|
|
1678
|
+
_DEFAULT_SLANG.update(_cat)
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1682
|
+
# REPEATED CHARACTER NORMALIZATION PATTERNS
|
|
1683
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1684
|
+
|
|
1685
|
+
# Vowels: reduce 2+ consecutive identical vowels → 1
|
|
1686
|
+
# e.g. "manaa" → "mana", "bangeeeet" → "banget"
|
|
1687
|
+
# Rationale: vowel elongation is always expressive, never meaningful.
|
|
1688
|
+
_VOWEL_REPEAT = re.compile(r"([aeiouAEIOU])\1+")
|
|
1689
|
+
|
|
1690
|
+
# Strict vowel reduction: only collapse 3+ consecutive identical vowels.
|
|
1691
|
+
# Used in the global fallback pass so that valid standard Indonesian spellings
|
|
1692
|
+
# containing double vowels (e.g. "pekerjaan", "maaf", "laal") are NOT touched,
|
|
1693
|
+
# while obvious elongation ("manaaaa", "beneeer") is still reduced.
|
|
1694
|
+
_VOWEL_REPEAT_STRICT = re.compile(r"([aeiouAEIOU])\1{2,}")
|
|
1695
|
+
|
|
1696
|
+
# Consonants: reduce 3+ consecutive identical consonants → 1
|
|
1697
|
+
# e.g. "bgttt" → "bgt", "wkwwwk" → "wkwk"
|
|
1698
|
+
# Rationale: keep "kk" (kakak), "ll" (dalam "dll"), "mm" etc. intact;
|
|
1699
|
+
# only collapse truly elongated forms (3+).
|
|
1700
|
+
# Note: [^\W\s\d] matches letter-only consonants, excluding punctuation
|
|
1701
|
+
# so that "!!!" is NOT reduced here (that is handled by normalize_punctuation).
|
|
1702
|
+
_CONSONANT_REPEAT = re.compile(r"([^\W\s\daeiouAEIOU])\1{2,}")
|
|
1703
|
+
|
|
1704
|
+
# Whitespace normalization
|
|
1705
|
+
_WHITESPACE = re.compile(r"\s+")
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1709
|
+
# MAIN CLASS
|
|
1710
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
class SlangNormalizer:
|
|
1714
|
+
"""
|
|
1715
|
+
Normalizes informal/colloquial Indonesian text to standard Indonesian.
|
|
1716
|
+
|
|
1717
|
+
Args:
|
|
1718
|
+
custom_mapping: Optional additional slang entries that override or
|
|
1719
|
+
extend the built-in dictionary.
|
|
1720
|
+
|
|
1721
|
+
Example:
|
|
1722
|
+
>>> normalizer = SlangNormalizer()
|
|
1723
|
+
>>> normalizer.normalize("gw gamau pergi krn lg baper bgt")
|
|
1724
|
+
'saya tidak mau pergi karena sedang bawa perasaan banget'
|
|
1725
|
+
|
|
1726
|
+
>>> normalizer.add("npwp", "nomor pokok wajib pajak")
|
|
1727
|
+
>>> normalizer.normalize("masukin npwp dulu")
|
|
1728
|
+
'masukkan nomor pokok wajib pajak dulu'
|
|
1729
|
+
|
|
1730
|
+
>>> normalizer.normalize_batch(["gw mau makan", "km udah makan?"])
|
|
1731
|
+
['saya mau makan', 'kamu sudah makan?']
|
|
1732
|
+
"""
|
|
1733
|
+
|
|
1734
|
+
def __init__(self, custom_mapping: dict[str, str] | None = None):
|
|
1735
|
+
self.mapping: dict[str, str] = {k.lower(): v for k, v in _DEFAULT_SLANG.items()}
|
|
1736
|
+
if custom_mapping:
|
|
1737
|
+
self.mapping.update({k.lower(): v for k, v in custom_mapping.items()})
|
|
1738
|
+
self._regex: re.Pattern | None = None
|
|
1739
|
+
self._compile_pattern()
|
|
1740
|
+
|
|
1741
|
+
# ─── Internal ────────────────────────────────────────────────────────────
|
|
1742
|
+
|
|
1743
|
+
def _compile_pattern(self) -> None:
|
|
1744
|
+
"""
|
|
1745
|
+
Build a compiled regex from the current mapping.
|
|
1746
|
+
|
|
1747
|
+
Keys are sorted longest-first so compound slang like "gamau"
|
|
1748
|
+
matches before its shorter substring "ga".
|
|
1749
|
+
"""
|
|
1750
|
+
if not self.mapping:
|
|
1751
|
+
self._regex = None
|
|
1752
|
+
return
|
|
1753
|
+
sorted_keys = sorted(self.mapping.keys(), key=len, reverse=True)
|
|
1754
|
+
escaped = [re.escape(k) for k in sorted_keys]
|
|
1755
|
+
pattern = r"\b(" + "|".join(escaped) + r")\b"
|
|
1756
|
+
self._regex = re.compile(pattern, re.IGNORECASE)
|
|
1757
|
+
|
|
1758
|
+
@staticmethod
|
|
1759
|
+
def _reduce_repeated_chars(text: str) -> str:
|
|
1760
|
+
"""
|
|
1761
|
+
Collapse elongated characters to their canonical form.
|
|
1762
|
+
|
|
1763
|
+
Rules:
|
|
1764
|
+
- Vowels (a, e, i, o, u): 2+ consecutive → 1
|
|
1765
|
+
"manaaaa" → "mana", "bangeeeet" → "banget"
|
|
1766
|
+
- Consonants: 3+ consecutive → 1
|
|
1767
|
+
"bgttttt" → "bgt", "wkwwwwk" → "wkwk"
|
|
1768
|
+
"kk" → "kk" (preserved — abbreviation for "kakak")
|
|
1769
|
+
"dll" → "dll" (preserved — "dan lain-lain")
|
|
1770
|
+
|
|
1771
|
+
Vowels are processed first so that a string like "aaakk" is handled
|
|
1772
|
+
correctly in two distinct passes without cross-contamination.
|
|
1773
|
+
"""
|
|
1774
|
+
text = _VOWEL_REPEAT.sub(r"\1", text)
|
|
1775
|
+
text = _CONSONANT_REPEAT.sub(r"\1", text)
|
|
1776
|
+
return text
|
|
1777
|
+
|
|
1778
|
+
@staticmethod
|
|
1779
|
+
def _reduce_repeated_chars_strict(text: str) -> str:
|
|
1780
|
+
"""
|
|
1781
|
+
Like _reduce_repeated_chars but uses a stricter threshold for vowels:
|
|
1782
|
+
only collapses 3+ consecutive identical vowels (not 2+).
|
|
1783
|
+
|
|
1784
|
+
This is used as the global fallback pass inside normalize() so that
|
|
1785
|
+
standard Indonesian words with legitimate double vowels (e.g.
|
|
1786
|
+
"pekerjaan", "maaf") are not corrupted, while obvious elongation
|
|
1787
|
+
("manaaaa", "beneeer") is still collapsed.
|
|
1788
|
+
"""
|
|
1789
|
+
text = _VOWEL_REPEAT_STRICT.sub(r"\1", text)
|
|
1790
|
+
text = _CONSONANT_REPEAT.sub(r"\1", text)
|
|
1791
|
+
return text
|
|
1792
|
+
|
|
1793
|
+
# ─── Public API ──────────────────────────────────────────────────────────
|
|
1794
|
+
|
|
1795
|
+
@staticmethod
|
|
1796
|
+
def _mirror_case(original: str, replacement: str) -> str:
|
|
1797
|
+
"""
|
|
1798
|
+
Mirror the casing pattern of ``original`` onto ``replacement``.
|
|
1799
|
+
|
|
1800
|
+
Rules (applied in priority order):
|
|
1801
|
+
- All-uppercase original → replacement.upper()
|
|
1802
|
+
- Title-case original → replacement.capitalize()
|
|
1803
|
+
- Mixed / lowercase → replacement unchanged (already lowercase)
|
|
1804
|
+
|
|
1805
|
+
This lets ``normalize(lowercase=False)`` preserve casing intent
|
|
1806
|
+
even after slang substitution.
|
|
1807
|
+
|
|
1808
|
+
Examples:
|
|
1809
|
+
>>> SlangNormalizer._mirror_case("GW", "saya")
|
|
1810
|
+
'SAYA'
|
|
1811
|
+
>>> SlangNormalizer._mirror_case("Gw", "saya")
|
|
1812
|
+
'Saya'
|
|
1813
|
+
>>> SlangNormalizer._mirror_case("gw", "saya")
|
|
1814
|
+
'saya'
|
|
1815
|
+
"""
|
|
1816
|
+
if original.isupper():
|
|
1817
|
+
return replacement.upper()
|
|
1818
|
+
if original[0].isupper():
|
|
1819
|
+
return replacement.capitalize()
|
|
1820
|
+
return replacement
|
|
1821
|
+
|
|
1822
|
+
def normalize(
|
|
1823
|
+
self,
|
|
1824
|
+
text: str,
|
|
1825
|
+
normalize_whitespace: bool = True,
|
|
1826
|
+
lowercase: bool = True,
|
|
1827
|
+
) -> str:
|
|
1828
|
+
"""
|
|
1829
|
+
Normalize a single text string.
|
|
1830
|
+
|
|
1831
|
+
Pipeline:
|
|
1832
|
+
1. Slang replacement with two-pass per-token lookup
|
|
1833
|
+
2. Global repeated-char reduction for out-of-vocab elongated words
|
|
1834
|
+
3. Second regex pass for words newly recognisable after reduction
|
|
1835
|
+
(e.g. "gwwww" → step2 → "gw" → step3 → "saya")
|
|
1836
|
+
4. (Optionally) collapse multiple whitespace into one
|
|
1837
|
+
|
|
1838
|
+
Args:
|
|
1839
|
+
text: Input text string.
|
|
1840
|
+
normalize_whitespace: If True, collapse multi-space into single
|
|
1841
|
+
space and strip leading/trailing whitespace.
|
|
1842
|
+
lowercase: If True (default), replacement values are returned as-is
|
|
1843
|
+
(all lowercase). If False, the casing pattern of the
|
|
1844
|
+
original matched token is mirrored onto the replacement
|
|
1845
|
+
(ALL-CAPS → upper, Title → capitalize, mixed → as-is).
|
|
1846
|
+
|
|
1847
|
+
Returns:
|
|
1848
|
+
Normalized text string.
|
|
1849
|
+
"""
|
|
1850
|
+
if not text or not text.strip():
|
|
1851
|
+
return text
|
|
1852
|
+
|
|
1853
|
+
# Step 1: Slang replacement with two-pass per-token lookup.
|
|
1854
|
+
# The regex matches candidates from the slang dict; for each match:
|
|
1855
|
+
# Pass A – lookup the original token (handles "krjaan" which has a
|
|
1856
|
+
# meaningful double-a that char-reduction would destroy).
|
|
1857
|
+
# Pass B – reduce repeated chars first, then lookup (handles elongated
|
|
1858
|
+
# forms like "gkkkk" → "gk" → "tidak").
|
|
1859
|
+
# Fallback – return the char-reduced form so elongation is still
|
|
1860
|
+
# collapsed even when no dict entry exists.
|
|
1861
|
+
if self._regex:
|
|
1862
|
+
|
|
1863
|
+
def _replace(match: re.Match) -> str:
|
|
1864
|
+
original = match.group(1)
|
|
1865
|
+
word = original.lower()
|
|
1866
|
+
|
|
1867
|
+
# Pass A: direct lookup (preserve meaningful repeated vowels)
|
|
1868
|
+
if word in self.mapping:
|
|
1869
|
+
result = self.mapping[word]
|
|
1870
|
+
if not lowercase:
|
|
1871
|
+
return self._mirror_case(original, result)
|
|
1872
|
+
return result
|
|
1873
|
+
|
|
1874
|
+
# Pass B: reduce chars first, then lookup
|
|
1875
|
+
reduced = self._reduce_repeated_chars(word)
|
|
1876
|
+
if reduced in self.mapping:
|
|
1877
|
+
result = self.mapping[reduced]
|
|
1878
|
+
if not lowercase:
|
|
1879
|
+
return self._mirror_case(original, result)
|
|
1880
|
+
return result
|
|
1881
|
+
|
|
1882
|
+
# Fallback: return char-reduced form (preserves original case)
|
|
1883
|
+
return self._reduce_repeated_chars(original)
|
|
1884
|
+
|
|
1885
|
+
text = self._regex.sub(_replace, text)
|
|
1886
|
+
|
|
1887
|
+
# Step 2: Global char reduction (strict mode) for words not captured
|
|
1888
|
+
# by the dict regex, e.g. out-of-vocab elongated words ("manaaaa" ->
|
|
1889
|
+
# "mana") or words whose elongated form isn't in the regex ("gwwww" ->
|
|
1890
|
+
# "gw").
|
|
1891
|
+
# STRICT: only collapses 3+ consecutive identical vowels so that valid
|
|
1892
|
+
# standard Indonesian double vowels in replacement outputs (e.g.
|
|
1893
|
+
# "pekerjaan") are NOT corrupted.
|
|
1894
|
+
text = self._reduce_repeated_chars_strict(text)
|
|
1895
|
+
|
|
1896
|
+
# Step 3: Second regex pass — catches words that only became recognisable
|
|
1897
|
+
# after Step 2 (e.g. "gwwww" -> "gw" -> "saya", "gkkkk" -> "gk" -> "tidak").
|
|
1898
|
+
if self._regex:
|
|
1899
|
+
text = self._regex.sub(_replace, text)
|
|
1900
|
+
|
|
1901
|
+
# Step 4: Normalize whitespace
|
|
1902
|
+
if normalize_whitespace:
|
|
1903
|
+
text = _WHITESPACE.sub(" ", text).strip()
|
|
1904
|
+
|
|
1905
|
+
return text
|
|
1906
|
+
|
|
1907
|
+
def normalize_batch(
|
|
1908
|
+
self,
|
|
1909
|
+
texts: list[str],
|
|
1910
|
+
normalize_whitespace: bool = True,
|
|
1911
|
+
lowercase: bool = True,
|
|
1912
|
+
) -> list[str]:
|
|
1913
|
+
"""
|
|
1914
|
+
Normalize a list of text strings efficiently.
|
|
1915
|
+
|
|
1916
|
+
Args:
|
|
1917
|
+
texts: List of input strings.
|
|
1918
|
+
normalize_whitespace: Passed through to normalize().
|
|
1919
|
+
lowercase: Passed through to normalize().
|
|
1920
|
+
|
|
1921
|
+
Returns:
|
|
1922
|
+
List of normalized strings (same order as input).
|
|
1923
|
+
|
|
1924
|
+
Example:
|
|
1925
|
+
>>> slang.normalize_batch(["gw udah makan", "km blm tidur?"])
|
|
1926
|
+
['saya sudah makan', 'kamu belum tidur?']
|
|
1927
|
+
"""
|
|
1928
|
+
return [self.normalize(t, normalize_whitespace, lowercase) for t in texts]
|
|
1929
|
+
|
|
1930
|
+
def add(self, word: str, replacement: str) -> None:
|
|
1931
|
+
"""
|
|
1932
|
+
Add a single entry to the slang dictionary.
|
|
1933
|
+
|
|
1934
|
+
Triggers regex recompilation. For adding many entries at once,
|
|
1935
|
+
prefer bulk_add() to avoid repeated recompilation.
|
|
1936
|
+
|
|
1937
|
+
Args:
|
|
1938
|
+
word: Slang word (stored as lowercase).
|
|
1939
|
+
replacement: Standard replacement string.
|
|
1940
|
+
|
|
1941
|
+
Example:
|
|
1942
|
+
>>> normalizer.add("npwp", "nomor pokok wajib pajak")
|
|
1943
|
+
"""
|
|
1944
|
+
self.mapping[word.lower()] = replacement
|
|
1945
|
+
self._compile_pattern()
|
|
1946
|
+
|
|
1947
|
+
def bulk_add(self, mapping: dict[str, str]) -> None:
|
|
1948
|
+
"""
|
|
1949
|
+
Add multiple entries at once with a single regex recompilation.
|
|
1950
|
+
|
|
1951
|
+
More efficient than calling add() repeatedly when inserting
|
|
1952
|
+
many domain-specific terms.
|
|
1953
|
+
|
|
1954
|
+
Args:
|
|
1955
|
+
mapping: Dict of {slang: replacement} pairs.
|
|
1956
|
+
|
|
1957
|
+
Example:
|
|
1958
|
+
>>> normalizer.bulk_add({
|
|
1959
|
+
... "kk": "kakak",
|
|
1960
|
+
... "adek": "adik",
|
|
1961
|
+
... "bokap": "ayah",
|
|
1962
|
+
... "nyokap": "ibu",
|
|
1963
|
+
... })
|
|
1964
|
+
"""
|
|
1965
|
+
self.mapping.update({k.lower(): v for k, v in mapping.items()})
|
|
1966
|
+
self._compile_pattern()
|
|
1967
|
+
|
|
1968
|
+
def remove(self, word: str) -> bool:
|
|
1969
|
+
"""
|
|
1970
|
+
Remove a word from the dictionary.
|
|
1971
|
+
|
|
1972
|
+
Args:
|
|
1973
|
+
word: Slang word to remove.
|
|
1974
|
+
|
|
1975
|
+
Returns:
|
|
1976
|
+
True if the word was found and removed, False otherwise.
|
|
1977
|
+
"""
|
|
1978
|
+
word_lower = word.lower()
|
|
1979
|
+
if word_lower in self.mapping:
|
|
1980
|
+
del self.mapping[word_lower]
|
|
1981
|
+
self._compile_pattern()
|
|
1982
|
+
return True
|
|
1983
|
+
return False
|
|
1984
|
+
|
|
1985
|
+
def reset(self) -> None:
|
|
1986
|
+
"""
|
|
1987
|
+
Reset dictionary to built-in defaults, discarding all custom changes.
|
|
1988
|
+
|
|
1989
|
+
Example:
|
|
1990
|
+
>>> normalizer.add("x", "ekstra")
|
|
1991
|
+
>>> "x" in normalizer
|
|
1992
|
+
True
|
|
1993
|
+
>>> normalizer.reset()
|
|
1994
|
+
>>> "x" in normalizer
|
|
1995
|
+
False
|
|
1996
|
+
"""
|
|
1997
|
+
self.mapping = {k.lower(): v for k, v in _DEFAULT_SLANG.items()}
|
|
1998
|
+
self._compile_pattern()
|
|
1999
|
+
|
|
2000
|
+
def export(self) -> dict[str, str]:
|
|
2001
|
+
"""
|
|
2002
|
+
Export the current mapping as a plain dictionary.
|
|
2003
|
+
|
|
2004
|
+
Returns:
|
|
2005
|
+
A copy of the current {slang: replacement} mapping.
|
|
2006
|
+
"""
|
|
2007
|
+
return self.mapping.copy()
|
|
2008
|
+
|
|
2009
|
+
def supported_words(self) -> dict[str, str]:
|
|
2010
|
+
"""
|
|
2011
|
+
Return all supported slang words and their standard replacements.
|
|
2012
|
+
|
|
2013
|
+
Useful for debugging, documentation, or building custom UIs.
|
|
2014
|
+
|
|
2015
|
+
Returns:
|
|
2016
|
+
A copy of the current {slang: standard} mapping, sorted
|
|
2017
|
+
alphabetically by slang key.
|
|
2018
|
+
|
|
2019
|
+
Example:
|
|
2020
|
+
>>> from basa import slang
|
|
2021
|
+
>>> words = slang.supported_words()
|
|
2022
|
+
>>> words["gw"]
|
|
2023
|
+
'saya'
|
|
2024
|
+
>>> len(slang)
|
|
2025
|
+
120
|
|
2026
|
+
"""
|
|
2027
|
+
return dict(sorted(self.mapping.items()))
|
|
2028
|
+
|
|
2029
|
+
def lookup(self, word: str) -> str | None:
|
|
2030
|
+
"""
|
|
2031
|
+
Look up a single slang word without normalizing a full sentence.
|
|
2032
|
+
|
|
2033
|
+
Args:
|
|
2034
|
+
word: Word to look up (case-insensitive).
|
|
2035
|
+
|
|
2036
|
+
Returns:
|
|
2037
|
+
The replacement string, or None if not found.
|
|
2038
|
+
|
|
2039
|
+
Example:
|
|
2040
|
+
>>> slang.lookup("bgt")
|
|
2041
|
+
'banget'
|
|
2042
|
+
>>> slang.lookup("makan")
|
|
2043
|
+
None
|
|
2044
|
+
"""
|
|
2045
|
+
return self.mapping.get(word.lower())
|
|
2046
|
+
|
|
2047
|
+
# ─── Dunder helpers ──────────────────────────────────────────────────────
|
|
2048
|
+
|
|
2049
|
+
def __len__(self) -> int:
|
|
2050
|
+
"""Return number of entries in the slang dictionary."""
|
|
2051
|
+
return len(self.mapping)
|
|
2052
|
+
|
|
2053
|
+
def __contains__(self, word: str) -> bool:
|
|
2054
|
+
"""Check if a word is in the slang dictionary (case-insensitive)."""
|
|
2055
|
+
return word.lower() in self.mapping
|
|
2056
|
+
|
|
2057
|
+
def __repr__(self) -> str:
|
|
2058
|
+
return f"SlangNormalizer(entries={len(self.mapping)})"
|
|
2059
|
+
|
|
2060
|
+
|
|
2061
|
+
# Backward-compatible alias
|
|
2062
|
+
SlangDictionary = SlangNormalizer
|
|
2063
|
+
|
|
2064
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2065
|
+
# MODULE-LEVEL CONVENIENCE SINGLETON
|
|
2066
|
+
#
|
|
2067
|
+
# Import and use directly without instantiation:
|
|
2068
|
+
# from basa.core.slang import slang
|
|
2069
|
+
# slang.normalize("gw gamau pergi")
|
|
2070
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2071
|
+
slang = SlangNormalizer()
|