@ckeditor/ckeditor5-utils 41.1.0 → 41.3.0-alpha.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.
Files changed (80) hide show
  1. package/dist/content-index.css +4 -0
  2. package/dist/editor-index.css +4 -0
  3. package/dist/index.css +4 -0
  4. package/dist/index.js +6040 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/types/abortabledebounce.d.ts +17 -0
  7. package/dist/types/areconnectedthroughproperties.d.ts +11 -0
  8. package/dist/types/ckeditorerror.d.ts +123 -0
  9. package/dist/types/collection.d.ts +433 -0
  10. package/dist/types/comparearrays.d.ts +30 -0
  11. package/dist/types/config.d.ts +163 -0
  12. package/dist/types/count.d.ts +18 -0
  13. package/dist/types/delay.d.ts +19 -0
  14. package/dist/types/diff.d.ts +31 -0
  15. package/dist/types/difftochanges.d.ts +59 -0
  16. package/dist/types/dom/createelement.d.ts +57 -0
  17. package/dist/types/dom/emittermixin.d.ts +142 -0
  18. package/dist/types/dom/findclosestscrollableancestor.d.ts +11 -0
  19. package/dist/types/dom/getancestors.d.ts +17 -0
  20. package/dist/types/dom/getborderwidths.d.ts +24 -0
  21. package/dist/types/dom/getcommonancestor.d.ts +12 -0
  22. package/dist/types/dom/getdatafromelement.d.ts +14 -0
  23. package/dist/types/dom/getpositionedancestor.d.ts +10 -0
  24. package/dist/types/dom/global.d.ts +32 -0
  25. package/dist/types/dom/indexof.d.ts +14 -0
  26. package/dist/types/dom/insertat.d.ts +15 -0
  27. package/dist/types/dom/iscomment.d.ts +11 -0
  28. package/dist/types/dom/isnode.d.ts +11 -0
  29. package/dist/types/dom/isrange.d.ts +11 -0
  30. package/dist/types/dom/istext.d.ts +11 -0
  31. package/dist/types/dom/isvalidattributename.d.ts +10 -0
  32. package/dist/types/dom/isvisible.d.ts +18 -0
  33. package/dist/types/dom/iswindow.d.ts +11 -0
  34. package/dist/types/dom/position.d.ts +211 -0
  35. package/dist/types/dom/rect.d.ts +195 -0
  36. package/dist/types/dom/remove.d.ts +13 -0
  37. package/dist/types/dom/resizeobserver.d.ts +74 -0
  38. package/dist/types/dom/scroll.d.ts +73 -0
  39. package/dist/types/dom/setdatainelement.d.ts +14 -0
  40. package/dist/types/dom/tounit.d.ts +22 -0
  41. package/dist/types/elementreplacer.d.ts +31 -0
  42. package/dist/types/emittermixin.d.ts +312 -0
  43. package/dist/types/env.d.ts +117 -0
  44. package/dist/types/eventinfo.d.ts +58 -0
  45. package/dist/types/fastdiff.d.ts +112 -0
  46. package/dist/types/first.d.ts +11 -0
  47. package/dist/types/focustracker.d.ts +75 -0
  48. package/dist/types/index.d.ts +64 -0
  49. package/dist/types/inserttopriorityarray.d.ts +30 -0
  50. package/dist/types/isiterable.d.ts +14 -0
  51. package/dist/types/keyboard.d.ts +126 -0
  52. package/dist/types/keystrokehandler.d.ts +87 -0
  53. package/dist/types/language.d.ts +17 -0
  54. package/dist/types/locale.d.ts +141 -0
  55. package/dist/types/mapsequal.d.ts +15 -0
  56. package/dist/types/mix.d.ts +85 -0
  57. package/dist/types/nth.d.ts +16 -0
  58. package/dist/types/objecttomap.d.ts +23 -0
  59. package/dist/types/observablemixin.d.ts +560 -0
  60. package/dist/types/priorities.d.ts +33 -0
  61. package/dist/types/retry.d.ts +33 -0
  62. package/dist/types/splicearray.d.ts +26 -0
  63. package/dist/types/spy.d.ts +21 -0
  64. package/dist/types/toarray.d.ts +25 -0
  65. package/dist/types/tomap.d.ts +19 -0
  66. package/dist/types/translation-service.d.ts +174 -0
  67. package/dist/types/uid.d.ts +15 -0
  68. package/dist/types/unicode.d.ts +54 -0
  69. package/dist/types/verifylicense.d.ts +15 -0
  70. package/dist/types/version.d.ts +10 -0
  71. package/dist/types/wait.d.ts +16 -0
  72. package/package.json +2 -1
  73. package/src/index.d.ts +1 -1
  74. package/src/keyboard.js +30 -4
  75. package/src/locale.d.ts +22 -1
  76. package/src/locale.js +5 -3
  77. package/src/translation-service.d.ts +15 -9
  78. package/src/translation-service.js +27 -16
  79. package/src/version.d.ts +1 -1
  80. package/src/version.js +2 -2
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/spy
7
+ */
8
+ /**
9
+ * Creates a spy function (ala Sinon.js) that can be used to inspect call to it.
10
+ *
11
+ * The following are the present features:
12
+ *
13
+ * * spy.called: property set to `true` if the function has been called at least once.
14
+ *
15
+ * @returns The spy function.
16
+ */
17
+ declare function spy(): {
18
+ (): void;
19
+ called?: boolean;
20
+ };
21
+ export default spy;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/toarray
7
+ */
8
+ /**
9
+ * Transforms any value to an array. If the provided value is already an array, it is returned unchanged.
10
+ *
11
+ * @label MUTABLE
12
+ * @param data The value to transform to an array.
13
+ * @returns An array created from data.
14
+ */
15
+ export default function toArray<T>(data: ArrayOrItem<T>): Array<T>;
16
+ /**
17
+ * Transforms any value to an array. If the provided value is already an array, it is returned unchanged.
18
+ *
19
+ * @label IMMUTABLE
20
+ * @param data The value to transform to an array.
21
+ * @returns An array created from data.
22
+ */
23
+ export default function toArray<T>(data: ReadonlyArrayOrItem<T>): ReadonlyArray<T>;
24
+ export type ArrayOrItem<T> = T | Array<T>;
25
+ export type ReadonlyArrayOrItem<T> = T | ReadonlyArray<T>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Transforms object or iterable to map. Iterable needs to be in the format acceptable by the `Map` constructor.
7
+ *
8
+ * ```ts
9
+ * map = toMap( { 'foo': 1, 'bar': 2 } );
10
+ * map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
11
+ * map = toMap( anotherMap );
12
+ * ```
13
+ *
14
+ * @param data Object or iterable to transform.
15
+ * @returns Map created from data.
16
+ */
17
+ export default function toMap<T>(data: {
18
+ readonly [key: string]: T;
19
+ } | Iterable<readonly [string, T]> | null | undefined): Map<string, T>;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/translation-service
7
+ */
8
+ import type { Translations } from './locale.js';
9
+ import { type ArrayOrItem } from './toarray.js';
10
+ declare global {
11
+ var CKEDITOR_TRANSLATIONS: Translations;
12
+ }
13
+ /**
14
+ * Adds translations to existing ones or overrides the existing translations. These translations will later
15
+ * be available for the {@link module:utils/locale~Locale#t `t()`} function.
16
+ *
17
+ * The `translations` is an object which consists of `messageId: translation` pairs. Note that the message ID can be
18
+ * either constructed from the message string or from the message ID if it was passed
19
+ * (this happens rarely and mostly for short messages or messages with placeholders).
20
+ * Since the editor displays only the message string, the message ID can be found either in the source code or in the
21
+ * built translations for another language.
22
+ *
23
+ * ```ts
24
+ * add( 'pl', {
25
+ * 'Cancel': 'Anuluj',
26
+ * 'IMAGE': 'obraz', // Note that the `IMAGE` comes from the message ID, while the string can be `image`.
27
+ * } );
28
+ * ```
29
+ *
30
+ * If the message is supposed to support various plural forms, make sure to provide an array with the singular form and all plural forms:
31
+ *
32
+ * ```ts
33
+ * add( 'pl', {
34
+ * 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
35
+ * } );
36
+ * ```
37
+ *
38
+ * You should also specify the third argument (the `getPluralForm()` function) that will be used to determine the plural form if no
39
+ * language file was loaded for that language. All language files coming from CKEditor 5 sources will have this option set, so
40
+ * these plural form rules will be reused by other translations added to the registered languages. The `getPluralForm()` function
41
+ * can return either a Boolean or a number.
42
+ *
43
+ * ```ts
44
+ * add( 'en', {
45
+ * // ... Translations.
46
+ * }, n => n !== 1 );
47
+ * add( 'pl', {
48
+ * // ... Translations.
49
+ * }, n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
50
+ * ```
51
+ *
52
+ * All translations extend the global `window.CKEDITOR_TRANSLATIONS` object. An example of this object can be found below:
53
+ *
54
+ * ```ts
55
+ * {
56
+ * pl: {
57
+ * dictionary: {
58
+ * 'Cancel': 'Anuluj',
59
+ * 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
60
+ * },
61
+ * // A function that returns the plural form index.
62
+ * getPluralForm: n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
63
+ * }
64
+ * // Other languages.
65
+ * }
66
+ * ```
67
+ *
68
+ * If you cannot import this function from this module (e.g. because you use a CKEditor 5 build), you can
69
+ * still add translations by extending the global `window.CKEDITOR_TRANSLATIONS` object by using a function like
70
+ * the one below:
71
+ *
72
+ * ```ts
73
+ * function addTranslations( language, translations, getPluralForm ) {
74
+ * if ( !global.window.CKEDITOR_TRANSLATIONS ) {
75
+ * global.window.CKEDITOR_TRANSLATIONS = {};
76
+ * }
77
+
78
+ * if ( !global.window.CKEDITOR_TRANSLATIONS[ language ] ) {
79
+ * global.window.CKEDITOR_TRANSLATIONS[ language ] = {};
80
+ * }
81
+ *
82
+ * const languageTranslations = global.window.CKEDITOR_TRANSLATIONS[ language ];
83
+ *
84
+ * languageTranslations.dictionary = languageTranslations.dictionary || {};
85
+ * languageTranslations.getPluralForm = getPluralForm || languageTranslations.getPluralForm;
86
+ *
87
+ * // Extend the dictionary for the given language.
88
+ * Object.assign( languageTranslations.dictionary, translations );
89
+ * }
90
+ * ```
91
+ *
92
+ * @param language Target language.
93
+ * @param translations An object with translations which will be added to the dictionary.
94
+ * For each message ID the value should be either a translation or an array of translations if the message
95
+ * should support plural forms.
96
+ * @param getPluralForm A function that returns the plural form index (a number).
97
+ */
98
+ export declare function add(language: string, translations: {
99
+ readonly [messageId: string]: string | ReadonlyArray<string>;
100
+ }, getPluralForm?: (n: number) => number): void;
101
+ /**
102
+ * **Note:** This method is internal, use {@link module:utils/locale~Locale#t the `t()` function} instead to translate
103
+ * the editor UI parts.
104
+ *
105
+ * This function is responsible for translating messages to the specified language. It uses translations added perviously
106
+ * by {@link module:utils/translation-service~add} (a translations dictionary and the `getPluralForm()` function
107
+ * to provide accurate translations of plural forms).
108
+ *
109
+ * When no translation is defined in the dictionary or the dictionary does not exist, this function returns
110
+ * the original message string or the message plural depending on the number of elements.
111
+ *
112
+ * ```ts
113
+ * translate( 'pl', { string: 'Cancel' } ); // 'Cancel'
114
+ * ```
115
+ *
116
+ * The third optional argument is the number of elements, based on which the single form or one of the plural forms
117
+ * should be picked when the message is supposed to support various plural forms.
118
+ *
119
+ * ```ts
120
+ * translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Add a space'
121
+ * translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 3 ); // 'Add %0 spaces'
122
+ * ```
123
+ *
124
+ * The message should provide an ID using the `id` property when the message strings are not unique and their
125
+ * translations should be different.
126
+ *
127
+ * ```ts
128
+ * translate( 'en', { string: 'image', id: 'ADD_IMAGE' } );
129
+ * translate( 'en', { string: 'image', id: 'AN_IMAGE' } );
130
+ * ```
131
+ *
132
+ * @internal
133
+ * @param language Target language.
134
+ * @param message A message that will be translated.
135
+ * @param quantity The number of elements for which a plural form should be picked from the target language dictionary.
136
+ * @param translations Translations passed in editor config, if not provided use the global `window.CKEDITOR_TRANSLATIONS`.
137
+ * @returns Translated sentence.
138
+ */
139
+ export declare function _translate(language: string, message: Message, quantity?: number, translations?: Translations): string;
140
+ /**
141
+ * Clears dictionaries for test purposes.
142
+ *
143
+ * @internal
144
+ */
145
+ export declare function _clear(): void;
146
+ /**
147
+ * If array then merge objects which are inside otherwise return given object.
148
+ *
149
+ * @internal
150
+ * @param translations Translations passed in editor config.
151
+ */
152
+ export declare function _unifyTranslations(translations?: ArrayOrItem<Translations>): Translations | undefined;
153
+ /**
154
+ * The internationalization message interface. A message that implements this interface can be passed to the `t()` function
155
+ * to be translated to the target UI language.
156
+ */
157
+ export interface Message {
158
+ /**
159
+ * The message string to translate. Acts as a default translation if the translation for a given language
160
+ * is not defined. When the message is supposed to support plural forms, the string should be the English singular form of the message.
161
+ */
162
+ readonly string: string;
163
+ /**
164
+ * The message ID. If passed, the message ID is taken from this property instead of the `message.string`.
165
+ * This property is useful when various messages share the same message string, for example, the `editor` string in `in the editor`
166
+ * and `my editor` sentences.
167
+ */
168
+ readonly id?: string;
169
+ /**
170
+ * The plural form of the message. This property should be skipped when a message is not supposed
171
+ * to support plural forms. Otherwise it should always be set to a string with the English plural form of the message.
172
+ */
173
+ readonly plural?: string;
174
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Returns a unique id. The id starts with an "e" character and a randomly generated string of
7
+ * 32 alphanumeric characters.
8
+ *
9
+ * **Note**: The characters the unique id is built from correspond to the hex number notation
10
+ * (from "0" to "9", from "a" to "f"). In other words, each id corresponds to an "e" followed
11
+ * by 16 8-bit numbers next to each other.
12
+ *
13
+ * @returns An unique id string.
14
+ */
15
+ export default function uid(): string;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Set of utils to handle unicode characters.
7
+ *
8
+ * @module utils/unicode
9
+ */
10
+ /**
11
+ * Checks whether given `character` is a combining mark.
12
+ *
13
+ * @param character Character to check.
14
+ */
15
+ export declare function isCombiningMark(character: string): boolean;
16
+ /**
17
+ * Checks whether given `character` is a high half of surrogate pair.
18
+ *
19
+ * Using UTF-16 terminology, a surrogate pair denotes UTF-16 character using two UTF-8 characters. The surrogate pair
20
+ * consist of high surrogate pair character followed by low surrogate pair character.
21
+ *
22
+ * @param character Character to check.
23
+ */
24
+ export declare function isHighSurrogateHalf(character: string): boolean;
25
+ /**
26
+ * Checks whether given `character` is a low half of surrogate pair.
27
+ *
28
+ * Using UTF-16 terminology, a surrogate pair denotes UTF-16 character using two UTF-8 characters. The surrogate pair
29
+ * consist of high surrogate pair character followed by low surrogate pair character.
30
+ *
31
+ * @param character Character to check.
32
+ */
33
+ export declare function isLowSurrogateHalf(character: string): boolean;
34
+ /**
35
+ * Checks whether given offset in a string is inside a surrogate pair (between two surrogate halves).
36
+ *
37
+ * @param string String to check.
38
+ * @param offset Offset to check.
39
+ */
40
+ export declare function isInsideSurrogatePair(string: string, offset: number): boolean;
41
+ /**
42
+ * Checks whether given offset in a string is between base character and combining mark or between two combining marks.
43
+ *
44
+ * @param string String to check.
45
+ * @param offset Offset to check.
46
+ */
47
+ export declare function isInsideCombinedSymbol(string: string, offset: number): boolean;
48
+ /**
49
+ * Checks whether given offset in a string is inside multi-character emoji sequence.
50
+ *
51
+ * @param string String to check.
52
+ * @param offset Offset to check.
53
+ */
54
+ export declare function isInsideEmojiSequence(string: string, offset: number): boolean;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Possible states of the key after verification.
7
+ */
8
+ export type VerifiedKeyStatus = 'VALID' | 'INVALID';
9
+ /**
10
+ * Checks whether the given string contains information that allows you to verify the license status.
11
+ *
12
+ * @param token The string to check.
13
+ * @returns String that represents the state of given `token` parameter.
14
+ */
15
+ export default function verifyLicense(token: string | undefined): VerifiedKeyStatus;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ declare const version = "41.3.0-alpha.0";
6
+ export default version;
7
+ export declare const releaseDate: Date;
8
+ declare global {
9
+ var CKEDITOR_VERSION: string;
10
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/wait
7
+ */
8
+ /**
9
+ * Returns a promise that is resolved after the specified time.
10
+ *
11
+ * @param timeout The time in milliseconds to wait.
12
+ * @param options.signal A signal to abort the waiting.
13
+ */
14
+ export default function wait(timeout: number, options?: {
15
+ signal?: AbortSignal;
16
+ }): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-utils",
3
- "version": "41.1.0",
3
+ "version": "41.3.0-alpha.0",
4
4
  "description": "Miscellaneous utilities used by CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -24,6 +24,7 @@
24
24
  "directory": "packages/ckeditor5-utils"
25
25
  },
26
26
  "files": [
27
+ "dist",
27
28
  "lang",
28
29
  "src/**/*.js",
29
30
  "src/**/*.d.ts",
package/src/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export { default as remove } from './dom/remove.js';
45
45
  export * from './dom/scroll.js';
46
46
  export * from './keyboard.js';
47
47
  export * from './language.js';
48
- export { default as Locale, type LocaleTranslate } from './locale.js';
48
+ export { default as Locale, type LocaleTranslate, type Translations } from './locale.js';
49
49
  export { default as Collection, type CollectionAddEvent, type CollectionChangeEvent, type CollectionRemoveEvent } from './collection.js';
50
50
  export { default as first } from './first.js';
51
51
  export { default as FocusTracker } from './focustracker.js';
package/src/keyboard.js CHANGED
@@ -15,6 +15,13 @@ const modifiersToGlyphsNonMac = {
15
15
  alt: 'Alt+',
16
16
  shift: 'Shift+'
17
17
  };
18
+ const keyCodesToGlyphs = {
19
+ 37: '←',
20
+ 38: '↑',
21
+ 39: '→',
22
+ 40: '↓',
23
+ 9: '⇥'
24
+ };
18
25
  /**
19
26
  * An object with `keyName => keyCode` pairs for a set of known keys.
20
27
  *
@@ -29,7 +36,16 @@ const modifiersToGlyphsNonMac = {
29
36
  * * `ctrl`, `cmd`, `shift`, `alt`.
30
37
  */
31
38
  export const keyCodes = generateKnownKeyCodes();
32
- const keyCodeNames = Object.fromEntries(Object.entries(keyCodes).map(([name, code]) => [code, name.charAt(0).toUpperCase() + name.slice(1)]));
39
+ const keyCodeNames = Object.fromEntries(Object.entries(keyCodes).map(([name, code]) => {
40
+ let prettyKeyName;
41
+ if (code in keyCodesToGlyphs) {
42
+ prettyKeyName = keyCodesToGlyphs[code];
43
+ }
44
+ else {
45
+ prettyKeyName = name.charAt(0).toUpperCase() + name.slice(1);
46
+ }
47
+ return [code, prettyKeyName];
48
+ }));
33
49
  /**
34
50
  * Converts a key name or {@link module:utils/keyboard~KeystrokeInfo keystroke info} into a key code.
35
51
  *
@@ -211,9 +227,19 @@ function generateKnownKeyCodes() {
211
227
  keyCodes['f' + (code - 111)] = code;
212
228
  }
213
229
  // other characters
214
- for (const char of '`-=[];\',./\\') {
215
- keyCodes[char] = char.charCodeAt(0);
216
- }
230
+ Object.assign(keyCodes, {
231
+ '\'': 222,
232
+ ',': 108,
233
+ '-': 109,
234
+ '.': 110,
235
+ '/': 111,
236
+ ';': 186,
237
+ '=': 187,
238
+ '[': 219,
239
+ '\\': 220,
240
+ ']': 221,
241
+ '`': 223
242
+ });
217
243
  return keyCodes;
218
244
  }
219
245
  function splitKeystrokeText(keystroke) {
package/src/locale.d.ts CHANGED
@@ -2,6 +2,10 @@
2
2
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
+ /**
6
+ * @module utils/locale
7
+ */
8
+ import { type ArrayOrItem } from './toarray.js';
5
9
  import { type Message } from './translation-service.js';
6
10
  import { type LanguageDirection } from './language.js';
7
11
  /**
@@ -83,6 +87,10 @@ export default class Locale {
83
87
  * ```
84
88
  */
85
89
  readonly t: LocaleTranslate;
90
+ /**
91
+ * Object that contains translations.
92
+ */
93
+ translations?: Translations;
86
94
  /**
87
95
  * Creates a new instance of the locale class. Learn more about
88
96
  * {@glink features/ui-language configuring the language of the editor}.
@@ -93,10 +101,12 @@ export default class Locale {
93
101
  * @param options.contentLanguage The editor content language code in the
94
102
  * [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. If not specified, the same as `options.language`.
95
103
  * See {@link #contentLanguage}.
104
+ * @param translations Translations passed as a editor config parameter.
96
105
  */
97
- constructor({ uiLanguage, contentLanguage }?: {
106
+ constructor({ uiLanguage, contentLanguage, translations }?: {
98
107
  readonly uiLanguage?: string;
99
108
  readonly contentLanguage?: string;
109
+ readonly translations?: ArrayOrItem<Translations>;
100
110
  });
101
111
  /**
102
112
  * The editor UI language code in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format.
@@ -118,3 +128,14 @@ export default class Locale {
118
128
  * For messages supporting plural forms the first value will determine the plural form.
119
129
  */
120
130
  export type LocaleTranslate = (message: string | Message, values?: number | string | ReadonlyArray<number | string>) => string;
131
+ /**
132
+ * Translations object definition.
133
+ */
134
+ export type Translations = {
135
+ [language: string]: {
136
+ dictionary: {
137
+ [messageId: string]: string | ReadonlyArray<string>;
138
+ };
139
+ getPluralForm?: (n: number) => number;
140
+ };
141
+ };
package/src/locale.js CHANGED
@@ -7,7 +7,7 @@
7
7
  */
8
8
  /* globals console */
9
9
  import toArray from './toarray.js';
10
- import { _translate } from './translation-service.js';
10
+ import { _translate, _unifyTranslations } from './translation-service.js';
11
11
  import { getLanguageDirection } from './language.js';
12
12
  /**
13
13
  * Represents the localization services.
@@ -23,12 +23,14 @@ export default class Locale {
23
23
  * @param options.contentLanguage The editor content language code in the
24
24
  * [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. If not specified, the same as `options.language`.
25
25
  * See {@link #contentLanguage}.
26
+ * @param translations Translations passed as a editor config parameter.
26
27
  */
27
- constructor({ uiLanguage = 'en', contentLanguage } = {}) {
28
+ constructor({ uiLanguage = 'en', contentLanguage, translations } = {}) {
28
29
  this.uiLanguage = uiLanguage;
29
30
  this.contentLanguage = contentLanguage || this.uiLanguage;
30
31
  this.uiLanguageDirection = getLanguageDirection(this.uiLanguage);
31
32
  this.contentLanguageDirection = getLanguageDirection(this.contentLanguage);
33
+ this.translations = _unifyTranslations(translations);
32
34
  this.t = (message, values) => this._t(message, values);
33
35
  }
34
36
  /**
@@ -62,7 +64,7 @@ export default class Locale {
62
64
  }
63
65
  const hasPluralForm = !!message.plural;
64
66
  const quantity = hasPluralForm ? values[0] : 1;
65
- const translatedString = _translate(this.uiLanguage, message, quantity);
67
+ const translatedString = _translate(this.uiLanguage, message, quantity, this.translations);
66
68
  return interpolateString(translatedString, values);
67
69
  }
68
70
  }
@@ -2,15 +2,13 @@
2
2
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
+ /**
6
+ * @module utils/translation-service
7
+ */
8
+ import type { Translations } from './locale.js';
9
+ import { type ArrayOrItem } from './toarray.js';
5
10
  declare global {
6
- var CKEDITOR_TRANSLATIONS: {
7
- [language: string]: {
8
- dictionary: {
9
- [messageId: string]: string | ReadonlyArray<string>;
10
- };
11
- getPluralForm?: (n: number) => number;
12
- };
13
- };
11
+ var CKEDITOR_TRANSLATIONS: Translations;
14
12
  }
15
13
  /**
16
14
  * Adds translations to existing ones or overrides the existing translations. These translations will later
@@ -135,15 +133,23 @@ export declare function add(language: string, translations: {
135
133
  * @param language Target language.
136
134
  * @param message A message that will be translated.
137
135
  * @param quantity The number of elements for which a plural form should be picked from the target language dictionary.
136
+ * @param translations Translations passed in editor config, if not provided use the global `window.CKEDITOR_TRANSLATIONS`.
138
137
  * @returns Translated sentence.
139
138
  */
140
- export declare function _translate(language: string, message: Message, quantity?: number): string;
139
+ export declare function _translate(language: string, message: Message, quantity?: number, translations?: Translations): string;
141
140
  /**
142
141
  * Clears dictionaries for test purposes.
143
142
  *
144
143
  * @internal
145
144
  */
146
145
  export declare function _clear(): void;
146
+ /**
147
+ * If array then merge objects which are inside otherwise return given object.
148
+ *
149
+ * @internal
150
+ * @param translations Translations passed in editor config.
151
+ */
152
+ export declare function _unifyTranslations(translations?: ArrayOrItem<Translations>): Translations | undefined;
147
153
  /**
148
154
  * The internationalization message interface. A message that implements this interface can be passed to the `t()` function
149
155
  * to be translated to the target UI language.
@@ -2,12 +2,9 @@
2
2
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* eslint-disable no-var */
6
- /**
7
- * @module utils/translation-service
8
- */
9
5
  import CKEditorError from './ckeditorerror.js';
10
6
  import global from './dom/global.js';
7
+ import { merge } from 'lodash-es';
11
8
  /* istanbul ignore else -- @preserve */
12
9
  if (!global.window.CKEDITOR_TRANSLATIONS) {
13
10
  global.window.CKEDITOR_TRANSLATIONS = {};
@@ -141,9 +138,10 @@ export function add(language, translations, getPluralForm) {
141
138
  * @param language Target language.
142
139
  * @param message A message that will be translated.
143
140
  * @param quantity The number of elements for which a plural form should be picked from the target language dictionary.
141
+ * @param translations Translations passed in editor config, if not provided use the global `window.CKEDITOR_TRANSLATIONS`.
144
142
  * @returns Translated sentence.
145
143
  */
146
- export function _translate(language, message, quantity = 1) {
144
+ export function _translate(language, message, quantity = 1, translations) {
147
145
  if (typeof quantity !== 'number') {
148
146
  /**
149
147
  * An incorrect value was passed to the translation function. This was probably caused
@@ -154,22 +152,23 @@ export function _translate(language, message, quantity = 1) {
154
152
  */
155
153
  throw new CKEditorError('translation-service-quantity-not-a-number', null, { quantity });
156
154
  }
157
- const numberOfLanguages = getNumberOfLanguages();
155
+ const normalizedTranslations = translations || global.window.CKEDITOR_TRANSLATIONS;
156
+ const numberOfLanguages = getNumberOfLanguages(normalizedTranslations);
158
157
  if (numberOfLanguages === 1) {
159
158
  // Override the language to the only supported one.
160
159
  // This can't be done in the `Locale` class, because the translations comes after the `Locale` class initialization.
161
- language = Object.keys(global.window.CKEDITOR_TRANSLATIONS)[0];
160
+ language = Object.keys(normalizedTranslations)[0];
162
161
  }
163
162
  const messageId = message.id || message.string;
164
- if (numberOfLanguages === 0 || !hasTranslation(language, messageId)) {
163
+ if (numberOfLanguages === 0 || !hasTranslation(language, messageId, normalizedTranslations)) {
165
164
  if (quantity !== 1) {
166
165
  // Return the default plural form that was passed in the `message.plural` parameter.
167
166
  return message.plural;
168
167
  }
169
168
  return message.string;
170
169
  }
171
- const dictionary = global.window.CKEDITOR_TRANSLATIONS[language].dictionary;
172
- const getPluralForm = global.window.CKEDITOR_TRANSLATIONS[language].getPluralForm || (n => n === 1 ? 0 : 1);
170
+ const dictionary = normalizedTranslations[language].dictionary;
171
+ const getPluralForm = normalizedTranslations[language].getPluralForm || (n => n === 1 ? 0 : 1);
173
172
  const translation = dictionary[messageId];
174
173
  if (typeof translation === 'string') {
175
174
  return translation;
@@ -184,15 +183,27 @@ export function _translate(language, message, quantity = 1) {
184
183
  * @internal
185
184
  */
186
185
  export function _clear() {
187
- global.window.CKEDITOR_TRANSLATIONS = {};
186
+ if (global.window.CKEDITOR_TRANSLATIONS) {
187
+ global.window.CKEDITOR_TRANSLATIONS = {};
188
+ }
189
+ }
190
+ /**
191
+ * If array then merge objects which are inside otherwise return given object.
192
+ *
193
+ * @internal
194
+ * @param translations Translations passed in editor config.
195
+ */
196
+ export function _unifyTranslations(translations) {
197
+ return Array.isArray(translations) ?
198
+ translations.reduce((acc, translation) => merge(acc, translation)) :
199
+ translations;
188
200
  }
189
201
  /**
190
202
  * Checks whether the dictionary exists and translation in that dictionary exists.
191
203
  */
192
- function hasTranslation(language, messageId) {
193
- return (!!global.window.CKEDITOR_TRANSLATIONS[language] &&
194
- !!global.window.CKEDITOR_TRANSLATIONS[language].dictionary[messageId]);
204
+ function hasTranslation(language, messageId, translations) {
205
+ return !!translations[language] && !!translations[language].dictionary[messageId];
195
206
  }
196
- function getNumberOfLanguages() {
197
- return Object.keys(global.window.CKEDITOR_TRANSLATIONS).length;
207
+ function getNumberOfLanguages(translations) {
208
+ return Object.keys(translations).length;
198
209
  }
package/src/version.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- declare const version = "41.1.0";
5
+ declare const version = "41.3.0-alpha.0";
6
6
  export default version;
7
7
  export declare const releaseDate: Date;
8
8
  declare global {