DEV Community

Cover image for Format Indonesian Rupiah Like a Pro with formatRupiah()
Adamm
Adamm

Posted on

Format Indonesian Rupiah Like a Pro with formatRupiah()

If you're building apps for the Indonesian market, you've probably struggled with formatting Rupiah currency. Different apps need different formats - some show decimals, some don't, some need the "Rp" symbol, others don't.

I built @indodev/toolkit to solve exactly this problem. Today, I'll show you formatRupiah() - a flexible utility that handles all your Rupiah formatting needs.

Installation

npm install @indodev/toolkit
# or
yarn add @indodev/toolkit
# or
pnpm add @indodev/toolkit
Enter fullscreen mode Exit fullscreen mode

Basic Usage

The simplest use case - just format the number:

import { formatRupiah } from '@indodev/toolkit';

formatRupiah(1500000);
// → 'Rp 1.500.000'
Enter fullscreen mode Exit fullscreen mode

Clean, readable, and follows Indonesian conventions (period as thousand separator).

Real-World Use Cases

1. E-commerce Product Display

Most e-commerce sites don't need decimal places for prices:

const products = [
  { name: 'Laptop ASUS', price: 12500000 },
  { name: 'Mouse Logitech', price: 350000 },
  { name: 'Keyboard Mechanical', price: 1250000 }
];

products.forEach(product => {
  console.log(`${product.name}: ${formatRupiah(product.price)}`);
});

// Output:
// Laptop ASUS: Rp 12.500.000
// Mouse Logitech: Rp 350.000
// Keyboard Mechanical: Rp 1.250.000
Enter fullscreen mode Exit fullscreen mode

2. Payment Gateway Integration

When showing transaction amounts with cents:

const transaction = {
  subtotal: 1500000,
  tax: 150000.50,
  total: 1650000.50
};

console.log('Subtotal:', formatRupiah(transaction.subtotal));
console.log('Tax:', formatRupiah(transaction.tax, { decimal: true }));
console.log('Total:', formatRupiah(transaction.total, { decimal: true }));

// Output:
// Subtotal: Rp 1.500.000
// Tax: Rp 150.000,50
// Total: Rp 1.650.000,50
Enter fullscreen mode Exit fullscreen mode

3. Financial Reports (No Symbol)

For CSV exports or table displays where you don't want the "Rp" symbol:

const revenue = [
  { month: 'January', amount: 45000000 },
  { month: 'February', amount: 52000000 },
  { month: 'March', amount: 48500000 }
];

console.log('Month\t\tRevenue');
revenue.forEach(r => {
  console.log(`${r.month}\t\t${formatRupiah(r.amount, { symbol: false })}`);
});

// Output:
// Month           Revenue
// January         45.000.000
// February        52.000.000
// March           48.500.000
Enter fullscreen mode Exit fullscreen mode

4. International Apps (Custom Separators)

Some apps targeting international users might need comma separators:

const price = 1500000;

// For Indonesian users
console.log(formatRupiah(price));
// → 'Rp 1.500.000'

// For international formatting preference
console.log(formatRupiah(price, { separator: ',' }));
// → 'Rp 1,500,000'
Enter fullscreen mode Exit fullscreen mode

5. Banking Apps (Precision Control)

Control decimal precision for different scenarios:

const balance = 1500000.789;

// Default precision (2 decimal places)
console.log(formatRupiah(balance, { decimal: true }));
// → 'Rp 1.500.000,79'

// High precision for internal calculations
console.log(formatRupiah(balance, { decimal: true, precision: 3 }));
// → 'Rp 1.500.000,789'

// No decimals for display
console.log(formatRupiah(balance));
// → 'Rp 1.500.000'
Enter fullscreen mode Exit fullscreen mode

6. Mobile Apps (Compact Display)

Remove space after symbol for tighter layouts:

const price = 1500000;

// Standard (with space)
console.log(formatRupiah(price));
// → 'Rp 1.500.000'

// Compact (no space)
console.log(formatRupiah(price, { spaceAfterSymbol: false }));
// → 'Rp1.500.000'
Enter fullscreen mode Exit fullscreen mode

7. Handling Negative Values

For refunds, discounts, or debts:

const refund = -250000;
const discount = -50000;

console.log('Refund:', formatRupiah(refund));
console.log('Discount:', formatRupiah(discount));

// Output:
// Refund: -Rp 250.000
// Discount: -Rp 50.000
Enter fullscreen mode Exit fullscreen mode

All Options

Here's the complete API:

interface RupiahOptions {
  symbol?: boolean;              // Show "Rp" symbol (default: true)
  decimal?: boolean;             // Show decimal places (default: false)
  separator?: string;            // Thousands separator (default: '.')
  decimalSeparator?: string;     // Decimal separator (default: ',')
  spaceAfterSymbol?: boolean;    // Space after "Rp" (default: true)
  precision?: number;            // Decimal places (default: 2 if decimal=true)
}
Enter fullscreen mode Exit fullscreen mode

TypeScript Support

Fully typed with IntelliSense support:

import { formatRupiah, type RupiahOptions } from '@indodev/toolkit';

const options: RupiahOptions = {
  decimal: true,
  precision: 2
};

const formatted: string = formatRupiah(1500000, options);
Enter fullscreen mode Exit fullscreen mode

Why Use This?

  • Zero dependencies - lightweight and fast
  • Fully tested - 95%+ test coverage
  • TypeScript native - complete type definitions
  • Tree-shakeable - only import what you need
  • Indonesian-first - built by Indonesian developers for Indonesian apps

What's Next?

Check out other utilities in @indodev/toolkit:

  • formatCompact() - Compact Rupiah format (e.g., "Rp 1,5 juta")
  • validateNIK() - Validate Indonesian National ID numbers
  • validatePhoneNumber() - Validate Indonesian phone numbers

Try it now:

npm install @indodev/toolkit
Enter fullscreen mode Exit fullscreen mode

Found this helpful? Give it a star on GitHub! 🌟

Top comments (0)