From 86fcff1e5eaa7189cec7477877872f496d4a513d Mon Sep 17 00:00:00 2001 From: Nathan Booker Date: Sat, 29 Jun 2019 17:46:38 -0500 Subject: [PATCH] Add "localizePrice" helper --- helpers/lib/icu-detect.js | 15 ++++++++++++ helpers/localizePrice.js | 46 +++++++++++++++++++++++++++++++++++ spec/helpers.js | 1 + spec/helpers/localizePrice.js | 40 ++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 helpers/lib/icu-detect.js create mode 100644 helpers/localizePrice.js create mode 100644 spec/helpers/localizePrice.js diff --git a/helpers/lib/icu-detect.js b/helpers/lib/icu-detect.js new file mode 100644 index 00000000..20d98dcf --- /dev/null +++ b/helpers/lib/icu-detect.js @@ -0,0 +1,15 @@ +'use strict'; + +const hasFullICU = (() => { + try { + const january = new Date(9e8); + const spanish = new Intl.DateTimeFormat('es', { month: 'long' }); + return spanish.format(january) === 'enero'; + } catch (err) { + return false; + } +})(); + +module.exports = { + hasFullICU +}; diff --git a/helpers/localizePrice.js b/helpers/localizePrice.js new file mode 100644 index 00000000..6a2e6bd6 --- /dev/null +++ b/helpers/localizePrice.js @@ -0,0 +1,46 @@ +'use strict'; +const utils = require('handlebars-utils'); +// Detect ICU support +const { hasFullICU } = require('./lib/icu-detect.js'); + +const factory = () => { + return function(price, locale) { + if (!utils.isObject(price) || !utils.isString(price.currency) + || isNaN(price.value) || !utils.isString(price.formatted)) { + // Return empty string if this does not appear to be a price object + return ''; + } + + if (!utils.isString(locale) || locale.length < 2) { + // Valid browser language strings are at least two characters + // https://www.metamodpro.com/browser-language-codes + // If provided locale is less than two characters (or not a string), + // return the normal formatted price + return price.formatted; + } + + // If the if full ICU is not installed, fall back to normal price + if (!hasFullICU){ + return price.formatted; + } + + // Try to format the price to the provided locale, + // but if anything goes wrong, + // just return the usual price + // Could happen if the full ICU is not installed, + // or if an invalid locale is provided. + try { + return new Intl.NumberFormat( + locale, { style: 'currency', currency: price.currency} + ).format(price.value); + } + catch (err){ + return price.formatted; + } + }; +}; + +module.exports = [{ + name: 'localizePrice', + factory: factory, +}]; diff --git a/spec/helpers.js b/spec/helpers.js index deb26835..fb89a60e 100644 --- a/spec/helpers.js +++ b/spec/helpers.js @@ -50,6 +50,7 @@ describe('helper registration', () => { 'lang', 'langJson', 'limit', + 'localizePrice', 'money', 'nl2br', 'occurrences', diff --git a/spec/helpers/localizePrice.js b/spec/helpers/localizePrice.js new file mode 100644 index 00000000..e1a0619d --- /dev/null +++ b/spec/helpers/localizePrice.js @@ -0,0 +1,40 @@ +require('full-icu'); + +const Lab = require('lab'), + lab = exports.lab = Lab.script(), + describe = lab.experiment, + it = lab.it, + specHelpers = require('../spec-helpers'), + testRunner = specHelpers.testRunner + +describe('localizePrice helper', function() { + const context = { + "price": { + "tax_label": "GST", + "without_tax": { + "currency": "USD", + "formatted": "$123,456.78", + "value": 123456.78 + } + } + }; + + const runTestCases = testRunner({context}); + + it('should return return correct prices across a number of locales', function(done) { + runTestCases([ + { + input: '{{localizePrice price.without_tax "en-US"}}', + output: '$123,456.78', + }, + { + input: '{{localizePrice price.without_tax "ja-JP"}}', + output: '$123,456.78', + }, + { + input: '{{localizePrice price.without_tax "de"}}', + output: '123.456,78 $', + }, + ], done); + }); +});