@ckeditor/ckeditor5-language 48.2.0 → 48.3.0-alpha.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.
- package/dist/augmentation.d.ts +45 -45
- package/dist/index-content.css +1 -0
- package/dist/index-editor.css +1 -0
- package/dist/index.css +0 -2
- package/dist/index.d.ts +12 -12
- package/dist/index.js +395 -394
- package/dist/index.js.map +1 -1
- package/dist/textpartlanguage.d.ts +34 -34
- package/dist/textpartlanguagecommand.d.ts +65 -65
- package/dist/textpartlanguageconfig.d.ts +20 -20
- package/dist/textpartlanguageediting.d.ts +28 -28
- package/dist/textpartlanguageui.d.ts +26 -26
- package/dist/utils.d.ts +35 -35
- package/package.json +5 -5
- package/dist/index.css.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,412 +2,413 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
4
4
|
*/
|
|
5
|
-
import { Command, Plugin } from
|
|
6
|
-
import { ModelDocumentSelection } from
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { Command, Plugin } from "@ckeditor/ckeditor5-core";
|
|
6
|
+
import { ModelDocumentSelection } from "@ckeditor/ckeditor5-engine";
|
|
7
|
+
import { Collection, getLanguageDirection } from "@ckeditor/ckeditor5-utils";
|
|
8
|
+
import { ListSeparatorView, MenuBarMenuListItemButtonView, MenuBarMenuListItemView, MenuBarMenuListView, MenuBarMenuView, UIModel, addListToDropdown, createDropdown } from "@ckeditor/ckeditor5-ui";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
11
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
12
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @module language/utils
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Returns the language attribute value in a human-readable text format:
|
|
19
|
+
*
|
|
20
|
+
* ```
|
|
21
|
+
* <languageCode>:<textDirection>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* * `languageCode` - The language code used for the `lang` attribute in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format.
|
|
25
|
+
* * `textDirection` - One of the following values: `rtl` or `ltr`, indicating the reading direction of the language.
|
|
26
|
+
*
|
|
27
|
+
* See the {@link module:core/editor/editorconfig~LanguageConfig#textPartLanguage text part language configuration}
|
|
28
|
+
* for more information about language properties.
|
|
29
|
+
*
|
|
30
|
+
* If the `textDirection` argument is omitted, it will be automatically detected based on `languageCode`.
|
|
31
|
+
*
|
|
32
|
+
* @param languageCode The language code in the ISO 639-1 format.
|
|
33
|
+
* @param textDirection The language text direction. Automatically detected if omitted.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
function stringifyLanguageAttribute(languageCode, textDirection) {
|
|
37
|
+
textDirection = textDirection || getLanguageDirection(languageCode);
|
|
38
|
+
return `${languageCode}:${textDirection}`;
|
|
31
39
|
}
|
|
32
40
|
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
* Retrieves language properties converted to attribute value by the
|
|
42
|
+
* {@link module:language/utils~stringifyLanguageAttribute stringifyLanguageAttribute} function.
|
|
43
|
+
*
|
|
44
|
+
* @internal
|
|
45
|
+
* @param str The attribute value.
|
|
46
|
+
* @returns The object with properties:
|
|
47
|
+
* * languageCode - The language code in the ISO 639 format.
|
|
48
|
+
* * textDirection - The language text direction.
|
|
49
|
+
*/
|
|
50
|
+
function parseLanguageAttribute(str) {
|
|
51
|
+
const [languageCode, textDirection] = str.split(":");
|
|
52
|
+
return {
|
|
53
|
+
languageCode,
|
|
54
|
+
textDirection
|
|
55
|
+
};
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
for (const range of selection.getRanges()){
|
|
124
|
-
for (const item of range.getItems()){
|
|
125
|
-
if (schema.checkAttribute(item, 'language')) {
|
|
126
|
-
return item.getAttribute('language') || false;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
59
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
60
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* The text part language command plugin.
|
|
64
|
+
*/
|
|
65
|
+
var TextPartLanguageCommand = class extends Command {
|
|
66
|
+
/**
|
|
67
|
+
* @inheritDoc
|
|
68
|
+
*/
|
|
69
|
+
refresh() {
|
|
70
|
+
const model = this.editor.model;
|
|
71
|
+
const doc = model.document;
|
|
72
|
+
this.value = this._getValueFromFirstAllowedNode();
|
|
73
|
+
this.isEnabled = model.schema.checkAttributeInSelection(doc.selection, "language");
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Executes the command. Applies the attribute to the selection or removes it from the selection.
|
|
77
|
+
*
|
|
78
|
+
* If `languageCode` is set to `false` or a `null` value, it will remove attributes. Otherwise, it will set
|
|
79
|
+
* the attribute in the `{@link #value value}` format.
|
|
80
|
+
*
|
|
81
|
+
* The execution result differs, depending on the {@link module:engine/model/document~ModelDocument#selection}:
|
|
82
|
+
*
|
|
83
|
+
* * If the selection is on a range, the command applies the attribute to all nodes in that range
|
|
84
|
+
* (if they are allowed to have this attribute by the {@link module:engine/model/schema~ModelSchema schema}).
|
|
85
|
+
* * If the selection is collapsed in a non-empty node, the command applies the attribute to the
|
|
86
|
+
* {@link module:engine/model/document~ModelDocument#selection} itself (note that typed characters copy attributes from the selection).
|
|
87
|
+
* * If the selection is collapsed in an empty node, the command applies the attribute to the parent node of the selection (note
|
|
88
|
+
* that the selection inherits all attributes from a node if it is in an empty node).
|
|
89
|
+
*
|
|
90
|
+
* @fires execute
|
|
91
|
+
* @param options Command options.
|
|
92
|
+
* @param options.languageCode The language code to be applied to the model.
|
|
93
|
+
* @param options.textDirection The language text direction.
|
|
94
|
+
*/
|
|
95
|
+
execute({ languageCode, textDirection } = {}) {
|
|
96
|
+
const model = this.editor.model;
|
|
97
|
+
const selection = model.document.selection;
|
|
98
|
+
const value = languageCode ? stringifyLanguageAttribute(languageCode, textDirection) : false;
|
|
99
|
+
model.change((writer) => {
|
|
100
|
+
if (selection.isCollapsed) if (value) writer.setSelectionAttribute("language", value);
|
|
101
|
+
else writer.removeSelectionAttribute("language");
|
|
102
|
+
else {
|
|
103
|
+
const ranges = model.schema.getValidRanges(selection.getRanges(), "language", { includeEmptyRanges: true });
|
|
104
|
+
for (const range of ranges) {
|
|
105
|
+
let itemOrRange = range;
|
|
106
|
+
let attributeKey = "language";
|
|
107
|
+
if (range.isCollapsed) {
|
|
108
|
+
itemOrRange = range.start.parent;
|
|
109
|
+
attributeKey = ModelDocumentSelection._getStoreAttributeKey("language");
|
|
110
|
+
}
|
|
111
|
+
if (value) writer.setAttribute(attributeKey, value, itemOrRange);
|
|
112
|
+
else writer.removeAttribute(attributeKey, itemOrRange);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Returns the attribute value of the first node in the selection that allows the attribute.
|
|
119
|
+
* For a collapsed selection it returns the selection attribute.
|
|
120
|
+
*
|
|
121
|
+
* @returns The attribute value.
|
|
122
|
+
*/
|
|
123
|
+
_getValueFromFirstAllowedNode() {
|
|
124
|
+
const model = this.editor.model;
|
|
125
|
+
const schema = model.schema;
|
|
126
|
+
const selection = model.document.selection;
|
|
127
|
+
if (selection.isCollapsed) return selection.getAttribute("language") || false;
|
|
128
|
+
for (const range of selection.getRanges()) for (const item of range.getItems()) if (schema.checkAttribute(item, "language")) return item.getAttribute("language") || false;
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
133
132
|
|
|
134
133
|
/**
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
lang: languageCode,
|
|
218
|
-
dir: textDirection
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
134
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
135
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
136
|
+
*/
|
|
137
|
+
/**
|
|
138
|
+
* The text part language editing.
|
|
139
|
+
*
|
|
140
|
+
* Introduces the `'textPartLanguage'` command and the `'language'` model element attribute.
|
|
141
|
+
*/
|
|
142
|
+
var TextPartLanguageEditing = class extends Plugin {
|
|
143
|
+
/**
|
|
144
|
+
* @inheritDoc
|
|
145
|
+
*/
|
|
146
|
+
static get pluginName() {
|
|
147
|
+
return "TextPartLanguageEditing";
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* @inheritDoc
|
|
151
|
+
*/
|
|
152
|
+
static get isOfficialPlugin() {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* @inheritDoc
|
|
157
|
+
*/
|
|
158
|
+
constructor(editor) {
|
|
159
|
+
super(editor);
|
|
160
|
+
editor.config.define("language", { textPartLanguage: [
|
|
161
|
+
{
|
|
162
|
+
title: "Arabic",
|
|
163
|
+
languageCode: "ar"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
title: "French",
|
|
167
|
+
languageCode: "fr"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
title: "Spanish",
|
|
171
|
+
languageCode: "es"
|
|
172
|
+
}
|
|
173
|
+
] });
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* @inheritDoc
|
|
177
|
+
*/
|
|
178
|
+
init() {
|
|
179
|
+
const editor = this.editor;
|
|
180
|
+
editor.model.schema.extend("$text", { allowAttributes: "language" });
|
|
181
|
+
editor.model.schema.setAttributeProperties("language", { copyOnEnter: true });
|
|
182
|
+
this._defineConverters();
|
|
183
|
+
editor.commands.add("textPartLanguage", new TextPartLanguageCommand(editor));
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
188
|
+
_defineConverters() {
|
|
189
|
+
const conversion = this.editor.conversion;
|
|
190
|
+
conversion.for("upcast").elementToAttribute({
|
|
191
|
+
model: {
|
|
192
|
+
key: "language",
|
|
193
|
+
value: (viewElement) => {
|
|
194
|
+
return stringifyLanguageAttribute(viewElement.getAttribute("lang"), viewElement.getAttribute("dir"));
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
view: {
|
|
198
|
+
name: "span",
|
|
199
|
+
attributes: { lang: /[\s\S]+/ }
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
conversion.for("downcast").attributeToElement({
|
|
203
|
+
model: "language",
|
|
204
|
+
view: (attributeValue, { writer }, data) => {
|
|
205
|
+
if (!attributeValue) return;
|
|
206
|
+
if (!data.item.is("$textProxy") && !data.item.is("documentSelection")) return;
|
|
207
|
+
const { languageCode, textDirection } = parseLanguageAttribute(attributeValue);
|
|
208
|
+
return writer.createAttributeElement("span", {
|
|
209
|
+
lang: languageCode,
|
|
210
|
+
dir: textDirection
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
};
|
|
224
216
|
|
|
225
217
|
/**
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
titles
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
}
|
|
218
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
219
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
220
|
+
*/
|
|
221
|
+
/**
|
|
222
|
+
* @module language/textpartlanguageui
|
|
223
|
+
*/
|
|
224
|
+
/**
|
|
225
|
+
* The text part language UI plugin.
|
|
226
|
+
*
|
|
227
|
+
* It introduces the `'language'` dropdown.
|
|
228
|
+
*/
|
|
229
|
+
var TextPartLanguageUI = class extends Plugin {
|
|
230
|
+
/**
|
|
231
|
+
* @inheritDoc
|
|
232
|
+
*/
|
|
233
|
+
static get pluginName() {
|
|
234
|
+
return "TextPartLanguageUI";
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* @inheritDoc
|
|
238
|
+
*/
|
|
239
|
+
static get isOfficialPlugin() {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* @inheritDoc
|
|
244
|
+
*/
|
|
245
|
+
init() {
|
|
246
|
+
const editor = this.editor;
|
|
247
|
+
const t = editor.t;
|
|
248
|
+
const defaultTitle = t("Choose language");
|
|
249
|
+
const accessibleLabel = t("Language");
|
|
250
|
+
editor.ui.componentFactory.add("textPartLanguage", (locale) => {
|
|
251
|
+
const { definitions, titles } = this._getItemMetadata();
|
|
252
|
+
const languageCommand = editor.commands.get("textPartLanguage");
|
|
253
|
+
const dropdownView = createDropdown(locale);
|
|
254
|
+
addListToDropdown(dropdownView, definitions, {
|
|
255
|
+
ariaLabel: accessibleLabel,
|
|
256
|
+
role: "menu"
|
|
257
|
+
});
|
|
258
|
+
dropdownView.buttonView.set({
|
|
259
|
+
ariaLabel: accessibleLabel,
|
|
260
|
+
ariaLabelledBy: void 0,
|
|
261
|
+
isOn: false,
|
|
262
|
+
withText: true,
|
|
263
|
+
tooltip: accessibleLabel
|
|
264
|
+
});
|
|
265
|
+
dropdownView.extendTemplate({ attributes: { class: ["ck-text-fragment-language-dropdown"] } });
|
|
266
|
+
dropdownView.bind("isEnabled").to(languageCommand, "isEnabled");
|
|
267
|
+
dropdownView.buttonView.bind("label").to(languageCommand, "value", (value) => {
|
|
268
|
+
return value && titles[value] || defaultTitle;
|
|
269
|
+
});
|
|
270
|
+
dropdownView.buttonView.bind("ariaLabel").to(languageCommand, "value", (value) => {
|
|
271
|
+
const selectedLanguageTitle = value && titles[value];
|
|
272
|
+
if (!selectedLanguageTitle) return accessibleLabel;
|
|
273
|
+
return `${selectedLanguageTitle}, ${accessibleLabel}`;
|
|
274
|
+
});
|
|
275
|
+
this.listenTo(dropdownView, "execute", (evt) => {
|
|
276
|
+
languageCommand.execute({
|
|
277
|
+
languageCode: evt.source.languageCode,
|
|
278
|
+
textDirection: evt.source.textDirection
|
|
279
|
+
});
|
|
280
|
+
editor.editing.view.focus();
|
|
281
|
+
});
|
|
282
|
+
return dropdownView;
|
|
283
|
+
});
|
|
284
|
+
editor.ui.componentFactory.add("menuBar:textPartLanguage", (locale) => {
|
|
285
|
+
const { definitions } = this._getItemMetadata();
|
|
286
|
+
const languageCommand = editor.commands.get("textPartLanguage");
|
|
287
|
+
const menuView = new MenuBarMenuView(locale);
|
|
288
|
+
menuView.buttonView.set({ label: accessibleLabel });
|
|
289
|
+
const listView = new MenuBarMenuListView(locale);
|
|
290
|
+
listView.set({
|
|
291
|
+
ariaLabel: t("Language"),
|
|
292
|
+
role: "menu"
|
|
293
|
+
});
|
|
294
|
+
for (const definition of definitions) {
|
|
295
|
+
if (definition.type != "button") {
|
|
296
|
+
listView.items.add(new ListSeparatorView(locale));
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
const listItemView = new MenuBarMenuListItemView(locale, menuView);
|
|
300
|
+
const buttonView = new MenuBarMenuListItemButtonView(locale);
|
|
301
|
+
buttonView.set({
|
|
302
|
+
role: "menuitemradio",
|
|
303
|
+
isToggleable: true
|
|
304
|
+
});
|
|
305
|
+
buttonView.bind(...Object.keys(definition.model)).to(definition.model);
|
|
306
|
+
buttonView.delegate("execute").to(menuView);
|
|
307
|
+
listItemView.children.add(buttonView);
|
|
308
|
+
listView.items.add(listItemView);
|
|
309
|
+
}
|
|
310
|
+
menuView.bind("isEnabled").to(languageCommand, "isEnabled");
|
|
311
|
+
menuView.panelView.children.add(listView);
|
|
312
|
+
menuView.on("execute", (evt) => {
|
|
313
|
+
languageCommand.execute({
|
|
314
|
+
languageCode: evt.source.languageCode,
|
|
315
|
+
textDirection: evt.source.textDirection
|
|
316
|
+
});
|
|
317
|
+
editor.editing.view.focus();
|
|
318
|
+
});
|
|
319
|
+
return menuView;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Returns metadata for dropdown and menu items.
|
|
324
|
+
*/
|
|
325
|
+
_getItemMetadata() {
|
|
326
|
+
const editor = this.editor;
|
|
327
|
+
const itemDefinitions = new Collection();
|
|
328
|
+
const titles = {};
|
|
329
|
+
const languageCommand = editor.commands.get("textPartLanguage");
|
|
330
|
+
const options = editor.config.get("language.textPartLanguage");
|
|
331
|
+
const t = editor.locale.t;
|
|
332
|
+
const removeTitle = t("Remove language");
|
|
333
|
+
itemDefinitions.add({
|
|
334
|
+
type: "button",
|
|
335
|
+
model: new UIModel({
|
|
336
|
+
label: removeTitle,
|
|
337
|
+
languageCode: false,
|
|
338
|
+
withText: true
|
|
339
|
+
})
|
|
340
|
+
});
|
|
341
|
+
itemDefinitions.add({ type: "separator" });
|
|
342
|
+
for (const option of options) {
|
|
343
|
+
const def = {
|
|
344
|
+
type: "button",
|
|
345
|
+
model: new UIModel({
|
|
346
|
+
label: option.title,
|
|
347
|
+
languageCode: option.languageCode,
|
|
348
|
+
role: "menuitemradio",
|
|
349
|
+
textDirection: option.textDirection,
|
|
350
|
+
withText: true
|
|
351
|
+
})
|
|
352
|
+
};
|
|
353
|
+
const language = stringifyLanguageAttribute(option.languageCode, option.textDirection);
|
|
354
|
+
def.model.bind("isOn").to(languageCommand, "value", (value) => value === language);
|
|
355
|
+
itemDefinitions.add(def);
|
|
356
|
+
titles[language] = option.title;
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
definitions: itemDefinitions,
|
|
360
|
+
titles
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
};
|
|
376
364
|
|
|
377
365
|
/**
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
366
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
367
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
368
|
+
*/
|
|
369
|
+
/**
|
|
370
|
+
* @module language/textpartlanguage
|
|
371
|
+
*/
|
|
372
|
+
/**
|
|
373
|
+
* The text part language feature.
|
|
374
|
+
*
|
|
375
|
+
* This feature allows setting a language of the document's text part to support
|
|
376
|
+
* [WCAG 3.1.2 Language of Parts](https://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-other-lang-id.html) specification.
|
|
377
|
+
*
|
|
378
|
+
* To change the editor's UI language, refer to the {@glink getting-started/setup/ui-language Setting the UI language} guide.
|
|
379
|
+
*
|
|
380
|
+
* For more information about this feature, check the {@glink api/language package page} as well as the {@glink features/language
|
|
381
|
+
* Text part language} feature guide.
|
|
382
|
+
*
|
|
383
|
+
* This is a "glue" plugin which loads the
|
|
384
|
+
* {@link module:language/textpartlanguageediting~TextPartLanguageEditing text part language editing feature}
|
|
385
|
+
* and the {@link module:language/textpartlanguageui~TextPartLanguageUI text part language UI feature}.
|
|
386
|
+
*/
|
|
387
|
+
var TextPartLanguage = class extends Plugin {
|
|
388
|
+
/**
|
|
389
|
+
* @inheritDoc
|
|
390
|
+
*/
|
|
391
|
+
static get requires() {
|
|
392
|
+
return [TextPartLanguageEditing, TextPartLanguageUI];
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* @inheritDoc
|
|
396
|
+
*/
|
|
397
|
+
static get pluginName() {
|
|
398
|
+
return "TextPartLanguage";
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* @inheritDoc
|
|
402
|
+
*/
|
|
403
|
+
static get isOfficialPlugin() {
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
|
|
410
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
411
|
+
*/
|
|
411
412
|
|
|
412
413
|
export { TextPartLanguage, TextPartLanguageCommand, TextPartLanguageEditing, TextPartLanguageUI, parseLanguageAttribute as _parseLanguageAttribute, stringifyLanguageAttribute as _stringifyLanguageAttribute };
|
|
413
|
-
//# sourceMappingURL=index.js.map
|
|
414
|
+
//# sourceMappingURL=index.js.map
|