Skip to content

Commit

Permalink
Add translation for the frontend in Lab (#709)
Browse files Browse the repository at this point in the history
* Add translation for the frontend in Lab

* Add missing strings

* Fix show base option

* Fix labextension watch mode

* More translator propagation

* More translation

* Update Playwright Snapshots

* Update Playwright Snapshots

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
fcollonval and github-actions[bot] committed Oct 26, 2023
1 parent 5efc481 commit cbc57d2
Show file tree
Hide file tree
Showing 22 changed files with 261 additions and 97 deletions.
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"updated": "lerna updated",
"watch:webapp": "run-p watch:lib watch:app",
"watch:app": "lerna exec --stream --scope \"nbdime-webapp\" npm run watch",
"watch:lib": "lerna exec --stream --scope \"nbdime\" --scope \"nbdime-jupyterlab\" npm run watch"
"watch:lib": "lerna exec --stream --parallel --scope \"nbdime\" --scope \"nbdime-jupyterlab\" npm run watch"
},
"devDependencies": {
"@jupyterlab/buildutils": "^4.0.0",
Expand Down
11 changes: 8 additions & 3 deletions packages/labextension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,19 @@
],
"style": "style/index.css",
"scripts": {
"build": "npm run build:lib && npm run build:labextension",
"build": "npm run build:lib:prod && npm run build:labextension",
"build:dev": "npm run build:lib && jupyter labextension build --development True .",
"build:labextension": "rimraf ../../nbdime/labextension && mkdirp ../../nbdime/labextension && jupyter labextension build .",
"build:lib": "tsc --build",
"build:lib": "tsc --sourceMap",
"build:lib:prod": "tsc --build",
"clean": "npm run clean:lib && npm run clean:labextension",
"clean:labextension": "rimraf ../../nbdime/labextension",
"clean:lib": "rimraf tsconfig.tsbuildinfo lib",
"prepublishOnly": "npm run build",
"update": "rimraf node_modules/nbdime && npm install && npm run build",
"watch": "tsc --build --watch"
"watch": "run-p watch:src watch:labextension",
"watch:src": "tsc -w --sourceMap",
"watch:labextension": "jupyter labextension watch ."
},
"dependencies": {
"@jupyterlab/apputils": "^4.0.0",
Expand All @@ -50,6 +53,7 @@
"@jupyterlab/rendermime": "^4.0.0",
"@jupyterlab/services": "^7.0.0",
"@jupyterlab/settingregistry": "^4.0.0",
"@jupyterlab/translation": "^4.0.0",
"@lumino/algorithm": "^2.0.1",
"@lumino/coreutils": "^2.1.2",
"@lumino/disposable": "^2.1.2",
Expand All @@ -62,6 +66,7 @@
"@jupyterlab/docregistry": "^4.0.0",
"@lumino/commands": "^2.0.0",
"mkdirp": "^3.0.0",
"npm-run-all": "^4.1.5",
"rimraf": "^5.0.0",
"typescript": "^4.9.0"
},
Expand Down
38 changes: 26 additions & 12 deletions packages/labextension/src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { CodeEditor } from '@jupyterlab/codeeditor';

import { PathExt, URLExt } from '@jupyterlab/coreutils';

import type { IRenderMimeRegistry } from '@jupyterlab/rendermime';

import type { CodeEditor } from '@jupyterlab/codeeditor';

import { ServerConnection } from '@jupyterlab/services';

import { nullTranslator, type ITranslator } from '@jupyterlab/translation';

import type { Widget } from '@lumino/widgets';

import { NbdimeWidget } from './widget';
Expand All @@ -22,11 +24,13 @@ export function diffNotebook(args: {
readonly rendermime: IRenderMimeRegistry;
readonly editorFactory: CodeEditor.Factory;
hideUnchanged?: boolean;
translator?: ITranslator;
}): Widget {
let { base, remote } = args;
let { base, remote, translator } = args;
const trans = (translator ?? nullTranslator).load('nbdime');
let widget = new NbdimeWidget(args);
widget.title.label = `Diff: ${base}${remote}`;
widget.title.caption = `Local: ${base}\nRemote: '${remote}'`;
widget.title.label = trans.__('Diff: %1%2', base, remote);
widget.title.caption = trans.__("Local: '%1'\nRemote: '%2'", base, remote);
return widget;
}

