Skip to content

Bahasa Indonesia UI Conventions

RetailOS is built for Indonesian users. This guide covers language conventions, formatting rules, and tone of voice for all UI text.

Tone & Formality

App TypeRegisterPronounExample
Admin portals (HO, Store Admin, HR)Formal"Anda""Apakah Anda yakin ingin menghapus?"
Customer-facing (Customer App)Casual"kamu""Mau redeem poin kamu?"
POS (cashier-facing)Neutral— (imperative)"Scan barcode produk"
Error messagesPolite"Koneksi terputus. Coba lagi?"

Common UI Terms

EnglishIndonesianContext
SaveSimpanForm submit (non-destructive)
CancelBatalDismiss action
DeleteHapusDestructive action
SubmitKirimForm submission to server
SearchCariSearch input
CloseTutupClose modal/sheet
EditUbahModify existing data
AddTambahCreate new item
BackKembaliNavigation
NextLanjutMulti-step wizard
PreviousSebelumnyaNavigation
ConfirmKonfirmasiConfirmation dialog
LoadingMemuat...Loading state
RefreshMuat ulangReload data
SettingsPengaturanApp settings
ProfileProfilUser profile
LogoutKeluarSign out
LoginMasukSign in
RegisterDaftarCreate account
FilterFilter(loan word, accepted)
ExportEksporDownload data
ImportImporUpload data
UploadUnggahFile upload
DownloadUnduhFile download
SelectPilihChoose from options
AllSemuaFilter: show all
NoneTidak adaEmpty selection
YesYaConfirmation
NoTidakRejection
DoneSelesaiCompletion
PendingMenungguAwaiting action
ApprovedDisetujuiApproval granted
RejectedDitolakApproval denied

Number Formatting

Indonesian convention uses dots for thousands and commas for decimals (opposite of English).

FormatCorrectIncorrect
Thousands separator12.450.00012,450,000
Decimal separator3,53.5
CurrencyRp 12.450.000Rp 12,450,000 or IDR 12450000
Percentage12,4%12.4%
Quantity1.250 pcs1,250 pcs

Currency Rules

RuleExample
Prefix: "Rp" with spaceRp 12.450.000
No decimal for IDRRp 12.450.000 not Rp 12.450.000,00
Negative: minus before Rp-Rp 150.000
Abbreviated: use "rb" or "jt"Rp 12,4jt (informal, charts only)

Code Implementation

ts
function formatIDR(amount: number): string {
  return `Rp ${amount.toLocaleString('id-ID')}`
}

// formatIDR(12450000) → "Rp 12.450.000"
// formatIDR(-150000) → "-Rp 150.000"

Date & Time

Date Formats

ContextFormatExample
Full (formal)EEEE, dd MMMM yyyySabtu, 22 Maret 2026
Mediumdd MMM yyyy22 Mar 2026
Shortdd/MM/yyyy22/03/2026
Relative (recent)Natural language2 jam lalu, Kemarin
Table columnsdd MMM yyyy22 Mar 2026
Timestampsdd MMM, HH:mm22 Mar, 14:32

Indonesian Day Names

DayFullAbbreviated
MondaySeninSen
TuesdaySelasaSel
WednesdayRabuRab
ThursdayKamisKam
FridayJumatJum
SaturdaySabtuSab
SundayMingguMin

Indonesian Month Names

MonthFullAbbreviated
JanuaryJanuariJan
FebruaryFebruariFeb
MarchMaretMar
AprilAprilApr
MayMeiMei
JuneJuniJun
JulyJuliJul
AugustAgustusAgu
SeptemberSeptemberSep
OctoberOktoberOkt
NovemberNovemberNov
DecemberDesemberDes

Time Format

Always use 24-hour format:

CorrectIncorrect
14:322:32 PM
08:058:05 AM
00:0012:00 AM

Code Implementation

ts
import { format } from 'date-fns'
import { id } from 'date-fns/locale'

// Full date
format(date, 'EEEE, dd MMMM yyyy', { locale: id })
// → "Sabtu, 22 Maret 2026"

// Medium date
format(date, 'dd MMM yyyy', { locale: id })
// → "22 Mar 2026"

// Timestamp
format(date, 'dd MMM, HH:mm', { locale: id })
// → "22 Mar, 14:32"

Error Messages

Write error messages that are polite, specific, and suggest a next action.

PatternGoodBad
Connection error"Koneksi terputus. Coba lagi?""Network error"
Not found"Produk tidak ditemukan""404 Not Found"
Validation"Nama harus diisi""Field required"
Permission"Anda tidak memiliki akses ke halaman ini""403 Forbidden"
Server error"Terjadi kesalahan. Tim kami sedang memperbaiki.""Internal Server Error"
Timeout"Permintaan terlalu lama. Coba lagi.""Request timeout"

Always actionable

Every error message should answer: "What happened?" and "What can I do about it?"

Success Messages

Keep success messages concise. Users don't need a sentence --- a word or two is enough.

ContextGoodBad
Save"Tersimpan""Data berhasil disimpan ke database"
Delete"Terhapus""Item telah berhasil dihapus dari sistem"
Send"Terkirim""Pesan Anda telah berhasil dikirim"
Update"Diperbarui""Perubahan telah berhasil diterapkan"
Copy"Tersalin""Teks berhasil disalin ke clipboard"

Empty States

Empty states should be friendly and guide users to take action.

ContextGoodBad
No transactions today"Belum ada transaksi hari ini""No data found"
Empty search"Tidak ada hasil untuk '{query}'""0 results"
No items"Belum ada produk. Tambah produk pertama?""Empty"
No notifications"Semua sudah ditangani!""No notifications"

Confirmation Dialogs

Structure: Question + Context + Actions

Hapus produk ini?
"Indomie Goreng (SKU: 001234)" akan dihapus secara permanen.

[Batal]  [Hapus]
  • Title: question format ("Hapus produk ini?")
  • Body: name the specific item in quotes, state consequence
  • Cancel button: left, ghost style
  • Destructive button: right, red style

Pluralization

Indonesian does not conjugate for plural. Context or explicit numbers handle it:

EnglishIndonesian
1 item1 item
5 items5 item
No itemsTidak ada item

Do NOT use "item-item" or reduplication in UI text.

Consistency

Use the same Indonesian term for the same concept across all apps. If "Simpan" is used for save in HO Finance, use "Simpan" everywhere --- never mix with "Save" or "Taruh".

RetailOS - Sistem ERP Retail Modern untuk Indonesia