@jupyterlab/translation-extension 4.4.0-alpha.3 → 4.4.0-beta.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/lib/index.js +99 -100
- package/lib/index.js.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +112 -113
package/lib/index.js
CHANGED
|
@@ -10,19 +10,39 @@ import { ILabShell, JupyterFrontEnd } from '@jupyterlab/application';
|
|
|
10
10
|
import { Dialog, ICommandPalette, showDialog } from '@jupyterlab/apputils';
|
|
11
11
|
import { IMainMenu } from '@jupyterlab/mainmenu';
|
|
12
12
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
13
|
-
import { ITranslator,
|
|
13
|
+
import { ITranslator, ITranslatorConnector, TranslationManager, TranslatorConnector } from '@jupyterlab/translation';
|
|
14
14
|
/**
|
|
15
15
|
* Translation plugins
|
|
16
16
|
*/
|
|
17
17
|
const PLUGIN_ID = '@jupyterlab/translation-extension:plugin';
|
|
18
|
+
/**
|
|
19
|
+
* Provide the translator connector as a separate plugin to allow for alternative
|
|
20
|
+
* implementations that may want to fetch translation bundles from a different
|
|
21
|
+
* source or endpoint.
|
|
22
|
+
*/
|
|
23
|
+
const translatorConnector = {
|
|
24
|
+
id: '@jupyterlab/translation-extension:translator-connector',
|
|
25
|
+
description: 'Provides the application translation connector.',
|
|
26
|
+
autoStart: true,
|
|
27
|
+
requires: [JupyterFrontEnd.IPaths],
|
|
28
|
+
provides: ITranslatorConnector,
|
|
29
|
+
activate: (app, paths) => {
|
|
30
|
+
const url = paths.urls.translations;
|
|
31
|
+
const serverSettings = app.serviceManager.serverSettings;
|
|
32
|
+
return new TranslatorConnector(url, serverSettings);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The main translator plugin.
|
|
37
|
+
*/
|
|
18
38
|
const translator = {
|
|
19
|
-
id: '@jupyterlab/translation:translator',
|
|
39
|
+
id: '@jupyterlab/translation-extension:translator',
|
|
20
40
|
description: 'Provides the application translation object.',
|
|
21
41
|
autoStart: true,
|
|
22
42
|
requires: [JupyterFrontEnd.IPaths, ISettingRegistry],
|
|
23
|
-
optional: [ILabShell],
|
|
43
|
+
optional: [ILabShell, ITranslatorConnector],
|
|
24
44
|
provides: ITranslator,
|
|
25
|
-
activate: async (app, paths, settings, labShell) => {
|
|
45
|
+
activate: async (app, paths, settings, labShell, connector) => {
|
|
26
46
|
const setting = await settings.load(PLUGIN_ID);
|
|
27
47
|
const currentLocale = setting.get('locale').composite;
|
|
28
48
|
let stringsPrefix = setting.get('stringsPrefix')
|
|
@@ -31,8 +51,13 @@ const translator = {
|
|
|
31
51
|
.composite;
|
|
32
52
|
stringsPrefix = displayStringsPrefix ? stringsPrefix : '';
|
|
33
53
|
const serverSettings = app.serviceManager.serverSettings;
|
|
34
|
-
const translationManager = new TranslationManager(paths.urls.translations, stringsPrefix, serverSettings);
|
|
54
|
+
const translationManager = new TranslationManager(paths.urls.translations, stringsPrefix, serverSettings, connector !== null && connector !== void 0 ? connector : undefined);
|
|
55
|
+
// As we wait for fetching the translation, ITranslator is guarantee to be
|
|
56
|
+
// ready when consumed in other plugins.
|
|
35
57
|
await translationManager.fetch(currentLocale);
|
|
58
|
+
// Set the document language after optionally fetching the system language
|
|
59
|
+
// if the setting 'locale' is set to 'default'
|
|
60
|
+
document.documentElement.lang = translationManager.languageCode;
|
|
36
61
|
// Set translator to UI
|
|
37
62
|
if (labShell) {
|
|
38
63
|
labShell.translator = translationManager;
|
|
@@ -47,115 +72,89 @@ const translator = {
|
|
|
47
72
|
const langMenu = {
|
|
48
73
|
id: PLUGIN_ID,
|
|
49
74
|
description: 'Adds translation commands and settings.',
|
|
50
|
-
requires: [ISettingRegistry, ITranslator],
|
|
75
|
+
requires: [ISettingRegistry, ITranslator, ITranslatorConnector],
|
|
51
76
|
optional: [IMainMenu, ICommandPalette],
|
|
52
77
|
autoStart: true,
|
|
53
|
-
activate: (app, settings, translator, mainMenu, palette) => {
|
|
78
|
+
activate: (app, settings, translator, translatorConnector, mainMenu, palette) => {
|
|
79
|
+
var _a;
|
|
54
80
|
const trans = translator.load('jupyterlab');
|
|
55
81
|
const { commands } = app;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.then(
|
|
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
|
-
.then(data => {
|
|
94
|
-
for (const locale in data['data']) {
|
|
95
|
-
const value = data['data'][locale];
|
|
96
|
-
const displayName = value.displayName;
|
|
97
|
-
const nativeName = value.nativeName;
|
|
98
|
-
const toggled = (currentLocale === 'default' ? 'en' : currentLocale) === locale;
|
|
99
|
-
const label = toggled
|
|
100
|
-
? `${displayName}`
|
|
101
|
-
: `${displayName} - ${nativeName}`;
|
|
102
|
-
// Add a command per language
|
|
103
|
-
command = `jupyterlab-translation:${locale}`;
|
|
104
|
-
commands.addCommand(command, {
|
|
105
|
-
label: label,
|
|
106
|
-
caption: label,
|
|
107
|
-
isEnabled: () => !toggled,
|
|
108
|
-
isVisible: () => true,
|
|
109
|
-
isToggled: () => toggled,
|
|
110
|
-
execute: () => {
|
|
111
|
-
return showDialog({
|
|
112
|
-
title: trans.__('Change interface language?'),
|
|
113
|
-
body: trans.__('After changing the interface language to %1, you will need to reload JupyterLab to see the changes.', label),
|
|
114
|
-
buttons: [
|
|
115
|
-
Dialog.cancelButton({ label: trans.__('Cancel') }),
|
|
116
|
-
Dialog.okButton({ label: trans.__('Change and reload') })
|
|
117
|
-
]
|
|
118
|
-
}).then(result => {
|
|
119
|
-
if (result.button.accept) {
|
|
120
|
-
setting
|
|
121
|
-
.set('locale', locale)
|
|
122
|
-
.then(() => {
|
|
123
|
-
window.location.reload();
|
|
124
|
-
})
|
|
125
|
-
.catch(reason => {
|
|
126
|
-
console.error(reason);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
// Add the language command to the menu
|
|
133
|
-
if (languagesMenu) {
|
|
134
|
-
languagesMenu.addItem({
|
|
135
|
-
command,
|
|
136
|
-
args: {}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
if (palette) {
|
|
140
|
-
palette.addItem({
|
|
141
|
-
category: trans.__('Display Languages'),
|
|
142
|
-
command
|
|
82
|
+
// Create a languages menu
|
|
83
|
+
const languagesMenu = mainMenu
|
|
84
|
+
? (_a = mainMenu.settingsMenu.items.find(item => {
|
|
85
|
+
var _a;
|
|
86
|
+
return item.type === 'submenu' &&
|
|
87
|
+
((_a = item.submenu) === null || _a === void 0 ? void 0 : _a.id) === 'jp-mainmenu-settings-language';
|
|
88
|
+
})) === null || _a === void 0 ? void 0 : _a.submenu
|
|
89
|
+
: null;
|
|
90
|
+
// Get list of available locales
|
|
91
|
+
translatorConnector
|
|
92
|
+
.fetch({ language: '' })
|
|
93
|
+
// TODO: fix usage of any
|
|
94
|
+
.then((data) => {
|
|
95
|
+
const appLocale = translator.languageCode.replace('-', '_');
|
|
96
|
+
for (const locale in data['data']) {
|
|
97
|
+
const value = data['data'][locale];
|
|
98
|
+
const displayName = value.displayName;
|
|
99
|
+
const nativeName = value.nativeName;
|
|
100
|
+
const toggled = appLocale === locale;
|
|
101
|
+
const label = toggled
|
|
102
|
+
? `${displayName}`
|
|
103
|
+
: `${displayName} - ${nativeName}`;
|
|
104
|
+
// Add a command per language
|
|
105
|
+
const command = `jupyterlab-translation:${locale}`;
|
|
106
|
+
commands.addCommand(command, {
|
|
107
|
+
label: label,
|
|
108
|
+
caption: trans.__('Change interface language to %1', label),
|
|
109
|
+
isEnabled: () => !toggled,
|
|
110
|
+
isToggled: () => toggled,
|
|
111
|
+
execute: async () => {
|
|
112
|
+
const result = await showDialog({
|
|
113
|
+
title: trans.__('Change interface language?'),
|
|
114
|
+
body: trans.__('After changing the interface language to %1, you will need to reload JupyterLab to see the changes.', label),
|
|
115
|
+
buttons: [
|
|
116
|
+
Dialog.cancelButton(),
|
|
117
|
+
Dialog.okButton({ label: trans.__('Change and reload') })
|
|
118
|
+
]
|
|
143
119
|
});
|
|
120
|
+
if (result.button.accept) {
|
|
121
|
+
try {
|
|
122
|
+
await settings.set(PLUGIN_ID, 'locale', locale);
|
|
123
|
+
window.location.reload();
|
|
124
|
+
}
|
|
125
|
+
catch (reason) {
|
|
126
|
+
console.error(`Failed to update language locale to ${locale}`, reason);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
144
129
|
}
|
|
130
|
+
});
|
|
131
|
+
// Add the language command to the menu
|
|
132
|
+
if (languagesMenu) {
|
|
133
|
+
languagesMenu.addItem({
|
|
134
|
+
command,
|
|
135
|
+
args: {}
|
|
136
|
+
});
|
|
145
137
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
138
|
+
if (palette) {
|
|
139
|
+
palette.addItem({
|
|
140
|
+
category: trans.__('Display Languages'),
|
|
141
|
+
command
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
150
145
|
})
|
|
151
146
|
.catch(reason => {
|
|
152
|
-
console.error(`
|
|
147
|
+
console.error(`Available locales errored!\n${reason}`);
|
|
153
148
|
});
|
|
154
149
|
}
|
|
155
150
|
};
|
|
156
151
|
/**
|
|
157
152
|
* Export the plugins as default.
|
|
158
153
|
*/
|
|
159
|
-
const plugins = [
|
|
154
|
+
const plugins = [
|
|
155
|
+
translatorConnector,
|
|
156
|
+
translator,
|
|
157
|
+
langMenu
|
|
158
|
+
];
|
|
160
159
|
export default plugins;
|
|
161
160
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;+EAG+E;AAC/E;;;GAGG;AAEH,OAAO,EACL,SAAS,EACT,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EACL,WAAW,EACX,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;+EAG+E;AAC/E;;;GAGG;AAEH,OAAO,EACL,SAAS,EACT,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAEjC;;GAEG;AACH,MAAM,SAAS,GAAG,0CAA0C,CAAC;AAE7D;;;;GAIG;AACH,MAAM,mBAAmB,GAAgD;IACvE,EAAE,EAAE,wDAAwD;IAC5D,WAAW,EAAE,iDAAiD;IAC9D,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC;IAClC,QAAQ,EAAE,oBAAoB;IAC9B,QAAQ,EAAE,CAAC,GAAoB,EAAE,KAA6B,EAAE,EAAE;QAChE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;QACpC,MAAM,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC;QACzD,OAAO,IAAI,mBAAmB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IACtD,CAAC;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,GAAuC;IACrD,EAAE,EAAE,8CAA8C;IAClD,WAAW,EAAE,8CAA8C;IAC3D,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,gBAAgB,CAAC;IACpD,QAAQ,EAAE,CAAC,SAAS,EAAE,oBAAoB,CAAC;IAC3C,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,KAAK,EACb,GAAoB,EACpB,KAA6B,EAC7B,QAA0B,EAC1B,QAA0B,EAC1B,SAAsC,EACtC,EAAE;QACF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,aAAa,GAAW,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,SAAmB,CAAC;QACxE,IAAI,aAAa,GAAW,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;aACrD,SAAmB,CAAC;QACvB,MAAM,oBAAoB,GAAY,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;aACtE,SAAoB,CAAC;QACxB,aAAa,GAAG,oBAAoB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC;QACzD,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,CAC/C,KAAK,CAAC,IAAI,CAAC,YAAY,EACvB,aAAa,EACb,cAAc,EACd,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,SAAS,CACvB,CAAC;QACF,0EAA0E;QAC1E,wCAAwC;QACxC,MAAM,kBAAkB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAE9C,0EAA0E;QAC1E,8CAA8C;QAC9C,QAAQ,CAAC,eAAe,CAAC,IAAI,GAAG,kBAAkB,CAAC,YAAY,CAAC;QAEhE,uBAAuB;QACvB,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,UAAU,GAAG,kBAAkB,CAAC;QAC3C,CAAC;QAED,MAAM,CAAC,UAAU,GAAG,kBAAkB,CAAC;QAEvC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,QAAQ,GAAgC;IAC5C,EAAE,EAAE,SAAS;IACb,WAAW,EAAE,yCAAyC;IACtD,QAAQ,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,oBAAoB,CAAC;IAC/D,QAAQ,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;IACtC,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,CACR,GAAoB,EACpB,QAA0B,EAC1B,UAAuB,EACvB,mBAAyC,EACzC,QAA0B,EAC1B,OAA+B,EAC/B,EAAE;;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;QAEzB,0BAA0B;QAC1B,MAAM,aAAa,GAAG,QAAQ;YAC5B,CAAC,CAAC,MAAA,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAC9B,IAAI,CAAC,EAAE;;gBACL,OAAA,IAAI,CAAC,IAAI,KAAK,SAAS;oBACvB,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,EAAE,MAAK,+BAA+B,CAAA;aAAA,CACvD,0CAAE,OAAO;YACZ,CAAC,CAAC,IAAI,CAAC;QAET,gCAAgC;QAChC,mBAAmB;aAChB,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACxB,yBAAyB;aACxB,IAAI,CAAC,CAAC,IAAS,EAAE,EAAE;YAClB,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC5D,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;gBACnC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;gBACtC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;gBACpC,MAAM,OAAO,GAAG,SAAS,KAAK,MAAM,CAAC;gBACrC,MAAM,KAAK,GAAG,OAAO;oBACnB,CAAC,CAAC,GAAG,WAAW,EAAE;oBAClB,CAAC,CAAC,GAAG,WAAW,MAAM,UAAU,EAAE,CAAC;gBAErC,6BAA6B;gBAC7B,MAAM,OAAO,GAAG,0BAA0B,MAAM,EAAE,CAAC;gBACnD,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE;oBAC3B,KAAK,EAAE,KAAK;oBACZ,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,CAAC;oBAC3D,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO;oBACzB,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO;oBACxB,OAAO,EAAE,KAAK,IAAI,EAAE;wBAClB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;4BAC9B,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,4BAA4B,CAAC;4BAC7C,IAAI,EAAE,KAAK,CAAC,EAAE,CACZ,qGAAqG,EACrG,KAAK,CACN;4BACD,OAAO,EAAE;gCACP,MAAM,CAAC,YAAY,EAAE;gCACrB,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC;6BAC1D;yBACF,CAAC,CAAC;wBAEH,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;4BACzB,IAAI,CAAC;gCACH,MAAM,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;gCAChD,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;4BAC3B,CAAC;4BAAC,OAAO,MAAM,EAAE,CAAC;gCAChB,OAAO,CAAC,KAAK,CACX,uCAAuC,MAAM,EAAE,EAC/C,MAAM,CACP,CAAC;4BACJ,CAAC;wBACH,CAAC;oBACH,CAAC;iBACF,CAAC,CAAC;gBAEH,uCAAuC;gBACvC,IAAI,aAAa,EAAE,CAAC;oBAClB,aAAa,CAAC,OAAO,CAAC;wBACpB,OAAO;wBACP,IAAI,EAAE,EAAE;qBACT,CAAC,CAAC;gBACL,CAAC;gBAED,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,OAAO,CAAC;wBACd,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAAC;wBACvC,OAAO;qBACR,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,MAAM,CAAC,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACP,CAAC;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,GAAiC;IAC5C,mBAAmB;IACnB,UAAU;IACV,QAAQ;CACT,CAAC;AACF,eAAe,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/translation-extension",
|
|
3
|
-
"version": "4.4.0-
|
|
3
|
+
"version": "4.4.0-beta.1",
|
|
4
4
|
"description": "JupyterLab - Translation services",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"watch": "tsc -w"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@jupyterlab/application": "^4.4.0-
|
|
41
|
-
"@jupyterlab/apputils": "^4.5.0-
|
|
42
|
-
"@jupyterlab/mainmenu": "^4.4.0-
|
|
43
|
-
"@jupyterlab/settingregistry": "^4.4.0-
|
|
44
|
-
"@jupyterlab/translation": "^4.4.0-
|
|
40
|
+
"@jupyterlab/application": "^4.4.0-beta.1",
|
|
41
|
+
"@jupyterlab/apputils": "^4.5.0-beta.1",
|
|
42
|
+
"@jupyterlab/mainmenu": "^4.4.0-beta.1",
|
|
43
|
+
"@jupyterlab/settingregistry": "^4.4.0-beta.1",
|
|
44
|
+
"@jupyterlab/translation": "^4.4.0-beta.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"rimraf": "~5.0.5",
|
|
48
|
-
"typescript": "~5.
|
|
48
|
+
"typescript": "~5.5.4"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -17,8 +17,9 @@ import { IMainMenu } from '@jupyterlab/mainmenu';
|
|
|
17
17
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
18
18
|
import {
|
|
19
19
|
ITranslator,
|
|
20
|
-
|
|
21
|
-
TranslationManager
|
|
20
|
+
ITranslatorConnector,
|
|
21
|
+
TranslationManager,
|
|
22
|
+
TranslatorConnector
|
|
22
23
|
} from '@jupyterlab/translation';
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -26,18 +27,40 @@ import {
|
|
|
26
27
|
*/
|
|
27
28
|
const PLUGIN_ID = '@jupyterlab/translation-extension:plugin';
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Provide the translator connector as a separate plugin to allow for alternative
|
|
32
|
+
* implementations that may want to fetch translation bundles from a different
|
|
33
|
+
* source or endpoint.
|
|
34
|
+
*/
|
|
35
|
+
const translatorConnector: JupyterFrontEndPlugin<ITranslatorConnector> = {
|
|
36
|
+
id: '@jupyterlab/translation-extension:translator-connector',
|
|
37
|
+
description: 'Provides the application translation connector.',
|
|
38
|
+
autoStart: true,
|
|
39
|
+
requires: [JupyterFrontEnd.IPaths],
|
|
40
|
+
provides: ITranslatorConnector,
|
|
41
|
+
activate: (app: JupyterFrontEnd, paths: JupyterFrontEnd.IPaths) => {
|
|
42
|
+
const url = paths.urls.translations;
|
|
43
|
+
const serverSettings = app.serviceManager.serverSettings;
|
|
44
|
+
return new TranslatorConnector(url, serverSettings);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The main translator plugin.
|
|
50
|
+
*/
|
|
29
51
|
const translator: JupyterFrontEndPlugin<ITranslator> = {
|
|
30
|
-
id: '@jupyterlab/translation:translator',
|
|
52
|
+
id: '@jupyterlab/translation-extension:translator',
|
|
31
53
|
description: 'Provides the application translation object.',
|
|
32
54
|
autoStart: true,
|
|
33
55
|
requires: [JupyterFrontEnd.IPaths, ISettingRegistry],
|
|
34
|
-
optional: [ILabShell],
|
|
56
|
+
optional: [ILabShell, ITranslatorConnector],
|
|
35
57
|
provides: ITranslator,
|
|
36
58
|
activate: async (
|
|
37
59
|
app: JupyterFrontEnd,
|
|
38
60
|
paths: JupyterFrontEnd.IPaths,
|
|
39
61
|
settings: ISettingRegistry,
|
|
40
|
-
labShell: ILabShell | null
|
|
62
|
+
labShell: ILabShell | null,
|
|
63
|
+
connector: ITranslatorConnector | null
|
|
41
64
|
) => {
|
|
42
65
|
const setting = await settings.load(PLUGIN_ID);
|
|
43
66
|
const currentLocale: string = setting.get('locale').composite as string;
|
|
@@ -50,10 +73,17 @@ const translator: JupyterFrontEndPlugin<ITranslator> = {
|
|
|
50
73
|
const translationManager = new TranslationManager(
|
|
51
74
|
paths.urls.translations,
|
|
52
75
|
stringsPrefix,
|
|
53
|
-
serverSettings
|
|
76
|
+
serverSettings,
|
|
77
|
+
connector ?? undefined
|
|
54
78
|
);
|
|
79
|
+
// As we wait for fetching the translation, ITranslator is guarantee to be
|
|
80
|
+
// ready when consumed in other plugins.
|
|
55
81
|
await translationManager.fetch(currentLocale);
|
|
56
82
|
|
|
83
|
+
// Set the document language after optionally fetching the system language
|
|
84
|
+
// if the setting 'locale' is set to 'default'
|
|
85
|
+
document.documentElement.lang = translationManager.languageCode;
|
|
86
|
+
|
|
57
87
|
// Set translator to UI
|
|
58
88
|
if (labShell) {
|
|
59
89
|
labShell.translator = translationManager;
|
|
@@ -71,131 +101,96 @@ const translator: JupyterFrontEndPlugin<ITranslator> = {
|
|
|
71
101
|
const langMenu: JupyterFrontEndPlugin<void> = {
|
|
72
102
|
id: PLUGIN_ID,
|
|
73
103
|
description: 'Adds translation commands and settings.',
|
|
74
|
-
requires: [ISettingRegistry, ITranslator],
|
|
104
|
+
requires: [ISettingRegistry, ITranslator, ITranslatorConnector],
|
|
75
105
|
optional: [IMainMenu, ICommandPalette],
|
|
76
106
|
autoStart: true,
|
|
77
107
|
activate: (
|
|
78
108
|
app: JupyterFrontEnd,
|
|
79
109
|
settings: ISettingRegistry,
|
|
80
110
|
translator: ITranslator,
|
|
111
|
+
translatorConnector: ITranslatorConnector,
|
|
81
112
|
mainMenu: IMainMenu | null,
|
|
82
113
|
palette: ICommandPalette | null
|
|
83
114
|
) => {
|
|
84
115
|
const trans = translator.load('jupyterlab');
|
|
85
116
|
const { commands } = app;
|
|
86
|
-
let currentLocale: string;
|
|
87
|
-
/**
|
|
88
|
-
* Load the settings for this extension
|
|
89
|
-
*
|
|
90
|
-
* @param setting Extension settings
|
|
91
|
-
*/
|
|
92
|
-
function loadSetting(setting: ISettingRegistry.ISettings): void {
|
|
93
|
-
// Read the settings and convert to the correct type
|
|
94
|
-
currentLocale = setting.get('locale').composite as string;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
settings
|
|
98
|
-
.load(PLUGIN_ID)
|
|
99
|
-
.then(setting => {
|
|
100
|
-
// Read the settings
|
|
101
|
-
loadSetting(setting);
|
|
102
|
-
|
|
103
|
-
// Ensure currentLocale is not 'default' which is not a valid language code
|
|
104
|
-
if (currentLocale !== 'default') {
|
|
105
|
-
document.documentElement.lang = (currentLocale ?? '').replace(
|
|
106
|
-
'_',
|
|
107
|
-
'-'
|
|
108
|
-
);
|
|
109
|
-
} else {
|
|
110
|
-
document.documentElement.lang = 'en-US';
|
|
111
|
-
}
|
|
112
117
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
),
|
|
156
|
-
buttons: [
|
|
157
|
-
Dialog.cancelButton({ label: trans.__('Cancel') }),
|
|
158
|
-
Dialog.okButton({ label: trans.__('Change and reload') })
|
|
159
|
-
]
|
|
160
|
-
}).then(result => {
|
|
161
|
-
if (result.button.accept) {
|
|
162
|
-
setting
|
|
163
|
-
.set('locale', locale)
|
|
164
|
-
.then(() => {
|
|
165
|
-
window.location.reload();
|
|
166
|
-
})
|
|
167
|
-
.catch(reason => {
|
|
168
|
-
console.error(reason);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
}
|
|
118
|
+
// Create a languages menu
|
|
119
|
+
const languagesMenu = mainMenu
|
|
120
|
+
? mainMenu.settingsMenu.items.find(
|
|
121
|
+
item =>
|
|
122
|
+
item.type === 'submenu' &&
|
|
123
|
+
item.submenu?.id === 'jp-mainmenu-settings-language'
|
|
124
|
+
)?.submenu
|
|
125
|
+
: null;
|
|
126
|
+
|
|
127
|
+
// Get list of available locales
|
|
128
|
+
translatorConnector
|
|
129
|
+
.fetch({ language: '' })
|
|
130
|
+
// TODO: fix usage of any
|
|
131
|
+
.then((data: any) => {
|
|
132
|
+
const appLocale = translator.languageCode.replace('-', '_');
|
|
133
|
+
for (const locale in data['data']) {
|
|
134
|
+
const value = data['data'][locale];
|
|
135
|
+
const displayName = value.displayName;
|
|
136
|
+
const nativeName = value.nativeName;
|
|
137
|
+
const toggled = appLocale === locale;
|
|
138
|
+
const label = toggled
|
|
139
|
+
? `${displayName}`
|
|
140
|
+
: `${displayName} - ${nativeName}`;
|
|
141
|
+
|
|
142
|
+
// Add a command per language
|
|
143
|
+
const command = `jupyterlab-translation:${locale}`;
|
|
144
|
+
commands.addCommand(command, {
|
|
145
|
+
label: label,
|
|
146
|
+
caption: trans.__('Change interface language to %1', label),
|
|
147
|
+
isEnabled: () => !toggled,
|
|
148
|
+
isToggled: () => toggled,
|
|
149
|
+
execute: async () => {
|
|
150
|
+
const result = await showDialog({
|
|
151
|
+
title: trans.__('Change interface language?'),
|
|
152
|
+
body: trans.__(
|
|
153
|
+
'After changing the interface language to %1, you will need to reload JupyterLab to see the changes.',
|
|
154
|
+
label
|
|
155
|
+
),
|
|
156
|
+
buttons: [
|
|
157
|
+
Dialog.cancelButton(),
|
|
158
|
+
Dialog.okButton({ label: trans.__('Change and reload') })
|
|
159
|
+
]
|
|
173
160
|
});
|
|
174
161
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
category: trans.__('Display Languages'),
|
|
186
|
-
command
|
|
187
|
-
});
|
|
162
|
+
if (result.button.accept) {
|
|
163
|
+
try {
|
|
164
|
+
await settings.set(PLUGIN_ID, 'locale', locale);
|
|
165
|
+
window.location.reload();
|
|
166
|
+
} catch (reason) {
|
|
167
|
+
console.error(
|
|
168
|
+
`Failed to update language locale to ${locale}`,
|
|
169
|
+
reason
|
|
170
|
+
);
|
|
171
|
+
}
|
|
188
172
|
}
|
|
189
173
|
}
|
|
190
|
-
})
|
|
191
|
-
.catch(reason => {
|
|
192
|
-
console.error(`Available locales errored!\n${reason}`);
|
|
193
174
|
});
|
|
175
|
+
|
|
176
|
+
// Add the language command to the menu
|
|
177
|
+
if (languagesMenu) {
|
|
178
|
+
languagesMenu.addItem({
|
|
179
|
+
command,
|
|
180
|
+
args: {}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (palette) {
|
|
185
|
+
palette.addItem({
|
|
186
|
+
category: trans.__('Display Languages'),
|
|
187
|
+
command
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
194
191
|
})
|
|
195
192
|
.catch(reason => {
|
|
196
|
-
console.error(
|
|
197
|
-
`The jupyterlab translation extension appears to be missing.\n${reason}`
|
|
198
|
-
);
|
|
193
|
+
console.error(`Available locales errored!\n${reason}`);
|
|
199
194
|
});
|
|
200
195
|
}
|
|
201
196
|
};
|
|
@@ -203,5 +198,9 @@ const langMenu: JupyterFrontEndPlugin<void> = {
|
|
|
203
198
|
/**
|
|
204
199
|
* Export the plugins as default.
|
|
205
200
|
*/
|
|
206
|
-
const plugins: JupyterFrontEndPlugin<any>[] = [
|
|
201
|
+
const plugins: JupyterFrontEndPlugin<any>[] = [
|
|
202
|
+
translatorConnector,
|
|
203
|
+
translator,
|
|
204
|
+
langMenu
|
|
205
|
+
];
|
|
207
206
|
export default plugins;
|