@jupyterlab/translation-extension 4.4.0-beta.0 → 4.4.0-beta.2
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.d.ts +1 -1
- package/lib/index.js +98 -100
- package/lib/index.js.map +1 -1
- package/package.json +6 -6
- package/src/index.ts +111 -113
package/lib/index.d.ts
CHANGED
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,88 @@ 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
|
-
.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
requestTranslationsAPI('', '', {}, serverSettings)
|
|
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()
|
|
93
|
+
.then(languageList => {
|
|
94
|
+
const appLocale = translator.languageCode.replace('-', '_');
|
|
95
|
+
for (const locale in languageList.data) {
|
|
96
|
+
const value = languageList.data[locale];
|
|
97
|
+
const displayName = value.displayName;
|
|
98
|
+
const nativeName = value.nativeName;
|
|
99
|
+
const toggled = appLocale === locale;
|
|
100
|
+
const label = toggled
|
|
101
|
+
? `${displayName}`
|
|
102
|
+
: `${displayName} - ${nativeName}`;
|
|
103
|
+
// Add a command per language
|
|
104
|
+
const command = `jupyterlab-translation:${locale}`;
|
|
105
|
+
commands.addCommand(command, {
|
|
106
|
+
label: label,
|
|
107
|
+
caption: trans.__('Change interface language to %1', label),
|
|
108
|
+
isEnabled: () => !toggled,
|
|
109
|
+
isToggled: () => toggled,
|
|
110
|
+
execute: async () => {
|
|
111
|
+
const result = await 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(),
|
|
116
|
+
Dialog.okButton({ label: trans.__('Change and reload') })
|
|
117
|
+
]
|
|
143
118
|
});
|
|
119
|
+
if (result.button.accept) {
|
|
120
|
+
try {
|
|
121
|
+
await settings.set(PLUGIN_ID, 'locale', locale);
|
|
122
|
+
window.location.reload();
|
|
123
|
+
}
|
|
124
|
+
catch (reason) {
|
|
125
|
+
console.error(`Failed to update language locale to ${locale}`, reason);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
144
128
|
}
|
|
129
|
+
});
|
|
130
|
+
// Add the language command to the menu
|
|
131
|
+
if (languagesMenu) {
|
|
132
|
+
languagesMenu.addItem({
|
|
133
|
+
command,
|
|
134
|
+
args: {}
|
|
135
|
+
});
|
|
145
136
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
137
|
+
if (palette) {
|
|
138
|
+
palette.addItem({
|
|
139
|
+
category: trans.__('Display Languages'),
|
|
140
|
+
command
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
150
144
|
})
|
|
151
145
|
.catch(reason => {
|
|
152
|
-
console.error(`
|
|
146
|
+
console.error(`Available locales errored!\n${reason}`);
|
|
153
147
|
});
|
|
154
148
|
}
|
|
155
149
|
};
|
|
156
150
|
/**
|
|
157
151
|
* Export the plugins as default.
|
|
158
152
|
*/
|
|
159
|
-
const plugins = [
|
|
153
|
+
const plugins = [
|
|
154
|
+
translatorConnector,
|
|
155
|
+
translator,
|
|
156
|
+
langMenu
|
|
157
|
+
];
|
|
160
158
|
export default plugins;
|
|
161
159
|
//# 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":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/translation-extension",
|
|
3
|
-
"version": "4.4.0-beta.
|
|
3
|
+
"version": "4.4.0-beta.2",
|
|
4
4
|
"description": "JupyterLab - Translation services",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"watch": "tsc -w"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@jupyterlab/application": "^4.4.0-beta.
|
|
41
|
-
"@jupyterlab/apputils": "^4.5.0-beta.
|
|
42
|
-
"@jupyterlab/mainmenu": "^4.4.0-beta.
|
|
43
|
-
"@jupyterlab/settingregistry": "^4.4.0-beta.
|
|
44
|
-
"@jupyterlab/translation": "^4.4.0-beta.
|
|
40
|
+
"@jupyterlab/application": "^4.4.0-beta.2",
|
|
41
|
+
"@jupyterlab/apputils": "^4.5.0-beta.2",
|
|
42
|
+
"@jupyterlab/mainmenu": "^4.4.0-beta.2",
|
|
43
|
+
"@jupyterlab/settingregistry": "^4.4.0-beta.2",
|
|
44
|
+
"@jupyterlab/translation": "^4.4.0-beta.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"rimraf": "~5.0.5",
|
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,95 @@ 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
|
-
label
|
|
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()
|
|
130
|
+
.then(languageList => {
|
|
131
|
+
const appLocale = translator.languageCode.replace('-', '_');
|
|
132
|
+
for (const locale in languageList.data) {
|
|
133
|
+
const value = languageList.data[locale];
|
|
134
|
+
const displayName = value.displayName;
|
|
135
|
+
const nativeName = value.nativeName;
|
|
136
|
+
const toggled = appLocale === locale;
|
|
137
|
+
const label = toggled
|
|
138
|
+
? `${displayName}`
|
|
139
|
+
: `${displayName} - ${nativeName}`;
|
|
140
|
+
|
|
141
|
+
// Add a command per language
|
|
142
|
+
const command = `jupyterlab-translation:${locale}`;
|
|
143
|
+
commands.addCommand(command, {
|
|
144
|
+
label: label,
|
|
145
|
+
caption: trans.__('Change interface language to %1', label),
|
|
146
|
+
isEnabled: () => !toggled,
|
|
147
|
+
isToggled: () => toggled,
|
|
148
|
+
execute: async () => {
|
|
149
|
+
const result = await showDialog({
|
|
150
|
+
title: trans.__('Change interface language?'),
|
|
151
|
+
body: trans.__(
|
|
152
|
+
'After changing the interface language to %1, you will need to reload JupyterLab to see the changes.',
|
|
153
|
+
label
|
|
154
|
+
),
|
|
155
|
+
buttons: [
|
|
156
|
+
Dialog.cancelButton(),
|
|
157
|
+
Dialog.okButton({ label: trans.__('Change and reload') })
|
|
158
|
+
]
|
|
173
159
|
});
|
|
174
160
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
category: trans.__('Display Languages'),
|
|
186
|
-
command
|
|
187
|
-
});
|
|
161
|
+
if (result.button.accept) {
|
|
162
|
+
try {
|
|
163
|
+
await settings.set(PLUGIN_ID, 'locale', locale);
|
|
164
|
+
window.location.reload();
|
|
165
|
+
} catch (reason) {
|
|
166
|
+
console.error(
|
|
167
|
+
`Failed to update language locale to ${locale}`,
|
|
168
|
+
reason
|
|
169
|
+
);
|
|
170
|
+
}
|
|
188
171
|
}
|
|
189
172
|
}
|
|
190
|
-
})
|
|
191
|
-
.catch(reason => {
|
|
192
|
-
console.error(`Available locales errored!\n${reason}`);
|
|
193
173
|
});
|
|
174
|
+
|
|
175
|
+
// Add the language command to the menu
|
|
176
|
+
if (languagesMenu) {
|
|
177
|
+
languagesMenu.addItem({
|
|
178
|
+
command,
|
|
179
|
+
args: {}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (palette) {
|
|
184
|
+
palette.addItem({
|
|
185
|
+
category: trans.__('Display Languages'),
|
|
186
|
+
command
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
194
190
|
})
|
|
195
191
|
.catch(reason => {
|
|
196
|
-
console.error(
|
|
197
|
-
`The jupyterlab translation extension appears to be missing.\n${reason}`
|
|
198
|
-
);
|
|
192
|
+
console.error(`Available locales errored!\n${reason}`);
|
|
199
193
|
});
|
|
200
194
|
}
|
|
201
195
|
};
|
|
@@ -203,5 +197,9 @@ const langMenu: JupyterFrontEndPlugin<void> = {
|
|
|
203
197
|
/**
|
|
204
198
|
* Export the plugins as default.
|
|
205
199
|
*/
|
|
206
|
-
const plugins: JupyterFrontEndPlugin<
|
|
200
|
+
const plugins: JupyterFrontEndPlugin<unknown>[] = [
|
|
201
|
+
translatorConnector,
|
|
202
|
+
translator,
|
|
203
|
+
langMenu
|
|
204
|
+
];
|
|
207
205
|
export default plugins;
|