JavaScript Intl API: The hidden gem of web internationalization
Tags: javascript, webdev, beginners, typescript
Published: 2023-08-13 06:22:53

Lots of time us web devs try to explore multiple libraries/frameworks for solution to the biggest reason of debt "Internationalization". But we often overlook the default browser APIs and how capable these are. JavaScript's `Intl` API is one of those hidden gems. If you use `Intl` half of the time you can avoid those date, currency etc. formatting & parsing libraries which are huge impact on the bundle size sometimes. The advantage is that the API is designed to be locale agnostic so with internationalization we're also getting localization features

> [Learn the difference between internationalization & localization](https://en.wikipedia.org/wiki/Internationalization_and_localization)

### Formatting Dates

Who doesn't remember the days of moment.js. Thank God date-fns and dayjs like libs helped us getting of that bundle of latency, Phew! But dates can be tricky to format consistently across different locales and require heavy libraries to do so
So the `Intl.DateTimeFormat` object saves the day. By specifying locale-specific options, you can even present dates in a format that's both readable and familiar to users:

```javascript
const date = new Date();
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const formattedDate = new Intl.DateTimeFormat('en-US', options).format(date);
console.log(formattedDate); // Output: August 13, 2023

// or if you give bengali locale
const formattedBnDate = new Intl.DateTimeFormat('bn-BD', options).format(date);
console.log(formattedBnDate); // Output: ১৩ আগস্ট, ২০২৩
```

### Relative Time formatting

Relative times are a better UX. It lets the user know the time in an instant. But formatting relative time is a trouble & datetime libraries provides us with an easy way to do so. But did you know `Intl` already has an API that does the exact same job & also respects locale. Crazy, right! See this official example from MDN

```typescript
const rtf1 = new Intl.RelativeTimeFormat('en', { style: 'short', numeric: 'always' });
console.log(rtf1.format(3, 'quarter')); // Expected output: "in 3 qtrs."
console.log(rtf1.format(-1, 'day')); // Expected output: "1 day ago"

const rtf2 = new Intl.RelativeTimeFormat('es', { numeric: 'auto' });
console.log(rtf2.format(2, 'day')); // Expected output: "pasado mañana"
```

### Number Formatting across Locales

Displaying numbers in a way that matches each user's language and cultural norms is crucial. The `Intl.NumberFormat` object allows you to achieve this effortlessly:

```javascript
const number = 12345.6789;
const formattedNumber = new Intl.NumberFormat('bn-BD').format(number);
console.log(formattedNumber); // Output: ১২,৩৪৫.৬৭৯

const formattedNumber = new Intl.NumberFormat('ar-SA').format(number);
console.log(formattedNumber); // Output: ١٢٬٣٤٥٫٦٧٩
```

### Currency Formatting

There's libraries that can handle currency formatting. But the `Intl.NumberFormat` API steps up by providing built-in currency formatting eliminating the need for third party libs:

```javascript
const amount = 1234.56;
const currency = 'USD';
const formattedCurrency = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: currency
}).format(amount);
console.log(formattedCurrency); // Output: $1,234.56
```

### Pluralization

The rules for pluralization vary across languages, and the `Intl.PluralRules` object helps you manage this intricacy:

```javascript
const enOrdinalRules = new Intl.PluralRules("en-US", { type: "ordinal" });

const suffixes = new Map([
  ["one", "st"],
  ["two", "nd"],
  ["few", "rd"],
  ["other", "th"],
]);
const formatOrdinals = (n) => {
  const rule = enOrdinalRules.select(n);
  const suffix = suffixes.get(rule);
  return `${n}${suffix}`;
};

formatOrdinals(0); // '0th'
formatOrdinals(1); // '1st'
formatOrdinals(2); // '2nd'
formatOrdinals(3); // '3rd'
formatOrdinals(4); // '4th'
formatOrdinals(11); // '11th'
formatOrdinals(21); // '21st'
formatOrdinals(42); // '42nd'
formatOrdinals(103); // '103rd'
```
> Believe me before `Intl.PluralRules`, we needed to utilize a algorithm to stuff like this

### Sorting Strings Globally
JavaScript alphanumeric sorting is a jock which everyone knows. The `Array.sort` works for mostly numbers. For alphanumeric strings (strings that include both numbers & letters) we need to do some manual works before so it acts correctly 

For example with sort:
```javascript
const strings = ['200', '50', 'hundred', 'good'];
strings.sort((a, b) => a.localeCompare(b))

console.log(strings) // 200, 50, good, hundred
```

To fix this we need `Intl.Collator` with `numeric: true`
```javascript
var  collator  =  new  Intl.Collator('en-US', {numeric:  true});
var  strings  = ['200', '50', 'hundred', 'good'];
strings.sort((a, b) =>  collator.compare(a, b))

console.log(strings) // 50, 200, good, hundred
```

But i doesn't stop there. Sorting strings can be surprisingly tricky due to varying language rules also. The `Intl.Collator` object comes to the rescue by ensuring your sorting stays true to the user's locale:

```javascript
const strings = ['apple', 'banana', 'cherry'];
const collator = new Intl.Collator('es-ES');
const sortedStrings = strings.sort(collator.compare);
console.log(sortedStrings); // Output: [ 'banana', 'cherry', 'apple' ]
```


### Easy Time Zones

Dealing with time zones can be complex, but the `Intl.DateTimeFormat` API simplifies it:

```javascript
const date = new Date();
const options = {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  timeZoneName: 'short'
};
const formattedDate = new Intl.DateTimeFormat('en-US', options).format(date);
console.log(formattedDate); // Output: August 13, 2023, GMT+2
```

### Embracing User Locale

Understanding your users' preferred language and formatting preferences is key. The `Intl.Locale` object streamlines this process:

```javascript
const userLocale = new Intl.Locale(navigator.language);
console.log(userLocale.language); // Output: en
console.log(userLocale.region);   // Output: US
```

By mastering the `Intl` API, you can create applications that bridge cultural gaps and resonate with a diverse global audience & fundamentally increases your revenue. I hope this guide provides you with insights that can transform your internationalization efforts into a seamless and user-centric experience.
But for full understanding of the API and mastering it visit the [official MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)

## My socials:
- [X](https://x.com/@KrTirtho) (Formerly Twitter)
- [Github](https://github.com/KRTirtho)
- [DEVCommunity](https://dev.to/KRTirtho)

## Support me & my work

<a href="https://patreon.com/krtirtho"><img alt="Support me on Patron" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/donate/patreon-singular_vector.svg"></a>

<a href="https://www.buymeacoffee.com/krtirtho"><img alt="Buy me a Coffee" height="56" src="https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/donate/buymeacoffee-singular_vector.svg"></a>