From 39bef81a74bd823dea4e0535fad086b8ae309f0b Mon Sep 17 00:00:00 2001 From: John Emmons Date: Thu, 15 Dec 2016 13:37:22 -0600 Subject: [PATCH 01/26] WIP: Preliminary work for message extraction --- babel.cfg | 7 + locale/notebook.pot | 831 +++++++++++++++++++++++++++++++ notebook/notebookapp.py | 311 ++++++------ notebook/templates/404.html | 2 +- notebook/templates/edit.html | 34 +- notebook/templates/error.html | 2 +- notebook/templates/login.html | 8 +- notebook/templates/logout.html | 4 +- notebook/templates/notebook.html | 222 ++++----- notebook/templates/tree.html | 72 +-- 10 files changed, 1174 insertions(+), 319 deletions(-) create mode 100644 babel.cfg create mode 100644 locale/notebook.pot diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000000..5bbc331582 --- /dev/null +++ b/babel.cfg @@ -0,0 +1,7 @@ +[python: **/**.py] +[jinja2: notebook/templates/**.html] + encoding = utf-8 +[extractors] + jinja2 = jinja2.ext:babel_extract +[javascript: notebook/static/tree/js/*.js] +extract_messages = $._ \ No newline at end of file diff --git a/locale/notebook.pot b/locale/notebook.pot new file mode 100644 index 0000000000..bff14f9738 --- /dev/null +++ b/locale/notebook.pot @@ -0,0 +1,831 @@ +# Translations template for PROJECT. +# Copyright (C) 2016 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2016. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2016-12-15 13:31-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.3.4\n" + +#: notebook/notebookapp.py:51 +msgid "The Jupyter Notebook requires tornado >= 4.0" +msgstr "" + +#: notebook/notebookapp.py:55 +msgid "The Jupyter Notebook requires tornado >= 4.0, but you have < 1.1.0" +msgstr "" + +#: notebook/notebookapp.py:57 +#, python-format +msgid "The Jupyter Notebook requires tornado >= 4.0, but you have %s" +msgstr "" + +#: notebook/notebookapp.py:155 +msgid "" +"It looks like you're running the notebook from source.\n" +"If you're working on the Javascript of the notebook, try running\n" +"\n" +"npm run build:watch\n" +"\n" +"in another terminal window to have the system incrementally\n" +"watch and build the notebook's JavaScript for you, as you make changes.\n" +msgstr "" + +#: notebook/notebookapp.py:201 +msgid "" +"The `ignore_minified_js` flag is deprecated and no \n" +" longer works. Alternatively use `npm run build:watch` when\n" +" working on the notebook's Javascript and LESS" +msgstr "" + +#: notebook/notebookapp.py:204 +msgid "The `ignore_minified_js` flag is deprecated and will be removed in Notebook 6.0" +msgstr "" + +#: notebook/notebookapp.py:296 +msgid "Widgets are unavailable. Please install widgetsnbextension or ipywidgets 4.0" +msgstr "" + +#: notebook/notebookapp.py:334 +msgid "List currently running notebook servers." +msgstr "" + +#: notebook/notebookapp.py:338 +msgid "Produce machine-readable JSON output." +msgstr "" + +#: notebook/notebookapp.py:342 +msgid "If True, each line of output will be a JSON object with the details from the server info file." +msgstr "" + +#: notebook/notebookapp.py:347 +msgid "Currently running servers:" +msgstr "" + +#: notebook/notebookapp.py:364 +msgid "Don't open the notebook in a browser after startup." +msgstr "" + +#: notebook/notebookapp.py:368 +msgid "DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib." +msgstr "" + +#: notebook/notebookapp.py:372 +msgid "" +"Disable MathJax\n" +" \n" +" MathJax is the javascript library Jupyter uses to render math/LaTeX. It is\n" +" very large, so you may want to disable it if you have a slow internet\n" +" connection, or for offline use of the notebook.\n" +" \n" +" When disabled, equations etc. will appear as their untransformed TeX source.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:384 +msgid "Allow the notebook to be run from root user." +msgstr "" + +#: notebook/notebookapp.py:415 +msgid "" +"\n" +" The Jupyter HTML Notebook.\n" +" \n" +" This launches a Tornado based HTML Notebook Server that serves up an\n" +" HTML5/Javascript Notebook client.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:455 +msgid "Deprecated: Use minified JS file or not, mainly use during dev to avoid JS recompilation" +msgstr "" + +#: notebook/notebookapp.py:464 +msgid "" +"Set the Access-Control-Allow-Origin header\n" +" \n" +" Use '*' to allow any origin to access your server.\n" +" \n" +" Takes precedence over allow_origin_pat.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:473 +msgid "" +"Use a regular expression for the Access-Control-Allow-Origin header\n" +" \n" +" Requests from an origin matching the expression will get replies with:\n" +" \n" +" Access-Control-Allow-Origin: origin\n" +" \n" +" where `origin` is the origin of the request.\n" +" \n" +" Ignored if allow_origin is set.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:486 +msgid "Set the Access-Control-Allow-Credentials: true header" +msgstr "" + +#: notebook/notebookapp.py:490 +msgid "Whether to allow the user to run the notebook as root." +msgstr "" + +#: notebook/notebookapp.py:494 +msgid "The default URL to redirect to from `/`" +msgstr "" + +#: notebook/notebookapp.py:498 +msgid "The IP address the notebook server will listen on." +msgstr "" + +#: notebook/notebookapp.py:511 +#, python-format +msgid "" +"Cannot bind to localhost, using 127.0.0.1 as default ip\n" +"%s" +msgstr "" + +#: notebook/notebookapp.py:525 +msgid "The port the notebook server will listen on." +msgstr "" + +#: notebook/notebookapp.py:529 +msgid "The number of additional ports to try if the specified port is not available." +msgstr "" + +#: notebook/notebookapp.py:533 +msgid "The full path to an SSL/TLS certificate file." +msgstr "" + +#: notebook/notebookapp.py:537 +msgid "The full path to a private key file for usage with SSL/TLS." +msgstr "" + +#: notebook/notebookapp.py:541 +msgid "The full path to a certificate authority certificate for SSL/TLS client authentication." +msgstr "" + +#: notebook/notebookapp.py:545 +msgid "The file where the cookie secret is stored." +msgstr "" + +#: notebook/notebookapp.py:553 +msgid "" +"The random bytes used to secure cookies.\n" +" By default this is a new random number every time you start the Notebook.\n" +" Set it to a value in a config file to enable logins to persist across server sessions.\n" +" \n" +" Note: Cookie secrets should be kept private, do not share config files with\n" +" cookie_secret stored in plaintext (you can read the value from a file).\n" +" " +msgstr "" + +#: notebook/notebookapp.py:574 +#, python-format +msgid "Writing notebook server cookie secret to %s" +msgstr "" + +#: notebook/notebookapp.py:581 +#, python-format +msgid "Could not set permissions on %s" +msgstr "" + +#: notebook/notebookapp.py:586 +msgid "" +"Token used for authenticating first-time connections to the server.\n" +" \n" +" Only used when no password is enabled.\n" +" \n" +" Setting to an empty string disables authentication altogether, which is NOT RECOMMENDED.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:595 +msgid "" +"One-time token used for opening a browser.\n" +"\n" +" Once used, this token cannot be used again.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:610 +msgid "" +"Hashed password to use for web authentication.\n" +"\n" +" To generate, type in a python/IPython shell:\n" +"\n" +" from notebook.auth import passwd; passwd()\n" +"\n" +" The string should be of the form type:salt:hashed-password.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:621 +msgid "" +"Forces users to use a password for the Notebook server.\n" +" This is useful in a multi user environment, for instance when\n" +" everybody in the LAN can access each other's machine though ssh.\n" +"\n" +" In such a case, server the notebook server on localhost is not secure\n" +" since any user can connect to the notebook server via ssh.\n" +"\n" +" " +msgstr "" + +#: notebook/notebookapp.py:632 +msgid "" +"Whether to open in a browser after starting.\n" +" The specific browser used is platform dependent and\n" +" determined by the python standard library `webbrowser`\n" +" module, unless it is overridden using the --browser\n" +" (NotebookApp.browser) configuration option.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:640 +msgid "" +"Specify what command to use to invoke a web\n" +" browser when opening the notebook. If not specified, the\n" +" default browser will be determined by the `webbrowser`\n" +" standard library module, which allows setting of the\n" +" BROWSER environment variable to override it.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:648 +msgid "DEPRECATED, use tornado_settings" +msgstr "" + +#: notebook/notebookapp.py:653 +msgid "" +"\n" +" webapp_settings is deprecated, use tornado_settings.\n" +msgstr "" + +#: notebook/notebookapp.py:657 +msgid "Supply overrides for the tornado.web.Application that the Jupyter notebook uses." +msgstr "" + +#: notebook/notebookapp.py:661 +msgid "Supply overrides for terminado. Currently only supports \"shell_command\"." +msgstr "" + +#: notebook/notebookapp.py:664 +msgid "Extra keyword arguments to pass to `set_secure_cookie`. See tornado's set_secure_cookie docs for details." +msgstr "" + +#: notebook/notebookapp.py:668 +msgid "" +"Supply SSL options for the tornado HTTPServer.\n" +" See the tornado docs for details." +msgstr "" + +#: notebook/notebookapp.py:672 +msgid "Supply extra arguments that will be passed to Jinja environment." +msgstr "" + +#: notebook/notebookapp.py:676 +msgid "Extra variables to supply to jinja templates when rendering." +msgstr "" + +#: notebook/notebookapp.py:680 +msgid "" +"Whether to enable MathJax for typesetting math/TeX\n" +"\n" +" MathJax is the javascript library Jupyter uses to render math/LaTeX. It is\n" +" very large, so you may want to disable it if you have a slow internet\n" +" connection, or for offline use of the notebook.\n" +"\n" +" When disabled, equations etc. will appear as their untransformed TeX source.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:697 +msgid "" +"The base URL for the notebook server.\n" +"\n" +" Leading and trailing slashes can be omitted,\n" +" and will automatically be added.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:712 +msgid "DEPRECATED use base_url" +msgstr "" + +#: notebook/notebookapp.py:716 +msgid "base_project_url is deprecated, use base_url" +msgstr "" + +#: notebook/notebookapp.py:720 +msgid "" +"Extra paths to search for serving static files.\n" +" \n" +" This allows adding javascript/css to be available from the notebook server machine,\n" +" or overriding individual files in the IPython" +msgstr "" + +#: notebook/notebookapp.py:732 +msgid "Path to search for custom.js, css" +msgstr "" + +#: notebook/notebookapp.py:744 +msgid "" +"Extra paths to search for serving jinja templates.\n" +"\n" +" Can be used to override templates from notebook.templates." +msgstr "" + +#: notebook/notebookapp.py:755 +msgid "extra paths to look for Javascript notebook extensions" +msgstr "" + +#: notebook/notebookapp.py:772 +msgid "" +"The base URL for websockets,\n" +" if it differs from the HTTP server (hint: it almost certainly doesn't).\n" +" \n" +" Should be in the form of an HTTP origin: ws[s]://hostname[:port]\n" +" " +msgstr "" + +#: notebook/notebookapp.py:780 +msgid "" +"A custom url for MathJax.js.\n" +" Should be in the form of a case-sensitive url to MathJax,\n" +" for example: /static/components/MathJax/MathJax.js\n" +" " +msgstr "" + +#: notebook/notebookapp.py:800 +#, python-format +msgid "Using MathJax: %s" +msgstr "" + +#: notebook/notebookapp.py:803 +msgid "The MathJax.js configuration file that is to be used." +msgstr "" + +#: notebook/notebookapp.py:808 +#, python-format +msgid "Using MathJax configuration file: %s" +msgstr "" + +#: notebook/notebookapp.py:814 +msgid "The notebook manager class to use." +msgstr "" + +#: notebook/notebookapp.py:820 +msgid "The kernel manager class to use." +msgstr "" + +#: notebook/notebookapp.py:826 +msgid "The session manager class to use." +msgstr "" + +#: notebook/notebookapp.py:832 +msgid "The config manager class to use" +msgstr "" + +#: notebook/notebookapp.py:840 +msgid "" +"\n" +" The kernel spec manager class to use. Should be a subclass\n" +" of `jupyter_client.kernelspec.KernelSpecManager`.\n" +"\n" +" The Api of KernelSpecManager is provisional and might change\n" +" without warning between this version of Jupyter and the next stable one.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:853 +msgid "The login handler class to use." +msgstr "" + +#: notebook/notebookapp.py:860 +msgid "The logout handler class to use." +msgstr "" + +#: notebook/notebookapp.py:864 +msgid "Whether to trust or not X-Scheme/X-Forwarded-Proto and X-Real-Ip/X-Forwarded-For headerssent by the upstream reverse proxy. Necessary if the proxy handles SSL" +msgstr "" + +#: notebook/notebookapp.py:876 +msgid "" +"\n" +" DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib.\n" +" " +msgstr "" + +#: notebook/notebookapp.py:888 +msgid "Support for specifying --pylab on the command line has been removed." +msgstr "" + +#: notebook/notebookapp.py:890 +msgid "Please use `%pylab{0}` or `%matplotlib{0}` in the notebook itself." +msgstr "" + +#: notebook/notebookapp.py:895 +msgid "The directory to use for notebooks and kernels." +msgstr "" + +#: notebook/notebookapp.py:918 +#, python-format +msgid "No such notebook dir: %r" +msgstr "" + +#: notebook/notebookapp.py:931 +msgid "DEPRECATED use the nbserver_extensions dict instead" +msgstr "" + +#: notebook/notebookapp.py:936 +msgid "server_extensions is deprecated, use nbserver_extensions" +msgstr "" + +#: notebook/notebookapp.py:940 +msgid "Dict of Python modules to load as notebook server extensions.Entry values can be used to enable and disable the loading ofthe extensions. The extensions will be loaded in alphabetical order." +msgstr "" + +#: notebook/notebookapp.py:949 +msgid "Reraise exceptions encountered loading server extensions?" +msgstr "" + +#: notebook/notebookapp.py:952 +msgid "" +"(msgs/sec)\n" +" Maximum rate at which messages can be sent on iopub before they are\n" +" limited." +msgstr "" + +#: notebook/notebookapp.py:956 +msgid "" +"(bytes/sec)\n" +" Maximum rate at which messages can be sent on iopub before they are\n" +" limited." +msgstr "" + +#: notebook/notebookapp.py:960 +msgid "" +"(sec) Time window used to \n" +" check the message and data rate limits." +msgstr "" + +#: notebook/notebookapp.py:971 +#, python-format +msgid "No such file or directory: %s" +msgstr "" + +#: notebook/notebookapp.py:1041 +msgid "Notebook servers are configured to only be run with a password." +msgstr "" + +#: notebook/notebookapp.py:1042 +msgid "Hint: run the following command to set a password" +msgstr "" + +#: notebook/notebookapp.py:1043 +msgid "\t$ python -m notebook.auth password" +msgstr "" + +#: notebook/notebookapp.py:1081 +#, python-format +msgid "The port %i is already in use, trying another port." +msgstr "" + +#: notebook/notebookapp.py:1084 +#, python-format +msgid "Permission to listen on port %i denied" +msgstr "" + +#: notebook/notebookapp.py:1093 +msgid "ERROR: the notebook server could not be started because no available port could be found." +msgstr "" + +#: notebook/notebookapp.py:1099 +msgid "[all ip addresses on your system]" +msgstr "" + +#: notebook/notebookapp.py:1119 +#, python-format +msgid "Terminals not available (error was %s)" +msgstr "" + +#: notebook/notebookapp.py:1157 +msgid "y" +msgstr "" + +#: notebook/notebookapp.py:1158 +msgid "n" +msgstr "" + +#: notebook/notebookapp.py:1159 +#, python-format +msgid "Shutdown this notebook server (%s/[%s])? " +msgstr "" + +#: notebook/notebookapp.py:1165 +msgid "Shutdown confirmed" +msgstr "" + +#: notebook/notebookapp.py:1169 +msgid "No answer for 5s:" +msgstr "" + +#: notebook/notebookapp.py:1170 +msgid "resuming operation..." +msgstr "" + +#: notebook/notebookapp.py:1178 +#, python-format +msgid "received signal %s, stopping" +msgstr "" + +#: notebook/notebookapp.py:1215 +#, python-format +msgid "Error loading server extension %s" +msgstr "" + +#: notebook/notebookapp.py:1251 +#, python-format +msgid "%d active kernels \n" +msgstr "" + +#: notebook/notebookapp.py:1252 +#, python-format +msgid "The Jupyter Notebook is running at: %s" +msgstr "" + +#: notebook/notebookapp.py:1296 +msgid "Running as root is not recommended. Use --allow-root to bypass." +msgstr "" + +#: notebook/notebookapp.py:1304 +msgid "Use Control-C to stop this server and shut down all kernels (twice to skip confirmation)." +msgstr "" + +#: notebook/notebookapp.py:1312 +#, python-format +msgid "No web browser found: %s." +msgstr "" + +#: notebook/notebookapp.py:1317 +#, python-format +msgid "%s does not exist" +msgstr "" + +#: notebook/notebookapp.py:1341 +msgid "Interrupted..." +msgstr "" + +#: notebook/templates/404.html:3 +msgid "You are requesting a page that does not exist!" +msgstr "" + +#: notebook/templates/edit.html:35 +msgid "current mode" +msgstr "" + +#: notebook/templates/edit.html:46 +msgid "File" +msgstr "" + +#: notebook/templates/edit.html:48 notebook/templates/tree.html:51 +msgid "New" +msgstr "" + +#: notebook/templates/edit.html:49 +msgid "Save" +msgstr "" + +#: notebook/templates/edit.html:50 notebook/templates/tree.html:32 +msgid "Rename" +msgstr "" + +#: notebook/templates/edit.html:51 notebook/templates/tree.html:34 +msgid "Download" +msgstr "" + +#: notebook/templates/edit.html:54 +msgid "Edit" +msgstr "" + +#: notebook/templates/edit.html:56 +msgid "Find" +msgstr "" + +#: notebook/templates/edit.html:57 +msgid "Find & Replace" +msgstr "" + +#: notebook/templates/edit.html:59 +msgid "Key Map" +msgstr "" + +#: notebook/templates/edit.html:60 +msgid "Default" +msgstr "" + +#: notebook/templates/edit.html:61 +msgid "Sublime Text" +msgstr "" + +#: notebook/templates/edit.html:66 +msgid "View" +msgstr "" + +#: notebook/templates/edit.html:68 +msgid "Show/Hide the logo and notebook title (above menu bar)" +msgstr "" + +#: notebook/templates/edit.html:69 +msgid "Toggle Header" +msgstr "" + +#: notebook/templates/edit.html:70 +msgid "Toggle Line Numbers" +msgstr "" + +#: notebook/templates/edit.html:73 +msgid "Language" +msgstr "" + +#: notebook/templates/logout.html:24 +#, python-format +msgid "Proceed to the dashboard" +msgstr "" + +#: notebook/templates/logout.html:26 +#, python-format +msgid "Proceed to the login page" +msgstr "" + +#: notebook/templates/tree.html:19 +msgid "Files" +msgstr "" + +#: notebook/templates/tree.html:20 +msgid "Running" +msgstr "" + +#: notebook/templates/tree.html:21 +msgid "Clusters" +msgstr "" + +#: notebook/templates/tree.html:28 +msgid "Select items to perform actions on them." +msgstr "" + +#: notebook/templates/tree.html:31 +msgid "Duplicate selected" +msgstr "" + +#: notebook/templates/tree.html:31 +msgid "Duplicate" +msgstr "" + +#: notebook/templates/tree.html:32 +msgid "Rename selected" +msgstr "" + +#: notebook/templates/tree.html:33 +msgid "Move selected" +msgstr "" + +#: notebook/templates/tree.html:33 +msgid "Move" +msgstr "" + +#: notebook/templates/tree.html:34 +msgid "Download selected" +msgstr "" + +#: notebook/templates/tree.html:35 +msgid "Shutdown selected notebook(s)" +msgstr "" + +#: notebook/templates/tree.html:35 +msgid "Shutdown" +msgstr "" + +#: notebook/templates/tree.html:36 +msgid "Delete selected" +msgstr "" + +#: notebook/templates/tree.html:44 +msgid "Click to browse for a file to upload." +msgstr "" + +#: notebook/templates/tree.html:45 +msgid "Upload" +msgstr "" + +#: notebook/templates/tree.html:56 +msgid "Text File" +msgstr "" + +#: notebook/templates/tree.html:59 +msgid "Folder" +msgstr "" + +#: notebook/templates/tree.html:63 +msgid "Terminal" +msgstr "" + +#: notebook/templates/tree.html:67 +msgid "Terminals Unavailable" +msgstr "" + +#: notebook/templates/tree.html:71 +msgid "Notebook:" +msgstr "" + +#: notebook/templates/tree.html:83 +msgid "Select All / None" +msgstr "" + +#: notebook/templates/tree.html:86 +msgid "Select..." +msgstr "" + +#: notebook/templates/tree.html:91 +msgid "Select All Folders" +msgstr "" + +#: notebook/templates/tree.html:91 +msgid " Folders" +msgstr "" + +#: notebook/templates/tree.html:92 +msgid "Select All Notebooks" +msgstr "" + +#: notebook/templates/tree.html:92 +msgid " All Notebooks" +msgstr "" + +#: notebook/templates/tree.html:93 +msgid "Select Running Notebooks" +msgstr "" + +#: notebook/templates/tree.html:93 +msgid " Running" +msgstr "" + +#: notebook/templates/tree.html:94 +msgid "Select All Files" +msgstr "" + +#: notebook/templates/tree.html:94 +msgid " Files" +msgstr "" + +#: notebook/templates/tree.html:107 +msgid "Last Modified" +msgstr "" + +#: notebook/templates/tree.html:113 +msgid "Name" +msgstr "" + +#: notebook/templates/tree.html:123 +msgid "Currently running Jupyter processes" +msgstr "" + +#: notebook/templates/tree.html:127 +msgid "Refresh running list" +msgstr "" + +#: notebook/templates/tree.html:143 +msgid "There are no terminals running." +msgstr "" + +#: notebook/templates/tree.html:145 +msgid "Terminals are unavailable." +msgstr "" + +#: notebook/templates/tree.html:155 +msgid "Notebooks" +msgstr "" + +#: notebook/templates/tree.html:162 +msgid "There are no notebooks running." +msgstr "" + +#: notebook/templates/tree.html:171 +msgid "" +"Clusters tab is now provided by IPython parallel.\n" +" See IPython parallel for installation details." +msgstr "" + diff --git a/notebook/notebookapp.py b/notebook/notebookapp.py index f131a64f06..3932d557e3 100755 --- a/notebook/notebookapp.py +++ b/notebook/notebookapp.py @@ -10,6 +10,7 @@ import binascii import datetime import errno +import gettext import importlib import io import json @@ -34,23 +35,27 @@ from jinja2 import Environment, FileSystemLoader +# Set up message catalog access +base_dir = os.path.realpath(os.path.join(__file__, '..', '..')) +trans = gettext.translation('notebook', localedir=os.path.join(base_dir, 'locale'), fallback=True) +trans.install() + # Install the pyzmq ioloop. This has to be done before anything else from # tornado is imported. from zmq.eventloop import ioloop ioloop.install() # check for tornado 3.1.0 -msg = "The Jupyter Notebook requires tornado >= 4.0" try: import tornado except ImportError: - raise ImportError(msg) + raise ImportError(_("The Jupyter Notebook requires tornado >= 4.0")) try: version_info = tornado.version_info except AttributeError: - raise ImportError(msg + ", but you have < 1.1.0") + raise ImportError(_("The Jupyter Notebook requires tornado >= 4.0, but you have < 1.1.0")) if version_info < (4,0): - raise ImportError(msg + ", but you have %s" % tornado.version) + raise ImportError(_("The Jupyter Notebook requires tornado >= 4.0, but you have %s") % tornado.version) from tornado import httpserver from tornado import web @@ -113,15 +118,6 @@ jupyter notebook password # enter a password to protect the server """ -DEV_NOTE_NPM = """It looks like you're running the notebook from source. -If you're working on the Javascript of the notebook, try running - - npm run build:watch - -in another terminal window to have the system incrementally -watch and build the notebook's JavaScript for you, as you make changes. -""" - #----------------------------------------------------------------------------- # Helper functions #----------------------------------------------------------------------------- @@ -158,13 +154,23 @@ def __init__(self, jupyter_app, kernel_manager, contents_manager, # that this is a dev install and suggest to the developer `npm run build:watch`. base_dir = os.path.realpath(os.path.join(__file__, '..', '..')) dev_mode = os.path.exists(os.path.join(base_dir, '.git')) + + if dev_mode: + DEV_NOTE_NPM = _("""It looks like you're running the notebook from source. +If you're working on the Javascript of the notebook, try running + +npm run build:watch + +in another terminal window to have the system incrementally +watch and build the notebook's JavaScript for you, as you make changes. +""") log.info(DEV_NOTE_NPM) settings = self.init_settings( jupyter_app, kernel_manager, contents_manager, - session_manager, kernel_spec_manager, config_manager, log, base_url, - default_url, settings_overrides, jinja_env_options) + session_manager, kernel_spec_manager, config_manager, log, trans, + base_url, default_url, settings_overrides, jinja_env_options) handlers = self.init_handlers(settings) super(NotebookWebApplication, self).__init__(handlers, **settings) @@ -172,7 +178,7 @@ def __init__(self, jupyter_app, kernel_manager, contents_manager, def init_settings(self, jupyter_app, kernel_manager, contents_manager, session_manager, kernel_spec_manager, config_manager, - log, base_url, default_url, settings_overrides, + log, trans, base_url, default_url, settings_overrides, jinja_env_options=None): _template_path = settings_overrides.get( @@ -186,8 +192,8 @@ def init_settings(self, jupyter_app, kernel_manager, contents_manager, jenv_opt = {"autoescape": True} jenv_opt.update(jinja_env_options if jinja_env_options else {}) - env = Environment(loader=FileSystemLoader(template_path), **jenv_opt) - + env = Environment(loader=FileSystemLoader(template_path), extensions=['jinja2.ext.i18n'], **jenv_opt) + env.install_gettext_translations(trans, newstyle=False) sys_info = get_sys_info() if sys_info['commit_source'] == 'repository': # don't cache (rely on 304) when working from master @@ -197,10 +203,10 @@ def init_settings(self, jupyter_app, kernel_manager, contents_manager, version_hash = datetime.datetime.now().strftime("%Y%m%d%H%M%S") if jupyter_app.ignore_minified_js: - log.warning("""The `ignore_minified_js` flag is deprecated and no + log.warning(_("""The `ignore_minified_js` flag is deprecated and no longer works. Alternatively use `npm run build:watch` when - working on the notebook's Javascript and LESS""") - warnings.warn("The `ignore_minified_js` flag is deprecated and will be removed in Notebook 6.0", DeprecationWarning) + working on the notebook's Javascript and LESS""")) + warnings.warn(_("The `ignore_minified_js` flag is deprecated and will be removed in Notebook 6.0"), DeprecationWarning) now = utcnow() @@ -378,20 +384,20 @@ def start(self): class NbserverListApp(JupyterApp): version = __version__ - description="List currently running notebook servers." + description=_("List currently running notebook servers.") flags = dict( json=({'NbserverListApp': {'json': True}}, - "Produce machine-readable JSON output."), + _("Produce machine-readable JSON output.")), ) json = Bool(False, config=True, - help="If True, each line of output will be a JSON object with the " - "details from the server info file.") + help=_("If True, each line of output will be a JSON object with the " + "details from the server info file.")) def start(self): if not self.json: - print("Currently running servers:") + print(_("Currently running servers:")) for serverinfo in list_running_servers(self.runtime_dir): if self.json: print(json.dumps(serverinfo)) @@ -408,27 +414,27 @@ def start(self): flags = dict(base_flags) flags['no-browser']=( {'NotebookApp' : {'open_browser' : False}}, - "Don't open the notebook in a browser after startup." + _("Don't open the notebook in a browser after startup.") ) flags['pylab']=( {'NotebookApp' : {'pylab' : 'warn'}}, - "DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib." + _("DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib.") ) flags['no-mathjax']=( {'NotebookApp' : {'enable_mathjax' : False}}, - """Disable MathJax + _("""Disable MathJax MathJax is the javascript library Jupyter uses to render math/LaTeX. It is very large, so you may want to disable it if you have a slow internet connection, or for offline use of the notebook. When disabled, equations etc. will appear as their untransformed TeX source. - """ + """) ) flags['allow-root']=( {'NotebookApp' : {'allow_root' : True}}, - "Allow the notebook to be run from root user." + _("Allow the notebook to be run from root user.") ) # Add notebook manager flags @@ -459,12 +465,12 @@ class NotebookApp(JupyterApp): name = 'jupyter-notebook' version = __version__ - description = """ + description = _(""" The Jupyter HTML Notebook. This launches a Tornado based HTML Notebook Server that serves up an HTML5/Javascript Notebook client. - """ + """) examples = _examples aliases = aliases flags = flags @@ -501,7 +507,7 @@ def _default_log_format(self): ignore_minified_js = Bool(False, config=True, - help='Deprecated: Use minified JS file or not, mainly use during dev to avoid JS recompilation', + help=_('Deprecated: Use minified JS file or not, mainly use during dev to avoid JS recompilation'), ) # file to be opened in the notebook server @@ -510,16 +516,16 @@ def _default_log_format(self): # Network related information allow_origin = Unicode('', config=True, - help="""Set the Access-Control-Allow-Origin header + help=_("""Set the Access-Control-Allow-Origin header Use '*' to allow any origin to access your server. Takes precedence over allow_origin_pat. - """ + """) ) allow_origin_pat = Unicode('', config=True, - help="""Use a regular expression for the Access-Control-Allow-Origin header + help=_("""Use a regular expression for the Access-Control-Allow-Origin header Requests from an origin matching the expression will get replies with: @@ -528,23 +534,23 @@ def _default_log_format(self): where `origin` is the origin of the request. Ignored if allow_origin is set. - """ + """) ) allow_credentials = Bool(False, config=True, - help="Set the Access-Control-Allow-Credentials: true header" + help=_("Set the Access-Control-Allow-Credentials: true header") ) allow_root = Bool(False, config=True, - help="Whether to allow the user to run the notebook as root." + help=_("Whether to allow the user to run the notebook as root.") ) default_url = Unicode('/tree', config=True, - help="The default URL to redirect to from `/`" + help=_("The default URL to redirect to from `/`") ) ip = Unicode('localhost', config=True, - help="The IP address the notebook server will listen on." + help=_("The IP address the notebook server will listen on.") ) @default('ip') @@ -557,7 +563,7 @@ def _default_ip(self): try: s.bind(('localhost', 0)) except socket.error as e: - self.log.warning("Cannot bind to localhost, using 127.0.0.1 as default ip\n%s", e) + self.log.warning(_("Cannot bind to localhost, using 127.0.0.1 as default ip\n%s"), e) return '127.0.0.1' else: s.close() @@ -571,27 +577,27 @@ def _valdate_ip(self, proposal): return value port = Integer(8888, config=True, - help="The port the notebook server will listen on." + help=_("The port the notebook server will listen on.") ) port_retries = Integer(50, config=True, - help="The number of additional ports to try if the specified port is not available." + help=_("The number of additional ports to try if the specified port is not available.") ) certfile = Unicode(u'', config=True, - help="""The full path to an SSL/TLS certificate file.""" + help=_("""The full path to an SSL/TLS certificate file.""") ) keyfile = Unicode(u'', config=True, - help="""The full path to a private key file for usage with SSL/TLS.""" + help=_("""The full path to a private key file for usage with SSL/TLS.""") ) client_ca = Unicode(u'', config=True, - help="""The full path to a certificate authority certificate for SSL/TLS client authentication.""" + help=_("""The full path to a certificate authority certificate for SSL/TLS client authentication.""") ) cookie_secret_file = Unicode(config=True, - help="""The file where the cookie secret is stored.""" + help=_("""The file where the cookie secret is stored.""") ) @default('cookie_secret_file') @@ -599,13 +605,13 @@ def _default_cookie_secret_file(self): return os.path.join(self.runtime_dir, 'notebook_cookie_secret') cookie_secret = Bytes(b'', config=True, - help="""The random bytes used to secure cookies. + help=_("""The random bytes used to secure cookies. By default this is a new random number every time you start the Notebook. Set it to a value in a config file to enable logins to persist across server sessions. Note: Cookie secrets should be kept private, do not share config files with cookie_secret stored in plaintext (you can read the value from a file). - """ + """) ) @default('cookie_secret') @@ -620,32 +626,32 @@ def _default_cookie_secret(self): def _write_cookie_secret_file(self, secret): """write my secret to my secret_file""" - self.log.info("Writing notebook server cookie secret to %s", self.cookie_secret_file) + self.log.info(_("Writing notebook server cookie secret to %s"), self.cookie_secret_file) with io.open(self.cookie_secret_file, 'wb') as f: f.write(secret) try: os.chmod(self.cookie_secret_file, 0o600) except OSError: self.log.warning( - "Could not set permissions on %s", + _("Could not set permissions on %s"), self.cookie_secret_file ) token = Unicode('', - help="""Token used for authenticating first-time connections to the server. + help=_("""Token used for authenticating first-time connections to the server. When no password is enabled, the default is to generate a new, random token. Setting to an empty string disables authentication altogether, which is NOT RECOMMENDED. - """ + """) ).tag(config=True) one_time_token = Unicode( - help="""One-time token used for opening a browser. + help=_("""One-time token used for opening a browser. Once used, this token cannot be used again. - """ + """) ) _token_generated = True @@ -665,25 +671,25 @@ def _token_changed(self, change): self._token_generated = False password = Unicode(u'', config=True, - help="""Hashed password to use for web authentication. + help=_("""Hashed password to use for web authentication. To generate, type in a python/IPython shell: from notebook.auth import passwd; passwd() The string should be of the form type:salt:hashed-password. - """ + """) ) password_required = Bool(False, config=True, - help="""Forces users to use a password for the Notebook server. + help=_("""Forces users to use a password for the Notebook server. This is useful in a multi user environment, for instance when everybody in the LAN can access each other's machine though ssh. In such a case, server the notebook server on localhost is not secure since any user can connect to the notebook server via ssh. - """ + """) ) disable_check_xsrf = Bool(False, config=True, @@ -703,15 +709,15 @@ def _token_changed(self, change): ) open_browser = Bool(True, config=True, - help="""Whether to open in a browser after starting. + help=_("""Whether to open in a browser after starting. The specific browser used is platform dependent and determined by the python standard library `webbrowser` module, unless it is overridden using the --browser (NotebookApp.browser) configuration option. - """) + """)) browser = Unicode(u'', config=True, - help="""Specify what command to use to invoke a web + help=_("""Specify what command to use to invoke a web browser when opening the notebook. If not specified, the default browser will be determined by the `webbrowser` standard library module, which allows setting of the @@ -719,7 +725,7 @@ def _token_changed(self, change): """) webbrowser_open_new = Integer(2, config=True, - help="""Specify Where to open the notebook on startup. This is the + help=_("""Specify Where to open the notebook on startup. This is the `new` argument passed to the standard library method `webbrowser.open`. The behaviour is not guaranteed, but depends on browser support. Valid values are: @@ -727,23 +733,23 @@ def _token_changed(self, change): 1 opens a new window, 0 opens in an existing window. See the `webbrowser.open` documentation for details. - """) + """)) webapp_settings = Dict(config=True, - help="DEPRECATED, use tornado_settings" + help=_("DEPRECATED, use tornado_settings") ) @observe('webapp_settings') def _update_webapp_settings(self, change): - self.log.warning("\n webapp_settings is deprecated, use tornado_settings.\n") + self.log.warning(_("\n webapp_settings is deprecated, use tornado_settings.\n")) self.tornado_settings = change['new'] tornado_settings = Dict(config=True, - help="Supply overrides for the tornado.web.Application that the " - "Jupyter notebook uses.") + help=_("Supply overrides for the tornado.web.Application that the " + "Jupyter notebook uses.")) websocket_compression_options = Any(None, config=True, - help=""" + help=_(""" Set the tornado compression options for websocket connections. This value will be returned from :meth:`WebSocketHandler.get_compression_options`. @@ -751,36 +757,36 @@ def _update_webapp_settings(self, change): A dict (even an empty one) will enable compression. See the tornado docs for WebSocketHandler.get_compression_options for details. - """ + """) ) terminado_settings = Dict(config=True, - help='Supply overrides for terminado. Currently only supports "shell_command".') + help=_('Supply overrides for terminado. Currently only supports "shell_command".')) cookie_options = Dict(config=True, - help="Extra keyword arguments to pass to `set_secure_cookie`." - " See tornado's set_secure_cookie docs for details." + help=_("Extra keyword arguments to pass to `set_secure_cookie`." + " See tornado's set_secure_cookie docs for details.") ) ssl_options = Dict(config=True, - help="""Supply SSL options for the tornado HTTPServer. - See the tornado docs for details.""") + help=_("""Supply SSL options for the tornado HTTPServer. + See the tornado docs for details.""")) jinja_environment_options = Dict(config=True, - help="Supply extra arguments that will be passed to Jinja environment.") + help=_("Supply extra arguments that will be passed to Jinja environment.")) jinja_template_vars = Dict( config=True, - help="Extra variables to supply to jinja templates when rendering.", + help=_("Extra variables to supply to jinja templates when rendering."), ) enable_mathjax = Bool(True, config=True, - help="""Whether to enable MathJax for typesetting math/TeX + help=_("""Whether to enable MathJax for typesetting math/TeX MathJax is the javascript library Jupyter uses to render math/LaTeX. It is very large, so you may want to disable it if you have a slow internet connection, or for offline use of the notebook. When disabled, equations etc. will appear as their untransformed TeX source. - """ + """) ) @observe('enable_mathjax') @@ -790,11 +796,11 @@ def _update_enable_mathjax(self, change): self.mathjax_url = u'' base_url = Unicode('/', config=True, - help='''The base URL for the notebook server. + help=_('''The base URL for the notebook server. Leading and trailing slashes can be omitted, and will automatically be added. - ''') + ''')) @validate('base_url') def _update_base_url(self, proposal): @@ -805,18 +811,18 @@ def _update_base_url(self, proposal): value = value + '/' return value - base_project_url = Unicode('/', config=True, help="""DEPRECATED use base_url""") + base_project_url = Unicode('/', config=True, help=_("""DEPRECATED use base_url""")) @observe('base_project_url') def _update_base_project_url(self, change): - self.log.warning("base_project_url is deprecated, use base_url") + self.log.warning(_("base_project_url is deprecated, use base_url")) self.base_url = change['new'] extra_static_paths = List(Unicode(), config=True, - help="""Extra paths to search for serving static files. + help=_("""Extra paths to search for serving static files. This allows adding javascript/css to be available from the notebook server machine, - or overriding individual files in the IPython""" + or overriding individual files in the IPython""") ) @property @@ -825,7 +831,7 @@ def static_file_path(self): return self.extra_static_paths + [DEFAULT_STATIC_FILES_PATH] static_custom_path = List(Unicode(), - help="""Path to search for custom.js, css""" + help=_("""Path to search for custom.js, css""") ) @default('static_custom_path') @@ -837,9 +843,9 @@ def _default_static_custom_path(self): ] extra_template_paths = List(Unicode(), config=True, - help="""Extra paths to search for serving jinja templates. + help=_("""Extra paths to search for serving jinja templates. - Can be used to override templates from notebook.templates.""" + Can be used to override templates from notebook.templates.""") ) @property @@ -848,7 +854,7 @@ def template_file_path(self): return self.extra_template_paths + DEFAULT_TEMPLATE_PATH_LIST extra_nbextensions_path = List(Unicode(), config=True, - help="""extra paths to look for Javascript notebook extensions""" + help=_("""extra paths to look for Javascript notebook extensions""") ) @property @@ -865,18 +871,18 @@ def nbextensions_path(self): return path websocket_url = Unicode("", config=True, - help="""The base URL for websockets, + help=_("""The base URL for websockets, if it differs from the HTTP server (hint: it almost certainly doesn't). Should be in the form of an HTTP origin: ws[s]://hostname[:port] - """ + """) ) mathjax_url = Unicode("", config=True, - help="""A custom url for MathJax.js. + help=_("""A custom url for MathJax.js. Should be in the form of a case-sensitive url to MathJax, for example: /static/components/MathJax/MathJax.js - """ + """) ) @default('mathjax_url') @@ -893,39 +899,39 @@ def _update_mathjax_url(self, change): # enable_mathjax=False overrides mathjax_url self.mathjax_url = u'' else: - self.log.info("Using MathJax: %s", new) + self.log.info(_("Using MathJax: %s"), new) mathjax_config = Unicode("TeX-AMS-MML_HTMLorMML-full,Safe", config=True, - help="""The MathJax.js configuration file that is to be used.""" + help=_("""The MathJax.js configuration file that is to be used.""") ) @observe('mathjax_config') def _update_mathjax_config(self, change): - self.log.info("Using MathJax configuration file: %s", change['new']) + self.log.info(_("Using MathJax configuration file: %s"), change['new']) contents_manager_class = Type( default_value=LargeFileManager, klass=ContentsManager, config=True, - help='The notebook manager class to use.' + help=_('The notebook manager class to use.') ) kernel_manager_class = Type( default_value=MappingKernelManager, config=True, - help='The kernel manager class to use.' + help=_('The kernel manager class to use.') ) session_manager_class = Type( default_value=SessionManager, config=True, - help='The session manager class to use.' + help=_('The session manager class to use.') ) config_manager_class = Type( default_value=ConfigManager, config = True, - help='The config manager class to use' + help=_('The config manager class to use') ) kernel_spec_manager = Instance(KernelSpecManager, allow_none=True) @@ -933,32 +939,32 @@ def _update_mathjax_config(self, change): kernel_spec_manager_class = Type( default_value=KernelSpecManager, config=True, - help=""" + help=_(""" The kernel spec manager class to use. Should be a subclass of `jupyter_client.kernelspec.KernelSpecManager`. The Api of KernelSpecManager is provisional and might change without warning between this version of Jupyter and the next stable one. - """ + """) ) login_handler_class = Type( default_value=LoginHandler, klass=web.RequestHandler, config=True, - help='The login handler class to use.', + help=_('The login handler class to use.'), ) logout_handler_class = Type( default_value=LogoutHandler, klass=web.RequestHandler, config=True, - help='The logout handler class to use.', + help=_('The logout handler class to use.'), ) trust_xheaders = Bool(False, config=True, - help=("Whether to trust or not X-Scheme/X-Forwarded-Proto and X-Real-Ip/X-Forwarded-For headers" - "sent by the upstream reverse proxy. Necessary if the proxy handles SSL") + help=(_("Whether to trust or not X-Scheme/X-Forwarded-Proto and X-Real-Ip/X-Forwarded-For headers" + "sent by the upstream reverse proxy. Necessary if the proxy handles SSL")) ) info_file = Unicode() @@ -969,9 +975,9 @@ def _default_info_file(self): return os.path.join(self.runtime_dir, info_file) pylab = Unicode('disabled', config=True, - help=""" + help=_(""" DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib. - """ + """) ) @observe('pylab') @@ -981,14 +987,14 @@ def _update_pylab(self, change): backend = ' %s' % change['new'] else: backend = '' - self.log.error("Support for specifying --pylab on the command line has been removed.") + self.log.error(_("Support for specifying --pylab on the command line has been removed.")) self.log.error( - "Please use `%pylab{0}` or `%matplotlib{0}` in the notebook itself.".format(backend) + _("Please use `%pylab{0}` or `%matplotlib{0}` in the notebook itself.").format(backend) ) self.exit(1) notebook_dir = Unicode(config=True, - help="The directory to use for notebooks and kernels." + help=_("The directory to use for notebooks and kernels.") ) @default('notebook_dir') @@ -1011,7 +1017,7 @@ def _notebook_dir_validate(self, proposal): # If we receive a non-absolute path, make it absolute. value = os.path.abspath(value) if not os.path.isdir(value): - raise TraitError("No such notebook dir: %r" % value) + raise TraitError(_("No such notebook dir: %r") % value) return value @observe('notebook_dir') @@ -1024,37 +1030,37 @@ def _update_notebook_dir(self, change): # TODO: Remove me in notebook 5.0 server_extensions = List(Unicode(), config=True, - help=("DEPRECATED use the nbserver_extensions dict instead") + help=(_("DEPRECATED use the nbserver_extensions dict instead")) ) @observe('server_extensions') def _update_server_extensions(self, change): - self.log.warning("server_extensions is deprecated, use nbserver_extensions") + self.log.warning(_("server_extensions is deprecated, use nbserver_extensions")) self.server_extensions = change['new'] nbserver_extensions = Dict({}, config=True, - help=("Dict of Python modules to load as notebook server extensions." + help=(_("Dict of Python modules to load as notebook server extensions." "Entry values can be used to enable and disable the loading of" "the extensions. The extensions will be loaded in alphabetical " - "order.") + "order.")) ) reraise_server_extension_failures = Bool( False, config=True, - help="Reraise exceptions encountered loading server extensions?", + help=_("Reraise exceptions encountered loading server extensions?"), ) - iopub_msg_rate_limit = Float(1000, config=True, help="""(msgs/sec) + iopub_msg_rate_limit = Float(1000, config=True, help=_("""(msgs/sec) Maximum rate at which messages can be sent on iopub before they are - limited.""") + limited.""")) - iopub_data_rate_limit = Float(1000000, config=True, help="""(bytes/sec) + iopub_data_rate_limit = Float(1000000, config=True, help=_("""(bytes/sec) Maximum rate at which stream output can be sent on iopub before they are - limited.""") + limited.""")) - rate_limit_window = Float(3, config=True, help="""(sec) Time window used to - check the message and data rate limits.""") + rate_limit_window = Float(3, config=True, help=_("""(sec) Time window used to + check the message and data rate limits.""")) def parse_command_line(self, argv=None): super(NotebookApp, self).parse_command_line(argv) @@ -1064,7 +1070,7 @@ def parse_command_line(self, argv=None): f = os.path.abspath(arg0) self.argv.remove(arg0) if not os.path.exists(f): - self.log.critical("No such file or directory: %s", f) + self.log.critical(_("No such file or directory: %s"), f) self.exit(1) # Use config here, to ensure that it takes higher priority than @@ -1134,9 +1140,9 @@ def init_webapp(self): self.default_url = url_path_join(self.base_url, self.default_url) if self.password_required and (not self.password): - self.log.critical("Notebook servers are configured to only be run with a password.") - self.log.critical("Hint: run the following command to set a password") - self.log.critical("\t$ python -m notebook.auth password") + self.log.critical(_("Notebook servers are configured to only be run with a password.")) + self.log.critical(_("Hint: run the following command to set a password")) + self.log.critical(_("\t$ python -m notebook.auth password")) sys.exit(1) self.web_app = NotebookWebApplication( @@ -1174,10 +1180,10 @@ def init_webapp(self): self.http_server.listen(port, self.ip) except socket.error as e: if e.errno == errno.EADDRINUSE: - self.log.info('The port %i is already in use, trying another port.' % port) + self.log.info(_('The port %i is already in use, trying another port.') % port) continue elif e.errno in (errno.EACCES, getattr(errno, 'WSAEACCES', errno.EACCES)): - self.log.warning("Permission to listen on port %i denied" % port) + self.log.warning(_("Permission to listen on port %i denied") % port) continue else: raise @@ -1186,13 +1192,13 @@ def init_webapp(self): success = True break if not success: - self.log.critical('ERROR: the notebook server could not be started because ' - 'no available port could be found.') + self.log.critical(_('ERROR: the notebook server could not be started because ' + 'no available port could be found.')) self.exit(1) @property def display_url(self): - ip = self.ip if self.ip else '[all ip addresses on your system]' + ip = self.ip if self.ip else _('[all ip addresses on your system]') url = self._url(ip) if self.token: # Don't log full token if it came from config @@ -1216,7 +1222,7 @@ def init_terminals(self): self.web_app.settings['terminals_available'] = True except ImportError as e: log = self.log.debug if sys.platform == 'win32' else self.log.warning - log("Terminals not available (error was %s)", e) + log(_("Terminals not available (error was %s)"), e) def init_signal(self): if not sys.platform.startswith('win') and sys.stdin and sys.stdin.isatty(): @@ -1254,18 +1260,20 @@ def _confirm_exit(self): info = self.log.info info('interrupted') print(self.notebook_info()) - sys.stdout.write("Shutdown this notebook server (y/[n])? ") + yes = _('y') + no = _('n') + sys.stdout.write(_("Shutdown this notebook server (%s/[%s])? "), yes, no) sys.stdout.flush() r,w,x = select.select([sys.stdin], [], [], 5) if r: line = sys.stdin.readline() - if line.lower().startswith('y') and 'n' not in line.lower(): - self.log.critical("Shutdown confirmed") + if line.lower().startswith(yes) and no not in line.lower(): + self.log.critical(_("Shutdown confirmed")) ioloop.IOLoop.current().stop() return else: - print("No answer for 5s:", end=' ') - print("resuming operation...") + print(_("No answer for 5s:"), end=' ') + print(_("resuming operation...")) # no answer, or answer is no: # set it back to original SIGINT handler # use IOLoop.add_callback because signal.signal must be called @@ -1273,7 +1281,7 @@ def _confirm_exit(self): ioloop.IOLoop.current().add_callback(self._restore_sigint_handler) def _signal_stop(self, sig, frame): - self.log.critical("received signal %s, stopping", sig) + self.log.critical(_("received signal %s, stopping"), sig) ioloop.IOLoop.current().stop() def _signal_info(self, sig, frame): @@ -1329,7 +1337,7 @@ def init_server_extensions(self): except Exception: if self.reraise_server_extension_failures: raise - self.log.warning("Error loading server extension %s", modulename, + self.log.warning(_("Error loading server extension %s"), modulename, exc_info=True) def init_mime_overrides(self): @@ -1366,9 +1374,14 @@ def cleanup_kernels(self): def notebook_info(self): "Return the current working directory and the server url information" info = self.contents_manager.info_string() + "\n" +<<<<<<< HEAD info += "%d active kernels \n" % len(self.kernel_manager._kernels) # Format the info so that the URL fits on a single line in 80 char display return info + "The Jupyter Notebook is running at:\n\r%s" % self.display_url +======= + info += _("%d active kernels \n") % len(self.kernel_manager._kernels) + return info + _("The Jupyter Notebook is running at: %s") % self.display_url +>>>>>>> WIP: Preliminary work for message extraction def server_info(self): """Return a JSONable dict of information about this server.""" @@ -1414,18 +1427,18 @@ def start(self): except AttributeError: uid = -1 # anything nonzero here, since we can't check UID assume non-root if uid == 0: - self.log.critical("Running as root is not recommended. Use --allow-root to bypass.") + self.log.critical(_("Running as root is not recommended. Use --allow-root to bypass.")) self.exit(1) info = self.log.info for line in self.notebook_info().split("\n"): info(line) - info("Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).") + info(_("Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).")) if 'dev' in notebook.__version__: - info("Welcome to Project Jupyter! Explore the various tools available" + info(_("Welcome to Project Jupyter! Explore the various tools available" " and their corresponding documentation. If you are interested" " in contributing to the platform, please visit the community" - "resources section at http://jupyter.org/community.html.") + "resources section at http://jupyter.org/community.html.")) self.write_server_info_file() @@ -1433,12 +1446,12 @@ def start(self): try: browser = webbrowser.get(self.browser or None) except webbrowser.Error as e: - self.log.warning('No web browser found: %s.' % e) + self.log.warning(_('No web browser found: %s.') % e) browser = None if self.file_to_run: if not os.path.exists(self.file_to_run): - self.log.critical("%s does not exist" % self.file_to_run) + self.log.critical(_("%s does not exist") % self.file_to_run) self.exit(1) relpath = os.path.relpath(self.file_to_run, self.notebook_dir) @@ -1472,7 +1485,7 @@ def start(self): try: self.io_loop.start() except KeyboardInterrupt: - info("Interrupted...") + info(_("Interrupted...")) finally: self.remove_server_info_file() self.cleanup_kernels() diff --git a/notebook/templates/404.html b/notebook/templates/404.html index 7335051854..e29646af1a 100644 --- a/notebook/templates/404.html +++ b/notebook/templates/404.html @@ -1,5 +1,5 @@ {% extends "error.html" %} {% block error_detail %} -

You are requesting a page that does not exist!

+

{% trans %}You are requesting a page that does not exist!{% endtrans %}

{% endblock %} diff --git a/notebook/templates/edit.html b/notebook/templates/edit.html index b2001bf817..5ef9eecc74 100644 --- a/notebook/templates/edit.html +++ b/notebook/templates/edit.html @@ -34,7 +34,7 @@