dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

Numeral.jsのlocaleを変更して桁区切り文字をカンマからピリオドにする

日本だと桁区切り文字は,(カンマ)、小数点は. (ピリオド)だけど世界的に見ると国によって異なる。
世界各国での数字の区切り方 | コリス

JavaScript で数値を扱うときには Numeral.js を使っていたんだけど、Numeral でも(Moment.js などと同じく)locale という概念があり、これを使うと桁区切り文字と小数点を変更することができる。

1.x 系と 2.x 系でやり方がだいぶ変わっていたので、メモ。


v1.5.6

公式ドキュメント は 2.x 系の話しかないので、 https://github.com/adamwdraper/Numeral-js/tree/1.5.6 の README や テストメソッド を参考にする。
locale() ではなく language() らしい。

import numeral from 'numeral';
import it from 'numeral/languages/it';

// locale のセット。必要なものを import して `language` の第二引数に指定する必要がある
numeral.language('it', it);
// 実際の locale の変更のためにもう一度実行
numeral.language('it');

numeral.language(); // 'it'

console.log(numeral(1234.567).format('0,0.0000')); // 1.234,5670

numeral.reset();
numeral.language(); // 'en'

console.log(numeral(1234.567).format('0,0.0000')); // 1,234.5670


v2.0.6

2.x 系だとこんな感じになる。

import numeral from 'numeral';
import 'numeral/locales/it';

// numeral.register() は不要

// locale のセット
numeral.locale('it');
console.log(numeral.locale()); // 'it'

console.log(numeral(1234.567).format('0,0.0000')); // 1.234,5670

numeral.reset();
console.log(numeral.locale()); // 'en'

console.log(numeral(1234.567).format('0,0.0000')); // 1,234.5670

いくつか補足すると

1.x -> 2.x での変更

2.0.0 のときの Changelog を参考にすると、locale まわりに関係のある変更は

Breaking change: All language now renamed to locale and standardized to all lowercase filenames
Breaking change: The locale function no longer loads locales, it only sets the current locale

ということで language -> locale へ変更になった。


numeral.register()

最初、ドキュメントの Locales の項 を読むと
locale の load には numeral.register() を使えと書いてある。

// load a locale
numeral.register('locale', 'fr', {
    delimiters: {
        thousands: ' ',
        decimal: ','
    },
    abbreviations: {
        thousand: 'k',
        million: 'm',
        billion: 'b',
        trillion: 't'
    },
    ordinal : function (number) {
        return number === 1 ? 'er' : 'ème';
    },
    currency: {
        symbol: '€'
    }
});

// switch between locales
numeral.locale('fr');

なので、1.x 系と同じように必要な locale ファイルを import したあと、

import it from 'numeral/locales/it';

numeral.register('locale', 'it', it);

で登録する必要があるのかなと思ったんだけど、違った。

TypeError: it locale already registered.

というエラーが出る。

これは、実際の locales/xx.js ファイル
https://github.com/adamwdraper/Numeral-js/blob/master/locales/it.js

を見るとよくわかるんだけど、読み込むと自動的に register() されるみたい。

なので、用意されている locale を使わずに自分で定義する場合のみ register() を使う。


おわりに

最初、format() 文字列の 0,0.00 とかのカンマやピリオドを変更しないといけないのか!と思っていたけど
そんなことなくてよかった。

import numeral from 'numeral';
numeral.register('locale', 'foo', {
  delimiters: {
    thousands: 'あああ',
    decimal: 'えええ'
  },
});
numeral.locale('foo');
console.log(numeral(1234.567).format('0,0.0000')); // 1あああ234えええ5670