Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Localizing Notebooks - continued #16

Closed
wants to merge 10 commits into from
Closed

Conversation

srl295
Copy link

@srl295 srl295 commented Jun 10, 2016

Continuation of: #10

Based on @TwistedHardware ’s commits. (I dropped the ones which modified the base template.)

<a href="#">{{ _("New Notebook") }}</a>
```

### Javascript files
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this section is accurate - it looks like it's left over from when the proposal was to turn all JS files into templates, which we agreed we don't want to do.

@JCEmmons
Copy link

JCEmmons commented Nov 8, 2016

Updated proposal for translation of Jupyter notebook. Please review/approve, as I'm able to work on this now that I'm back on the job.

@rgbkrk
Copy link
Member

rgbkrk commented Nov 10, 2016

I'm certainly in favor of pressing forward. Let's see how it plays out.

@parente
Copy link
Member

parente commented Nov 10, 2016

I agree with Kyle. The best way to vet the approach is to try it out in a few PRs against notebook and adjust accordingly.

As for the proposal document, I took a quick read through. I want to go back and make a few minor suggestions.


## Detailed Explanation

The Jupyter notebook code presents a significant challenge in terms of enablement for translation,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A link to https://github.com/jupyter/notebook over the text "Jupyter notebook code" might help clarify that the document is explicitly talking about the classic notebook UI and not Jupyter Lab. Given the differences between the two implementations, I think it wise to focus on the former (if that is indeed your goal) and, based on lessons learned from that, tackle Lab localization as a separate task.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, Peter. I added these links and a scope section that makes it clear that this proposal is only for classic notebook. See 6c00c53

mostly because there are multiple different types of source code from which translatable UI strings
are derived.

In Jupyter, translatable strings can come from one of three places:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"In Jupyter Notebook"

```

Once this is complete, any calls to `_()` in the code will retrieve a translated string from
${base_dir}/locale/**xx**/LC_MESSAGES/notebook.mo, where **xx** is the language code in use
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming the locales will ship with notebook, not be external packages that users install. If so, it would be good to clarify this by defining base_dir.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See bff04d5

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think allowing to ship translation as external package would be good. Otherwise releases might get hold on by missing translations. I think trying to pull that from notebook-localisation (or similar), or even notebook-i18n-lang would be good for end-user translator to be able to work without having to install dev with node and all this stuff.
But that can be fixed later. I'm happy to leave that as-is, and modify this after the fact if we figure out how to implement it.

### Javascript files

