Package Exports
- @procore/globalization-toolkit
- @procore/globalization-toolkit/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@procore/globalization-toolkit) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
globalization-toolkit
i18n formatting library
Before implementing the Globalization Toolkit (GTK), please review the Globalization Toolkit Adoption Diagram to determine the best implementation strategy for you. Continue reading for instructions on direct usage of the GTK.
Engineering Documentation
The engineering documentation contains technical documentation for the GTK repo. It details classes, types, interfaces, and features. Continue reading for install and usage instructions. Further reading on the GTK:
Install
NPM
$ npm i --save @procore/globalization-toolkit
YARN
$ yarn add @procore/globalization-toolkit
Usage
The GTK has 3 available classes: NumberFormatter, DateTimeFormatter, CurrencyFormatter. The structure of the GTK Library allows for instantiation of a formatting class with defined options. The instantiated class gives access to related functions. In addition, the GTK makes the class functions available as stand-alone functions. Below are examples of GTK usage with class formatter and with stand-alone functions.
A Note on Locales
The GTK supports industry standard locale codes. The GTK does NOT support Procore Custom Locales. When implementing the GTK, please sanitize the locale to follow industry standard of 'region-language' like 'en-US'.
NumberFormatter Class
The GTK NumberFormatter
class has the ability to format numbers for a given locale. The NumberFormatter class is instantiated with NumberOptions and has 4 available functions:
formatNumber(value: number)
,formatNumberToParts(value: number)
,parseNumber(value: string)
, andgetNumberSeparators(locale: string)
.
The NumberOptions are summarized below:
locale
: stringmaximumFractionDigits?
: numberminimumFractionDigits?
: numberpercent?
: 'standard', 'decimal'
Below code blocks display usage of the NumberFormatter class and available functions.
formatNumber() & formatNumberToParts()
import { NumberFormatter } from '@procore/globalization-toolkit';
const value = 1234;
const numberOptions = { locale: "en-US", minimumFractionDigits: 3 };
const formatter = new NumberFormatter(numberOptions);
console.log(formatter.formatNumber(value)) // expected output: '1,234.000'
console.log(formatter.formatNumberToParts(value))
/**
* expected output is an array of objects representing the parts of the formatted number:
* [
* { type: "integer", value: "1", },
* { type: "group", value: ",", },
* { type: "integer", value: "234", },
* { type: "decimal", value: ".", },
* { type: "fraction", value: "000", },
* ];
*/
parseNumber()
import { NumberFormatter } from '@procore/globalization-toolkit';
const value = "123 456 789,12";
const numberOptions = { locale: "fr-FR" };
const formatter = new NumberFormatter(numberOptions);
console.log(formatter.parseNumber(value)); // expected output: '123456789.12'
console.log(formatter.parseNumber("Abcd")); // expected output: NaN
getSeparators()
import { NumberFormatter } from '@procore/globalization-toolkit';
const germanNumberOptions = { locale: "de-DE" };
const germanFormatter = new NumberFormatter(germanNumberOptions);
console.log(germanFormatter.getSeparators()); // expected output: { decimal: ",", group: "." }
const usNumberOptions = { locale: 'en-US' };
const formatter = new NumberFormatter(usNumberOptions);
console.log(formatter.getSeparators()); // expected output: { decimal: ".", group: "," }
NumberFormatter Functions
The functions used on the NumberFormatter class are also available as stand alone functions. Read more information about each function in the GTK Documentation.
The example below shows usage of the stand alone function: formatNumber()
.
import { formatNumber } from '@procore/globalization-toolkit';
const value = 1234;
const numberOptions = { locale: "en-US", minimumFractionDigits: 3 };
console.log(formatNumber(value, numberOptions)) // expected output: '1,234.000'
CurrencyFormatter class
The GTK CurrencyFormatter class has the ability to format a number with given options. The CurrencyFormatter class is instantiated with CurrencyOptions.
The CurrencyFormatter has 4 available functions:
formatCurrency(value: number)
,formatCurrencyToParts(value: number)
parseCurrency(value: string)
getCurrencySeparators()
getSupportedCurrencies()
The CurrencyOptions are summarized below:
currencyIsoCode
: string (acceptable ISO codes)locale
: stringcurrencySign?
: 'accounting', 'standard'currencyDisplay?
: 'code', 'name', 'narrowSymbol', 'symbol'maximumFractionDigits?
: numberminimumFractionDigits?
: number
Below code blocks display usage of the CurrencyFormatter class and available functions.
const value = 1234;
const currencyOptions = { locale: "en-US", currencyIsoCode: "USD" };
const formatter = new CurrencyFormatter(currencyOptions);
console.log(formatter.formatCurrency(value)) // expected outcome: '$1,234.00'
Usage with currencyDisplay option
import { CurrencyFormatter } from '@procore/globalization-toolkit';
const value = 1234.567;
const currencyOptions: CurrencyOptions = {
locale: "de-DE",
currencyIsoCode: "USD",
currencyDisplay: "name",
};
const formatter = new CurrencyFormatter(currencyOptions);
console.log(formatter.formatCurrency(value)); // expected outcome: '1.234,57 US-Dollar'
Usage with minimumFractionDigits and currencyDisplay
const value = 1234.567;
const currencyOptions = {
locale: "ja-JP",
minimumFractionDigits: 2,
currencyIsoCode: "JPY",
};
const formatter = new CurrencyFormatter(currencyOptions);
console.log(formatter.formatCurrency(value)); // expected outcome: '¥1,234.57'
import { CurrencyFormatter } from '@procore/globalization-toolkit';
const value = -1234.56;
const currencyOptions: CurrencyOptions = {
locale: "en-US",
currencyIsoCode: "CAD",
currencySign: "accounting",
};
const formatter = new CurrencyFormatter(currencyOptions);
console.log(formatter.formatCurrencyToParts(value));
/** expected output:
* [
* { type: "literal", value: "(", },
* { type: "currency", value: "CA$", },
* { type: "integer", value: "1", },
* { type: "group", value: ",", },
* { type: "integer", value: "234", },
* { type: "decimal", value: ".", },
* { type: "fraction", value: "56", },
* { type: "literal", value: ")", },
* ]
**/
const value = "(1 234 567,56 €)";
const currencyOptions: CurrencyOptions = {
locale: "fr-FR",
currencyIsoCode: "EUR",
currencySign: "accounting",
};
const formatter = new CurrencyFormatter(currencyOptions);
console.log(formatter.parseCurrency(value)); // expected outcome: -1234567.56
const currencyOptions = { locale: "de-DE", currencyIsoCode: "EUR" };
const formatter = new CurrencyFormatter(currencyOptions);
console.log(formatter.getCurrencySeparators()) // expected outcome: { decimal: ",", group: "." }
const currencyOptions = { locale: "es-MX", currencyIsoCode: MXN" }
const formatter = new CurrencyFormatter(currencyOption)
console.log(formatter.getSupportedCurrencies())
/** expected outcome
* [
* "AED",
* "AFN",
* "ALL",
* ...
* ...
* "ZWL"
* ]
*/
CurrencyFormatter Functions
The functions used on the CurrencyFormatter class are also available as stand alone functions. Read more information about each function in the GTK Documentation.
The example below shows usage of the stand alone function: formatCurrency(value, options)
.
import { formatCurrency, getCurrencySeparators } from '@procore/globalization-toolkit';
const value = 1234;
const currencyOptions = { locale: 'en-US', currencyIsoCode: 'USD' };
console.log(formatCurrency(value, currencyOptions)) // expected output: '$1,234.00'
console.log(getCurrencySeparators(currencyOptions)) // expected output: { decimal: ".", group: "," }
DateTimeFormatter
The GTK DateTimeFormatter class has the ability to format date and time for the correct timezone. The DateTimeFormatter class is instantiated with DateTimeOptions.
The DateTimeFormatter has 3 available functions:
formatDateTime(value: Date)
,formatDateTimeToParts(value: Date)
, andgetStartDayOfTheWeek()
The DateTimeOptions can be used in two ways, but the two options cannot be combined. This follows the pattern of Intl.DateTimeFormat.
- Style Options:
- timeStyle: 'short', 'medium', 'long', 'full'
- dateStyle: 'short', 'medium', 'long', 'full'
- Component Options
- weekday: 'long', 'short', 'narrow'
- year: 'numeric', '2-digit'
- month: numeric', '2-digit', 'long', 'short', 'narrow'
- day: 'numeric', '2-digit'
- hour: 'numeric', '2-digit'
- minute: 'numeric', '2-digit'
- second: 'numeric', '2-digit'
Below code blocks display usage of the DateTimeFormatter class and available functions.
formatDateTime(value: Date)
SIMPLE OPTIONS
import { DateTimeFormatter } from '@procore/globalization-toolkit';
const value = new Date(1445419756738);
const dateTimeOptions = {
locale: 'en-US',
timeZone: 'UTC',
dateStyle: 'full',
timeStyle: 'long',
};
const formatter = new DateTimeFormatter(dateTimeOptions);
console.log(formatter.formatDateTime(value))
// expected output: Wednesday, October 21, 2015 at 9:29:16 AM UTC
COMPLEX OPTIONS
const value = new Date(Date.UTC(1885, 8, 1, 12, 0, 16, 738));
const dateTimeOptions = {
locale: 'en-US',
timeZone: 'UTC',
weekday: 'long',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
};
const formatter = new DateTimeFormatter(dateTimeOptions);
console.log(formatter.formatDateTime(value))
// expected output: "Tuesday, 09/01/1885, 12:00:16 PM";
formatDateTimeToParts(value: Date)
const value = new Date(Date.UTC(1955, 10, 5, 6, 0, 16, 738));
const dateTimeOptions = {
locale: "en-GB",
timeZone: "UTC",
dateStyle: DateStyle.FULL,
timeStyle: TimeStyle.SHORT,
};
const formatter = new DateTimeFormatter(dateTimeOptions);
console.log(formatter.formatDateTime(value))
/** expected output:
* [ { type: "weekday", value: "Saturday", },
* { type: "literal", value: ", ", },
* { type: "day", value: "5", },
* { type: "literal", value: " ", },
* { type: "month", value: "November", },
* { type: "literal", value: " ", },
* { type: "year", value: "1955", },
* { type: "literal", value: " at ",},
* { type: "hour", value: "06",},
* { type: "literal", value: ":",},
* { type: "minute", value: "00",}, ];
**/
getStartDayOfTheWeek()
This function returns an index value representing the start day of the week on the locale's calendar { Sunday: 0, Monday: 1 ...etc }
const dateTimeOptions = { locale: 'en-US' };
const formatter = new DateTimeFormatter(dateTimeOptions);
console.log(formatter.startDayOfTheWeek()); // expected output: 0
DateTimeFormatter Functions
The functions used on the NumberFormatter class are also available as stand alone functions. Read more information about each function in the GTK Documentation.
The example below shows usage of the stand alone function: formatDateTime()
.
import { formatDateTime } from '@procore/globalization-toolkit';
const value = new Date(Date.UTC(1955, 10, 5, 6, 0, 16, 738));
const dateTimeOptions = { locale: "en-US", timeZone: "UTC" };
console.log(formatDateTime(value, dateTimeOptions)) // expected output: 11/5/1955
Developing
Install dependencies:
$ npm install
Prepare project:
$ npm run prepare
Compile Typescript:
$ npm run build
(Delete build npm run clean
)
Testing
$ npm run test
If adding a new supported export (or removing one in a breaking change), update the snapshot test output and commit the change.
$ npm run test -- -u
To check formatting run npm run lint:check
and npm run format:check
.
Committing Changes
Our repo follows the Conventional Commits
and Semantic Versioning specifications.
The Conventional Commit format is used to map commits to the next Semantic Version published to NPM
,
and helps to maintain a more easily readable commit history.
Generally, commits should be in the format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
We use the command line tool commitizen
to help walk you through generating a Conventional Commit.
To invoke this tool run:
$ npm run cm
(Optional: run commitizen on git commit
)
Certain commits are analyzed and mapped to versioning as follows:
MAJOR
release ifBREAKING CHANGE
exists in the commit footer.MINOR
release for commit typefeat
.PATCH
release for commit typesfix
orperf
.No release is triggered for all other commit types. And commits that do not match any format rules or have
no-release
as the scope will not trigger a release.
Additionally, releaseRules
are specified in package.json
for specific commits:
build(deps-dev):
does not trigger a release (development dependency changes, typically version bumps bydependabot
).build(deps):
triggers aPATCH
release.
Details about how commit types are mapped to versioning can be found in the commit-analyzer documentation.
Publishing
Merges to main
will trigger the publish
workflow in CircleCi.
We use semantic-release
to manage releases and publishing to NPM
.
Semantic Release relies on the project's commit history
to create release notes and determine the next version.
Release Notes:
The <description>
for commits selected for publishing are added to the release notes
and can be found in the Releases section of Github.
License
The package is available under the Procore Developers License
About Procore
Procore - building the software that builds the world.
Learn more about the #1 most widely used construction management software at procore.com