Skip to content

Commit f022efd

Browse files
authored
Merge pull request #4 from telerik/exception-handling
Improve error handling
2 parents c3f3a21 + 3647f44 commit f022efd

File tree

15 files changed

+284
-15
lines changed

15 files changed

+284
-15
lines changed

docs/cldr/index.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ The table below lists the data which is required for number and date formatting
1818

1919
| FORMATS | REQUIRED DATA |
2020
|:--- |:--- |
21-
| Any | `cldr/supplemental/likelySubtags.json` |
21+
| Any | `cldr/supplemental/likelySubtags.json` |
2222
| Basic numbers | `cldr/main/locale/numbers.json` |
2323
| Currency | `cldr/main/locale/currencies.json` and `cldr/supplemental/currencyData.json` |
2424
| Basic dates | `cldr/main/locale/ca-gregorian.json` |
@@ -30,6 +30,34 @@ Unicode CLDR is available as JSON at [https://github.com/unicode-cldr/](https://
3030

3131
It is also available as a single [cldr-data](https://www.npmjs.com/package/cldr-data) package.
3232

33+
## Loading CLDR Data
34+
35+
Load the CLDR data using the [`load`]({% cldrapi_internalization %}#load) method.
36+
37+
```
38+
import { cldr, load } from '@telerik/kendo-intl';
39+
40+
const likelySubtags = require("cldr-data/supplemental/likelySubtags.json");
41+
const numbers = require("cldr-data/main/bg/numbers.json");
42+
const timeZoneNames = require("cldr-data/main/bg/timeZoneNames.json");
43+
const calendar = require("cldr-data/main/bg/ca-gregorian.json");
44+
const currencies = require("cldr-data/main/bg/currencies.json");
45+
const weekData = require("cldr-data/supplemental/weekData.json");
46+
const currencyData = require("cldr-data/supplemental/currencyData.json");
47+
48+
load(
49+
likelySubtags,
50+
weekData,
51+
currencyData,
52+
numbers,
53+
currencies,
54+
calendar,
55+
timeZoneNames
56+
);
57+
58+
//the `cldr` object will consist the loaded data
59+
```
60+
3361
## Suggested Links
3462

3563
* [API Reference of the CLDR Module]({% slug cldrapi_internalization %})

docs/errors.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
title: Errors
3+
page_title: Errors | Kendo UI Internationalization Package
4+
description: "List of possible exceptions that the package could throw."
5+
slug: errors_internalization_kendoui
6+
position: 6
7+
---
8+
9+
# Errors list
10+
11+
Below is the list of all controlled errors that could be thrown:
12+
13+
| Type | Message
14+
|:--- |:---
15+
|`NoLocaleError` | Missing locale info for {locale}
16+
|`NoCurrencyError` | Cannot determine currency information. Please load the locale currencies data.
17+
|`NoSupplementalCurrencyError` | Cannot determine currency. Please load the supplemental currencyData.
18+
|`NoCurrencyRegionError` | No currency data for region ${territory}
19+
|`NoCurrencyDisplay` | Cannot determine currency display information. Please load the locale currencies data. The default culture does not include the all currencies data.
20+
|`NoGMTInfoError` | Cannot determine locale GMT format. Please load the locale timeZoneNames data.
21+
|`NoWeekDataError` | Cannot determine locale first day of week. Please load the supplemental weekData.
22+
|`NoFirstDayError` | Cannot determine locale first day of week. The default culture data includes only en-US first day info. Please load the supplemental weekData.
23+
24+
## Suggested Links
25+
26+
Articles on the Kendo UI Internationalization components:
27+
28+
* [Get Started with CLDR]({% slug cldrdata_overview_internalization %})
29+
* [Get Started with Date Parsing]({% slug dateparsing_internalization %})
30+
* [Get Started with Date Formatting]({% slug dateformatting_internalization %})
31+
* [Get Started with Number Parsing]({% slug numberparsing_internalization %})
32+
* [Get Started with Number Formatting]({% slug numbeformatting_internalization %})

src/cldr/currency.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { cldr, getLocaleInfo } from './info';
22
import localeTerritory from './territory';
3+
import { errors } from '../errors';
4+
5+
const {
6+
NoCurrency,
7+
NoCurrencyDisplay,
8+
NoSupplementalCurrency,
9+
NoCurrencyRegion
10+
} = errors;
311

412
const DEFAULT_CURRENCY_FRACTIONS = 2;
513
const SYMBOL = "symbol";
@@ -8,10 +16,16 @@ function getCurrencyInfo(locale, currency) {
816
const info = getLocaleInfo(locale);
917
const currencies = info.numbers.currencies;
1018
if (!currencies) {
11-
throw new Error("Cannot determine currency information. Please load the locale currencies data.");
19+
throw NoCurrency.error();
20+
}
21+
22+
const currencyDisplayInfo = currencies[currency];
23+
24+
if (!currencyDisplayInfo) {
25+
throw NoCurrencyDisplay.error();
1226
}
1327

14-
return currencies[currency];
28+
return currencyDisplayInfo;
1529
}
1630

1731
function lengthComparer(a, b) {
@@ -74,12 +88,12 @@ export function currencyFractionOptions(code) {
7488
export function territoryCurrencyCode(territory) {
7589
const currencyData = cldr.supplemental.currencyData;
7690
if (!currencyData) {
77-
throw new Error("Cannot determine currency. Please load the supplemental currencyData.");
91+
throw NoSupplementalCurrency.error();
7892
}
7993

8094
const regionCurrencies = currencyData.region[territory];
8195
if (!regionCurrencies) {
82-
throw new Error("No currency data for region " + territory);
96+
throw NoCurrencyRegion.error();
8397
}
8498
const currencyCode = Object.keys(regionCurrencies[regionCurrencies.length - 1])[0];
8599

src/cldr/first-day.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import { cldr, getLocaleInfo } from './info';
22
import localeTerritory from './territory';
33

4+
import { errors } from '../errors';
5+
6+
const { NoWeekData, NoFirstDay } = errors;
7+
48
const DAYS = [ "sun", "mon", "tue", "wed", "thu", "fri", "sat" ];
59

610
export default function firstDay(locale) {
711
const weekData = cldr.supplemental.weekData;
812
if (!weekData) {
9-
throw new Error("Cannot determine locale first day of week. Please load the supplemental weekData.");
13+
throw NoWeekData.error();
1014
}
1115

1216
const info = getLocaleInfo(locale);
1317
const firstDay = weekData.firstDay[localeTerritory(info)];
1418

19+
if (!firstDay) {
20+
throw NoFirstDay.error();
21+
}
22+
1523
return DAYS.indexOf(firstDay);
16-
}
24+
}

src/cldr/info.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import defaultData from './default-data';
2+
import { errors } from '../errors';
23

34
function availableLocaleInfo(fullName, suffixes) {
45
const parts = fullName.split("-");
@@ -53,5 +54,5 @@ export function localeInfo(locale) {
5354
}
5455
}
5556

56-
throw new Error("Missing locale info for: " + locale);
57-
}
57+
throw errors.NoLocale.error(locale);
58+
}

src/cldr/territory.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ export default function localeTerritory(info) {
2929
info.territory = territory;
3030

3131
return territory;
32-
}
32+
}

src/dates/parse-date.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { adjustDST, convertTimeZone } from './time-utils';
22
import { localeInfo } from '../cldr';
3+
import { errors } from '../errors';
34
import formatNames from './format-names';
45
import datePattern from './date-pattern';
56
import round from '../common/round';
@@ -112,7 +113,7 @@ function checkLiteral(state) {
112113
function calendarGmtFormats(calendar) {
113114
const { gmtFormat, gmtZeroFormat } = calendar;
114115
if (!gmtFormat) {
115-
throw new Error("Cannot determine locale GMT format. Please load the locale timeZoneNames data.");
116+
throw errors.NoGMTInfo.error();
116117
}
117118

118119
return [ gmtFormat.replace(PLACEHOLDER, "").toLowerCase(), gmtZeroFormat.replace(PLACEHOLDER, "").toLowerCase() ];
@@ -549,4 +550,4 @@ export default function parseDate(value, formats, locale = "en") {
549550
}
550551

551552
return date;
552-
}
553+
}

src/error-details.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//The error is represented by unique name and corresponding message
2+
//The message can contain placeholders with index, e.g. {0}, {1}
3+
4+
export default {
5+
"NoLocale": "Missing locale info for '{0}'",
6+
"NoCurrency": "Cannot determine currency information. Please load the locale currencies data.",
7+
"NoSupplementalCurrency": "Cannot determine currency. Please load the supplemental currencyData.",
8+
"NoCurrencyRegion": "No currency data for region '{0}'",
9+
"NoCurrencyDisplay": "Cannot determine currency display information. Please load the locale currencies data. The default culture does not include the all currencies data.",
10+
"NoGMTInfo": "Cannot determine locale GMT format. Please load the locale timeZoneNames data.",
11+
"NoWeekData": "Cannot determine locale first day of week. Please load the supplemental weekData.",
12+
"NoFirstDay": "Cannot determine locale first day of week. Please load the supplemental weekData. The default culture includes only the 'en-US' first day info."
13+
};

src/errors.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
declare class IntlError {
2+
name: string;
3+
message: string;
4+
constructor(error: { name: string, message: string });
5+
formatMessage(...values: any[]): string;
6+
error(...values: any[]): Error;
7+
}
8+
declare const errors: any;
9+
declare const toIntlErrors: (errors: { [x: string]: string; }) => { [x: string]: IntlError };
10+
11+
export { errors, IntlError, toIntlErrors };

src/errors.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import errorDetails from './error-details';
2+
3+
const formatRegExp = /\{(\d+)}?\}/g;
4+
5+
class IntlError {
6+
name = "";
7+
message = "";
8+
9+
constructor({ name, message }) {
10+
if (!name || !message) {
11+
throw new Error("{ name: string, message: string } object is required!");
12+
}
13+
14+
this.name = name;
15+
this.message = message;
16+
}
17+
18+
formatMessage(...values) {
19+
const flattenValues = flatten(values);
20+
21+
const formattedMessage = this.message.replace(formatRegExp, function(match, index) {
22+
return flattenValues[parseInt(index, 10)];
23+
});
24+
25+
return `${this.name}: ${formattedMessage}`;
26+
}
27+
28+
error(...values) {
29+
return new Error(this.formatMessage(values));
30+
}
31+
}
32+
33+
const flatten = function(arr) {
34+
return arr.reduce((a, b) => a.concat(b), []);
35+
};
36+
37+
const mapErrors = function(errors) {
38+
const predicate = function(prev, name) {
39+
prev[name] = new IntlError({ name, message: errors[name] });
40+
return prev;
41+
};
42+
43+
return Object.keys(errors).reduce(predicate, {});
44+
};
45+
46+
const errors = mapErrors(errorDetails);
47+
48+
export {
49+
errors,
50+
mapErrors,
51+
IntlError
52+
};

0 commit comments

Comments
 (0)