JavaScript Intl API: The hidden gem of web internationalization
Kingkor Roy Tirtho
Posted on August 13, 2023
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: ১৩ আগস্ট, ২০২৩
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"
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: ١٢٬٣٤٥٫٦٧٩
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
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'
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
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
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' ]
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
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
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:
- X (Formerly Twitter)
- Github
- DEVCommunity
Support me & my work
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
August 22, 2023