Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 84d1967

Browse files
author
Germain
authored
Change formatCount impl to use Intl.NumberFormat (#11379)
* Change formatCount impl to use Intl.NumberFormat * Update formatCount JSDoc description
1 parent 033c600 commit 84d1967

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

src/utils/FormattingUtils.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,33 @@ limitations under the License.
1717

1818
import { ReactElement, ReactNode } from "react";
1919

20-
import { _t } from "../languageHandler";
20+
import { _t, getCurrentLanguage } from "../languageHandler";
2121
import { jsxJoin } from "./ReactUtils";
22+
const locale = getCurrentLanguage();
23+
24+
// It's quite costly to instanciate `Intl.NumberFormat`, hence why we do not do
25+
// it in every function call
26+
const compactFormatter = new Intl.NumberFormat(locale, {
27+
notation: "compact",
28+
});
2229

2330
/**
24-
* formats numbers to fit into ~3 characters, suitable for badge counts
25-
* e.g: 999, 9.9K, 99K, 0.9M, 9.9M, 99M, 0.9B, 9.9B
31+
* formats and rounds numbers to fit into ~3 characters, suitable for badge counts
32+
* e.g: 999, 10K, 99K, 1M, 10M, 99M, 1B, 10B, ...
2633
*/
2734
export function formatCount(count: number): string {
28-
if (count < 1000) return count.toString();
29-
if (count < 10000) return (count / 1000).toFixed(1) + "K";
30-
if (count < 100000) return (count / 1000).toFixed(0) + "K";
31-
if (count < 10000000) return (count / 1000000).toFixed(1) + "M";
32-
if (count < 100000000) return (count / 1000000).toFixed(0) + "M";
33-
return (count / 1000000000).toFixed(1) + "B"; // 10B is enough for anyone, right? :S
35+
return compactFormatter.format(count);
3436
}
3537

38+
// It's quite costly to instanciate `Intl.NumberFormat`, hence why we do not do
39+
// it in every function call
40+
const formatter = new Intl.NumberFormat(locale);
41+
3642
/**
3743
* Format a count showing the whole number but making it a bit more readable.
3844
* e.g: 1000 => 1,000
3945
*/
4046
export function formatCountLong(count: number): string {
41-
const formatter = new Intl.NumberFormat();
4247
return formatter.format(count);
4348
}
4449

test/utils/FormattingUtils-test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { formatCount, formatCountLong } from "../../src/utils/FormattingUtils";
18+
19+
jest.mock("../../src/dispatcher/dispatcher");
20+
21+
describe("FormattingUtils", () => {
22+
describe("formatCount", () => {
23+
it.each([
24+
{ count: 999, expectedCount: "999" },
25+
{ count: 9999, expectedCount: "10K" },
26+
{ count: 99999, expectedCount: "100K" },
27+
{ count: 999999, expectedCount: "1M" },
28+
{ count: 9999999, expectedCount: "10M" },
29+
{ count: 99999999, expectedCount: "100M" },
30+
{ count: 999999999, expectedCount: "1B" },
31+
{ count: 9999999999, expectedCount: "10B" },
32+
])("formats $count as $expectedCount", ({ count, expectedCount }) => {
33+
expect(formatCount(count)).toBe(expectedCount);
34+
});
35+
});
36+
37+
describe("formatCountLong", () => {
38+
it("formats numbers according to the locale", () => {
39+
expect(formatCountLong(1000)).toBe("1,000");
40+
});
41+
});
42+
});

0 commit comments

Comments
 (0)