@brightspace-ui/intl 3.17.1 → 3.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -1
- package/lib/localize.js +9 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ const value = parseNumber('-8 942,39'); // -> -8942.39 in fr-CA
|
|
|
77
77
|
|
|
78
78
|
## Date/Time Formatting
|
|
79
79
|
|
|
80
|
-
Dates and times can be formatted in the user's locale using `formatDate`, `formatTime` and `
|
|
80
|
+
Dates and times can be formatted in the user's locale using `formatDate`, `formatTime`, `formatDateTime`, and `formatRelativeDateTime`.
|
|
81
81
|
|
|
82
82
|
Timestamps (milliseconds since the epoch) can be formatted in the user's locale and timezone using `formatDateTimeFromTimestamp`.
|
|
83
83
|
|
|
@@ -173,6 +173,16 @@ Options:
|
|
|
173
173
|
- **full**: includes timezone. e.g. `'1:25 PM EST'`
|
|
174
174
|
- **medium** or **short**: excludes timezone e.g. `'1:25 PM'`
|
|
175
175
|
|
|
176
|
+
To format a date/time in relative time, use `formatRelativeDateTime`:
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
import { formatRelativeDateTime } from '@brightspace-ui/intl/lib/dateTime.js';
|
|
180
|
+
|
|
181
|
+
const relativeDateTime = formatRelativeDateTime(
|
|
182
|
+
new Date(2024, 8, 18)
|
|
183
|
+
); // If today is 2024-08-22, -> 'last week' in en-US
|
|
184
|
+
```
|
|
185
|
+
|
|
176
186
|
## Date Parsing
|
|
177
187
|
|
|
178
188
|
To parse a date written in the user's locale, use `parseDate`:
|
|
@@ -258,6 +268,124 @@ const separator = getSeparator({ nonBreaking: true }); // -> ',\xa0' in en-US
|
|
|
258
268
|
Options:
|
|
259
269
|
- **nonBreaking**: a Boolean flag, whether to use non-breaking spaces instead of standard spaces; default is `false`
|
|
260
270
|
|
|
271
|
+
## Language Localization
|
|
272
|
+
|
|
273
|
+
The `Localize` class allows text to be displayed in the user's preferred language.
|
|
274
|
+
|
|
275
|
+
### Resources
|
|
276
|
+
|
|
277
|
+
Each resource is comprised of a name and a message, which must be provided as a key-value pair in a JavaScript object:
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
{ myMessage: "This is my message" }
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### Name
|
|
284
|
+
|
|
285
|
+
Names should succinctly and uniquely describe the text being localized. `camelCase` is recommended, although `snake_case` and `kebab-case` are also supported.
|
|
286
|
+
|
|
287
|
+
For large projects, resources may be grouped using the `:` character. For example: `parentGroup:subGroup:messageName`.
|
|
288
|
+
|
|
289
|
+
#### Message
|
|
290
|
+
|
|
291
|
+
Messages must conform to the [ICU Message Syntax](https://formatjs.io/docs/core-concepts/icu-syntax/) format. It supports features such as: [simple arguments](https://formatjs.io/docs/core-concepts/icu-syntax/#simple-argument), the [`select` format](https://formatjs.io/docs/core-concepts/icu-syntax/#select-format) and [pluralization](https://formatjs.io/docs/core-concepts/icu-syntax/#plural-format).
|
|
292
|
+
|
|
293
|
+
> **Note:** Avoid using the ICU Message Syntax number, date and time formatting functionality. Brightspace allows customization of how these are localized, so use `formatNumber`, `formatDate` and `formatTime` instead.
|
|
294
|
+
|
|
295
|
+
### Using `Localize`
|
|
296
|
+
|
|
297
|
+
Import `Localize` and create a new instance. The `importFunc` option is required. It will be passed a language tag which can be used to fetch resources:
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
import { Localize } from '@brightspace-ui/intl/lib/localize.js';
|
|
301
|
+
|
|
302
|
+
const localizer = new Localize({
|
|
303
|
+
importFunc: async lang => (await import(`../lang/${lang}.js`)).default
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Wait for resources to be available before attempting to use them:
|
|
308
|
+
```javascript
|
|
309
|
+
await localizer.ready;
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### `localize()`
|
|
313
|
+
|
|
314
|
+
The `localize()` method is used to localize a message.
|
|
315
|
+
|
|
316
|
+
If the message contains arguments, provide replacement values in the second parameter:
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
const helloText = localizer.localize('hello', { firstName: 'Mary' });
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### `localizeHTML()`
|
|
323
|
+
|
|
324
|
+
Rich formatting can be included in messages and safely converted to HTML with the `localizeHTML()` method.
|
|
325
|
+
|
|
326
|
+
#### Basic Formatting
|
|
327
|
+
|
|
328
|
+
The following formatting elements are supported out-of-the-box:
|
|
329
|
+
|
|
330
|
+
* `<p>paragraphs</p>`
|
|
331
|
+
* `line<br></br>breaks` (note the end tag is required)
|
|
332
|
+
* `<b>bold</b>`
|
|
333
|
+
* `<strong>strong</strong>`
|
|
334
|
+
* `<i>italic</i>`
|
|
335
|
+
* `<em>emphasis</em>`
|
|
336
|
+
|
|
337
|
+
Remember that `<strong>` is for content of greater importance (browsers show this visually using bold), while `<b>` only bolds the text visually without increasing its importance.
|
|
338
|
+
|
|
339
|
+
Similarly `<em>` *emphasizes* a particular piece of text (browsers show this visually using italics), whereas `<i>` only italicizes the text visually without emphasis.
|
|
340
|
+
|
|
341
|
+
Example:
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
{
|
|
345
|
+
myMessage: "This is <b>bold</b> but <em>not</em> all that <strong>important</strong>."
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Advanced Formatting
|
|
350
|
+
|
|
351
|
+
More advanced formatting can be achieved by providing replacement methods for custom tags, which are similar to arguments:
|
|
352
|
+
|
|
353
|
+
```javascript
|
|
354
|
+
{
|
|
355
|
+
goHome: "Go <homeLink>home</homeLink>"
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Then, import `localizeMarkup`:
|
|
360
|
+
```javascript
|
|
361
|
+
import { localizeMarkup } from '@brightspace-ui/intl/lib/localize.js';
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
and provide a tag replacement method:
|
|
365
|
+
```javascript
|
|
366
|
+
localizer.localizeHTML('goHome', {
|
|
367
|
+
homeLink: chunks => localizeMarkup`<d2l-link href="/home">${chunks}</d2l-link>`
|
|
368
|
+
});
|
|
369
|
+
```
|
|
370
|
+
In addition to the Basic Formatting elements, these additional elements may also be used in replacement methods:
|
|
371
|
+
|
|
372
|
+
* `<d2l-link>`
|
|
373
|
+
* `<d2l-tooltip-help>`
|
|
374
|
+
|
|
375
|
+
### `onResourcesChange`
|
|
376
|
+
Provide an `onResourcesChange` callback function to perform tasks when the document language is changed and updated resources are available:
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
const localizer = new Localize({
|
|
380
|
+
onResourcesChange: () => document.title = localizer.localize('pageTitle')
|
|
381
|
+
});
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
To stop listening for changes, disconnect the instance:
|
|
385
|
+
```javascript
|
|
386
|
+
localizer.disconnect()
|
|
387
|
+
```
|
|
388
|
+
|
|
261
389
|
## Developing and Contributing
|
|
262
390
|
|
|
263
391
|
After cloning the repo, run `npm install` to install dependencies.
|
package/lib/localize.js
CHANGED
|
@@ -41,8 +41,8 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e
|
|
|
41
41
|
const allResources = {};
|
|
42
42
|
const resolvedLocales = new Set();
|
|
43
43
|
for (const { language, resources } of localizeResources) {
|
|
44
|
-
for (const [
|
|
45
|
-
allResources[
|
|
44
|
+
for (const [name, value] of Object.entries(resources)) {
|
|
45
|
+
allResources[name] = { language, value };
|
|
46
46
|
resolvedLocales.add(language);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -80,15 +80,15 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e
|
|
|
80
80
|
this.#connected = false;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
localize(
|
|
83
|
+
localize(name, replacements) {
|
|
84
84
|
|
|
85
|
-
const { language, value } = this.localize.resources?.[
|
|
85
|
+
const { language, value } = this.localize.resources?.[name] ?? {};
|
|
86
86
|
if (!value) return '';
|
|
87
87
|
|
|
88
88
|
let params = {};
|
|
89
|
-
if (
|
|
89
|
+
if (replacements?.constructor === Object) {
|
|
90
90
|
// support for key-value replacements as a single arg
|
|
91
|
-
params =
|
|
91
|
+
params = replacements;
|
|
92
92
|
} else {
|
|
93
93
|
// legacy support for localize-behavior replacements as many args
|
|
94
94
|
for (let i = 1; i < arguments.length; i += 2) {
|
|
@@ -112,9 +112,9 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e
|
|
|
112
112
|
return formattedMessage;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
localizeHTML(
|
|
115
|
+
localizeHTML(name, replacements = {}) {
|
|
116
116
|
|
|
117
|
-
const { language, value } = this.localize.resources?.[
|
|
117
|
+
const { language, value } = this.localize.resources?.[name] ?? {};
|
|
118
118
|
if (!value) return '';
|
|
119
119
|
|
|
120
120
|
const translatedMessage = new IntlMessageFormat(value, language);
|
|
@@ -127,7 +127,7 @@ export const getLocalizeClass = (superclass = class {}) => class LocalizeClass e
|
|
|
127
127
|
i: chunks => LocalizeClass.#localizeMarkup`<i>${chunks}</i>`,
|
|
128
128
|
p: chunks => LocalizeClass.#localizeMarkup`<p>${chunks}</p>`,
|
|
129
129
|
strong: chunks => LocalizeClass.#localizeMarkup`<strong>${chunks}</strong>`,
|
|
130
|
-
...
|
|
130
|
+
...replacements
|
|
131
131
|
});
|
|
132
132
|
validateMarkup(unvalidated);
|
|
133
133
|
formattedMessage = unvalidated;
|
package/package.json
CHANGED