diff --git a/client/lib/format-number-compact/README.md b/client/lib/format-number-compact/README.md
deleted file mode 100644
index 4ac0c7276c3eba..00000000000000
--- a/client/lib/format-number-compact/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Format Number Compact
-
-Given a language code, this library will take in a number and display it in a compact format.
-
-## Usage
-
-```javascript
-import formatNumberCompact from 'calypso/lib/format-number-compact';
-
-const noChange = formatNumberCompact( 999, 'en' ); // '999'
-const shortEn = formatNumberCompact( 1234, 'en' ); // '1.2K'
-const shortEs = formatNumberCompact( 12567, 'es' ); // '12,6 mil'
-```
-
-## Parameters
-
-### `number`
-
-
- Type | Number |
- Required | Yes |
-
-
-The number to format.
-
-### `code`
-
-
- Type | String |
- Required | Yes |
-
-
-The language code to format with.
diff --git a/client/lib/format-number-compact/index.js b/client/lib/format-number-compact/index.js
deleted file mode 100644
index f77ba261a35b22..00000000000000
--- a/client/lib/format-number-compact/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import i18n, { numberFormat } from 'i18n-calypso';
-import { THOUSANDS } from './thousands';
-
-/**
- * Formats a number to a short format given a language code
- * @param {number} number number to format
- * @param {string} code language code e.g. 'es'
- * @returns {?string} A formatted string.
- */
-export default function formatNumberCompact( number, code = i18n.getLocaleSlug() ) {
- //use numberFormat directly from i18n in this case!
- if ( isNaN( number ) || ! THOUSANDS[ code ] ) {
- return null;
- }
-
- const { symbol, unitValue = 1000 } = THOUSANDS[ code ];
-
- const sign = number < 0 ? '-' : '';
- const absNumber = Math.abs( number );
-
- // no-op if we have a small number
- if ( absNumber < unitValue ) {
- return `${ sign }${ absNumber }`;
- }
-
- //show 2 sig figs, otherwise take leading sig figs.
- const decimals = absNumber < unitValue * 10 ? 1 : 0;
-
- // TODO clk numberFormat
- // can deprecate complately in favour of `{ notation: 'compact' }` in Intl.NumberFormat
- const value = numberFormat( absNumber / unitValue, {
- decimals,
- } );
-
- return `${ sign }${ value }${ symbol }`;
-}
-
-const ONE_K = 1000;
-const ONE_M = ONE_K * 1000;
-const ONE_G = ONE_M * 1000;
-
-/*
- * Format a number larger than 1000 by appending a metric unit (K, M, G) and rounding to
- * the received decimal point, defaults to 0.
- * TODO: merge with formatNumberCompact by adding support for metric units other than 'K'
- */
-export function formatNumberMetric( number, decimalPoints = 1 ) {
- if ( number < ONE_K ) {
- return String( number );
- }
-
- if ( number < ONE_M ) {
- return ( number / ONE_K ).toFixed( decimalPoints ) + 'K';
- }
-
- if ( number < ONE_G ) {
- return ( number / ONE_M ).toFixed( decimalPoints ) + 'M';
- }
-
- return ( number / ONE_G ).toFixed( decimalPoints ) + 'G';
-}
diff --git a/client/lib/format-number-compact/test/index.js b/client/lib/format-number-compact/test/index.js
deleted file mode 100644
index 772de50eac87d6..00000000000000
--- a/client/lib/format-number-compact/test/index.js
+++ /dev/null
@@ -1,341 +0,0 @@
-import i18n from 'i18n-calypso';
-import formatNumberCompact, { formatNumberMetric } from 'calypso/lib/format-number-compact';
-
-describe( 'formatNumberCompact', () => {
- beforeEach( function () {
- i18n.configure(); // ensure everything is reset
- i18n.setLocale( {
- '': {
- localeSlug: 'en',
- },
- } );
- } );
-
- test( 'does nothing if number is < 1000', () => {
- const counts = formatNumberCompact( 999, 'en' );
- expect( counts ).toEqual( '999' );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'en' );
- expect( counts ).toEqual( '1.2K' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'en' );
- expect( counts ).toEqual( '123K' );
- } );
- test( 'rounds abbreviated counts', () => {
- const counts = formatNumberCompact( 1897, 'en' );
- expect( counts ).toEqual( '1.9K' );
- } );
- test( 'shows groupings for huge numbers', () => {
- const counts = formatNumberCompact( 123456789, 'en' );
- expect( counts ).toEqual( '123,457K' );
- } );
- test( 'handles negative numbers', () => {
- const counts = formatNumberCompact( -123456789, 'en' );
- expect( counts ).toEqual( '-123,457K' );
- } );
- describe( 'es', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'es',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'es' );
- expect( counts ).toEqual( '1,2 mil' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'es' );
- expect( counts ).toEqual( '123 mil' );
- } );
- } );
- describe( 'pt-br', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeVariant: 'pt-br',
- localeSlug: 'pt',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'pt-br' );
- expect( counts ).toEqual( '1,2 mil' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'pt-br' );
- expect( counts ).toEqual( '123 mil' );
- } );
- } );
- describe( 'de', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'de',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'de' );
- expect( counts ).toEqual( '1,2 Tsd.' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'de' );
- expect( counts ).toEqual( '123 Tsd.' );
- } );
- } );
- describe( 'fr', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'fr',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'fr' );
- expect( counts ).toEqual( '1,2 k' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'fr' );
- expect( counts ).toEqual( '123 k' );
- } );
- } );
- describe( 'he', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'he',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'he' );
- expect( counts ).toEqual( '1.2K' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'he' );
- expect( counts ).toEqual( '123K' );
- } );
- } );
- describe( 'ja', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'ja',
- },
- } );
- } );
- test( 'does not modify counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'ja' );
- expect( counts ).toEqual( '1234' );
- } );
- test( 'shows 2 sig figs for counts just over 10000', () => {
- const counts = formatNumberCompact( 12345, 'ja' );
- expect( counts ).toEqual( '1.2万' );
- } );
- test( 'shows leading sig figs for counts > 100000', () => {
- const counts = formatNumberCompact( 1234567, 'ja' );
- expect( counts ).toEqual( '123万' );
- } );
- } );
- describe( 'it', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'it',
- },
- } );
- } );
- test( 'does not support a compact format, use numberFormat directly from i18n', () => {
- const counts = formatNumberCompact( 1234, 'it' );
- expect( counts ).toEqual( null );
- } );
- } );
- describe( 'nl', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'nl',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'nl' );
- expect( counts ).toEqual( '1,2K' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'nl' );
- expect( counts ).toEqual( '123K' );
- } );
- } );
- describe( 'ru', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'ru',
- },
- } );
- } );
- test( 'the short form is too long to be useful, use numberFormat directly from i18n', () => {
- const counts = formatNumberCompact( 1234, 'ru' );
- expect( counts ).toEqual( null );
- } );
- } );
- describe( 'tr', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'tr',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'tr' );
- expect( counts ).toEqual( '1,2 B' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'tr' );
- expect( counts ).toEqual( '123 B' );
- } );
- } );
- describe( 'id', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'id',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'id' );
- expect( counts ).toEqual( '1,2 rb' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'id' );
- expect( counts ).toEqual( '123 rb' );
- } );
- } );
- describe( 'zh-cn', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeVariant: 'zh-cn',
- localeSlug: 'zh',
- },
- } );
- } );
- test( 'does not modify counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'zh-cn' );
- expect( counts ).toEqual( '1234' );
- } );
- test( 'shows 2 sig figs for counts just over 10000', () => {
- const counts = formatNumberCompact( 12345, 'zh-cn' );
- expect( counts ).toEqual( '1.2万' );
- } );
- test( 'shows leading sig figs for counts > 100000', () => {
- const counts = formatNumberCompact( 1234567, 'zh-cn' );
- expect( counts ).toEqual( '123万' );
- } );
- } );
- describe( 'zh-tw', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeVariant: 'zh-tw',
- localeSlug: 'zh',
- },
- } );
- } );
- test( 'does not modify counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'zh-tw' );
- expect( counts ).toEqual( '1234' );
- } );
- test( 'shows 2 sig figs for counts just over 10000', () => {
- const counts = formatNumberCompact( 12345, 'zh-tw' );
- expect( counts ).toEqual( '1.2萬' );
- } );
- test( 'shows leading sig figs for counts > 100000', () => {
- const counts = formatNumberCompact( 1234567, 'zh-tw' );
- expect( counts ).toEqual( '123萬' );
- } );
- } );
- describe( 'ko', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'ko',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'ko' );
- expect( counts ).toEqual( '1.2천' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'ko' );
- expect( counts ).toEqual( '123천' );
- } );
- } );
- describe( 'ar', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'ar',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'ar' );
- expect( counts ).toEqual( '1.2 ألف' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'ar' );
- expect( counts ).toEqual( '123 ألف' );
- } );
- } );
- describe( 'sv', () => {
- beforeEach( function () {
- i18n.setLocale( {
- '': {
- localeSlug: 'sv',
- },
- } );
- } );
- test( 'shows 2 sig figs for counts < 10000', () => {
- const counts = formatNumberCompact( 1234, 'sv' );
- expect( counts ).toEqual( '1,2 tn' );
- } );
- test( 'shows leading sig figs for counts > 10000', () => {
- const counts = formatNumberCompact( 123456, 'sv' );
- expect( counts ).toEqual( '123 tn' );
- } );
- } );
-} );
-
-describe( 'formatNumberMetric', () => {
- test( 'does not abbreviate numbers smaller than 1000', () => {
- expect( formatNumberMetric( 123 ) ).toEqual( '123' );
- } );
-
- test( 'appends the K unit', () => {
- expect( formatNumberMetric( 123456 ) ).toEqual( '123.5K' );
- } );
-
- test( 'appends the M unit', () => {
- expect( formatNumberMetric( 123456789 ) ).toEqual( '123.5M' );
- } );
-
- test( 'appends the G unit', () => {
- expect( formatNumberMetric( 123456789012 ) ).toEqual( '123.5G' );
- } );
-
- test( 'rounds numbers with metric units to 1 decimal point', () => {
- expect( formatNumberMetric( 4500 ) ).toEqual( '4.5K' );
- expect( formatNumberMetric( 12490 ) ).toEqual( '12.5K' );
- expect( formatNumberMetric( 123546789 ) ).toEqual( '123.5M' );
- } );
-} );
diff --git a/client/lib/format-number-compact/thousands.js b/client/lib/format-number-compact/thousands.js
deleted file mode 100644
index 2de703c8a26e24..00000000000000
--- a/client/lib/format-number-compact/thousands.js
+++ /dev/null
@@ -1,50 +0,0 @@
-export const THOUSANDS = {
- en: {
- symbol: 'K',
- },
- es: {
- symbol: ' mil',
- },
- 'pt-br': {
- symbol: ' mil',
- },
- de: {
- symbol: ' Tsd.',
- },
- fr: {
- symbol: ' k',
- },
- he: {
- symbol: 'K',
- },
- ja: {
- symbol: '万',
- unitValue: 10000,
- },
- nl: {
- symbol: 'K',
- },
- tr: {
- symbol: ' B',
- },
- id: {
- symbol: ' rb',
- },
- 'zh-cn': {
- symbol: '万',
- unitValue: 10000,
- },
- 'zh-tw': {
- symbol: '萬',
- unitValue: 10000,
- },
- ko: {
- symbol: '천',
- },
- ar: {
- symbol: ' ألف',
- },
- sv: {
- symbol: ' tn',
- },
-};
diff --git a/client/my-sites/marketing/do-it-for-me/difm-landing.tsx b/client/my-sites/marketing/do-it-for-me/difm-landing.tsx
index d124c0cfb38eb8..16f537f4028197 100644
--- a/client/my-sites/marketing/do-it-for-me/difm-landing.tsx
+++ b/client/my-sites/marketing/do-it-for-me/difm-landing.tsx
@@ -699,7 +699,7 @@ export default function DIFMLanding( {
components: {
strong: ,
},
- args: [ numberFormat( CHARACTER_LIMIT, {} ) ],
+ args: [ numberFormat( CHARACTER_LIMIT ) ],
}
) }
diff --git a/client/my-sites/plugins/plugin-details-header/index.jsx b/client/my-sites/plugins/plugin-details-header/index.jsx
index 05edf530fa9cef..8260a200abd9cd 100644
--- a/client/my-sites/plugins/plugin-details-header/index.jsx
+++ b/client/my-sites/plugins/plugin-details-header/index.jsx
@@ -1,12 +1,11 @@
import { Badge, Button } from '@automattic/components';
-import { useTranslate } from 'i18n-calypso';
+import { useTranslate, numberFormat } from 'i18n-calypso';
import { useSelector } from 'react-redux';
import { useLocalizedMoment } from 'calypso/components/localized-moment';
import {
useMarketplaceReviewsQuery,
useMarketplaceReviewsStatsQuery,
} from 'calypso/data/marketplace/use-marketplace-reviews';
-import { formatNumberMetric } from 'calypso/lib/format-number-compact';
import { preventWidows } from 'calypso/lib/formatting';
import PluginIcon from 'calypso/my-sites/plugins/plugin-icon/plugin-icon';
import PluginRatings from 'calypso/my-sites/plugins/plugin-ratings/';
@@ -133,7 +132,7 @@ const PluginDetailsHeader = ( {
{ translate( 'Active installations' ) }
- { formatNumberMetric( plugin.active_installs, 0 ) }
+ { numberFormat( plugin.active_installs, { notation: 'compact' } ) }
) }
diff --git a/client/my-sites/plugins/plugin-details-sidebar/index.jsx b/client/my-sites/plugins/plugin-details-sidebar/index.jsx
index 70e5762d68ba3a..46f0743e82c034 100644
--- a/client/my-sites/plugins/plugin-details-sidebar/index.jsx
+++ b/client/my-sites/plugins/plugin-details-sidebar/index.jsx
@@ -4,12 +4,11 @@ import {
WPCOM_FEATURES_INSTALL_PURCHASED_PLUGINS,
} from '@automattic/calypso-products';
import { localizeUrl } from '@automattic/i18n-utils';
-import { useTranslate } from 'i18n-calypso';
+import { useTranslate, numberFormat } from 'i18n-calypso';
import { useCallback } from 'react';
import { useSelector } from 'react-redux';
import './style.scss';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
-import { formatNumberMetric } from 'calypso/lib/format-number-compact';
import { PlanUSPS, USPS } from 'calypso/my-sites/plugins/plugin-details-CTA/usps';
import PluginDetailsSidebarUSP from 'calypso/my-sites/plugins/plugin-details-sidebar-usp';
import usePluginsSupportText from 'calypso/my-sites/plugins/use-plugins-support-text/';
@@ -161,7 +160,7 @@ const PluginDetailsSidebar = ( {
{ translate( 'Active installations' ) }
- { formatNumberMetric( active_installs, 0 ) }
+ { numberFormat( active_installs, { notation: 'compact' } ) }
) }
diff --git a/client/my-sites/stats/stats-views/months.jsx b/client/my-sites/stats/stats-views/months.jsx
index 4eeeb3cb6cfe16..26457c5ab559e0 100644
--- a/client/my-sites/stats/stats-views/months.jsx
+++ b/client/my-sites/stats/stats-views/months.jsx
@@ -1,10 +1,9 @@
import page from '@automattic/calypso-router';
import { Popover } from '@automattic/components';
-import { localize } from 'i18n-calypso';
+import { localize, numberFormat } from 'i18n-calypso';
import PropTypes from 'prop-types';
import { createRef, createElement, PureComponent } from 'react';
import { withLocalizedMoment } from 'calypso/components/localized-moment';
-import { formatNumberMetric } from 'calypso/lib/format-number-compact';
class Month extends PureComponent {
static propTypes = {
@@ -64,7 +63,7 @@ class Month extends PureComponent {
}
const StatsViewsMonths = ( props ) => {
- const { translate, dataKey, data, numberFormat, moment, siteSlug, showYearTotal = false } = props;
+ const { translate, dataKey, data, moment, siteSlug, showYearTotal = false } = props;
const dataEntries = data ? Object.entries( data ) : [];
const isAverageChart = dataKey === 'average';
let earliestDate = moment();
@@ -132,7 +131,7 @@ const StatsViewsMonths = ( props ) => {
totals.months[ month ] += value;
totals.yearsCount[ year ] += 1;
totals.monthsCount[ month ] += 1;
- displayValue = formatNumberMetric( value );
+ displayValue = numberFormat( value, { decimals: 1, notation: 'compact' } );
}
totalValue += value;
diff --git a/client/reader/stream/reader-tag-sidebar/index.jsx b/client/reader/stream/reader-tag-sidebar/index.jsx
index 9724cb208d663c..2720ce81f9efbb 100644
--- a/client/reader/stream/reader-tag-sidebar/index.jsx
+++ b/client/reader/stream/reader-tag-sidebar/index.jsx
@@ -1,13 +1,12 @@
import { Button } from '@automattic/components';
import { addLocaleToPathLocaleInFront } from '@automattic/i18n-utils';
-import { useTranslate } from 'i18n-calypso';
+import { useTranslate, numberFormat } from 'i18n-calypso';
import moment from 'moment';
import { connect, useDispatch, useSelector } from 'react-redux';
import TagLink from 'calypso/blocks/reader-post-card/tag-link';
import { useBloggingPrompts } from 'calypso/data/blogging-prompt/use-blogging-prompts';
import { useRelatedMetaByTag } from 'calypso/data/reader/use-related-meta-by-tag';
import { useTagStats } from 'calypso/data/reader/use-tag-stats';
-import formatNumberCompact from 'calypso/lib/format-number-compact';
import { recordAction, recordGaEvent } from 'calypso/reader/stats';
import ReaderListFollowingItem from 'calypso/reader/stream/reader-list-followed-sites/item';
import { isUserLoggedIn } from 'calypso/state/current-user/selectors';
@@ -86,13 +85,13 @@ const ReaderTagSidebar = ( {
- { formatNumberCompact( tagStats?.data?.total_posts ) }
+ { numberFormat( tagStats?.data?.total_posts, { notation: 'compact' } ) }
{ translate( 'Posts' ) }
- { formatNumberCompact( tagStats?.data?.total_sites ) }
+ { numberFormat( tagStats?.data?.total_sites, { notation: 'compact' } ) }
{ translate( 'Sites' ) }
diff --git a/client/reader/stream/site-feed-sidebar/index.jsx b/client/reader/stream/site-feed-sidebar/index.jsx
index a6ef4b094ccb81..fe31508fbb19be 100644
--- a/client/reader/stream/site-feed-sidebar/index.jsx
+++ b/client/reader/stream/site-feed-sidebar/index.jsx
@@ -1,9 +1,8 @@
import formatNumber from '@automattic/components/src/number-formatters/lib/format-number';
-import { useTranslate, getLocaleSlug } from 'i18n-calypso';
+import { useTranslate, getLocaleSlug, numberFormat } from 'i18n-calypso';
import { useDispatch } from 'react-redux';
import ReaderFeedHeaderFollow from 'calypso/blocks/reader-feed-header/follow';
import TagLink from 'calypso/blocks/reader-post-card/tag-link';
-import formatNumberCompact from 'calypso/lib/format-number-compact';
import { recordAction, recordGaEvent } from 'calypso/reader/stats';
import { recordReaderTracksEvent } from 'calypso/state/reader/analytics/actions';
import '../style.scss';
@@ -47,7 +46,7 @@ const FeedStreamSidebar = ( {
{ postCount && (
- { formatNumberCompact( postCount ) }
+ { numberFormat( postCount, { notation: 'compact' } ) }
{ translate( 'Post', 'Posts', { count: postCount } ) }
diff --git a/client/reader/tags/trending-tags.tsx b/client/reader/tags/trending-tags.tsx
index d8138b61fdf8fa..d45236616a3c51 100644
--- a/client/reader/tags/trending-tags.tsx
+++ b/client/reader/tags/trending-tags.tsx
@@ -1,7 +1,7 @@
import { addLocaleToPathLocaleInFront } from '@automattic/i18n-utils';
+import { numberFormat } from 'i18n-calypso';
import titlecase from 'to-title-case';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
-import formatNumberCompact from 'calypso/lib/format-number-compact';
import { TagResult } from './controller';
interface TrendingTagsProps {
@@ -27,7 +27,9 @@ const TagRow = ( props: TagRowProps ) => {
);
diff --git a/client/signup/steps/website-content/dialogs.tsx b/client/signup/steps/website-content/dialogs.tsx
index 28e3835823ac90..37d5d3f61ac9eb 100644
--- a/client/signup/steps/website-content/dialogs.tsx
+++ b/client/signup/steps/website-content/dialogs.tsx
@@ -124,7 +124,7 @@ export function ContentGuidelinesDialog( {
components: {
strong: ,
},
- args: [ numberFormat( CHARACTER_LIMIT, {} ) ],
+ args: [ numberFormat( CHARACTER_LIMIT ) ],
}
) }
diff --git a/client/signup/steps/website-content/section-types/contact-page-details.tsx b/client/signup/steps/website-content/section-types/contact-page-details.tsx
index 5c48784dd60959..9e8f594bd81637 100644
--- a/client/signup/steps/website-content/section-types/contact-page-details.tsx
+++ b/client/signup/steps/website-content/section-types/contact-page-details.tsx
@@ -36,7 +36,7 @@ export function ContactPageDetails( {
"Please shorten your text to under %(characterLimit)s characters for optimal formatting. If it remains over this limit, we'll optimize it with AI when building your site.",
{
args: {
- characterLimit: numberFormat( CHARACTER_LIMIT, {} ),
+ characterLimit: numberFormat( CHARACTER_LIMIT ),
},
comment: '%(characterLimit)s is a formatted number, eg: 5,000.',
}
diff --git a/client/signup/steps/website-content/section-types/custom-page-details.tsx b/client/signup/steps/website-content/section-types/custom-page-details.tsx
index 41ea5918025c06..6b277fc3145aad 100644
--- a/client/signup/steps/website-content/section-types/custom-page-details.tsx
+++ b/client/signup/steps/website-content/section-types/custom-page-details.tsx
@@ -59,7 +59,7 @@ export function CustomPageDetails( {
"Please shorten your text to under %(characterLimit)s characters for optimal formatting. If it remains over this limit, we'll optimize it with AI when building your site.",
{
args: {
- characterLimit: numberFormat( CHARACTER_LIMIT, {} ),
+ characterLimit: numberFormat( CHARACTER_LIMIT ),
},
comment: '%(characterLimit)s is a formatted number, eg: 5,000.',
}
diff --git a/client/signup/steps/website-content/section-types/default-page-details.tsx b/client/signup/steps/website-content/section-types/default-page-details.tsx
index f1cae37324d6a1..4b5ab596cbc5d9 100644
--- a/client/signup/steps/website-content/section-types/default-page-details.tsx
+++ b/client/signup/steps/website-content/section-types/default-page-details.tsx
@@ -47,7 +47,7 @@ export function DefaultPageDetails( {
"Please shorten your text to under %(characterLimit)s characters for optimal formatting. If it remains over this limit, we'll optimize it with AI when building your site.",
{
args: {
- characterLimit: numberFormat( CHARACTER_LIMIT, {} ),
+ characterLimit: numberFormat( CHARACTER_LIMIT ),
},
comment: '%(characterLimit)s is a formatted number, eg: 5,000.',
}
diff --git a/packages/components/src/count/format-number-compact.js b/packages/components/src/count/format-number-compact.js
deleted file mode 100644
index f77ba261a35b22..00000000000000
--- a/packages/components/src/count/format-number-compact.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import i18n, { numberFormat } from 'i18n-calypso';
-import { THOUSANDS } from './thousands';
-
-/**
- * Formats a number to a short format given a language code
- * @param {number} number number to format
- * @param {string} code language code e.g. 'es'
- * @returns {?string} A formatted string.
- */
-export default function formatNumberCompact( number, code = i18n.getLocaleSlug() ) {
- //use numberFormat directly from i18n in this case!
- if ( isNaN( number ) || ! THOUSANDS[ code ] ) {
- return null;
- }
-
- const { symbol, unitValue = 1000 } = THOUSANDS[ code ];
-
- const sign = number < 0 ? '-' : '';
- const absNumber = Math.abs( number );
-
- // no-op if we have a small number
- if ( absNumber < unitValue ) {
- return `${ sign }${ absNumber }`;
- }
-
- //show 2 sig figs, otherwise take leading sig figs.
- const decimals = absNumber < unitValue * 10 ? 1 : 0;
-
- // TODO clk numberFormat
- // can deprecate complately in favour of `{ notation: 'compact' }` in Intl.NumberFormat
- const value = numberFormat( absNumber / unitValue, {
- decimals,
- } );
-
- return `${ sign }${ value }${ symbol }`;
-}
-
-const ONE_K = 1000;
-const ONE_M = ONE_K * 1000;
-const ONE_G = ONE_M * 1000;
-
-/*
- * Format a number larger than 1000 by appending a metric unit (K, M, G) and rounding to
- * the received decimal point, defaults to 0.
- * TODO: merge with formatNumberCompact by adding support for metric units other than 'K'
- */
-export function formatNumberMetric( number, decimalPoints = 1 ) {
- if ( number < ONE_K ) {
- return String( number );
- }
-
- if ( number < ONE_M ) {
- return ( number / ONE_K ).toFixed( decimalPoints ) + 'K';
- }
-
- if ( number < ONE_G ) {
- return ( number / ONE_M ).toFixed( decimalPoints ) + 'M';
- }
-
- return ( number / ONE_G ).toFixed( decimalPoints ) + 'G';
-}
diff --git a/packages/components/src/count/index.jsx b/packages/components/src/count/index.jsx
index 0d7abd91057ca6..72ef374d3487a1 100644
--- a/packages/components/src/count/index.jsx
+++ b/packages/components/src/count/index.jsx
@@ -1,7 +1,6 @@
import clsx from 'clsx';
-import { localize } from 'i18n-calypso';
+import { localize, numberFormat } from 'i18n-calypso';
import PropTypes from 'prop-types';
-import formatNumberCompact from './format-number-compact';
import './style.scss';
@@ -10,14 +9,16 @@ export const Count = ( {
primary = false,
compact = false,
forwardRef,
- numberFormat,
+ numberFormat: numberFormatFromProps,
translate,
locale,
...props
} ) => {
+ const effectiveNumberFormat = numberFormatFromProps ?? numberFormat;
+
return (
- { compact ? formatNumberCompact( count ) || numberFormat( count ) : numberFormat( count ) }
+ { compact ? numberFormat( count, { notation: 'compact' } ) : effectiveNumberFormat( count ) }
);
};
diff --git a/packages/components/src/count/test/index.jsx b/packages/components/src/count/test/index.jsx
index b63492f66cee25..5bdc13406acfb7 100644
--- a/packages/components/src/count/test/index.jsx
+++ b/packages/components/src/count/test/index.jsx
@@ -11,9 +11,9 @@ describe( 'Count', () => {
expect( numberFormatSpy ).toHaveBeenCalledWith( 23 );
} );
- test( 'should call `formatNumberCompact` if `compact` prop is `true`', () => {
+ test( 'should call `i18n.numberFormat` with `compact` if `true`', () => {
const { container } = render( );
- expect( container.firstChild ).toHaveTextContent( '1.0K' );
+ expect( container.firstChild ).toHaveTextContent( '1K' );
} );
test( 'should render with primary class', () => {
diff --git a/packages/components/src/count/thousands.js b/packages/components/src/count/thousands.js
deleted file mode 100644
index 2de703c8a26e24..00000000000000
--- a/packages/components/src/count/thousands.js
+++ /dev/null
@@ -1,50 +0,0 @@
-export const THOUSANDS = {
- en: {
- symbol: 'K',
- },
- es: {
- symbol: ' mil',
- },
- 'pt-br': {
- symbol: ' mil',
- },
- de: {
- symbol: ' Tsd.',
- },
- fr: {
- symbol: ' k',
- },
- he: {
- symbol: 'K',
- },
- ja: {
- symbol: '万',
- unitValue: 10000,
- },
- nl: {
- symbol: 'K',
- },
- tr: {
- symbol: ' B',
- },
- id: {
- symbol: ' rb',
- },
- 'zh-cn': {
- symbol: '万',
- unitValue: 10000,
- },
- 'zh-tw': {
- symbol: '萬',
- unitValue: 10000,
- },
- ko: {
- symbol: '천',
- },
- ar: {
- symbol: ' ألف',
- },
- sv: {
- symbol: ' tn',
- },
-};
diff --git a/packages/i18n-calypso/CHANGELOG.md b/packages/i18n-calypso/CHANGELOG.md
index 99f795ac761b71..eff465b1153275 100644
--- a/packages/i18n-calypso/CHANGELOG.md
+++ b/packages/i18n-calypso/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 7.2.1
+
+- `compact` option for `numberFormat`
+
## 7.2.0
- Replace `number_format` with `Intl.NumberFormat`
diff --git a/packages/i18n-calypso/package.json b/packages/i18n-calypso/package.json
index 593474b538868e..3bc262cbe096c9 100644
--- a/packages/i18n-calypso/package.json
+++ b/packages/i18n-calypso/package.json
@@ -1,6 +1,6 @@
{
"name": "i18n-calypso",
- "version": "7.2.0",
+ "version": "7.2.1",
"description": "I18n JavaScript library on top of Tannin originally used in Calypso.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
diff --git a/packages/i18n-calypso/src/i18n.js b/packages/i18n-calypso/src/i18n.js
index edc0e17381c5e2..ded0c78ffb5532 100644
--- a/packages/i18n-calypso/src/i18n.js
+++ b/packages/i18n-calypso/src/i18n.js
@@ -171,20 +171,30 @@ I18N.prototype.emit = function ( ...args ) {
* @param {string | number} number to format (required)
* @param {number | Object} options Number of decimal places or options object (optional)
* @param {boolean} forceLatin Whether to use latin numbers by default (optional. default = true)
- * @returns {string | number} Formatted number as string, or original number if formatting fails
+ * @returns {string | number} Formatted number as string, or original number if formatting fails. Null otherwise.
*/
I18N.prototype.numberFormat = function ( number, options = {}, forceLatin = true ) {
const decimals = typeof options === 'number' ? options : options.decimals || 0;
const browserSafeLocale = this.getBrowserSafeLocale();
+ /**
+ * TS will flag this as an error, but best to check for undefined here for older usages
+ * `Intl.NumberFormat` will return NaN for undefined values, which is not helpful. Null becomes 0, also potentially risky.
+ */
+ if ( typeof number === 'undefined' || number === null ) {
+ warn( 'numberFormat() requires a defined and non-null value as the first argument' );
+ return number;
+ }
+
try {
return Intl.NumberFormat( `${ browserSafeLocale }${ forceLatin ? '-u-nu-latn' : '' }`, {
minimumFractionDigits: decimals, // default is 0
maximumFractionDigits: decimals, // default is the greater between minimumFractionDigits and 3
// TODO clk numberFormat this may be the only difference, where some cases use 2 (they can just pass the option to Intl.NumberFormat)
+ ...( options?.notation && { notation: options.notation } ),
} ).format( number );
} catch ( error ) {
- warn( 'Error formatting number with Intl.NumberFormat: ', number, error );
+ warn( 'numberFormat(): Error formatting number with Intl.NumberFormat: ', number, error );
}
return number;
diff --git a/packages/i18n-calypso/test/index.js b/packages/i18n-calypso/test/index.js
index 443e1d24af806c..ab33fc4945ad1c 100644
--- a/packages/i18n-calypso/test/index.js
+++ b/packages/i18n-calypso/test/index.js
@@ -202,7 +202,7 @@ describe( 'I18n', function () {
} );
describe( 'getBrowserSafeLocale()', function () {
- it( 'should return locale without variant when localeVariant is set', function () {
+ it( 'should return locale without variant when localeVariant is set with underscore _', function () {
i18n.setLocale( {
'': {
localeVariant: 'de_AT',
@@ -212,7 +212,7 @@ describe( 'I18n', function () {
expect( i18n.getBrowserSafeLocale() ).toBe( 'de' );
} );
- it( 'should return locale with region code when localeVariant is set', function () {
+ it( 'should return locale with region code when localeVariant is set with dash -', function () {
i18n.setLocale( {
'': {
localeVariant: 'en-US',
@@ -281,6 +281,27 @@ describe( 'I18n', function () {
).toBe( '2.500,330' );
} );
} );
+
+ describe( 'compact notation', function () {
+ describe( 'ar', () => {
+ beforeEach( function () {
+ i18n.setLocale( {
+ '': {
+ localeVariant: undefined,
+ localeSlug: 'ar',
+ },
+ } );
+ } );
+ test( 'defaults to latin notation and localised unit', () => {
+ expect( numberFormat( 1234, { notation: 'compact', decimals: 1 } ) ).toEqual( '1.2 ألف' );
+ } );
+ test( 'non-latin/original notation and localised unit', () => {
+ expect( numberFormat( 1234, { notation: 'compact', decimals: 1 }, false ) ).toEqual(
+ '١٫٢ ألف'
+ );
+ } );
+ } );
+ } );
} );
describe( 'hashed locale data', function () {
diff --git a/packages/i18n-calypso/types/index.d.ts b/packages/i18n-calypso/types/index.d.ts
index 4bab489aca8427..c438c745ab3746 100644
--- a/packages/i18n-calypso/types/index.d.ts
+++ b/packages/i18n-calypso/types/index.d.ts
@@ -64,6 +64,7 @@ export type TranslateResult = ExistingReactNode;
export interface NumberFormatOptions {
decimals?: number;
+ notation: Intl.NumberFormatOptions[ 'notation' ];
}
export type TranslateHook = (
@@ -92,8 +93,8 @@ export interface I18N {
translate( original: string, plural: string, options: TranslateOptionsPlural ): ExistingReactNode;
translate( original: string, plural: string, options: TranslateOptionsPluralText ): string;
- numberFormat( number: number, numberOfDecimalPlaces: number ): string;
- numberFormat( number: number, options: NumberFormatOptions ): string;
+ numberFormat( number: number, numberOfDecimalPlaces?: number ): string | number;
+ numberFormat( number: number, options?: NumberFormatOptions ): string | number;
setLocale( localeData: LocaleData ): void;
addTranslations( localeData: LocaleData ): void;