npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@vintl/compact-number

v2.0.7

Published

Pluralisable compact notation numbers using @formatjs/intl

Downloads

949

Readme

@vintl/compact-number

Pluralisable compact notation numbers using @formatjs/intl.

Supports: ESM only Depends on @formatjs/intl

Prehistory

There has been a long-standing issue with the Intl.NumberFormat API that it does not provide any means to use a formatted number to choose the correct plural form. In contrast, this is possible in Java implementation of ICU4J. Unfortunately, this issue has not seen much progress for a long time, so something had to be done.

Issue

Many people mistakenly assume that they can simply take the original number and pluralise it. However, this is not correct in languages with complex pluralisation rules, as the declension of the following noun depends on the compact unit rather than the number.

For example, in Ukrainian:

If you have 1,452 cats, you may want to display it in compact notation (e.g. 1.4K in English). Using Intl.NumberFormat, you get 1,4 тис. If you then pluralise it using the original number (1,452), you get ‘1,4 тис. коти’, which is incorrect. The correct result should be ‘1,4 тис. котів’.

This is because you are pluralising the wrong thing — the original number, without compact notation. The correct pluralisation for ‘1,452 коти’ is ‘1,452 котів’, but when you use compact notation, you need to select a plural form based on the unit (thousands in this case).

Mitigation

This module attempts to address this issue by doing ‘smart rounding’. Using CLDR data, it calculates the exponent, the same one that is used to format the number, and then rounds the original number using it. The result is a number that roughly represents the rounded number. Using this number for pluralisation seems to work with most languages (however, additional testing from native speakers would be appreciated).

Installation

With your package manager of choice:

npm

npm i @vintl/compact-number

pnpm

pnpm add @vintl/compact-number

yarn

yarn add @vintl/compact-number

Example

import { createFormatter } from '@vintl/compact-number'
import { createIntl } from '@formatjs/intl'
import '@vintl/compact-number/locale-data/en'

const intl = createIntl({ locale: 'en-US' })

const formatCompactNumber = createFormatter(intl)

const compactNumber = formatCompactNumber(1_456)

console.log(String(compactNumber))
// => "1.4K"

console.log(Number(compactNumber))
// => 1400

API

createFormatter

A function that accepts an IntlShape object as an argument and returns a function that can be used to create the CompactNumber objects.

const formatCompactNumber = createFormatter(intl)

normalize

A function that accepts a string, a CompactNumber object, an element of T type, or an array of those. It then converts all CompactNumber objects in the provided value to strings.

If the provided value is an array and contains elements that are either strings or CompactNumber objects, the strings are joined together into a single string.

Likewise, when only a CompactNumber is given, the return value is equivalent to String(value).

This function can be useful for filtering out invalid objects in React projects.

normalize([formatCompactNumber(1_350), { value: 'Hello' }])
// => ['1.3K', { value: 'Hello' }]

normalize([formatCompactNumber(1_350), ' cats'])
// => '1.3K cats'

wrapFormatMessage

A function that accepts an IntlShape object as an argument and returns a wrapping function over the formatMessage method of the given IntlShape object. This wrapper calls the original formatMessage method and then normalizes all output using normalize.

const formatMessage = wrapFormatMessage(intl)
formatMessage(messages.greeting, {
  letters: formatCompactNumber(12_522),
})
// => 'Hello! You have 12.5K unread mail.'

supportedLocalesOf

Accepts a locale or an array of BCP 47 language tags and returns an array of language tags that are supported for generating a pluralisable rounded number.

if (supportedLocalesOf(['en-US']).length < 1) {
  console.log('Missing locale data for English')
}

addLocaleData

A function that accepts BCP 47 language tag and locale data object to store for use.

import data from '@vintl/compact-number/locale-data/en.data'
addLocaleData('en', enData)
supportedLocalesOf(['en-US'])
// => ['en']

CompactNumber

Describes an object that holds the original number value as well as formatting options. This object has toString, valueOf and toParts methods that can be used to convert this object into a useful value.

Converting this object to a string (using toString or String()) will invoke number formatter and return the formatted string.

Converting it to a number (using valueOf or Number()) will invoke calculation of pluralisable number.

Calling toParts method will invoke the number formatter and return the formatted parts.

Return values of all methods are cached for a lifetime of the CompactNumber object.

Locale data

In order to accurately round the numbers, CLDR locale data is required.

This module is built with of a subset of locale data provided by the cldr-numbers-modern module.

You can auto-add this data using @vintl/compact-number/locale-data/[tag].