From 30a091cb06bf96ed7e1bff9088a402d71789d6b6 Mon Sep 17 00:00:00 2001 From: FloWa Date: Mon, 26 Aug 2024 16:17:52 +0200 Subject: [PATCH 01/14] feat: added new function _dateAdd --- dist/handlebars-i18n.js | 61 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/dist/handlebars-i18n.js b/dist/handlebars-i18n.js index fa1b4b9..d8b2a65 100644 --- a/dist/handlebars-i18n.js +++ b/dist/handlebars-i18n.js @@ -2,7 +2,7 @@ * handlebars-i18n.js * * @author: Florian Walzel - * @date: 2024-05 + * @date: 2024-08 * * handlebars-i18n adds features for localization/ * internationalization to handlebars.js @@ -444,6 +444,65 @@ return dateFormat.format(date); } ); + handlebars.registerHelper('_dateAdd', + /** + * adds a time offset in a given unit to a date + * -> returns the modified date + * + * @param dateInput + * @param offset + * @param unit + * @param options + * @returns {string} + */ + function (dateInput, offset, unit, options) { + const date = __createDateObj(dateInput); + + unit = unit || 'hour'; + + switch (unit) { + case 'second': + case 'seconds': + date.setSeconds(date.getSeconds() + offset); + break; + case 'minute': + case 'minutes': + date.setMinutes(date.getMinutes() + offset); + break; + case 'hour': + case 'hours': + date.setHours(date.getHours() + offset); + break; + case 'day': + case 'days': + date.setDate(date.getDate() + offset); + break; + case 'week': + case 'weeks': + date.setDate(date.getDate() + offset * 7); + break; + case 'month': + case 'months': + date.setMonth(date.getMonth() + offset); + break; + case 'quarter': + case 'quarters': + date.setMonth(date.getMonth() + offset * 3); + break; + case 'year': + case 'years': + date.setFullYear(date.getFullYear() + offset); + break; + default: + throw new Error('@ handlebars-i18n: invalid argument "unit" was given for _dateAdd.' + + 'Unit must be either "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year".'); + } + + const opts = __configLookup(options, i18next.language, optionsConf.DateTimeFormat); + const dateFormat = new Intl.DateTimeFormat(i18next.language, opts); + return dateFormat.format(date); + } + ); handlebars.registerHelper('_dateRel', /** * returns a relative date formatted according the options From 3606bfc8863ec1adab8c0a5ff3f6ef5fa690dfc5 Mon Sep 17 00:00:00 2001 From: FloWa Date: Mon, 26 Aug 2024 16:30:20 +0200 Subject: [PATCH 02/14] feat: added error handling to _dateAdd, wrote a test for _dateAdd --- dist/handlebars-i18n.js | 7 +++++++ test/handlebars-i18n.test.js | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/dist/handlebars-i18n.js b/dist/handlebars-i18n.js index d8b2a65..8d0bfe3 100644 --- a/dist/handlebars-i18n.js +++ b/dist/handlebars-i18n.js @@ -456,6 +456,13 @@ * @returns {string} */ function (dateInput, offset, unit, options) { + + if (typeof dateInput !== 'number' && typeof dateInput !== 'string') + throw new Error('@ handlebars-i18n: invalid first argument "dateInput" was given for _dateAdd.'); + + if (typeof offset !== 'number') + throw new Error('@ handlebars-i18n: invalid second argument "offset" was given for _dateAdd.'); + const date = __createDateObj(dateInput); unit = unit || 'hour'; diff --git a/test/handlebars-i18n.test.js b/test/handlebars-i18n.test.js index 85ff469..8864b54 100644 --- a/test/handlebars-i18n.test.js +++ b/test/handlebars-i18n.test.js @@ -59,6 +59,10 @@ describe('handlebars-i18n Tests', function () { assert.isFunction(hI18n.helpers._date); }); + it('after method call init() HandlebarsEnvironment object should have a function _dateAdd', function () { + assert.isFunction(hI18n.helpers._dateAdd); + }); + it('after method call init() HandlebarsEnvironment object should have a function _dateRel', function () { assert.isFunction(hI18n.helpers._dateRel); }); @@ -256,6 +260,20 @@ describe('handlebars-i18n Tests', function () { }); + /**************************************** + Tests against function _date + ****************************************/ + + + it('function _dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { + i18next.changeLanguage('en'); + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day"); + assert.equal('12/18/1995', res); + }); + + + + /**************************************** Tests against function _dateRel ****************************************/ From 75a7fcdd34828bec8cbfa1fb346dab0608611557 Mon Sep 17 00:00:00 2001 From: FloWa Date: Fri, 30 Aug 2024 08:15:07 +0200 Subject: [PATCH 03/14] refactor/test: shortened test descriptions --- test/handlebars-i18n.test.js | 170 ++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 82 deletions(-) diff --git a/test/handlebars-i18n.test.js b/test/handlebars-i18n.test.js index 8864b54..c3b9376 100644 --- a/test/handlebars-i18n.test.js +++ b/test/handlebars-i18n.test.js @@ -103,19 +103,19 @@ describe('handlebars-i18n Tests', function () { Tests against function _locale ****************************************/ - it('expecting function _locale to be [undefined] as long as no language was set with i18next.init', function () { + it('expecting _locale to be [undefined] as long as no language was set with i18next.init', function () { i18next.init(); // empty init const res = hI18n.helpers._locale(); expect(res).to.be.undefined; }); - it('function _locale should return "en" if language is specified as "en" by init Object', function () { + it('_locale should return "en" if language is specified as "en" by init Object', function () { i18next.init(i18nInitObj); // initialize with data const res = hI18n.helpers._locale(); assert.equal('en', res); }); - it('function _locale should return "de" after language change to "de"', function () { + it('_locale should return "de" after language change to "de"', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._locale(); assert.equal('de', res); @@ -149,29 +149,29 @@ describe('handlebars-i18n Tests', function () { }).to.throw(); }); - it('function __ should return a SafeString object with property "string" where "string" returns the first argument given to __', function () { + it('__ should return a SafeString object with property "string" where "string" returns the first argument given to __', function () { const res = hI18n.helpers.__("someNoneExitingKey", {hash: {}}); assert.equal("someNoneExitingKey", res.string); }); - it('function __ should return a SafeString object with property "string" where "string" contains "What is good?!', function () { + it('__ should return a SafeString object with property "string" where "string" contains "What is good?!', function () { const res = hI18n.helpers.__("key1", {hash: {}}); assert.equal("What is good?", res.string); }); - it('function __ should return a SafeString object with property "string" where "string" contains "Was ist gut?"', function () { + it('__ should return a SafeString object with property "string" where "string" contains "Was ist gut?"', function () { i18next.changeLanguage('de'); const res = hI18n.helpers.__("key1", {hash: {}}); assert.equal("Was ist gut?", res.string); }); - it('function __ should return a SafeString object with property "string" where "string" contains "handlebarsI18next is good."', function () { + it('__ should return a SafeString object with property "string" where "string" contains "handlebarsI18next is good."', function () { i18next.changeLanguage('en'); const res = hI18n.helpers.__("key2", {hash: {what: "handlebarsI18next", adverb: "good"}}); assert.equal("handlebarsI18next is good.", res.string); }); - it('function __ should return a SafeString object with property "string" where "string" contains "handlebarsI18next ist gut."', function () { + it('__ should return a SafeString object with property "string" where "string" contains "handlebarsI18next ist gut."', function () { i18next.changeLanguage('de'); const res = hI18n.helpers.__("key2", {hash: {what: "handlebarsI18next", adverb: "gut"}}); assert.equal("handlebarsI18next ist gut.", res.string); @@ -182,13 +182,13 @@ describe('handlebars-i18n Tests', function () { Tests against function _date ****************************************/ - it('expect function _date to throw error when called with invalid date parameter', function () { + it('expect _date to throw error when called with invalid date parameter', function () { expect(function () { hI18n.helpers._date('someStrangeString') }).to.throw("Invalid valid date passed to format"); }); - it('function _date should return today’s date in Intl default format when called without parameter', function () { + it('_date should return today’s date in Intl default format when called without parameter', function () { i18next.changeLanguage('en'); const today = new Date(); const todayFormated = new Intl.DateTimeFormat().format(today); @@ -197,7 +197,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(todayFormated, res); }); - it('function _date should return today’s date in Intl default format when called with parameter, "Today" or "Now" no matter of upper or lower case writing', + it('_date should return today’s date in Intl default format when called with parameter, "Today" or "Now" no matter of upper or lower case writing', function () { i18next.changeLanguage('en'); const today = new Date(); @@ -211,49 +211,49 @@ describe('handlebars-i18n Tests', function () { assert.equal(todayFormated, hI18n.helpers._date("NOW")); }); - it('function _date should return "1/1/1970" (Intl default format) when called with parameter 1 as number ', function () { + it('_date should return "1/1/1970" (Intl default format) when called with parameter 1 as number ', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date(1); assert.equal('1/1/1970', res); }); - it('function _date should return "12/17/1995" (Intl default format) when called with parameter "1995-12-17T03:24:00"', function () { + it('_date should return "12/17/1995" (Intl default format) when called with parameter "1995-12-17T03:24:00"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date('1995-12-17T03:24:00'); assert.equal('12/17/1995', res); }); - it('function _date should return "12/17/1995" (Intl default format) when called with parameter "December 17, 1995 03:24:00"', function () { + it('_date should return "12/17/1995" (Intl default format) when called with parameter "December 17, 1995 03:24:00"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date('December 17, 1995 03:24:00'); assert.equal('12/17/1995', res); }); - it('function _date should return "1/1/2020" (Intl default format) when called with parameter "[2020]"', function () { + it('_date should return "1/1/2020" (Intl default format) when called with parameter "[2020]"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date('[1995]'); assert.equal('1/1/1995', res); }); - it('function _date should return "12/1/1995" (Intl default format) when called with parameter "[2020,11]"', function () { + it('_date should return "12/1/1995" (Intl default format) when called with parameter "[2020,11]"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date('[1995,11]'); assert.equal('12/1/1995', res); }); - it('function _date should return "12/17/1995" (Intl default format) when called with parameter "[2020,11,17]"', function () { + it('_date should return "12/17/1995" (Intl default format) when called with parameter "[2020,11,17]"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date('[1995,11,17]'); assert.equal('12/17/1995', res); }); - it('function _date should return "12/1/95" when called with parameter "[2020,11,01] and specifying options"', function () { + it('_date should return "12/1/95" when called with parameter "[2020,11,01] and specifying options"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._date('[1995,11,1]', {hash: {year: "2-digit", month: "2-digit", day: "2-digit"}}); assert.equal('12/1/95', res); }); - it('function _date should return "01.12.95" when called with parameter "[2020,11,01] and specifying options an language set to "de"', function () { + it('_date should return "01.12.95" when called with parameter "[2020,11,01] and specifying options an language set to "de"', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._date('[1995,11,1]', {hash: {year: "2-digit", month: "2-digit", day: "2-digit"}}); assert.equal('01.12.95', res); @@ -264,8 +264,14 @@ describe('handlebars-i18n Tests', function () { Tests against function _date ****************************************/ + it('_dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { + i18next.changeLanguage('en'); + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day"); + assert.equal('12/18/1995', res); + }); + - it('function _dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { + it('_dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day"); assert.equal('12/18/1995', res); @@ -278,38 +284,38 @@ describe('handlebars-i18n Tests', function () { Tests against function _dateRel ****************************************/ - it('expect function _dateRel to throw error when called without parameter', function () { + it('expect _dateRel to throw error when called without parameter', function () { expect(function () { hI18n.helpers._dateRel() }).to.throw('Invalid "number" argument: NaN'); }); - it('expect function _dateRel to throw error when called with invalid date parameter', function () { + it('expect _dateRel to throw error when called with invalid date parameter', function () { expect(function () { hI18n.helpers._dateRel('someStrangeString') }).to.throw('Invalid "number" argument: NaN'); }); - it('expect function _dateRel to throw error when called with non-existent language shortcode', function () { + it('expect _dateRel to throw error when called with non-existent language shortcode', function () { i18next.changeLanguage('invalid'); expect(function () { hI18n.helpers._dateRel(1, {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: "day"}}) }).to.throw('No locale data passed'); }); - it('expect function _dateRel to return \'in 1 hour\' when called with \'en\' and first parameter being 1', function () { + it('expect _dateRel to return \'in 1 hour\' when called with \'en\' and first parameter being 1', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateRel(1); assert.equal('in 1 hour', res); }); - it('expect function _dateRel to return \'1 hour ago\' when called with \'en\' and first parameter being -1', function () { + it('expect _dateRel to return \'1 hour ago\' when called with \'en\' and first parameter being -1', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateRel(-1); assert.equal('1 hour ago', res); }); - it('expect function _dateRel to return \'in 1 second\' when called with \'en\' and first parameter being 1 and according options', function () { + it('expect _dateRel to return \'in 1 second\' when called with \'en\' and first parameter being 1 and according options', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateRel(1, { hash: { @@ -322,7 +328,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('in 1 second', res); }); - it('expect function _dateRel to return \'in 1 Tag\' when called with \'de\' and paramter 1 and according options', function () { + it('expect _dateRel to return \'in 1 Tag\' when called with \'de\' and paramter 1 and according options', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._dateRel(1, { hash: { @@ -340,33 +346,33 @@ describe('handlebars-i18n Tests', function () { Tests against function _dateDiff ****************************************/ - it('function _dateDiff should return null when called with no parameter', function () { + it('_dateDiff should return null when called with no parameter', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateDiff(); assert.equal(null, res); }); - it('expect function _dateDiff to throw error when called with invalid 1. date parameter', function () { + it('expect _dateDiff to throw error when called with invalid 1. date parameter', function () { expect(function () { hI18n.helpers._dateDiff('someStrangeString', '1995-12-17T03:24:00') }) .to.throw('Invalid "number" argument: NaN'); }); - it('expect function _dateDiff to throw error when called with invalid 2. date parameter', function () { + it('expect _dateDiff to throw error when called with invalid 2. date parameter', function () { expect(function () { hI18n.helpers._dateDiff('1995-12-17T03:24:00', 'someStrangeString') }) .to.throw('Invalid "number" argument: NaN'); }); - it('expect function _dateDiff to return null when called with empty argument', function () { + it('expect _dateDiff to return null when called with empty argument', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateDiff(''); assert.equal(null, res); }); - it('expect function _dateDiff to return "in 0 hours", when dates are identical', function () { + it('expect _dateDiff to return "in 0 hours", when dates are identical', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateDiff('1995-12-17T00:00:00', '1995-12-17T00:00:00'); assert.equal('in 0 hours', res); @@ -374,14 +380,14 @@ describe('handlebars-i18n Tests', function () { // -- Test year -- // - it('expect function _dateDiff to return "in 1 year"', function () { + it('expect _dateDiff to return "in 1 year"', function () { i18next.changeLanguage('en'); const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: "year"}}; const res = hI18n.helpers._dateDiff('1996-12-17T00:00:00', '1995-12-17T00:00:00', hash); assert.equal('in 1 year', res); }); - it('expect function _dateDiff to return "1 year ago"', function () { + it('expect _dateDiff to return "1 year ago"', function () { i18next.changeLanguage('en'); const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: "year"}}; const res = hI18n.helpers._dateDiff('1995-12-17T00:00:00', '1996-12-17T00:00:00', hash); @@ -390,7 +396,7 @@ describe('handlebars-i18n Tests', function () { // -- Test quarter -- // - it('expect function _dateDiff to return "in 1 quarter"', function () { + it('expect _dateDiff to return "in 1 quarter"', function () { i18next.changeLanguage('en'); const unit = 'quarter'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -398,7 +404,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(`in 1 ${unit}`, res); }); - it('expect function _dateDiff to return "1 quarter ago"', function () { + it('expect _dateDiff to return "1 quarter ago"', function () { i18next.changeLanguage('en'); const unit = 'quarter'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -408,7 +414,7 @@ describe('handlebars-i18n Tests', function () { // -- Test month -- // - it('expect function _dateDiff to return "in 1 month"', function () { + it('expect _dateDiff to return "in 1 month"', function () { i18next.changeLanguage('en'); const unit = 'month'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -416,7 +422,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(`in 1 ${unit}`, res); }); - it('expect function _dateDiff to return "1 month ago"', function () { + it('expect _dateDiff to return "1 month ago"', function () { i18next.changeLanguage('en'); const unit = 'month'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -426,7 +432,7 @@ describe('handlebars-i18n Tests', function () { // -- Test week -- // - it('expect function _dateDiff to return "in 1 week"', function () { + it('expect _dateDiff to return "in 1 week"', function () { i18next.changeLanguage('en'); const unit = 'week'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -434,7 +440,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(`in 1 ${unit}`, res); }); - it('expect function _dateDiff to return "1 week ago"', function () { + it('expect _dateDiff to return "1 week ago"', function () { i18next.changeLanguage('en'); const unit = 'week'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -444,7 +450,7 @@ describe('handlebars-i18n Tests', function () { // -- Test day -- // - it('expect function _dateDiff to return "in 1 day"', function () { + it('expect _dateDiff to return "in 1 day"', function () { i18next.changeLanguage('en'); const unit = 'day'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -452,7 +458,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(`in 1 ${unit}`, res); }); - it('expect function _dateDiff to return "1 day ago"', function () { + it('expect _dateDiff to return "1 day ago"', function () { i18next.changeLanguage('en'); const unit = 'day'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -462,7 +468,7 @@ describe('handlebars-i18n Tests', function () { // -- Test minute -- // - it('expect function _dateDiff to return "in 1 minute"', function () { + it('expect _dateDiff to return "in 1 minute"', function () { i18next.changeLanguage('en'); const unit = 'minute'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -470,7 +476,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(`in 1 ${unit}`, res); }); - it('expect function _dateDiff to return "1 minute ago"', function () { + it('expect _dateDiff to return "1 minute ago"', function () { i18next.changeLanguage('en'); const unit = 'minute'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -480,7 +486,7 @@ describe('handlebars-i18n Tests', function () { // -- Test second -- // - it('expect function _dateDiff to return "in 1 second"', function () { + it('expect _dateDiff to return "in 1 second"', function () { i18next.changeLanguage('en'); const unit = 'second'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -488,7 +494,7 @@ describe('handlebars-i18n Tests', function () { assert.equal(`in 1 ${unit}`, res); }); - it('expect function _dateDiff to return "1 second ago"', function () { + it('expect _dateDiff to return "1 second ago"', function () { i18next.changeLanguage('en'); const unit = 'second'; const hash = {hash: {localeMatcher: "best fit", numeric: "always", style: "long", unit: unit}}; @@ -501,25 +507,25 @@ describe('handlebars-i18n Tests', function () { Tests against function _num ****************************************/ - it('function _num should return comma separated triples of decimals when language is "en"', function () { + it('_num should return comma separated triples of decimals when language is "en"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._num(4000000, {hash: {}}); assert.equal('4,000,000', res); }); - it('function _num should return dot separated triples of decimals when language is "de"', function () { + it('_num should return dot separated triples of decimals when language is "de"', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._num(4000000, {hash: {}}); assert.equal('4.000.000', res); }); - it('function _num should return comma separated triples of decimals and 2 fraction digits"', function () { + it('_num should return comma separated triples of decimals and 2 fraction digits"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._num(4000000, {hash: {minimumFractionDigits: 2}}); assert.equal('4,000,000.00', res); }); - it('function _num should return dot separated triples of decimals and 2 fraction digits when language is "de"', function () { + it('_num should return dot separated triples of decimals and 2 fraction digits when language is "de"', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._num(4000000, {hash: {minimumFractionDigits: 2}}); assert.equal('4.000.000,00', res); @@ -530,26 +536,26 @@ describe('handlebars-i18n Tests', function () { Tests against function _price ****************************************/ - it('function _currency should return price in € written in comma separated triples of decimals and 2 fraction digits with leading currency symbol', function () { + it('_currency should return price in € written in comma separated triples of decimals and 2 fraction digits with leading currency symbol', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._price(4000000, {hash: {}}); assert.equal('€4,000,000.00', res); }); - it('function _currency should return price in € written in dot separated triples of decimals and 2 fraction digits with trailing currency symbol', function () { + it('_currency should return price in € written in dot separated triples of decimals and 2 fraction digits with trailing currency symbol', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._price(4000000, {hash: {}}); assert.isString(res); assert.equal('4.000.000,00 €', res); }); - it('function _currency should return price in ¥ written in comma separated triples of decimals with leading currency symbol', function () { + it('_currency should return price in ¥ written in comma separated triples of decimals with leading currency symbol', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._price(4000000, {hash: {currency: 'JPY', maximumFractionDigits: 0}}); assert.equal('¥4,000,000', res); }); - it('function _currency should return price in ¥ written in comma separated triples of decimals with trailing currency symbol', function () { + it('_currency should return price in ¥ written in comma separated triples of decimals with trailing currency symbol', function () { i18next.changeLanguage('de'); const res = hI18n.helpers._price(4000000, {hash: {currency: 'JPY', maximumFractionDigits: 0}}); assert.equal('4.000.000 ¥', res); @@ -624,7 +630,7 @@ describe('handlebars-i18n Tests', function () { assert.isOk(res); }); - it('function _num should return Intl standard format (no fraction digits) after reset() being called', function () { + it('_num should return Intl standard format (no fraction digits) after reset() being called', function () { HandlebarsI18n.configure('en', 'NumberFormat', {minimumFractionDigits: 4}); i18next.changeLanguage('en'); HandlebarsI18n.reset(); @@ -637,7 +643,7 @@ describe('handlebars-i18n Tests', function () { Tests for custom format configurations for function _date ********************************************************************/ - it('function _date when called after configure() with defined custom format (year:2-digit) should return ' + + it('_date when called after configure() with defined custom format (year:2-digit) should return ' + 'date "95" when language is "en"', function () { HandlebarsI18n.configure('en', 'DateTimeFormat', {year: "2-digit"}, 'my-custom-format'); i18next.changeLanguage('en'); @@ -645,7 +651,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('95', res); }); - it('function _date when called after configure() with defined custom format (year:numeric) given as ARRAY should return ' + + it('_date when called after configure() with defined custom format (year:numeric) given as ARRAY should return ' + 'date "12/17/95" when language is "en"', function () { HandlebarsI18n.configure(['en', 'DateTimeFormat', {year: "numeric"}, 'my-custom-format']); i18next.changeLanguage('en'); @@ -653,7 +659,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('95', res); }); - it('function _date when called after configure() with defined custom format (year:2-digit) should override ' + + it('_date when called after configure() with defined custom format (year:2-digit) should override ' + 'standard configuration when language is "en"', function () { HandlebarsI18n.configure([ ['en', 'DateTimeFormat', {year: "numeric"}], @@ -664,7 +670,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('95', res); }); - it('function _date when called after configure() with defined custom format (year:2-digit) should override ' + + it('_date when called after configure() with defined custom format (year:2-digit) should override ' + 'standard configuration also when being defined first', function () { HandlebarsI18n.configure([ ['en', 'DateTimeFormat', {year: "2-digit"}, 'my-custom-format'], @@ -675,7 +681,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('95', res); }); - it('function _date when called after configure() should fall back to generic language format "en" when custom format is unknown' + + it('_date when called after configure() should fall back to generic language format "en" when custom format is unknown' + 'standard configuration also when being defined first', function () { HandlebarsI18n.configure([ ['en', 'DateTimeFormat', {year: "2-digit"}, 'my-custom-format'], @@ -686,7 +692,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('1995', res); }); - it('function _date when called after configure() should fall back to generic language format "all" when custom format is unknown' + + it('_date when called after configure() should fall back to generic language format "all" when custom format is unknown' + 'standard configuration also when being defined first', function () { HandlebarsI18n.configure([ ['all', 'DateTimeFormat', {year: "2-digit"}, 'my-custom-format'], @@ -697,7 +703,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('1995', res); }); - it('function _date when called after configure() should fall back to Intl default format when custom format is unknown' + + it('_date when called after configure() should fall back to Intl default format when custom format is unknown' + 'standard configuration also when being defined first', function () { HandlebarsI18n.reset(); HandlebarsI18n.configure([ @@ -713,7 +719,7 @@ describe('handlebars-i18n Tests', function () { Tests for custom format configurations for _dateRel / _dateDiff ********************************************************************/ - it('function _dateRel called after configure() with defined "all" (style: "long", unit: "second") should return ' + + it('_dateRel called after configure() with defined "all" (style: "long", unit: "second") should return ' + '"in 12 seconds" when language is "en"', function () { HandlebarsI18n.configure('all', 'RelativeTimeFormat', {style: "long", unit: "second"}); i18next.changeLanguage('en'); @@ -721,7 +727,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('in 12 seconds', res); }); - it('function _dateRel called after configure() with defined custom format (style: "long", unit: "year") should return ' + + it('_dateRel called after configure() with defined custom format (style: "long", unit: "year") should return ' + '"in 12 Jahren" when language is "de"', function () { HandlebarsI18n.configure('de', 'RelativeTimeFormat', {style: "long", unit: "year"}, 'date-rel-custom'); i18next.changeLanguage('de'); @@ -729,7 +735,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('in 12 Jahren', res); }); - it('function _dateRel called after configure() with defined custom format { style: "short", unit: "minutes" } should override ' + + it('_dateRel called after configure() with defined custom format { style: "short", unit: "minutes" } should override ' + 'standard configuration when language is "en"', function () { HandlebarsI18n.configure([ ['en', 'RelativeTimeFormat', {style: "short", unit: "day"}, 'date-rel-spec'], @@ -740,7 +746,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('in 12 days', res); }); - it('function _dateRel called after configure() with defined custom format { style: "short", unit: "minutes" } should override ' + + it('_dateRel called after configure() with defined custom format { style: "short", unit: "minutes" } should override ' + 'standard configuration when language is "en" and output: \'in 12 days\'', function () { HandlebarsI18n.configure([ ['en', 'RelativeTimeFormat', {style: "short", unit: "day"}, 'date-rel-spec'], @@ -751,7 +757,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('in 12 days', res); }); - it('function _dateDiff called after configure() with defined custom format { style: "short", unit: "minutes" } should override ' + + it('_dateDiff called after configure() with defined custom format { style: "short", unit: "minutes" } should override ' + 'standard configuration when language is "en" and output: \'in in 1 yr.\'', function () { HandlebarsI18n.configure([ ['en', 'RelativeTimeFormat', {style: "short", unit: "year"}, 'date-rel-spec'], @@ -767,7 +773,7 @@ describe('handlebars-i18n Tests', function () { Tests for custom format configurations for function _num ********************************************************************/ - it('function _num when called after configure() with defined custom format (minimumFractionDigits:4) should return ' + + it('_num when called after configure() with defined custom format (minimumFractionDigits:4) should return ' + 'comma separated triples of decimals and 4 fraction of digits when language is "en"', function () { HandlebarsI18n.configure('en', 'NumberFormat', {minimumFractionDigits: 4}, 'my-custom-format'); i18next.changeLanguage('en'); @@ -775,7 +781,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('4,000,000.0000', res); }); - it('function _num when called after configure() with defined custom format (minimumFractionDigits:4) given as ARRAY should return ' + + it('_num when called after configure() with defined custom format (minimumFractionDigits:4) given as ARRAY should return ' + 'comma separated triples of decimals and 4 fraction of digits when language is "en"', function () { HandlebarsI18n.configure(['en', 'NumberFormat', {minimumFractionDigits: 4}, 'my-custom-format']); i18next.changeLanguage('en'); @@ -783,7 +789,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('4,000,000.0000', res); }); - it('function _num when called after configure() with defined custom format (minimumFractionDigits:4) should override' + + it('_num when called after configure() with defined custom format (minimumFractionDigits:4) should override' + 'standard configuration when language is "en"', function () { HandlebarsI18n.configure([ ['en', 'NumberFormat', {maximumFractionDigits: 1}], @@ -794,7 +800,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('4,000,000.0000', res); }); - it('function _num when called after configure() with defined custom format (minimumFractionDigits:4) should override' + + it('_num when called after configure() with defined custom format (minimumFractionDigits:4) should override' + 'standard configuration also when being defined first', function () { HandlebarsI18n.configure([ ['en', 'NumberFormat', {minimumFractionDigits: 4}, 'my-custom-format'], @@ -805,7 +811,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('4,000,000.0000', res); }); - it('function _num when called after configure() should fall back to standard language format "en" when custom format is unknown', function () { + it('_num when called after configure() should fall back to standard language format "en" when custom format is unknown', function () { HandlebarsI18n.configure([ ['en', 'NumberFormat', {minimumFractionDigits: 4}, 'my-custom-format'], ['en', 'NumberFormat', {minimumFractionDigits: 1}] @@ -815,7 +821,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('4,000,000.0', res); }); - it('function _num when called after configure() should fall back to standard language format "all" when custom format is unknown', function () { + it('_num when called after configure() should fall back to standard language format "all" when custom format is unknown', function () { HandlebarsI18n.configure([ ['en', 'NumberFormat', {minimumFractionDigits: 4}, 'my-custom-format'], ['all', 'NumberFormat', {minimumFractionDigits: 1}] @@ -825,7 +831,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('4,000,000.0', res); }); - it('function _num when called after configure() should fall back to Intl default when custom format is unknown', function () { + it('_num when called after configure() should fall back to Intl default when custom format is unknown', function () { HandlebarsI18n.reset(); HandlebarsI18n.configure([ ['en', 'NumberFormat', {minimumFractionDigits: 4}, 'my-custom-format'] @@ -840,7 +846,7 @@ describe('handlebars-i18n Tests', function () { Tests for custom format configurations for function _price ********************************************************************/ - it('function _price when called after configure() with defined custom format (minimumFractionDigits:4) should return ' + + it('_price when called after configure() with defined custom format (minimumFractionDigits:4) should return ' + 'comma separated triples of decimals and 4 fraction of digits when language is "en"', function () { HandlebarsI18n.configure('en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format'); i18next.changeLanguage('en'); @@ -848,7 +854,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('€2.000', res); }); - it('function _price when called after configure() with defined custom format (minimumFractionDigits:4) should return ' + + it('_price when called after configure() with defined custom format (minimumFractionDigits:4) should return ' + 'comma separated triples of decimals and 4 fraction of digits when language is "en"', function () { HandlebarsI18n.configure('en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format'); i18next.changeLanguage('en'); @@ -856,7 +862,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('€2.000', res); }); - it('function _price when called after configure() with defined custom format (minimumFractionDigits:4) given as ARRAY should return ' + + it('_price when called after configure() with defined custom format (minimumFractionDigits:4) given as ARRAY should return ' + 'comma separated triples of decimals and 4 fraction of digits when language is "en"', function () { HandlebarsI18n.configure(['en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format']); i18next.changeLanguage('en'); @@ -864,7 +870,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('€2.000', res); }); - it('function _price when called after configure() with defined custom format (minimumFractionDigits:3) should override' + + it('_price when called after configure() with defined custom format (minimumFractionDigits:3) should override' + 'standard configuration when language is "en"', function () { HandlebarsI18n.configure([ ['en', 'PriceFormat', {currency: 'USD'}], @@ -875,7 +881,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('€2.000', res); }); - it('function _price when called after configure() with defined custom format (minimumFractionDigits:3) should override' + + it('_price when called after configure() with defined custom format (minimumFractionDigits:3) should override' + 'standard configuration also when being defined first', function () { HandlebarsI18n.configure([ ['en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format'], @@ -886,7 +892,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('€2.000', res); }); - it('function _price when called after configure() should fall back to standard language format "en" when custom format is unknown', function () { + it('_price when called after configure() should fall back to standard language format "en" when custom format is unknown', function () { HandlebarsI18n.configure([ ['en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format'], ['en', 'PriceFormat', {currency: 'USD'}] @@ -896,7 +902,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('$2.00', res); }); - it('function _price when called after configure() should fall back to standard language format "all" when custom format is unknown', function () { + it('_price when called after configure() should fall back to standard language format "all" when custom format is unknown', function () { HandlebarsI18n.configure([ ['en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format'], ['all', 'PriceFormat', {currency: 'USD'}] @@ -906,7 +912,7 @@ describe('handlebars-i18n Tests', function () { assert.equal('$2.00', res); }); - it('function _price when called after configure() should fall back to Intl default when custom format is unknown', function () { + it('_price when called after configure() should fall back to Intl default when custom format is unknown', function () { HandlebarsI18n.configure([ ['en', 'PriceFormat', {currency: 'EUR', minimumFractionDigits: 3}, 'my-custom-format'] ]); From 8bd242cd8565469fbd77ca3bf350b1dd8a158e17 Mon Sep 17 00:00:00 2001 From: FloWa Date: Fri, 30 Aug 2024 08:25:42 +0200 Subject: [PATCH 04/14] test: added 3 test cases for _dateAdd --- test/handlebars-i18n.test.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/handlebars-i18n.test.js b/test/handlebars-i18n.test.js index c3b9376..503b485 100644 --- a/test/handlebars-i18n.test.js +++ b/test/handlebars-i18n.test.js @@ -264,13 +264,24 @@ describe('handlebars-i18n Tests', function () { Tests against function _date ****************************************/ - it('_dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { + it('_dateAdd should throw error when called without params', function () { + expect(function () { + hI18n.helpers._dateAdd() + }).to.throw("@ handlebars-i18n: invalid first argument \"dateInput\" was given for _dateAdd."); + }); + + it('_dateAdd should throw error when called without 2nd param', function () { + expect(function () { + hI18n.helpers._dateAdd('December 17, 1995 02:00:00') + }).to.throw("@ handlebars-i18n: invalid second argument \"offset\" was given for _dateAdd."); + }); + + it('_dateAdd should use default unit "hour" when called without 3rd param', function () { i18next.changeLanguage('en'); - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day"); + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 25); assert.equal('12/18/1995', res); }); - it('_dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { i18next.changeLanguage('en'); const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day"); From 73d7a1b56e3b9b768bf36a0d773f74b43d54f2b1 Mon Sep 17 00:00:00 2001 From: FloWa Date: Sat, 31 Aug 2024 19:18:30 +0200 Subject: [PATCH 05/14] test: added complete set of test cases for _dateAdd --- test/handlebars-i18n.test.js | 72 +++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/test/handlebars-i18n.test.js b/test/handlebars-i18n.test.js index 503b485..3d4ea1f 100644 --- a/test/handlebars-i18n.test.js +++ b/test/handlebars-i18n.test.js @@ -284,11 +284,81 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { i18next.changeLanguage('en'); - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day"); + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day" ); assert.equal('12/18/1995', res); }); + // -- Test for "second" -- // + it('_dateAdd should return "12/18/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "second"', function () { + i18next.changeLanguage('en'); + const options = {hash: {hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "second", options); + assert.equal('02:00:01', res); + }); + + // -- Test for "minute" -- // + + it('_dateAdd should return "02:01:00" when called with parameters "December 17, 1995 02:00:00", 1, and "minute"', function () { + i18next.changeLanguage('en'); + const options = {hash: {hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "minute", options); + assert.equal('02:01:00', res); + }); + + // -- Test for "hour" -- // + + it('_dateAdd should return "03:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "hour"', function () { + i18next.changeLanguage('en'); + const options = {hash: {hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "hour", options); + assert.equal('03:00:00', res); + }); + + // -- Test for "day" -- // + + it('_dateAdd should return "December 18, 1995 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { + i18next.changeLanguage('en'); + const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day", options); + assert.equal('December 18, 1995 at 02:00:00', res); + }); + + // -- Test for "week" -- // + + it('_dateAdd should return "December 24, 1995 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "week"', function () { + i18next.changeLanguage('en'); + const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "week", options); + assert.equal('December 24, 1995 at 02:00:00', res); + }); + + // -- Test for "month" -- // + + it('_dateAdd should return "January 17, 1996 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "month"', function () { + i18next.changeLanguage('en'); + const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "month", options); + assert.equal('January 17, 1996 at 02:00:00', res); + }); + + // -- Test for "quarter" -- // + + it('_dateAdd should return "March 17, 1996 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "quarter"', function () { + i18next.changeLanguage('en'); + const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "quarter", options); + assert.equal('March 17, 1996 at 02:00:00', res); + }); + + // -- Test for "year" -- // + + it('_dateAdd should return "December 17, 1996 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "year"', function () { + i18next.changeLanguage('en'); + const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "year", options); + assert.equal('December 17, 1996 at 02:00:00', res); + }); /**************************************** From 25c87515e4f8b1d829a8324809fa365a795bcf9a Mon Sep 17 00:00:00 2001 From: FloWa Date: Sat, 31 Aug 2024 19:22:04 +0200 Subject: [PATCH 06/14] feat: updated minified version handlebars-i18n.min.js --- dist/handlebars-i18n.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/handlebars-i18n.min.js b/dist/handlebars-i18n.min.js index d94f7f2..e41959f 100644 --- a/dist/handlebars-i18n.min.js +++ b/dist/handlebars-i18n.min.js @@ -1 +1 @@ -!function(e,r){if("object"==typeof exports&&"object"==typeof module){const e=require("handlebars"),t=require("i18next"),n=require("intl"),a=require("relative-time-format");module.exports=r(e,t,n,a,"TEST"===process?.env?.NODE_ENV)}else if("function"==typeof define&&define.amd)define(["Handlebars","i18next","Intl"],r);else{if("object"!=typeof e.Handlebars||"object"!=typeof e.i18next||"object"!=typeof e.Intl)return console.error("@ handlebars-i18n: One or more dependencies are missing. Check for Handlebars, i18next and Intl."),!1;e.HandlebarsI18n=r(e.Handlebars,e.i18next,e.Intl)}}(this,(function(e,r,t,n,a){"use strict";const o={DateTimeFormat:{standard:{},custom:{}},RelativeTimeFormat:{standard:{all:{unit:"hours"}},custom:{}},NumberFormat:{standard:{},custom:{}},PriceFormat:{standard:{all:{style:"currency",currency:"EUR"}},custom:{}}};let i=JSON.parse(JSON.stringify(o));const u={};function s(e,r){let t=[null].concat(r);return new(e.bind.apply(e,t))}function l(e,r,t){if("object"==typeof e&&"object"==typeof e.hash&&Object.keys(e.hash).length>0){let n=e.hash;if(void 0===n.format)return n;if(void 0!==t.custom[n.format]&&void 0!==t.custom[n.format][r])return t.custom[n.format][r]}return void 0!==t.standard[r]?t.standard[r]:void 0!==t.standard.all?t.standard.all:{}}function c(e,r,t,n){return"string"!=typeof e?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en".'),!1):["DateTimeFormat","RelativeTimeFormat","NumberFormat","PriceFormat"].includes(r)?"object"!=typeof t?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+t+"> Third argument must be an object containing the configuration parameters."),!1):(null==n||"string"==typeof n)&&""!==n&&" "!==n||(console.error("@ handlebars-i18n.configure(): Invalid argument <"+n+"> Fourth argument (optional) must be a string naming your custom format configuration."),!1):(console.error("@ handlebars-i18n.configure(): Invalid argument <"+r+'>. Second argument must be a string with the options key. Use either "DateTimeFormat", "RelativeTimeFormat", "NumberFormat", or "PriceFormat".'),!1)}function m(e,r,t,n){return null!=n?(void 0===i[r].custom[n]&&(i[r].custom[n]={}),i[r].custom[n][e]=t):i[r].standard[e]=t,!0}function f(e){return"number"==typeof e||"string"==typeof e&&""!==e}function g(e){let r;if("number"==typeof e)r=new Date(e);else if("string"==typeof e)if("["===e.charAt(0)&&"]"===e.slice(-1)){let t=(e=e.substring(1,e.length-1).replace(/ /g,"")).split(",");r=s.bind(null,Date)(t)}else r="now"===e.toLowerCase()||"today"===e.toLowerCase()?new Date:new Date(e);else r=new Date;return r}function d(e,r){if("function"==typeof t.RelativeTimeFormat)return new t.RelativeTimeFormat(e,r);if(void 0===u[e])try{u[e]=require(`relative-time-format/locale/${e}`)}catch(e){console.error(e)}return n.addLocale(u[e]),new n(e,r)}function b(e,r){return r=r||"hour",Math.trunc(e/{second:1e3,seconds:1e3,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5,month:2629746e3,months:2629746e3,quarter:78894e5,quarters:78894e5,year:315576e5,years:315576e5}[r])}return{configure:function(e,r,t,n){if("string"!=typeof e&&!Array.isArray(e))return console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en" or an array with language parameters.'),!1;if(Array.isArray(e)){if(e.length<1)return console.log("@ handlebars-i18n.configure(): You passed an empty array, no parameters taken."),!1;e.forEach((e=>{if(!c(e[0],e[1],e[2],e[3]))return!1;m(e[0],e[1],e[2],e[3])}))}else{if(!c(e,r,t,n))return!1;m(e,r,t,n)}return!0},reset:function(){return i=JSON.parse(JSON.stringify(o)),!0},init:function(n,a){return"object"==typeof n&&null!==n?e=n:null!=n&&console.error("@ handlebars-i18n.init(): Invalid Argument [1] given for overrideHndlbrs. Argument must be the Handlebars object. Using generic Handlebars object instead."),"object"==typeof a&&null!==a?r=a:null!=a&&console.error("@ handlebars-i18n.init(): Invalid Argument [2] given for overrideI18n. Argument must be the i18next object. Using generic i18next object on module level instead."),e.registerHelper("__",(function(t,n){return new e.SafeString(void 0!==r?r.t(t,n.hash):t)})),e.registerHelper("_locale",(function(){return r.language})),e.registerHelper("localeIs",(function(e){return r.language===e})),e.registerHelper("_date",(function(e,n){const a=g(e),o=l(n,r.language,i.DateTimeFormat);return new t.DateTimeFormat(r.language,o).format(a)})),e.registerHelper("_dateRel",(function(e,t){const n=parseInt(e),a=l(t,r.language,i.RelativeTimeFormat);return d(r.language,a).format(n,a.unit)})),e.registerHelper("_dateDiff",(function(e,t,n){let a,o=l(n,r.language,i.RelativeTimeFormat);if(!f(e))return console.error("@ handlebars-i18n: invalid first argument dateInputA was given for _dateDiff."),null;t=t||"now",a=g(e)-g(t);const u=b(a,o.unit);return d(r.language,o).format(u,o.unit)})),e.registerHelper("_num",(function(e,n){let a=l(n,r.language,i.NumberFormat);return new t.NumberFormat(r.language,a).format(e)})),e.registerHelper("_price",(function(e,n){let a=l(n,r.language,i.PriceFormat);"string"!=typeof a.style&&"string"==typeof a.currency&&(a.style="currency");return new t.NumberFormat(r.language,a).format(e)})),e},...a&&{private:{applyToConstructor:s,configLookup:l,validateArgs:c,setArgs:m,isNumOrString:f,createDateObj:g,getRelDateFormatPolyfill:d,getDateDiff:b}}}})); \ No newline at end of file +!function(e,t){if("object"==typeof exports&&"object"==typeof module){const e=require("handlebars"),r=require("i18next"),n=require("intl"),a=require("relative-time-format");module.exports=t(e,r,n,a,"TEST"===process?.env?.NODE_ENV)}else if("function"==typeof define&&define.amd)define(["Handlebars","i18next","Intl"],t);else{if("object"!=typeof e.Handlebars||"object"!=typeof e.i18next||"object"!=typeof e.Intl)return console.error("@ handlebars-i18n: One or more dependencies are missing. Check for Handlebars, i18next and Intl."),!1;e.HandlebarsI18n=t(e.Handlebars,e.i18next,e.Intl)}}(this,(function(e,t,r,n,a){"use strict";const o={DateTimeFormat:{standard:{},custom:{}},RelativeTimeFormat:{standard:{all:{unit:"hours"}},custom:{}},NumberFormat:{standard:{},custom:{}},PriceFormat:{standard:{all:{style:"currency",currency:"EUR"}},custom:{}}};let i=JSON.parse(JSON.stringify(o));const s={};function u(e,t){let r=[null].concat(t);return new(e.bind.apply(e,r))}function l(e,t,r){if("object"==typeof e&&"object"==typeof e.hash&&Object.keys(e.hash).length>0){let n=e.hash;if(void 0===n.format)return n;if(void 0!==r.custom[n.format]&&void 0!==r.custom[n.format][t])return r.custom[n.format][t]}return void 0!==r.standard[t]?r.standard[t]:void 0!==r.standard.all?r.standard.all:{}}function c(e,t,r,n){return"string"!=typeof e?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en".'),!1):["DateTimeFormat","RelativeTimeFormat","NumberFormat","PriceFormat"].includes(t)?"object"!=typeof r?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+r+"> Third argument must be an object containing the configuration parameters."),!1):(null==n||"string"==typeof n)&&""!==n&&" "!==n||(console.error("@ handlebars-i18n.configure(): Invalid argument <"+n+"> Fourth argument (optional) must be a string naming your custom format configuration."),!1):(console.error("@ handlebars-i18n.configure(): Invalid argument <"+t+'>. Second argument must be a string with the options key. Use either "DateTimeFormat", "RelativeTimeFormat", "NumberFormat", or "PriceFormat".'),!1)}function m(e,t,r,n){return null!=n?(void 0===i[t].custom[n]&&(i[t].custom[n]={}),i[t].custom[n][e]=r):i[t].standard[e]=r,!0}function g(e){return"number"==typeof e||"string"==typeof e&&""!==e}function d(e){let t;if("number"==typeof e)t=new Date(e);else if("string"==typeof e)if("["===e.charAt(0)&&"]"===e.slice(-1)){let r=(e=e.substring(1,e.length-1).replace(/ /g,"")).split(",");t=u.bind(null,Date)(r)}else t="now"===e.toLowerCase()||"today"===e.toLowerCase()?new Date:new Date(e);else t=new Date;return t}function f(e,t){if("function"==typeof r.RelativeTimeFormat)return new r.RelativeTimeFormat(e,t);if(void 0===s[e])try{s[e]=require(`relative-time-format/locale/${e}`)}catch(e){console.error(e)}return n.addLocale(s[e]),new n(e,t)}function b(e,t){return t=t||"hour",Math.trunc(e/{second:1e3,seconds:1e3,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5,month:2629746e3,months:2629746e3,quarter:78894e5,quarters:78894e5,year:315576e5,years:315576e5}[t])}return{configure:function(e,t,r,n){if("string"!=typeof e&&!Array.isArray(e))return console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en" or an array with language parameters.'),!1;if(Array.isArray(e)){if(e.length<1)return console.log("@ handlebars-i18n.configure(): You passed an empty array, no parameters taken."),!1;e.forEach((e=>{if(!c(e[0],e[1],e[2],e[3]))return!1;m(e[0],e[1],e[2],e[3])}))}else{if(!c(e,t,r,n))return!1;m(e,t,r,n)}return!0},reset:function(){return i=JSON.parse(JSON.stringify(o)),!0},init:function(n,a){return"object"==typeof n&&null!==n?e=n:null!=n&&console.error("@ handlebars-i18n.init(): Invalid Argument [1] given for overrideHndlbrs. Argument must be the Handlebars object. Using generic Handlebars object instead."),"object"==typeof a&&null!==a?t=a:null!=a&&console.error("@ handlebars-i18n.init(): Invalid Argument [2] given for overrideI18n. Argument must be the i18next object. Using generic i18next object on module level instead."),e.registerHelper("__",(function(r,n){return new e.SafeString(void 0!==t?t.t(r,n.hash):r)})),e.registerHelper("_locale",(function(){return t.language})),e.registerHelper("localeIs",(function(e){return t.language===e})),e.registerHelper("_date",(function(e,n){const a=d(e),o=l(n,t.language,i.DateTimeFormat);return new r.DateTimeFormat(t.language,o).format(a)})),e.registerHelper("_dateAdd",(function(e,n,a,o){if("number"!=typeof e&&"string"!=typeof e)throw new Error('@ handlebars-i18n: invalid first argument "dateInput" was given for _dateAdd.');if("number"!=typeof n)throw new Error('@ handlebars-i18n: invalid second argument "offset" was given for _dateAdd.');const s=d(e);switch(a=a||"hour"){case"second":case"seconds":s.setSeconds(s.getSeconds()+n);break;case"minute":case"minutes":s.setMinutes(s.getMinutes()+n);break;case"hour":case"hours":s.setHours(s.getHours()+n);break;case"day":case"days":s.setDate(s.getDate()+n);break;case"week":case"weeks":s.setDate(s.getDate()+7*n);break;case"month":case"months":s.setMonth(s.getMonth()+n);break;case"quarter":case"quarters":s.setMonth(s.getMonth()+3*n);break;case"year":case"years":s.setFullYear(s.getFullYear()+n);break;default:throw new Error('@ handlebars-i18n: invalid argument "unit" was given for _dateAdd.Unit must be either "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year".')}const u=l(o,t.language,i.DateTimeFormat);return new r.DateTimeFormat(t.language,u).format(s)})),e.registerHelper("_dateRel",(function(e,r){const n=parseInt(e),a=l(r,t.language,i.RelativeTimeFormat);return f(t.language,a).format(n,a.unit)})),e.registerHelper("_dateDiff",(function(e,r,n){let a,o=l(n,t.language,i.RelativeTimeFormat);if(!g(e))return console.error("@ handlebars-i18n: invalid first argument dateInputA was given for _dateDiff."),null;r=r||"now",a=d(e)-d(r);const s=b(a,o.unit);return f(t.language,o).format(s,o.unit)})),e.registerHelper("_num",(function(e,n){let a=l(n,t.language,i.NumberFormat);return new r.NumberFormat(t.language,a).format(e)})),e.registerHelper("_price",(function(e,n){let a=l(n,t.language,i.PriceFormat);"string"!=typeof a.style&&"string"==typeof a.currency&&(a.style="currency");return new r.NumberFormat(t.language,a).format(e)})),e},...a&&{private:{applyToConstructor:u,configLookup:l,validateArgs:c,setArgs:m,isNumOrString:g,createDateObj:d,getRelDateFormatPolyfill:f,getDateDiff:b}}}})); \ No newline at end of file From 13cb36e247b37842c127b5565b1b2baea9efa9ab Mon Sep 17 00:00:00 2001 From: FloWa Date: Sun, 1 Sep 2024 09:29:38 +0200 Subject: [PATCH 07/14] refactor: made argument "unit" part of the options for func _dateAdd in handlebars-i18n.js --- dist/handlebars-i18n.js | 9 +++--- readme.md | 72 ++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/dist/handlebars-i18n.js b/dist/handlebars-i18n.js index 8d0bfe3..a135967 100644 --- a/dist/handlebars-i18n.js +++ b/dist/handlebars-i18n.js @@ -451,11 +451,10 @@ * * @param dateInput * @param offset - * @param unit * @param options * @returns {string} */ - function (dateInput, offset, unit, options) { + function (dateInput, offset, options) { if (typeof dateInput !== 'number' && typeof dateInput !== 'string') throw new Error('@ handlebars-i18n: invalid first argument "dateInput" was given for _dateAdd.'); @@ -465,9 +464,10 @@ const date = __createDateObj(dateInput); - unit = unit || 'hour'; + const opts = __configLookup(options, i18next.language, optionsConf.DateTimeFormat); + opts.unit = opts.unit || 'hour'; - switch (unit) { + switch (opts.unit) { case 'second': case 'seconds': date.setSeconds(date.getSeconds() + offset); @@ -505,7 +505,6 @@ 'Unit must be either "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year".'); } - const opts = __configLookup(options, i18next.language, optionsConf.DateTimeFormat); const dateFormat = new Intl.DateTimeFormat(i18next.language, opts); return dateFormat.format(date); } diff --git a/readme.md b/readme.md index 39a9228..418789b 100644 --- a/readme.md +++ b/readme.md @@ -197,13 +197,9 @@ Template usage: The i18next resource: ```javascript -"en" -: -{ +"en" : { translation : { - "whatIsWhat" - : - "{{a}} is {{b}}." + "whatIsWhat" : "{{a}} is {{b}}." } } ``` @@ -215,19 +211,12 @@ The i18next resource: ``` ```javascript -"en" -: -{ +"en" : { translation : { - "keyWithCount" - : - "{{count}} item", - "keyWithCount_plural" - : - "{{count}} items" + "keyWithCount" : "{{count}} item", + "keyWithCount_plural" : "{{count}} items" } -} -, ... +}, ``` **Override globally selected language** @@ -311,44 +300,55 @@ in [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts). --- -### _dateRel :tada: new in 1.7 +### _dateAdd :tada: new in 1.8 -Outputs a string with a relative date statement, formatted according to the language specific conventions. +Adds a time offset in a given unit to a date, returns the modified date. ``` -{{_dateRel 7 unit="hour"}} +{{_dateAdd "1996-12-17T00:00:00" 24 unit="hour"}} ``` -Will output for "en" → **in 7 hours** - -``` -{{_dateRel -7 unit="hour"}} -``` -Will output for "en" → **7 hours ago** - -A positive number argument leads to a future event statement, a negative refers to a past date. Possible units -are `"second"` | `"minute"` | `"hour"` | `"day"` | `"week"` | `"month"` | `"quarter"` |`"year"` (default is `"hour"`). -For a complete set of options (such as `numberingSystem` or `localeMatcher`) -see [Intl.RelativeTimeFormat Constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat). -Alternatively check this repo’s TS types -in [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts). --- -### _dateDiff :tada: new in 1.7 +### _dateDiff Outputs the time difference between two given dates. ``` -{{_dateDiff "1996-12-17T00:00:00", "1995-12-17T00:00:00" unit="year"}} +{{_dateDiff "1996-12-17T00:00:00" "1995-12-17T00:00:00" unit="year"}} ``` Will output for "en" → **in 1 year** The second date argument is subtracted from the first. If the difference is a positive value, a future event statement is made. A negative value refers to a past date. Allowed date input formats are similar to *_date*, options equal -**_dateRel**. +**_dateRel**. Default unit is `"hour"`. + +--- + +### _dateRel + +Outputs a string with a relative date statement, formatted according to the language specific conventions. + +``` +{{_dateRel 7 unit="hour"}} +``` + +Will output for "en" → **in 7 hours** + +``` +{{_dateRel -7 unit="hour"}} +``` + +Will output for "en" → **7 hours ago** + +A positive number argument leads to a future event statement, a negative refers to a past date. Possible units +are `"second"` | `"minute"` | `"hour"` | `"day"` | `"week"` | `"month"` | `"quarter"` |`"year"` (default is `"hour"`). +For a complete set of options (such as `numberingSystem` or `localeMatcher`) +see [Intl.RelativeTimeFormat Constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat). +Alternatively check this repo’s TS types in [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts). --- From 548eedae1b2b6d963e34b065b330711bc50516b7 Mon Sep 17 00:00:00 2001 From: FloWa Date: Mon, 2 Sep 2024 09:20:46 +0200 Subject: [PATCH 08/14] refactor: changed test specifications for func _dateAdd in handlebars-i18n.test.js --- test/handlebars-i18n.test.js | 86 ++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 18 deletions(-) diff --git a/test/handlebars-i18n.test.js b/test/handlebars-i18n.test.js index 3d4ea1f..4b38b36 100644 --- a/test/handlebars-i18n.test.js +++ b/test/handlebars-i18n.test.js @@ -261,7 +261,7 @@ describe('handlebars-i18n Tests', function () { /**************************************** - Tests against function _date + Tests against function _dateAdd ****************************************/ it('_dateAdd should throw error when called without params', function () { @@ -284,7 +284,7 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "12/17/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { i18next.changeLanguage('en'); - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day" ); + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, {"hash": {unit: "day"}}); assert.equal('12/18/1995', res); }); @@ -292,8 +292,8 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "12/18/1995" when called with parameters "December 17, 1995 02:00:00", 1, and "second"', function () { i18next.changeLanguage('en'); - const options = {hash: {hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "second", options); + const options = {hash: {unit: "second", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('02:00:01', res); }); @@ -301,8 +301,8 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "02:01:00" when called with parameters "December 17, 1995 02:00:00", 1, and "minute"', function () { i18next.changeLanguage('en'); - const options = {hash: {hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "minute", options); + const options = {hash: {unit: "minute", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('02:01:00', res); }); @@ -310,8 +310,8 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "03:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "hour"', function () { i18next.changeLanguage('en'); - const options = {hash: {hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "hour", options); + const options = {hash: {unit: "hour", hour: "2-digit", minute: "2-digit", second: "2-digit"}} + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('03:00:00', res); }); @@ -319,8 +319,18 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "December 18, 1995 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "day"', function () { i18next.changeLanguage('en'); - const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "day", options); + const options = { + hash: { + unit: "day", + year: "numeric", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + } + } + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('December 18, 1995 at 02:00:00', res); }); @@ -328,8 +338,18 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "December 24, 1995 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "week"', function () { i18next.changeLanguage('en'); - const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "week", options); + const options = { + hash: { + unit: "week", + year: "numeric", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + } + } + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('December 24, 1995 at 02:00:00', res); }); @@ -337,8 +357,18 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "January 17, 1996 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "month"', function () { i18next.changeLanguage('en'); - const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "month", options); + const options = { + hash: { + unit: "month", + year: "numeric", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + } + } + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('January 17, 1996 at 02:00:00', res); }); @@ -346,8 +376,18 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "March 17, 1996 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "quarter"', function () { i18next.changeLanguage('en'); - const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "quarter", options); + const options = { + hash: { + unit: "quarter", + year: "numeric", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + } + } + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('March 17, 1996 at 02:00:00', res); }); @@ -355,8 +395,18 @@ describe('handlebars-i18n Tests', function () { it('_dateAdd should return "December 17, 1996 02:00:00" when called with parameters "December 17, 1995 02:00:00", 1, and "year"', function () { i18next.changeLanguage('en'); - const options = {hash: {year: "numeric", month: "long", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}} - const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, "year", options); + const options = { + hash: { + unit: "year", + year: "numeric", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + } + } + const res = hI18n.helpers._dateAdd('December 17, 1995 02:00:00', 1, options); assert.equal('December 17, 1996 at 02:00:00', res); }); From 3bec302355bcbdad391b0e395952443ca3b94be1 Mon Sep 17 00:00:00 2001 From: FloWa Date: Mon, 2 Sep 2024 16:47:20 +0200 Subject: [PATCH 09/14] refactor: minified file handlebars-i18n.min.js --- dist/handlebars-i18n.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/handlebars-i18n.min.js b/dist/handlebars-i18n.min.js index e41959f..ed8a8b4 100644 --- a/dist/handlebars-i18n.min.js +++ b/dist/handlebars-i18n.min.js @@ -1 +1 @@ -!function(e,t){if("object"==typeof exports&&"object"==typeof module){const e=require("handlebars"),r=require("i18next"),n=require("intl"),a=require("relative-time-format");module.exports=t(e,r,n,a,"TEST"===process?.env?.NODE_ENV)}else if("function"==typeof define&&define.amd)define(["Handlebars","i18next","Intl"],t);else{if("object"!=typeof e.Handlebars||"object"!=typeof e.i18next||"object"!=typeof e.Intl)return console.error("@ handlebars-i18n: One or more dependencies are missing. Check for Handlebars, i18next and Intl."),!1;e.HandlebarsI18n=t(e.Handlebars,e.i18next,e.Intl)}}(this,(function(e,t,r,n,a){"use strict";const o={DateTimeFormat:{standard:{},custom:{}},RelativeTimeFormat:{standard:{all:{unit:"hours"}},custom:{}},NumberFormat:{standard:{},custom:{}},PriceFormat:{standard:{all:{style:"currency",currency:"EUR"}},custom:{}}};let i=JSON.parse(JSON.stringify(o));const s={};function u(e,t){let r=[null].concat(t);return new(e.bind.apply(e,r))}function l(e,t,r){if("object"==typeof e&&"object"==typeof e.hash&&Object.keys(e.hash).length>0){let n=e.hash;if(void 0===n.format)return n;if(void 0!==r.custom[n.format]&&void 0!==r.custom[n.format][t])return r.custom[n.format][t]}return void 0!==r.standard[t]?r.standard[t]:void 0!==r.standard.all?r.standard.all:{}}function c(e,t,r,n){return"string"!=typeof e?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en".'),!1):["DateTimeFormat","RelativeTimeFormat","NumberFormat","PriceFormat"].includes(t)?"object"!=typeof r?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+r+"> Third argument must be an object containing the configuration parameters."),!1):(null==n||"string"==typeof n)&&""!==n&&" "!==n||(console.error("@ handlebars-i18n.configure(): Invalid argument <"+n+"> Fourth argument (optional) must be a string naming your custom format configuration."),!1):(console.error("@ handlebars-i18n.configure(): Invalid argument <"+t+'>. Second argument must be a string with the options key. Use either "DateTimeFormat", "RelativeTimeFormat", "NumberFormat", or "PriceFormat".'),!1)}function m(e,t,r,n){return null!=n?(void 0===i[t].custom[n]&&(i[t].custom[n]={}),i[t].custom[n][e]=r):i[t].standard[e]=r,!0}function g(e){return"number"==typeof e||"string"==typeof e&&""!==e}function d(e){let t;if("number"==typeof e)t=new Date(e);else if("string"==typeof e)if("["===e.charAt(0)&&"]"===e.slice(-1)){let r=(e=e.substring(1,e.length-1).replace(/ /g,"")).split(",");t=u.bind(null,Date)(r)}else t="now"===e.toLowerCase()||"today"===e.toLowerCase()?new Date:new Date(e);else t=new Date;return t}function f(e,t){if("function"==typeof r.RelativeTimeFormat)return new r.RelativeTimeFormat(e,t);if(void 0===s[e])try{s[e]=require(`relative-time-format/locale/${e}`)}catch(e){console.error(e)}return n.addLocale(s[e]),new n(e,t)}function b(e,t){return t=t||"hour",Math.trunc(e/{second:1e3,seconds:1e3,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5,month:2629746e3,months:2629746e3,quarter:78894e5,quarters:78894e5,year:315576e5,years:315576e5}[t])}return{configure:function(e,t,r,n){if("string"!=typeof e&&!Array.isArray(e))return console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en" or an array with language parameters.'),!1;if(Array.isArray(e)){if(e.length<1)return console.log("@ handlebars-i18n.configure(): You passed an empty array, no parameters taken."),!1;e.forEach((e=>{if(!c(e[0],e[1],e[2],e[3]))return!1;m(e[0],e[1],e[2],e[3])}))}else{if(!c(e,t,r,n))return!1;m(e,t,r,n)}return!0},reset:function(){return i=JSON.parse(JSON.stringify(o)),!0},init:function(n,a){return"object"==typeof n&&null!==n?e=n:null!=n&&console.error("@ handlebars-i18n.init(): Invalid Argument [1] given for overrideHndlbrs. Argument must be the Handlebars object. Using generic Handlebars object instead."),"object"==typeof a&&null!==a?t=a:null!=a&&console.error("@ handlebars-i18n.init(): Invalid Argument [2] given for overrideI18n. Argument must be the i18next object. Using generic i18next object on module level instead."),e.registerHelper("__",(function(r,n){return new e.SafeString(void 0!==t?t.t(r,n.hash):r)})),e.registerHelper("_locale",(function(){return t.language})),e.registerHelper("localeIs",(function(e){return t.language===e})),e.registerHelper("_date",(function(e,n){const a=d(e),o=l(n,t.language,i.DateTimeFormat);return new r.DateTimeFormat(t.language,o).format(a)})),e.registerHelper("_dateAdd",(function(e,n,a,o){if("number"!=typeof e&&"string"!=typeof e)throw new Error('@ handlebars-i18n: invalid first argument "dateInput" was given for _dateAdd.');if("number"!=typeof n)throw new Error('@ handlebars-i18n: invalid second argument "offset" was given for _dateAdd.');const s=d(e);switch(a=a||"hour"){case"second":case"seconds":s.setSeconds(s.getSeconds()+n);break;case"minute":case"minutes":s.setMinutes(s.getMinutes()+n);break;case"hour":case"hours":s.setHours(s.getHours()+n);break;case"day":case"days":s.setDate(s.getDate()+n);break;case"week":case"weeks":s.setDate(s.getDate()+7*n);break;case"month":case"months":s.setMonth(s.getMonth()+n);break;case"quarter":case"quarters":s.setMonth(s.getMonth()+3*n);break;case"year":case"years":s.setFullYear(s.getFullYear()+n);break;default:throw new Error('@ handlebars-i18n: invalid argument "unit" was given for _dateAdd.Unit must be either "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year".')}const u=l(o,t.language,i.DateTimeFormat);return new r.DateTimeFormat(t.language,u).format(s)})),e.registerHelper("_dateRel",(function(e,r){const n=parseInt(e),a=l(r,t.language,i.RelativeTimeFormat);return f(t.language,a).format(n,a.unit)})),e.registerHelper("_dateDiff",(function(e,r,n){let a,o=l(n,t.language,i.RelativeTimeFormat);if(!g(e))return console.error("@ handlebars-i18n: invalid first argument dateInputA was given for _dateDiff."),null;r=r||"now",a=d(e)-d(r);const s=b(a,o.unit);return f(t.language,o).format(s,o.unit)})),e.registerHelper("_num",(function(e,n){let a=l(n,t.language,i.NumberFormat);return new r.NumberFormat(t.language,a).format(e)})),e.registerHelper("_price",(function(e,n){let a=l(n,t.language,i.PriceFormat);"string"!=typeof a.style&&"string"==typeof a.currency&&(a.style="currency");return new r.NumberFormat(t.language,a).format(e)})),e},...a&&{private:{applyToConstructor:u,configLookup:l,validateArgs:c,setArgs:m,isNumOrString:g,createDateObj:d,getRelDateFormatPolyfill:f,getDateDiff:b}}}})); \ No newline at end of file +!function(e,t){if("object"==typeof exports&&"object"==typeof module){const e=require("handlebars"),r=require("i18next"),n=require("intl"),a=require("relative-time-format");module.exports=t(e,r,n,a,"TEST"===process?.env?.NODE_ENV)}else if("function"==typeof define&&define.amd)define(["Handlebars","i18next","Intl"],t);else{if("object"!=typeof e.Handlebars||"object"!=typeof e.i18next||"object"!=typeof e.Intl)return console.error("@ handlebars-i18n: One or more dependencies are missing. Check for Handlebars, i18next and Intl."),!1;e.HandlebarsI18n=t(e.Handlebars,e.i18next,e.Intl)}}(this,(function(e,t,r,n,a){"use strict";const o={DateTimeFormat:{standard:{},custom:{}},RelativeTimeFormat:{standard:{all:{unit:"hours"}},custom:{}},NumberFormat:{standard:{},custom:{}},PriceFormat:{standard:{all:{style:"currency",currency:"EUR"}},custom:{}}};let i=JSON.parse(JSON.stringify(o));const s={};function u(e,t){let r=[null].concat(t);return new(e.bind.apply(e,r))}function l(e,t,r){if("object"==typeof e&&"object"==typeof e.hash&&Object.keys(e.hash).length>0){let n=e.hash;if(void 0===n.format)return n;if(void 0!==r.custom[n.format]&&void 0!==r.custom[n.format][t])return r.custom[n.format][t]}return void 0!==r.standard[t]?r.standard[t]:void 0!==r.standard.all?r.standard.all:{}}function c(e,t,r,n){return"string"!=typeof e?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en".'),!1):["DateTimeFormat","RelativeTimeFormat","NumberFormat","PriceFormat"].includes(t)?"object"!=typeof r?(console.error("@ handlebars-i18n.configure(): Invalid argument <"+r+"> Third argument must be an object containing the configuration parameters."),!1):(null==n||"string"==typeof n)&&""!==n&&" "!==n||(console.error("@ handlebars-i18n.configure(): Invalid argument <"+n+"> Fourth argument (optional) must be a string naming your custom format configuration."),!1):(console.error("@ handlebars-i18n.configure(): Invalid argument <"+t+'>. Second argument must be a string with the options key. Use either "DateTimeFormat", "RelativeTimeFormat", "NumberFormat", or "PriceFormat".'),!1)}function m(e,t,r,n){return null!=n?(void 0===i[t].custom[n]&&(i[t].custom[n]={}),i[t].custom[n][e]=r):i[t].standard[e]=r,!0}function g(e){return"number"==typeof e||"string"==typeof e&&""!==e}function d(e){let t;if("number"==typeof e)t=new Date(e);else if("string"==typeof e)if("["===e.charAt(0)&&"]"===e.slice(-1)){let r=(e=e.substring(1,e.length-1).replace(/ /g,"")).split(",");t=u.bind(null,Date)(r)}else t="now"===e.toLowerCase()||"today"===e.toLowerCase()?new Date:new Date(e);else t=new Date;return t}function f(e,t){if("function"==typeof r.RelativeTimeFormat)return new r.RelativeTimeFormat(e,t);if(void 0===s[e])try{s[e]=require(`relative-time-format/locale/${e}`)}catch(e){console.error(e)}return n.addLocale(s[e]),new n(e,t)}function b(e,t){return t=t||"hour",Math.trunc(e/{second:1e3,seconds:1e3,minute:6e4,minutes:6e4,hour:36e5,hours:36e5,day:864e5,days:864e5,week:6048e5,weeks:6048e5,month:2629746e3,months:2629746e3,quarter:78894e5,quarters:78894e5,year:315576e5,years:315576e5}[t])}return{configure:function(e,t,r,n){if("string"!=typeof e&&!Array.isArray(e))return console.error("@ handlebars-i18n.configure(): Invalid argument <"+e+'> First argument must be a string with language code such as "en" or an array with language parameters.'),!1;if(Array.isArray(e)){if(e.length<1)return console.log("@ handlebars-i18n.configure(): You passed an empty array, no parameters taken."),!1;e.forEach((e=>{if(!c(e[0],e[1],e[2],e[3]))return!1;m(e[0],e[1],e[2],e[3])}))}else{if(!c(e,t,r,n))return!1;m(e,t,r,n)}return!0},reset:function(){return i=JSON.parse(JSON.stringify(o)),!0},init:function(n,a){return"object"==typeof n&&null!==n?e=n:null!=n&&console.error("@ handlebars-i18n.init(): Invalid Argument [1] given for overrideHndlbrs. Argument must be the Handlebars object. Using generic Handlebars object instead."),"object"==typeof a&&null!==a?t=a:null!=a&&console.error("@ handlebars-i18n.init(): Invalid Argument [2] given for overrideI18n. Argument must be the i18next object. Using generic i18next object on module level instead."),e.registerHelper("__",(function(r,n){return new e.SafeString(void 0!==t?t.t(r,n.hash):r)})),e.registerHelper("_locale",(function(){return t.language})),e.registerHelper("localeIs",(function(e){return t.language===e})),e.registerHelper("_date",(function(e,n){const a=d(e),o=l(n,t.language,i.DateTimeFormat);return new r.DateTimeFormat(t.language,o).format(a)})),e.registerHelper("_dateAdd",(function(e,n,a){if("number"!=typeof e&&"string"!=typeof e)throw new Error('@ handlebars-i18n: invalid first argument "dateInput" was given for _dateAdd.');if("number"!=typeof n)throw new Error('@ handlebars-i18n: invalid second argument "offset" was given for _dateAdd.');const o=d(e),s=l(a,t.language,i.DateTimeFormat);switch(s.unit=s.unit||"hour",s.unit){case"second":case"seconds":o.setSeconds(o.getSeconds()+n);break;case"minute":case"minutes":o.setMinutes(o.getMinutes()+n);break;case"hour":case"hours":o.setHours(o.getHours()+n);break;case"day":case"days":o.setDate(o.getDate()+n);break;case"week":case"weeks":o.setDate(o.getDate()+7*n);break;case"month":case"months":o.setMonth(o.getMonth()+n);break;case"quarter":case"quarters":o.setMonth(o.getMonth()+3*n);break;case"year":case"years":o.setFullYear(o.getFullYear()+n);break;default:throw new Error('@ handlebars-i18n: invalid argument "unit" was given for _dateAdd.Unit must be either "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year".')}return new r.DateTimeFormat(t.language,s).format(o)})),e.registerHelper("_dateRel",(function(e,r){const n=parseInt(e),a=l(r,t.language,i.RelativeTimeFormat);return f(t.language,a).format(n,a.unit)})),e.registerHelper("_dateDiff",(function(e,r,n){let a,o=l(n,t.language,i.RelativeTimeFormat);if(!g(e))return console.error("@ handlebars-i18n: invalid first argument dateInputA was given for _dateDiff."),null;r=r||"now",a=d(e)-d(r);const s=b(a,o.unit);return f(t.language,o).format(s,o.unit)})),e.registerHelper("_num",(function(e,n){let a=l(n,t.language,i.NumberFormat);return new r.NumberFormat(t.language,a).format(e)})),e.registerHelper("_price",(function(e,n){let a=l(n,t.language,i.PriceFormat);"string"!=typeof a.style&&"string"==typeof a.currency&&(a.style="currency");return new r.NumberFormat(t.language,a).format(e)})),e},...a&&{private:{applyToConstructor:u,configLookup:l,validateArgs:c,setArgs:m,isNumOrString:g,createDateObj:d,getRelDateFormatPolyfill:f,getDateDiff:b}}}})); \ No newline at end of file From 6b100572eeaf443f8feb134780a7a63f8b91208a Mon Sep 17 00:00:00 2001 From: FloWa Date: Tue, 3 Sep 2024 08:35:02 +0200 Subject: [PATCH 10/14] feat/doc: extended browser example index.html, added description of _dateAdd to readme.md --- examples/browser-example/index.html | 24 +++++++++++++++++------- readme.md | 13 +++++++++---- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/examples/browser-example/index.html b/examples/browser-example/index.html index 678db4e..10fd7da 100644 --- a/examples/browser-example/index.html +++ b/examples/browser-example/index.html @@ -218,6 +218,22 @@

Relative date representation

+

Date with positive time offset:

+ {{{{raw}}}} {{_dateAdd "December 17, 1995" 24 unit="hour"}} {{{{/raw}}}} +

→ {{_dateAdd "December 17, 1995 08:00:00" 24 unit="hour"}}

+ +

Date with negative time offset:

+ {{{{raw}}}} {{_dateAdd "December 17, 1995" -10 unit="day"}} {{{{/raw}}}} +

→ {{_dateAdd "December 17, 1995" -10 unit="day"}}

+ +

Relative difference between two dates:

+ {{{{raw}}}} {{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}} {{{{/raw}}}} +

→ {{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}}

+ +

Relative difference between two dates with custom configuration (subset "date-rel-spec"):

+ {{{{raw}}}} {{_dateDiff myDate "1995-12-17T00:00:00" format="date-rel-spec"}} {{{{/raw}}}} +

→ {{_dateDiff myDate "1995-12-17T00:00:00" format="date-rel-spec"}}

+

Relative date event in the future:

{{{{raw}}}} {{_dateRel 7 unit="hour"}} {{{{/raw}}}}

→ {{_dateRel 7 unit="hour"}}

@@ -226,13 +242,7 @@

Relative date event in the past:

{{{{raw}}}} {{_dateRel 7 unit="hour"}} {{{{/raw}}}}

→ {{_dateRel -7 unit="hour"}}

-

Date difference:

- {{{{raw}}}} {{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}} {{{{/raw}}}} -

→ {{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}}

- -

Date difference by custom configuration (subset "date-rel-spec"):

- {{{{raw}}}} {{_dateDiff mydate "1995-12-17T00:00:00" format="date-rel-spec"}} {{{{/raw}}}} -

→ {{_dateDiff mydate "1995-12-17T00:00:00" format="date-rel-spec"}}

+ {{_dateAdd "1996-12-17" 24 unit="hour"}}

 

`; diff --git a/readme.md b/readme.md index 418789b..af9939f 100644 --- a/readme.md +++ b/readme.md @@ -305,16 +305,21 @@ in [handlebars-i18n.d.ts](./dist/handlebars-i18n.d.ts). Adds a time offset in a given unit to a date, returns the modified date. ``` -{{_dateAdd "1996-12-17T00:00:00" 24 unit="hour"}} +{{_dateAdd "1996-12-17" 24 unit="hour"}} ``` +Will output for "en" → **12/18/1996** +The first argument is a date (see function **_date** for valid date inputs). The second argument is a time amount given +as number. The option **unit** specifies the time amount. Possible units +are `"second"` | `"minute"` | `"hour"` | `"day"` | `"week"` | `"month"` | `"quarter"` |`"year"` (default is `"hour"`). +Further options as for function **_date** can be applied. --- ### _dateDiff -Outputs the time difference between two given dates. +Outputs the relative time difference between two given dates. ``` {{_dateDiff "1996-12-17T00:00:00" "1995-12-17T00:00:00" unit="year"}} @@ -323,8 +328,8 @@ Outputs the time difference between two given dates. Will output for "en" → **in 1 year** The second date argument is subtracted from the first. If the difference is a positive value, a future event statement -is made. A negative value refers to a past date. Allowed date input formats are similar to *_date*, options equal -**_dateRel**. Default unit is `"hour"`. +is made. A negative value refers to a past date. (If no second argument is given, the default date is the present moment). +Allowed date input formats are similar to **_date**, options equal **_dateRel**. Default unit is `"hour"`. --- From 54d66f093f4622961d063569ef170e5d2426e965 Mon Sep 17 00:00:00 2001 From: FloWa Date: Tue, 3 Sep 2024 08:46:05 +0200 Subject: [PATCH 11/14] doc: fixed typos in readme.md --- examples/browser-example/index.html | 4 +--- readme.md | 10 ++++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/browser-example/index.html b/examples/browser-example/index.html index 10fd7da..30e38ed 100644 --- a/examples/browser-example/index.html +++ b/examples/browser-example/index.html @@ -242,9 +242,7 @@

Relative date event in the past:

{{{{raw}}}} {{_dateRel 7 unit="hour"}} {{{{/raw}}}}

→ {{_dateRel -7 unit="hour"}}

- {{_dateAdd "1996-12-17" 24 unit="hour"}} - -

 

`; + `; // -- Ignore this. It’s just a helper to display un-rendered {{handlebars code}} between the Tags Handlebars.registerHelper('raw', function(options) { diff --git a/readme.md b/readme.md index af9939f..b88d40c 100644 --- a/readme.md +++ b/readme.md @@ -359,8 +359,8 @@ Alternatively check this repo’s TS types in [handlebars-i18n.d.ts](./dist/hand ### _num -Outputs a formatted number according to the language specific conventions of number representation, e.g. * -*4,100,000.8314** for "**en**", but **4.100.000,8314** for "**de**". +Outputs a formatted number according to the language specific conventions of number representation, e.g. +**4,100,000.8314** for "**en**", but **4.100.000,8314** for "**de**". ``` {{_num 4100000.8314 }} @@ -383,8 +383,8 @@ Will output **3.14** for "**en**", but **3,14** for "**de**". ### _price -Outputs a formatted currency string according to the language specific conventions of price representation, e.g. * -*€9,999.99** for "**en**", but **9.999,99 €** for "**de**". +Outputs a formatted currency string according to the language specific conventions of price representation, e.g. +**€9,999.99** for "**en**", but **9.999,99 €** for "**de**". ``` {{_price 9999.99}} @@ -456,6 +456,8 @@ Call a subset in template with the parameter format="custom-name", like: {{_date myDate format="year-only"}} ``` +Subsets must be defined per language, a subset for "all" is invalid. + ### The lookup cascade The general lookup cascade is: From 60d776ae2dfc5e7c0ab665231e979097d96e15c0 Mon Sep 17 00:00:00 2001 From: FloWa Date: Tue, 3 Sep 2024 08:51:15 +0200 Subject: [PATCH 12/14] doc: removed obsolete install explanation in readme.md --- readme.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/readme.md b/readme.md index b88d40c..8b9ab19 100644 --- a/readme.md +++ b/readme.md @@ -28,16 +28,8 @@ If you use handlebars-i18n in a professional context, you could ## Install -If you use version npm >= 7: - -```bash -$ npm i handlebars-i18n -``` - -For older versions do: - ```bash -$ npm i handlebars-i18n handlebars@4.7.6 i18next@20.2.1 intl@1.2.5 +npm i handlebars-i18n ``` ## Usage @@ -147,7 +139,7 @@ Finally use in template: * returns for "en" → **$1,200.99** -## Further examples +## Detailed examples :point_right: See the *examples folder* in the repo for more use cases and details. From 82ba739aec703612cbb652d17e9aaf0e990086b6 Mon Sep 17 00:00:00 2001 From: FloWa Date: Tue, 3 Sep 2024 14:11:19 +0200 Subject: [PATCH 13/14] doc: added _dateAdd to /node-example and /typescript in examples folder --- examples/node-example/simple-example.js | 158 +++++++++++++----------- examples/typescript/test.hbs | 20 +-- 2 files changed, 100 insertions(+), 78 deletions(-) diff --git a/examples/node-example/simple-example.js b/examples/node-example/simple-example.js index e9a4496..92e8749 100644 --- a/examples/node-example/simple-example.js +++ b/examples/node-example/simple-example.js @@ -18,9 +18,9 @@ const htmlEntities = require('html-entities'); // -- The translation phrases for i18next i18next .init({ - resources : { - 'en' : { - translation : { + resources: { + 'en': { + translation: { 'key0': 'Change Language to', 'key1': 'What is good?', 'key2': '{{what}} is good.', @@ -29,7 +29,7 @@ i18next 'key4': 'Selected Language is:' } }, - 'de' : { + 'de': { translation: { 'key0': 'Sprache wechseln zu', 'key1': 'Was ist gut?', @@ -40,16 +40,16 @@ i18next } } }, - lng : 'en', + lng: 'en', compatibilityJSON: 'v2' }); // -- Handlebars' example data object let data = { - sayWhat : 'handlebars-i18n', - holdKey3 : 'key3WithCount', - holdKey4 : 'key4', - mynumber : 33.333, + sayWhat: 'handlebars-i18n', + holdKey3: 'key3WithCount', + holdKey4: 'key4', + mynumber: 33.333, myMmaxDigits: 1, myPrice: 12.99, myDate: '2020-03-11T03:24:00' @@ -59,23 +59,30 @@ let data = { HandlebarsI18n.init(); HandlebarsI18n.configure([ // generic configuration for all languages for number representation: - ['all', 'NumberFormat', { minimumFractionDigits: 2 }], + ['all', 'NumberFormat', {minimumFractionDigits: 2}], // generic configurations per language for price representation: - ['en', 'PriceFormat', { currency: 'USD'}], - ['de', 'PriceFormat', { currency: 'EUR'}], + ['en', 'PriceFormat', {currency: 'USD'}], + ['de', 'PriceFormat', {currency: 'EUR'}], // generic configurations per language for date representation: - ['en', 'DateTimeFormat', { year:'numeric', month:'long', day:'numeric', hour:'numeric', minute:'numeric'}], - ['de', 'DateTimeFormat', { year:'numeric', month:'numeric', day:'numeric', hour:'numeric', minute:'numeric', hour12:false}], + ['en', 'DateTimeFormat', {year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'}], + ['de', 'DateTimeFormat', { + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + hour12: false + }], // configurations per language with custom formats for date: - ['en', 'DateTimeFormat', { year:'numeric' }, 'custom-year-only'], - ['de', 'DateTimeFormat', { year:'numeric' }, 'custom-year-only'], - ['en', 'DateTimeFormat', { year:'numeric', month:'numeric', day:'numeric' }, 'custom-date-short'], - ['de', 'DateTimeFormat', { year:'numeric', month:'numeric', day:'numeric' }, 'custom-date-short'], - ['en', 'DateTimeFormat', { hour:'numeric', minute:'numeric', second:'numeric', hour12:false}, 'custom-time'], - ['de', 'DateTimeFormat', { hour:'numeric', minute:'numeric', second:'numeric', hour12:false}, 'custom-time'], + ['en', 'DateTimeFormat', {year: 'numeric'}, 'custom-year-only'], + ['de', 'DateTimeFormat', {year: 'numeric'}, 'custom-year-only'], + ['en', 'DateTimeFormat', {year: 'numeric', month: 'numeric', day: 'numeric'}, 'custom-date-short'], + ['de', 'DateTimeFormat', {year: 'numeric', month: 'numeric', day: 'numeric'}, 'custom-date-short'], + ['en', 'DateTimeFormat', {hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false}, 'custom-time'], + ['de', 'DateTimeFormat', {hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false}, 'custom-time'], // custom formats for relative dates: - ['en', 'RelativeTimeFormat', { style: 'short', unit: 'year' }, 'date-rel-spec'], - ['de', 'RelativeTimeFormat', { style: 'short', unit: 'year' }, 'date-rel-spec'] + ['en', 'RelativeTimeFormat', {style: 'short', unit: 'year'}, 'date-rel-spec'], + ['de', 'RelativeTimeFormat', {style: 'short', unit: 'year'}, 'date-rel-spec'] ]); let template; @@ -120,107 +127,116 @@ template += '{{__ "key1" lng="de"}}'; // ---------------------------------------- // Translation key given through handlebars variable and _locale output: -template += raw('{{__ holdKey4}} {{_locale}}'); -template += '{{__ holdKey4}} {{_locale}}'; + template += raw('{{__ holdKey4}} {{_locale}}'); + template += '{{__ holdKey4}} {{_locale}}'; // Check against selected language: -template += raw('{{#if (localeIs "en")}}English {{else}}Deutsch {{/if}}'); -template += '{{#if (localeIs "en")}}English {{else}}Deutsch {{/if}}'; + template += raw('{{#if (localeIs "en")}}English {{else}}Deutsch {{/if}}'); + template += '{{#if (localeIs "en")}}English {{else}}Deutsch {{/if}}'; // Number representation // ---------------------------------------- // Number representation as configured for all languages: -template += raw('{{_num 7000}}'); -template += '{{_num 7000}}'; + template += raw('{{_num 7000}}'); + template += '{{_num 7000}}'; // Number representation with specific format attribute: -template += raw('{{_num 3.1415926 maximumFractionDigits=0}}'); -template += '{{_num 3.1415926 maximumFractionDigits=0}}'; + template += raw('{{_num 3.1415926 maximumFractionDigits=0}}'); + template += '{{_num 3.1415926 maximumFractionDigits=0}}'; // Number and attribute given through handlebars variables: -template += raw('{{_num mynumber maximumFractionDigits=myMaxDigits}}'); -template += '{{_num mynumber maximumFractionDigits=myMaxDigits}}'; + template += raw('{{_num mynumber maximumFractionDigits=myMaxDigits}}'); + template += '{{_num mynumber maximumFractionDigits=myMaxDigits}}'; // Price representation // ---------------------------------------- // Price representation as configured per language: -template += raw('{{_price 9999.99}}'); -template += '{{_price 9999.99}}'; + template += raw('{{_price 9999.99}}'); + template += '{{_price 9999.99}}'; // Price representation with specific format attributes: -template += raw('{{_price 1000.99 currency="JPY" minimumFractionDigits=0}}'); -template += '{{_price 1000.99 currency="JPY" minimumFractionDigits=0}}'; + template += raw('{{_price 1000.99 currency="JPY" minimumFractionDigits=0}}'); + template += '{{_price 1000.99 currency="JPY" minimumFractionDigits=0}}'; // Price given through handlebars variable and with specific format attribute: -template += raw('{{_price myPrice currency="DKK"}}'); -template += '{{_price myPrice currency="DKK"}}'; + template += raw('{{_price myPrice currency="DKK"}}'); + template += '{{_price myPrice currency="DKK"}}'; // Date representation // ---------------------------------------- // Todays’ date as configured per language: -template += raw('{{_date}}'); -template += '{{_date}}'; + template += raw('{{_date}}'); + template += '{{_date}}'; // Date given as date string: -template += raw('{{_date "2020-03-11T03:24:00"}}'); -template += '{{_date "2020-03-11T03:24:00"}}'; + template += raw('{{_date "2020-03-11T03:24:00"}}'); + template += '{{_date "2020-03-11T03:24:00"}}'; // Date given in milliseconds since begin of unix epoch: -template += raw('{{_date 1583922952743}}'); -template += '{{_date 1583922952743}}'; + template += raw('{{_date 1583922952743}}'); + template += '{{_date 1583922952743}}'; // Date given as javascript date parameter array: -template += raw('{{_date "[2012, 11, 20, 3, 0, 0]"}}'); -template += '{{_date "[2012, 11, 20, 3, 0, 0]"}}'; + template += raw('{{_date "[2012, 11, 20, 3, 0, 0]"}}'); + template += '{{_date "[2012, 11, 20, 3, 0, 0]"}}'; // Todays’ date with specific format attributes: -template += raw('{{_date "today" year="2-digit" month="2-digit" day="2-digit"}}'); -template += '{{_date "today" year="2-digit" month="2-digit" day="2-digit"}}'; + template += raw('{{_date "today" year="2-digit" month="2-digit" day="2-digit"}}'); + template += '{{_date "today" year="2-digit" month="2-digit" day="2-digit"}}'; // Date given through handlebars variable: -template += raw('{{_date myDate}}'); -template += '{{_date myDate}}'; + template += raw('{{_date myDate}}'); + template += '{{_date myDate}}'; // Date formatted by custom configuration (subset "custom-year-only"): -template += raw('{{_date myDate format="custom-year-only"}}'); -template += '{{_date myDate format="custom-year-only"}}'; + template += raw('{{_date myDate format="custom-year-only"}}'); + template += '{{_date myDate format="custom-year-only"}}'; // Date formatted by custom configuration (subset "custom-date-short"): -template += raw('{{_date myDate format="custom-date-short"}}'); -template += '{{_date myDate format="custom-date-short"}}'; + template += raw('{{_date myDate format="custom-date-short"}}'); + template += '{{_date myDate format="custom-date-short"}}'; // Date formatted by custom configuration (subset "custom-date-short"): -template += raw('{{_date myDate format="custom-time"}}'); -template += '{{_date myDate format="custom-time"}}'; + template += raw('{{_date myDate format="custom-time"}}'); + template += '{{_date myDate format="custom-time"}}'; // Relative date representation // ---------------------------------------- +// Date with positive time offset: + template += raw('{{_dateAdd "December 17, 1995 08:00:00" 24 unit="hour"}}'); + template += '{{_dateAdd "December 17, 1995 08:00:00" 24 unit="hour"}}'; + +// Date with negative time offset: + template += raw('{{_dateAdd "December 17, 1995" -10 unit="day"}}'); + template += '{{_dateAdd "December 17, 1995" -10 unit="day"}}'; + +// Relative difference between two dates: + template += raw('{{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}}'); + template += '{{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}}'; + +// Relative difference between two dates with custom configuration (subset "date-rel-spec"): + template += raw('{{_dateDiff myDate "1995-12-17T00:00:00" format="date-rel-spec"}}'); + template += '{{_dateDiff myDate "1995-12-17T00:00:00" format="date-rel-spec"}}'; + // Relative date event in the future: -template += raw('{{_dateRel 7 unit="hour"}}'); -template += '{{_dateRel 7 unit="hour"}}'; + template += raw('{{_dateRel 7 unit="hour"}}'); + template += '{{_dateRel 7 unit="hour"}}'; // Relative date event in the past: -template += raw('{{_dateRel -7 unit="hour"}}'); -template += '{{_dateRel -7 unit="hour"}}'; - -// Date difference: -template += raw('{{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}}'); -template += '{{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}}'; + template += raw('{{_dateRel -7 unit="hour"}}'); + template += '{{_dateRel -7 unit="hour"}}'; -// Date difference by custom configuration (subset "date-rel-spec"): -template += raw('{{_dateDiff mydate "1995-12-17T00:00:00" format="date-rel-spec"}}'); -template += '{{_dateDiff mydate "1995-12-17T00:00:00" format="date-rel-spec"}}'; + const compiled = Handlebars.compile(template); + i18next.changeLanguage('de'); // --> Test the changes by replacing 'de' with 'en' -const compiled = Handlebars.compile(template); -i18next.changeLanguage('de'); // --> Test the changes by replacing 'de' with 'en' -const decoded = htmlEntities.decode(compiled(data)); + const decoded = htmlEntities.decode(compiled(data)); -console.log('\x1b[36m%s\x1b[0m', decoded); \ No newline at end of file + console.log('\x1b[36m%s\x1b[0m', decoded); \ No newline at end of file diff --git a/examples/typescript/test.hbs b/examples/typescript/test.hbs index 2f2246c..a5f0971 100644 --- a/examples/typescript/test.hbs +++ b/examples/typescript/test.hbs @@ -86,14 +86,20 @@ HandlebarsI18n example output from TS: // Relative date representation // ---------------------------------------- -// Relative date event in the future: -{{_dateRel 7 unit="hour"}} +// Date with positive time offset: +{{_dateAdd "December 17, 1995 08:00:00" 24 unit="hour"}} -// Relative date event in the past: -{{_dateRel -7 unit="hour"}} +// Date with negative time offset: +{{_dateAdd "December 17, 1995" -10 unit="day"}} -// Date difference: +// Relative difference between two dates: {{_dateDiff "1996-12-07T00:00:00" "1996-12-08T00:00:00" unit="day"}} -// Date difference by custom configuration (subset "date-rel-spec"): -{{_dateDiff mydate "1995-12-17T00:00:00" format="date-rel-spec"}} \ No newline at end of file +// Relative difference between two dates with custom configuration (subset "date-rel-spec"): +{{_dateDiff myDate "1995-12-17T00:00:00" format="date-rel-spec"}} + +// Relative date event in the future: +{{_dateRel 7 unit="hour"}} + +// Relative date event in the past: +{{_dateRel -7 unit="hour"}} \ No newline at end of file From 5a0e2f8490819bd141432e0b84e6162d08fa0288 Mon Sep 17 00:00:00 2001 From: FloWa Date: Tue, 3 Sep 2024 14:11:45 +0200 Subject: [PATCH 14/14] 1.8.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c6c4edc..1e784b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "handlebars-i18n", - "version": "1.7.1", + "version": "1.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "handlebars-i18n", - "version": "1.7.1", + "version": "1.8.0", "license": "MIT", "dependencies": { "handlebars": "^4.7.7", diff --git a/package.json b/package.json index 1ddfd21..6739529 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "handlebars-i18n", - "version": "1.7.1", + "version": "1.8.0", "description": "handlebars-i18n adds internationalization to handlebars.js using i18next and Intl.", "main": "dist/handlebars-i18n.js", "scripts": {