For Javascript, there are no established APIs that can consume a compiled `.mo` file directly in the same way as gettext().
However, there is a library called [Jed](https://slexaxton.github.io/Jed/) that provides an API set similar to gettext().
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Jed compatible with webpack and/or requirejs (both of which are used in Jupyter Notebook)?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm no javascript guru, but I think I would be, since the example on its main page shows using it as an AMD module.



## Prototype - Proof of Concept
I have created a **VERY** preliminary prototype of Jupyter notebook at (https://github.com/JCEmmons/notebook/tree/intl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, awesome! 🍰

@minrk
Copy link
Member

minrk commented Jan 12, 2017

Picking this up after the holiday. The only thing I have left is that this proposal is scoped only to "notebook classic" as opposed to JupyterLab, and I think the reverse makes a bit more sense. JupyterLab is the future of the notebook client, and the notebook package is heading for retirement pretty soon. Plus, the discussion of tooling sounds like it will fit better in the existing JupyterLab pipeline than the notebook classic one. What do people think about that?

@minrk
Copy link
Member

minrk commented Jan 12, 2017

My brain is rusty, I misunderstood the tooling question, because I read babel as babel. So that part doesn't seem relevant to notebook vs JupyterLab. Given that the server code is still the notebook package for both sides, I think this is a sensible proposal to start there.

Approved by me as-is.

@JCEmmons
Copy link

Thanks, and while I understand that Jupyter lab is the future, "classic" is the present at least for us. I'm close to being ready for a preliminary PR on this, so I will welcome your comments and advice.

@fperez
Copy link
Member

fperez commented Jan 26, 2017

As long as @JCEmmons doesn't mind the fact that there may be a bit of work to be re-done for JLab, I'm +1 here. In fact, there may be some advantage in doing it in Classic so we can kick the tires of the process atop a fairly stable and simpler codebase. Lab is more complex and moving rapidly, so I suspect doing this in Lab right now could prove quite tricky.

@JCEmmons, since you seem OK with that, I'd say let's go ahead and see what we learn!

@minrk pinged the steering council (thanks!) for feedback, but we'll treat silence as acquiescence if we don't hear back from the rest in a few days. No need to stall you here, and very sorry for the delay. We really appreciate your contribution, and this is an important problem we've long failed to tackle.

Copy link
Member

@takluyver takluyver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, we definitely need movement on this front. I've picked up a few specific things inline.


There is currently no standard approach for translating the GUI of [Jupyter notebook]( https://github.com/jupyter/notebook).
This has driven some people to do a
[single language translation for Jupyter 4.1](https://twitter.com/Mbussonn/status/685870031247400960).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be wrong, but I think @Carreau's tweet was pointing to a translation of the release announcement, not the UI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I often translate at least the release announce in French.

the string doesn't exist in the catalog, then the string passed as the argument to _() is
returned.

In this context, **${base_dir}** refers to the base installation directory for notebook. We are
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This definition is not entirely clear to me - I can think of a couple of directories that may be called the 'base installation directory'. I'm guessing you mean the notebook package directory (which contains, for instance, notebookapp.py).

can be consumed by Jed. The author of [Jed](https://slexaxton.github.io/Jed/) recommends
[po2json](https://www.npmjs.com/package/po2json), which can be used
either as a command line utility, or directly from Javascript. I suspect that the conversion from `.po` to either
`.mo` for Python or Jinja2, or conversion to JSON for Javascript would be something we would want to do at install time.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably at build time to be precise - i.e. at least the wheel packages will contain pre-built .mo and .json translation files.

var i18n = new Jed(nbjson);
var _ = function (text) {
return i18n.gettext(text);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have to be done before any JS code uses translatable strings? If all UI construction has to wait for an asynchronous request to get the JSON file, I can see that causing problems. Maybe we can stick the JSON data into the page when we fill the template to avoid that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with caching it should be ok, as we can query the file by its hash and make it expire in 99years. It depends on the size though.


[Babel](http://babel.pocoo.org/en/latest/) allows us to define a set of rules that define
where all the extractable strings are (whether Python, HTML template, or Javascript), what the
extraction methods are (i.e. `_()` for Python or Javascript, and `<% trans >`/`<% endtrans %>`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<> -> {}, based on the Jinja section above

@JCEmmons
Copy link

JCEmmons commented Jan 26, 2017 via email

@takluyver
Copy link
Member

I spotted a few minor things that I think should be fixed (see above). Once those are dealt with, I think we can merge this.

whenever the code base changes. The `.pot` file can be thought of as the source from which all translations are derived.

Translators and/or interested contributors can then use utilities such as [Poedit](https://poedit.net/) to create
translated `.po` files from the master `.pot` file for the desired languages.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did experiment with https://www.transifex.com/ipython/ipython-notebook/ which is online, and we hoped at some point to integrate this into the workflow.


At install time, convert the translated `.po` into two runtime formats:
* Convert to `.mo` which can be used by Python code using the gettext() APIs in Python, and can also be used by
the i18n extensions in [Jinja2](http://jinja.pocoo.org/docs/dev/extensions/#i18n-extension)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean by "install", does this require code execution ? If so we should find an alternative way, as wheels cannot execute code at install time.


In [Jupyter notebook]( https://github.com/jupyter/notebook), translatable strings can come from one of three places:

1. Directly from Python code
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking, and not really important to address here, but we might need to clarify that this will not/cannot address translations of message coming from the kernel. IE ?/?? will likely not be translated.

```

Once this is complete, any calls to `_()` in the code will retrieve a translated string from
${base_dir}/locale/**xx**/LC_MESSAGES/notebook.mo, where **xx** is the language code in use
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think allowing to ship translation as external package would be good. Otherwise releases might get hold on by missing translations. I think trying to pull that from notebook-localisation (or similar), or even notebook-i18n-lang would be good for end-user translator to be able to work without having to install dev with node and all this stuff.
But that can be fixed later. I'm happy to leave that as-is, and modify this after the fact if we figure out how to implement it.

var i18n = new Jed(nbjson);
var _ = function (text) {
return i18n.gettext(text);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with caching it should be ok, as we can query the file by its hash and make it expire in 99years. It depends on the size though.

@Carreau
Copy link
Member

Carreau commented Feb 9, 2017

Sorry for the delay. Minor comments none of them blocking this.
I'm pretty sure we can (and should) allow translation to be installed separately. I have no issue allowing some translation to be shipped with the notebook, but I believe if external translation are installed, we should pick these.

One other point about translating string I haven't seen is the use of {identifier} instead of %s (because translation may have a different order), but that's minor.

@Carreau
Copy link
Member

Carreau commented Feb 10, 2017

One more thing to think about : the notebook might not be the only package we need to localize for the UI to be fully localized.

@takluyver
Copy link
Member

There is a related proposal for bi-directional support in the notebook:
jupyter/notebook#2178

@Zsailer
Copy link
Member

Zsailer commented Mar 4, 2024

Hi @srl295 👋—Zach from the @jupyter/software-steering-council here.

We're working through old JEPs and closing proposals that are no longer active or may not be relevant anymore. Under Jupyter's new governance model, we have an active Software Steering Council who reviews JEPs weekly. We are catching up on the backlog now. Since there has been no active discussion on this JEP in awhile, I'd propose we close it here (we'll leave it open for two more weeks in case you'd like to revive the conversation). If you would like to re-open the discussion after we close it, you are welcome to do that too.

Keep in mind that JupyterLab (and Notebook v7) now includes a fairly robust internalization+localization system. If you have additional ideas to expand this system, free free to comment here anytime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants