@brightspace-ui/core 2.106.0 → 2.107.0

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.
@@ -1,135 +1,84 @@
1
- # Localization Mixins
1
+ # LocalizeMixin
2
2
 
3
- The `LocalizeMixin` and `LocalizeStaticMixin` allow you to localize text in your components and have it displayed to the user in their preferred language.
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 should be key-value JSON objects, where the keys are lowercase strings and the values are in [ICU Message Syntax](https://formatjs.io/docs/core-concepts/icu-syntax/) format.
7
+ Resources are stored as key-value JSON objects.
12
8
 
13
- The ICU Message Syntax supports some cool 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).
9
+ ### Keys
14
10
 
15
- **Note:** Avoid using the ICU Message Syntax number, date and time formatting functionality. D2L allows our users to customize how these are localized, so use [@brightspace-ui/intl](https://github.com/BrightspaceUI/intl)'s `formatNumber`, `formatDate` and `formatTime` instead.
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
- ```javascript
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
- Always provide language resources for base languages (e.g. `en`, `fr`, `pt`, etc.). 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.
15
+ ### Values
27
16
 
28
- ### Static vs. Dynamic Resources
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
- For components with local resources, use the `LocalizeStaticMixin` and implement a `static` `resources` getter that returns the local resources synchronously. To get resources asynchronously, use the `LocalizeMixin` and implement a `static` `localizeConfig` getter that returns details about where to find your resources.
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
- #### Example 1: Static Resources
21
+ ### Files
33
22
 
34
- If your component has a small number of translations, it may make sense to store them locally within the component in a constant.
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
- import { LocalizeStaticMixin } from '@brightspace-ui/core/mixins/localize/localize-mixin.js';
38
-
39
- class MyComponent extends LocalizeStaticMixin(LitElement) {
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
- // en.js
32
+ // fr.js
62
33
  export default {
63
- 'hello': 'Hello {firstName}!'
34
+ "hello": "Bonjour {firstName}!"
64
35
  };
65
36
  ```
66
37
 
67
- **Note:** To avoid accidental imports and errors, your resource files should have a dedicated directory with nothing else in it.
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
- If your build system does not support variable dynamic imports, you'll need to manually set up imports for each supported language:
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
- **Note:** If using `LocalizeCoreElement` or a mixin that utilizes `LocalizeCoreElement` as well as `LocalizeMixin` or a mixin that uses `LocalizeMixin`, `LocalizeMixin` **must** appear before `LocalizeCoreElement` in the chain. For example:
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
- Once your localization resources are available, the `localize()` method is used to localize a piece of text in your `render()` method.
66
+ The `localize()` method is used to localize a piece of text in the component's `render()` method.
119
67
 
120
- If your localized string contains arguments, pass them as a key-value object as the 2nd parameter:
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
- return html`<p>${this.localize('hello', { firstName: 'Mary' })}</p>`;
72
+ const message = this.localize('hello', { firstName: 'Mary' });
73
+ return html`<p>${message}</p>`;
125
74
  }
126
75
  ```
127
76
 
128
- ## `localizeHTML()`
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
- ### Basic Formatting
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
- ### Links
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
- ### Help Tooltips
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 term value:
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`).
@@ -230,31 +230,6 @@ export const LocalizeMixin = superclass => class extends _LocalizeMixinBase(supe
230
230
 
231
231
  };
232
232
 
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
233
  export const allowedTags = Object.freeze(['d2l-link', 'd2l-tooltip-help', 'p', 'br', 'b', 'strong', 'i', 'em']);
259
234
 
260
235
  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.106.0",
3
+ "version": "2.107.0",
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",