Expand All @@ -35,20 +39,27 @@ export function diffNotebookCheckpoint(args: {
readonly rendermime: IRenderMimeRegistry;
readonly editorFactory: CodeEditor.Factory;
hideUnchanged?: boolean;
translator?: ITranslator;
}): Widget {
const { path, rendermime, hideUnchanged, editorFactory } = args;
const { path, rendermime, hideUnchanged, editorFactory, translator } = args;
const trans = (translator ?? nullTranslator).load('nbdime');
let nb_dir = PathExt.dirname(path);
let name = PathExt.basename(path, '.ipynb');
let base = PathExt.join(nb_dir, name + '.ipynb');

let widget = new NbdimeWidget({
base,
editorFactory,
rendermime,
baseLabel: 'Checkpoint',
baseLabel: trans.__('Checkpoint'),
hideUnchanged,
translator,
});
widget.title.label = `Diff checkpoint: ${name}`;
widget.title.caption = `Local: latest checkpoint\nRemote: '${path}'`;
widget.title.label = trans.__('Diff checkpoint: %1', name);
widget.title.caption = trans.__(
"Local: latest checkpoint\nRemote: '%1'",
path,
);
widget.title.iconClass = 'fa fa-clock-o jp-fa-tabIcon';
return widget;
}
Expand All @@ -58,17 +69,20 @@ export function diffNotebookGit(args: {
readonly rendermime: IRenderMimeRegistry;
readonly editorFactory: CodeEditor.Factory;
hideUnchanged?: boolean;
translator?: ITranslator;
}): Widget {
const { path, rendermime, hideUnchanged, editorFactory } = args;
const { path, rendermime, hideUnchanged, editorFactory, translator } = args;
const trans = (translator ?? nullTranslator).load('nbdime');
let name = PathExt.basename(path, '.ipynb');
let widget = new NbdimeWidget({
base: path,
editorFactory,
rendermime,
hideUnchanged,
translator,
});
widget.title.label = `Diff git: ${name}`;
widget.title.caption = `Local: git HEAD\nRemote: '${path}'`;
widget.title.label = trans.__('Diff git: %1', name);
widget.title.caption = trans.__("Local: git HEAD\nRemote: '%1'", path);
widget.title.iconClass = 'fa fa-git jp-fa-tabIcon';
return widget;
}
Expand Down
44 changes: 30 additions & 14 deletions packages/labextension/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { NotebookPanel, INotebookTracker } from '@jupyterlab/notebook';

import { ISettingRegistry } from '@jupyterlab/settingregistry';

import { ITranslator, nullTranslator } from '@jupyterlab/translation';

import { find } from '@lumino/algorithm';

import type { CommandRegistry } from '@lumino/commands';
Expand All @@ -32,12 +34,6 @@ import { diffNotebookGit, diffNotebookCheckpoint, isNbInGit } from './actions';

const pluginId = 'nbdime-jupyterlab:plugin';

/**
* Error message if the nbdime API is unavailable.
*/
const serverMissingMsg =
'Unable to query nbdime API. Is the server extension enabled?';

const INITIAL_NETWORK_RETRY = 2; // ms

