@brightspace-ui/core 2.106.0 → 2.107.1
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.
|
@@ -491,6 +491,13 @@ class InputText extends FocusMixin(LabelledMixin(FormElementMixin(SkeletonMixin(
|
|
|
491
491
|
const tooltip = this.shadowRoot.querySelector('d2l-tooltip');
|
|
492
492
|
tooltip.updatePosition();
|
|
493
493
|
}
|
|
494
|
+
} else if (prop === 'type') {
|
|
495
|
+
const input = this.shadowRoot?.querySelector('.d2l-input');
|
|
496
|
+
setTimeout(() => {
|
|
497
|
+
if (input && this.value !== input.value) {
|
|
498
|
+
this._setValue(input.value, false);
|
|
499
|
+
}
|
|
500
|
+
}, 0);
|
|
494
501
|
}
|
|
495
502
|
});
|
|
496
503
|
}
|
|
@@ -589,7 +596,7 @@ class InputText extends FocusMixin(LabelledMixin(FormElementMixin(SkeletonMixin(
|
|
|
589
596
|
this.focus();
|
|
590
597
|
}
|
|
591
598
|
|
|
592
|
-
_setValue(val, updateInput) {
|
|
599
|
+
async _setValue(val, updateInput) {
|
|
593
600
|
|
|
594
601
|
const oldVal = this.value;
|
|
595
602
|
this._prevValue = (oldVal === undefined) ? '' : oldVal;
|
|
@@ -599,16 +606,17 @@ class InputText extends FocusMixin(LabelledMixin(FormElementMixin(SkeletonMixin(
|
|
|
599
606
|
if (!input) return;
|
|
600
607
|
|
|
601
608
|
this.setValidity({ tooShort: this.minlength && this.value.length > 0 && this.value.length < this.minlength });
|
|
602
|
-
this.requestValidate(false);
|
|
603
609
|
this.setFormValue(this.value);
|
|
604
610
|
|
|
605
611
|
// Can't bind to input's value as Safari moves the cursor each time an
|
|
606
612
|
// input's value gets set from render(). So we manually reach in
|
|
607
613
|
// and update it when source of the change isn't the input itself.
|
|
608
614
|
if (updateInput) {
|
|
615
|
+
await this.updateComplete;
|
|
609
616
|
input.value = this.value;
|
|
610
617
|
}
|
|
611
618
|
|
|
619
|
+
this.requestValidate(false);
|
|
612
620
|
}
|
|
613
621
|
|
|
614
622
|
_suppressEvent(e) {
|
|
@@ -1,135 +1,84 @@
|
|
|
1
|
-
#
|
|
1
|
+
# LocalizeMixin
|
|
2
2
|
|
|
3
|
-
The `LocalizeMixin`
|
|
4
|
-
|
|
5
|
-
## Providing Resources
|
|
6
|
-
|
|
7
|
-
Your component must provide resources by either implementing a `resources` getter for local resources, or a `localizeConfig` getter to fetch resources asynchronously. The `importFunc` method of `localizeConfig` will be called with lowercase languages in preferential order.
|
|
3
|
+
The `LocalizeMixin` allows text in components to be displayed in the user's preferred language.
|
|
8
4
|
|
|
9
5
|
## Language Resources
|
|
10
6
|
|
|
11
|
-
Resources
|
|
7
|
+
Resources are stored as key-value JSON objects.
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
### Keys
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Example:
|
|
11
|
+
The key should succinctly and uniquely describe the text being localized. `camelCase` is recommended, although `snake_case` and `kebab-case` are also supported.
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
"hello": "Hello {firstName}!",
|
|
22
|
-
"goodbye": "Goodbye."
|
|
23
|
-
}
|
|
24
|
-
```
|
|
13
|
+
For large projects, terms may be grouped using the `:` character. For example: `parentGroup:subGroup:termName`.
|
|
25
14
|
|
|
26
|
-
|
|
15
|
+
### Values
|
|
27
16
|
|
|
28
|
-
|
|
17
|
+
Term values 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).
|
|
29
18
|
|
|
30
|
-
|
|
19
|
+
> **Note:** Avoid using the ICU Message Syntax number, date and time formatting functionality. Brightspace allows customization of how these are localized, so use [@brightspace-ui/intl](https://github.com/BrightspaceUI/intl)'s `formatNumber`, `formatDate` and `formatTime` instead.
|
|
31
20
|
|
|
32
|
-
|
|
21
|
+
### Files
|
|
33
22
|
|
|
34
|
-
|
|
23
|
+
Store localization resources in their own directory with nothing else in it. There should be one JavaScript file for each supported locale.
|
|
35
24
|
|
|
36
25
|
```javascript
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
static get resources() {
|
|
42
|
-
return {
|
|
43
|
-
'en': {
|
|
44
|
-
hello: 'Hello {firstName}!'
|
|
45
|
-
},
|
|
46
|
-
'fr': {
|
|
47
|
-
hello: 'Bonjour {firstName}!'
|
|
48
|
-
},
|
|
49
|
-
...
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
}
|
|
26
|
+
// en.js
|
|
27
|
+
export default {
|
|
28
|
+
"hello": "Hello {firstName}!"
|
|
29
|
+
};
|
|
54
30
|
```
|
|
55
|
-
#### Example 2: Dynamically Imported Resources
|
|
56
|
-
|
|
57
|
-
This approach is better for components with many language resources. By importing them dynamically, only the resources for the requested language are actually fetched and downloaded.
|
|
58
|
-
|
|
59
|
-
Store your resources in individual files, one for each language:
|
|
60
31
|
```javascript
|
|
61
|
-
//
|
|
32
|
+
// fr.js
|
|
62
33
|
export default {
|
|
63
|
-
|
|
34
|
+
"hello": "Bonjour {firstName}!"
|
|
64
35
|
};
|
|
65
36
|
```
|
|
66
37
|
|
|
67
|
-
|
|
38
|
+
Always provide language resources for base languages (e.g. `en`, `fr`, `pt`). That way, if the user prefers a regional language (e.g. `pt-br`) that isn't recognized, it can fall back to the base language (`pt`).
|
|
39
|
+
|
|
40
|
+
## Using `LocalizeMixin`
|
|
41
|
+
|
|
42
|
+
The component should import and extend `LocalizeMixin`:
|
|
68
43
|
|
|
69
|
-
Then create your `localizeConfig` getter:
|
|
70
44
|
```javascript
|
|
71
45
|
import { LocalizeMixin } from '@brightspace-ui/core/mixins/localize/localize-mixin.js';
|
|
72
46
|
|
|
73
47
|
class MyComponent extends LocalizeMixin(LitElement) {
|
|
74
48
|
|
|
75
|
-
static get localizeConfig() {
|
|
76
|
-
return {
|
|
77
|
-
// Import path must be relative
|
|
78
|
-
importFunc: async lang => (await import(`../lang/${lang}.js`)).default,
|
|
79
|
-
// Optionally enable OSLO
|
|
80
|
-
osloCollection: '@d2l\\my-project\\myComponent',
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
49
|
}
|
|
84
50
|
```
|
|
85
|
-
Occasionally, it may be desirable to localize based on the user's browser settings. To do this, add `useBrowserLangs: true` to your `localizeConfig` object. This option should only be used if *all* supported *locales* have corresponding files named with their 4-character locale code, and all supported *languages*, in addition, have 2-character files. (e.g. `en-us.js`, `en-ca.js` and `en.js`)
|
|
86
51
|
|
|
87
|
-
|
|
52
|
+
Implement a static getter for `localizeConfig` that defines `importFunc()`. It will be passed a language which can subsequently be dynamically imported from the location of the component's resources.
|
|
53
|
+
|
|
54
|
+
The dynamic import path must be relative.
|
|
88
55
|
|
|
89
56
|
```javascript
|
|
90
57
|
static get localizeConfig() {
|
|
91
58
|
return {
|
|
92
|
-
importFunc: async lang => {
|
|
93
|
-
switch (lang) {
|
|
94
|
-
case 'en':
|
|
95
|
-
return (await import('./locales/en.js')).default;
|
|
96
|
-
case 'fr':
|
|
97
|
-
return (await import('./locales/fr.js')).default;
|
|
98
|
-
...
|
|
99
|
-
}
|
|
100
|
-
}
|
|
59
|
+
importFunc: async lang => (await import(`../lang/${lang}.js`)).default,
|
|
101
60
|
};
|
|
102
61
|
}
|
|
103
62
|
```
|
|
104
63
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```javascript
|
|
108
|
-
import { LocalizeCoreElement } from '@brightspace-ui/core/helpers/localize-core-element.js';
|
|
109
|
-
import { LocalizeMixin } from '@brightspace-ui/core/mixins/localize/localize-mixin.js';
|
|
110
|
-
|
|
111
|
-
class MyComponent extends LocalizeMixin(LocalizeCoreElement(LitElement)) {
|
|
112
|
-
...
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## `localize()`
|
|
64
|
+
### `localize()`
|
|
117
65
|
|
|
118
|
-
|
|
66
|
+
The `localize()` method is used to localize a piece of text in the component's `render()` method.
|
|
119
67
|
|
|
120
|
-
If
|
|
68
|
+
If the localized string contains arguments, pass them as a key-value object as the 2nd parameter:
|
|
121
69
|
|
|
122
70
|
```javascript
|
|
123
71
|
render() {
|
|
124
|
-
|
|
72
|
+
const message = this.localize('hello', { firstName: 'Mary' });
|
|
73
|
+
return html`<p>${message}</p>`;
|
|
125
74
|
}
|
|
126
75
|
```
|
|
127
76
|
|
|
128
|
-
|
|
77
|
+
### `localizeHTML()`
|
|
129
78
|
|
|
130
79
|
Rich formatting can be included in localization resources and safely converted to HTML with the `localizeHTML()` method.
|
|
131
80
|
|
|
132
|
-
|
|
81
|
+
#### Basic Formatting
|
|
133
82
|
|
|
134
83
|
The following formatting elements are supported out-of-the-box:
|
|
135
84
|
|
|
@@ -144,7 +93,19 @@ Remember that `<strong>` is for content of greater importance (browsers show thi
|
|
|
144
93
|
|
|
145
94
|
Similarly `<em>` *emphasizes* a particular piece of text (browsers show this visually using italics), whereas `<i>` only italicizes the text visually without emphasis.
|
|
146
95
|
|
|
147
|
-
|
|
96
|
+
Example:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"myTerm": "This is <b>bold</b> but <em>not</em> all that <strong>important</strong>."
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
this.localizeHTML('myTerm');
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### Links
|
|
148
109
|
|
|
149
110
|
To wrap text in [a link](../../components/link/), define a unique tag in the localization resource:
|
|
150
111
|
|
|
@@ -164,7 +125,7 @@ this.localizeHTML('myTerm', {
|
|
|
164
125
|
});
|
|
165
126
|
```
|
|
166
127
|
|
|
167
|
-
|
|
128
|
+
#### Help Tooltips
|
|
168
129
|
|
|
169
130
|
To use a [help tooltip](../../components/tooltip/), define a unique tag in the localization resource in addition to the tooltip's text:
|
|
170
131
|
|
|
@@ -175,7 +136,7 @@ To use a [help tooltip](../../components/tooltip/), define a unique tag in the l
|
|
|
175
136
|
}
|
|
176
137
|
```
|
|
177
138
|
|
|
178
|
-
Then import `generateTooltipHelp` and pass it the tooltip
|
|
139
|
+
Then import `generateTooltipHelp` and pass it the tooltip contents value:
|
|
179
140
|
|
|
180
141
|
```javascript
|
|
181
142
|
import { generateTooltipHelp } from '@brightspace-ui/core/mixins/localize/localize-mixin.js';
|
|
@@ -184,3 +145,38 @@ this.localizeHTML('octopus', {
|
|
|
184
145
|
tooltip: generateTooltipHelp({ contents: this.localize('cephalopodTooltip') })
|
|
185
146
|
});
|
|
186
147
|
```
|
|
148
|
+
|
|
149
|
+
## Off-Stack Language Overrides
|
|
150
|
+
|
|
151
|
+
To enable OSLO, map the project's localization resources to a language collection in Brightspace by defining `osloCollection` in `localizeConfig`:
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
static get localizeConfig() {
|
|
155
|
+
return {
|
|
156
|
+
osloCollection: '@d2l\\my-project\\myComponent',
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
> **Important:** When defining language resource keys, avoid using the Full Stop (`.`) character for grouping. OSLO does not support it.
|
|
162
|
+
|
|
163
|
+
## Advanced
|
|
164
|
+
|
|
165
|
+
### Chaining `LocalizeMixin`
|
|
166
|
+
|
|
167
|
+
If combining `LocalizeMixin` with `LocalizeCoreElement` (or a mixin that uses `LocalizeCoreElement`), `LocalizeMixin` **must** appear before `LocalizeCoreElement` in the chain.
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
import { LocalizeCoreElement } from '@brightspace-ui/core/helpers/localize-core-element.js';
|
|
171
|
+
import { LocalizeMixin } from '@brightspace-ui/core/mixins/localize/localize-mixin.js';
|
|
172
|
+
|
|
173
|
+
class MyComponent extends LocalizeMixin(LocalizeCoreElement(LitElement)) {
|
|
174
|
+
...
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Ignoring the Brightspace Language
|
|
179
|
+
|
|
180
|
+
Occasionally, it may be desirable to localize based on the browser's language instead of the language in Brightspace.
|
|
181
|
+
|
|
182
|
+
To do this, define `useBrowserLangs` as `true` in `localizeConfig`. This option should only be used if all supported locales have corresponding files named with their 4-character and 2-character locale codes (e.g. `en-us.js`, `en-ca.js` and `en.js`).
|
|
@@ -136,7 +136,7 @@ export const _LocalizeMixinBase = dedupeMixin(superclass => class LocalizeMixinC
|
|
|
136
136
|
const translatedMessage = new IntlMessageFormat(value, language);
|
|
137
137
|
let formattedMessage = value;
|
|
138
138
|
try {
|
|
139
|
-
|
|
139
|
+
const unvalidated = translatedMessage.format({
|
|
140
140
|
b: chunks => localizeMarkup`<b>${chunks}</b>`,
|
|
141
141
|
br: () => localizeMarkup`<br>`,
|
|
142
142
|
em: chunks => localizeMarkup`<em>${chunks}</em>`,
|
|
@@ -145,7 +145,8 @@ export const _LocalizeMixinBase = dedupeMixin(superclass => class LocalizeMixinC
|
|
|
145
145
|
strong: chunks => localizeMarkup`<strong>${chunks}</strong>`,
|
|
146
146
|
...params
|
|
147
147
|
});
|
|
148
|
-
validateMarkup(
|
|
148
|
+
validateMarkup(unvalidated);
|
|
149
|
+
formattedMessage = unvalidated;
|
|
149
150
|
} catch (e) {
|
|
150
151
|
console.error(e);
|
|
151
152
|
}
|
|
@@ -230,31 +231,6 @@ export const LocalizeMixin = superclass => class extends _LocalizeMixinBase(supe
|
|
|
230
231
|
|
|
231
232
|
};
|
|
232
233
|
|
|
233
|
-
export const LocalizeStaticMixin = superclass => class extends _LocalizeMixinBase(superclass) {
|
|
234
|
-
|
|
235
|
-
static async getLocalizeResources(langs) {
|
|
236
|
-
let resolvedLang = fallbackLang;
|
|
237
|
-
const resolvedResources = Object.assign({}, this.resources[fallbackLang]);
|
|
238
|
-
|
|
239
|
-
langs.reverse().forEach((lang) => {
|
|
240
|
-
if (this.resources[lang]) {
|
|
241
|
-
resolvedLang = lang;
|
|
242
|
-
Object.assign(resolvedResources, this.resources[lang]);
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
return {
|
|
247
|
-
language: resolvedLang,
|
|
248
|
-
resources: resolvedResources
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
static get resources() {
|
|
253
|
-
return { 'en': {} };
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
};
|
|
257
|
-
|
|
258
234
|
export const allowedTags = Object.freeze(['d2l-link', 'd2l-tooltip-help', 'p', 'br', 'b', 'strong', 'i', 'em']);
|
|
259
235
|
|
|
260
236
|
const markupError = `localizeHTML() rich-text replacements must use localizeMarkup templates with only the following allowed elements: ${allowedTags}. For more information, see: https://github.com/BrightspaceUI/core/blob/main/mixins/localize/`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.107.1",
|
|
4
4
|
"description": "A collection of accessible, free, open-source web components for building Brightspace applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/BrightspaceUI/core.git",
|