JavaScript Intl API: The hidden gem of web internationalization

krtirtho

Kingkor Roy Tirtho

Posted on August 13, 2023

JavaScript Intl API: The hidden gem of web internationalization

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

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:

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: ১৩ আগস্ট, ২০২৩
Enter fullscreen mode Exit fullscreen mode

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

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"
Enter fullscreen mode Exit fullscreen mode

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:

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: ١٢٬٣٤٥٫٦٧٩
Enter fullscreen mode Exit fullscreen mode

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:

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
Enter fullscreen mode Exit fullscreen mode

Pluralization

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

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'
Enter fullscreen mode Exit fullscreen mode

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:

const strings = ['200', '50', 'hundred', 'good'];
strings.sort((a, b) => a.localeCompare(b))

console.log(strings) // 200, 50, good, hundred
Enter fullscreen mode Exit fullscreen mode

To fix this we need Intl.Collator with numeric: true

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
Enter fullscreen mode Exit fullscreen mode

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:

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' ]
Enter fullscreen mode Exit fullscreen mode

Easy Time Zones

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

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
Enter fullscreen mode Exit fullscreen mode

Embracing User Locale

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

const userLocale = new Intl.Locale(navigator.language);
console.log(userLocale.language); // Output: en
console.log(userLocale.region);   // Output: US
Enter fullscreen mode Exit fullscreen mode

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

My socials:

Support me & my work

Support me on Patron

Buy me a Coffee

💖 💪 🙅 🚩
krtirtho
Kingkor Roy Tirtho

Posted on August 13, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related