export class NBDiffExtension
Expand Down Expand Up @@ -116,11 +112,20 @@ function addCommands(
rendermime: IRenderMimeRegistry,
settings: ISettingRegistry.ISettings,
editorServices: IEditorServices,
translator: ITranslator,
): void {
const { commands, shell } = app;
const editorFactory = editorServices.factoryService.newInlineEditor.bind(
editorServices.factoryService,
);
const trans = translator.load('nbdime');

/**
* Error message if the nbdime API is unavailable.
*/
const serverMissingMsg = trans.__(
'Unable to query nbdime API. Is the server extension enabled?',
);

// Whether we have our server extension available
let hasAPI = true;
Expand Down Expand Up @@ -194,10 +199,10 @@ function addCommands(
// TODO: Check args for base/remote
// if missing, prompt with dialog.
//let content = current.notebook;
//diffNotebook({base, remote});
//diffNotebook({base, remote, translator});
},
label: erroredGen('Notebook diff'),
caption: erroredGen('Display nbdiff between two notebooks'),
label: erroredGen(trans.__('Notebook diff')),
caption: erroredGen(trans.__('Display nbdiff between two notebooks')),
isEnabled: baseEnabled,
iconClass:
'jp-Icon jp-Icon-16 action-notebook-diff action-notebook-diff-notebooks',
Expand All @@ -215,15 +220,16 @@ function addCommands(
editorFactory,
rendermime,
hideUnchanged,
translator,
});
shell.add(widget);
if (args['activate'] !== false) {
shell.activateById(widget.id);
}
},
label: erroredGen('Notebook checkpoint diff'),
label: erroredGen(trans.__('Notebook checkpoint diff')),
caption: erroredGen(
'Display nbdiff from checkpoint to currently saved version',
trans.__('Display nbdiff from checkpoint to currently saved version'),
),
isEnabled: baseEnabled,
iconClass:
Expand All @@ -241,15 +247,16 @@ function addCommands(
editorFactory,
rendermime,
hideUnchanged,
translator,
});
shell.add(widget);
if (args['activate'] !== false) {
shell.activateById(widget.id);
}
},
label: erroredGen('Notebook Git diff'),
label: erroredGen(trans.__('Notebook Git diff')),
caption: erroredGen(
'Display nbdiff from git HEAD to currently saved version',
trans.__('Display nbdiff from git HEAD to currently saved version'),
),
isEnabled: hasGitNotebook,
iconClass:
Expand All @@ -268,6 +275,7 @@ const nbDiffProvider: JupyterFrontEndPlugin<void> = {
ISettingRegistry,
IEditorServices,
],
optional: [ITranslator],
activate: activateWidgetExtension,
autoStart: true,
};
Expand All @@ -283,13 +291,21 @@ async function activateWidgetExtension(
rendermime: IRenderMimeRegistry,
settingsRegistry: ISettingRegistry,
editorServices: IEditorServices,
translator: ITranslator | null,
): Promise<void> {
let { commands, docRegistry } = app;
let extension = new NBDiffExtension(commands);
docRegistry.addWidgetExtension('Notebook', extension);

const settings = await settingsRegistry.load(pluginId);
addCommands(app, tracker, rendermime, settings, editorServices);
addCommands(
app,
tracker,
rendermime,
settings,
editorServices,
translator ?? nullTranslator,
);
// Update the command registry when the notebook state changes.
tracker.currentChanged.connect(() => {
commands.notifyCommandChanged(CommandIDs.diffNotebookGit);
Expand Down
40 changes: 34 additions & 6 deletions packages/labextension/src/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import type { IRenderMimeRegistry } from '@jupyterlab/rendermime';

import { ServerConnection } from '@jupyterlab/services';

import {
nullTranslator,
type ITranslator,
type TranslationBundle,
} from '@jupyterlab/translation';

import type { JSONObject } from '@lumino/coreutils';

import type { Message } from '@lumino/messaging';
Expand Down Expand Up @@ -53,6 +59,8 @@ export class NbdimeWidget extends Panel {
this.remote = options.remote;
this.editorFactory = options.editorFactory;
this.rendermime = options.rendermime;
this.translator = options.translator ?? nullTranslator;
this.trans = this.translator.load('nbdime');

let header = Private.diffHeader(options);
this.addWidget(header);
Expand Down Expand Up @@ -116,10 +124,17 @@ export class NbdimeWidget extends Panel {
let base = data['base'] as nbformat.INotebookContent;
let diff = data['diff'] as any as IDiffEntry[];
let nbdModel = new NotebookDiffModel(base, diff);
if (nbdModel.metadata) {
const trans = this.translator.load('nbdime');
nbdModel.metadata.collapsibleHeader = trans.__(
'Notebook metadata changed',
);
}
let nbdWidget = new NotebookDiffWidget({
model: nbdModel,
rendermime: this.rendermime,
editorFactory: this.editorFactory,
translator: this.translator,
});

this.scroller.addWidget(nbdWidget);
Expand All @@ -135,7 +150,7 @@ export class NbdimeWidget extends Panel {
return;
}
let widget = new Widget();
widget.node.innerHTML = `Failed to fetch diff: ${error}`;
widget.node.textContent = this.trans.__('Failed to fetch diff: %1', error);
this.scroller.addWidget(widget);
}

Expand All @@ -144,6 +159,8 @@ export class NbdimeWidget extends Panel {

protected editorFactory: CodeEditor.Factory;
protected rendermime: IRenderMimeRegistry;
protected translator: ITranslator;
protected trans: TranslationBundle;

protected header: Widget;
protected scroller: Panel;
Expand Down Expand Up @@ -193,6 +210,11 @@ export namespace NbdimeWidget {
* Whether to hide unchanged cells by default.
*/
hideUnchanged?: boolean;

/**
* Application translator.
*/
translator?: ITranslator;
}
}

Expand All @@ -201,7 +223,8 @@ namespace Private {
* Create a header widget for the diff view.
*/
export function diffHeader(options: NbdimeWidget.IOptions): Widget {
let { base, remote, baseLabel, remoteLabel } = options;
let { base, remote, baseLabel, remoteLabel, translator } = options;
const trans = (translator ?? nullTranslator).load('nbdime');
if (remote) {
if (baseLabel === undefined) {
baseLabel = base;
Expand All @@ -220,19 +243,24 @@ namespace Private {
node.className = 'nbdime-Diff';
node.innerHTML = `
<div class="nbdime-header-buttonrow">
<label><input class="nbdime-hide-unchanged" type="checkbox">Hide unchanged cells</label>
<button class="nbdime-export" style="display: none">Export diff</button>
<label><input class="nbdime-hide-unchanged" type="checkbox"></label>
<button class="nbdime-export" style="display: none"></button>
</div>
<div class="nbdime-header-banner">
<span class="nbdime-header-base"></span>
<span class="nbdime-header-remote"></span>
</div>`;
node
.querySelector('.nbdime-header-buttonrow > label')!
.insertAdjacentText('beforeend', trans.__('Hide unchanged cells'));
node.querySelector('button.nbdime-export')!.textContent =
trans.__('Export diff');
(
node.getElementsByClassName('nbdime-header-base')[0] as HTMLSpanElement
).innerText = baseLabel;
).textContent = baseLabel;
(
node.getElementsByClassName('nbdime-header-remote')[0] as HTMLSpanElement
).innerText = remoteLabel;
).textContent = remoteLabel;

return new Widget({ node });
}
Expand Down

0 comments on commit cbc57d2

Please sign in to comment.