diff --git a/.tx/config b/.tx/config index 4f1355038a8b..26438e05f1b4 100644 --- a/.tx/config +++ b/.tx/config @@ -42,3 +42,9 @@ file_filter = conf/locale//LC_MESSAGES/messages.po source_file = conf/locale/en/LC_MESSAGES/messages.po source_lang = en type = PO + +[edx-platform.wiki] +file_filter = conf/locale//LC_MESSAGES/wiki.po +source_file = conf/locale/en/LC_MESSAGES/wiki.po +source_lang = en +type = PO diff --git a/conf/locale/babel.cfg b/conf/locale/babel.cfg deleted file mode 100644 index 039ef1aa5fb0..000000000000 --- a/conf/locale/babel.cfg +++ /dev/null @@ -1,23 +0,0 @@ -# Extraction from Python source files -#[python: cms/**.py] -#[python: lms/**.py] -#[python: common/**.py] - -# Extraction from Javscript source files -#[javascript: cms/**.js] -#[javascript: lms/**.js] -#[javascript: common/static/js/capa/**.js] -#[javascript: common/static/js/course_groups/**.js] -# do not extract from common/static/js/vendor/** - -# Extraction from Mako templates -[mako: cms/templates/**.html] -input_encoding = utf-8 -[mako: lms/templates/**.html] -input_encoding = utf-8 -[mako: lms/templates/**.mustache] -input_encoding = utf-8 -[mako: common/templates/**.html] -input_encoding = utf-8 -[mako: cms/templates/emails/**.txt] -input_encoding = utf-8 diff --git a/conf/locale/babel_mako.cfg b/conf/locale/babel_mako.cfg new file mode 100644 index 000000000000..a908b45afef6 --- /dev/null +++ b/conf/locale/babel_mako.cfg @@ -0,0 +1,11 @@ +# Extraction from Mako templates +[mako: cms/templates/**.html] +input_encoding = utf-8 +[mako: lms/templates/**.html] +input_encoding = utf-8 +[mako: lms/templates/**.mustache] +input_encoding = utf-8 +[mako: common/templates/**.html] +input_encoding = utf-8 +[mako: cms/templates/emails/**.txt] +input_encoding = utf-8 diff --git a/conf/locale/babel_third_party.cfg b/conf/locale/babel_third_party.cfg new file mode 100644 index 000000000000..8a6a50af06b4 --- /dev/null +++ b/conf/locale/babel_third_party.cfg @@ -0,0 +1,6 @@ +# Use this configuration file for third-party app source trees. +[python: **.py] +input_encoding = utf-8 + +[django: **/template/**.html] +input_encoding = utf-8 diff --git a/conf/locale/config.yaml b/conf/locale/config.yaml index ef9f1208eb42..96855d97132c 100644 --- a/conf/locale/config.yaml +++ b/conf/locale/config.yaml @@ -66,6 +66,14 @@ ignore_dirs: - common/static/xmodule/modules - common/static/xmodule/descriptors + +# Third-party installed apps that we also extract strings from. When adding a +# file here, also add it to the django.po merge files below, and to the +# .tx/config file so that it will be pushed to and pulled from transifex. +third_party: + - wiki + + # How should .po files be segmented? See i18n/segment.py for details. Strings # that are only found in a particular segment are segregated into that .po file # so that translators can focus on separate parts of the product. @@ -93,6 +101,7 @@ generate_merge: - mako.po - mako-studio.po - messages.po + - wiki.po djangojs.po: - djangojs-partial.po - djangojs-studio.po diff --git a/i18n/config.py b/i18n/config.py index 982fffaaac31..dbd5591b3fbe 100644 --- a/i18n/config.py +++ b/i18n/config.py @@ -23,6 +23,7 @@ class Configuration(object): 'locales': ['en'], 'segment': {}, 'source_locale': 'en', + 'third_party': [], } def __init__(self, filename): diff --git a/i18n/execute.py b/i18n/execute.py index e7c246533830..7a079ab1d65c 100644 --- a/i18n/execute.py +++ b/i18n/execute.py @@ -10,6 +10,7 @@ def execute(command, working_directory=BASE_DIR): Command is a string to pass to the shell. Output is ignored. """ + LOG.info("Executing in %s ...", working_directory) LOG.info(command) subprocess.check_call(command, cwd=working_directory, stderr=subprocess.STDOUT, shell=True) diff --git a/i18n/extract.py b/i18n/extract.py index 70ef33c3b526..35004ca857f1 100755 --- a/i18n/extract.py +++ b/i18n/extract.py @@ -15,8 +15,14 @@ """ -import os, sys, logging from datetime import datetime +import importlib +import os +import os.path +import logging +import sys + +from path import path from polib import pofile from i18n.config import BASE_DIR, LOCALE_DIR, CONFIGURATION @@ -24,18 +30,14 @@ from i18n.segment import segment_pofiles -# BABEL_CONFIG contains declarations for Babel to extract strings from mako template files -# Use relpath to reduce noise in logs -BABEL_CONFIG = BASE_DIR.relpathto(LOCALE_DIR.joinpath('babel.cfg')) - -# Strings from mako template files are written to BABEL_OUT -# Use relpath to reduce noise in logs -BABEL_OUT = BASE_DIR.relpathto(CONFIGURATION.source_messages_dir.joinpath('mako.po')) - EDX_MARKER = "edX translation file" LOG = logging.getLogger(__name__) +def base(path1, *paths): + """Return a relative path from BASE_DIR to path1 / paths[0] / ... """ + return BASE_DIR.relpathto(path1.joinpath(*paths)) + def main(): logging.basicConfig(stream=sys.stdout, level=logging.INFO) create_dir_if_necessary(LOCALE_DIR) @@ -43,7 +45,11 @@ def main(): remove_file(source_msgs_dir.joinpath('django.po')) # Extract strings from mako templates. - babel_mako_cmd = 'pybabel extract -F %s -c "Translators:" . -o %s' % (BABEL_CONFIG, BABEL_OUT) + babel_mako_cmd = 'pybabel extract -F {config} -c "Translators:" . -o {output}' + babel_mako_cmd = babel_mako_cmd.format( + config=base(LOCALE_DIR, 'babel_mako.cfg'), + output=base(CONFIGURATION.source_messages_dir, 'mako.po'), + ) execute(babel_mako_cmd, working_directory=BASE_DIR) makemessages = "django-admin.py makemessages -l en" @@ -73,6 +79,20 @@ def main(): source_msgs_dir.joinpath('djangojs-partial.po') ) + # Extract strings from third-party applications. + for app_name in CONFIGURATION.third_party: + # Import the app to find out where it is. Then use pybabel to extract + # from that directory. + app_module = importlib.import_module(app_name) + app_dir = path(app_module.__file__).dirname().dirname() + babel_cmd = 'pybabel extract -F {config} -c "Translators:" {app} -o {output}' + babel_cmd = babel_cmd.format( + config=LOCALE_DIR / 'babel_third_party.cfg', + app=app_name, + output=source_msgs_dir / (app_name + ".po"), + ) + execute(babel_cmd, working_directory=app_dir) + # Segment the generated files. segmented_files = segment_pofiles("en") diff --git a/lms/djangoapps/course_wiki/views.py b/lms/djangoapps/course_wiki/views.py index 2318fc4c8920..b7e6473dc47f 100644 --- a/lms/djangoapps/course_wiki/views.py +++ b/lms/djangoapps/course_wiki/views.py @@ -6,6 +6,8 @@ from django.contrib.sites.models import Site from django.core.exceptions import ImproperlyConfigured from django.shortcuts import redirect +from django.utils.translation import ugettext as _ + from wiki.core.exceptions import NoRootURL from wiki.models import URLPath, Article @@ -79,12 +81,19 @@ def course_wiki_redirect(request, course_id): # recerate it. urlpath.delete() + content = cgi.escape( + # Translators: this string includes wiki markup. Leave the ** and the _ alone. + _("This is the wiki for **{organization}**'s _{course_name}_.").format( + organization=course.display_org_with_default, + course_name=course.display_name_with_default, + ) + ) urlpath = URLPath.create_article( root, course_slug, title=course_slug, - content=cgi.escape(u"This is the wiki for **{0}**'s _{1}_.".format(course.display_org_with_default, course.display_name_with_default)), - user_message="Course page automatically created.", + content=content, + user_message=_("Course page automatically created."), user=None, ip_address=None, article_kwargs={'owner': None, @@ -112,12 +121,12 @@ def get_or_create_root(): pass starting_content = "\n".join(( - "Welcome to the edX Wiki", - "===", - "Visit a course wiki to add an article.")) + _("Welcome to the edX Wiki"), + "===", + _("Visit a course wiki to add an article."), + )) - root = URLPath.create_root(title="Wiki", - content=starting_content) + root = URLPath.create_root(title=_("Wiki"), content=starting_content) article = root.article article.group = None article.group_read = True diff --git a/lms/envs/test.py b/lms/envs/test.py index 3fa2b4cbf576..c48fe12c8ece 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -74,6 +74,7 @@ GITHUB_REPO_ROOT = ENV_ROOT / "data" USE_I18N = True +LANGUAGE_CODE = 'en' # tests assume they will get English. XQUEUE_INTERFACE = { "url": "http://sandbox-xqueue.edx.org", diff --git a/lms/templates/wiki/base.html b/lms/templates/wiki/base.html index 0b23d0173fc6..73e91c4a3b64 100644 --- a/lms/templates/wiki/base.html +++ b/lms/templates/wiki/base.html @@ -1,7 +1,7 @@ {% extends "main_django.html" %} {% load compressed %}{% load sekizai_tags i18n microsite %}{% load url from future %}{% load staticfiles %} -{% block title %}{% block pagetitle %}{% endblock %} | Wiki | {% platform_name %}{% endblock %} +{% block title %}{% block pagetitle %}{% endblock %} | {% trans "Wiki" %} | {% platform_name %}{% endblock %} {% block headextra %} {% compressed_css 'course' %} diff --git a/lms/templates/wiki/history.html b/lms/templates/wiki/history.html index 073a2872396a..78f595a112c9 100644 --- a/lms/templates/wiki/history.html +++ b/lms/templates/wiki/history.html @@ -111,7 +111,7 @@ {% elif revision.automatic_log %} {{ revision.automatic_log }} {% else %} - ({% trans "no log message" %}) + {% trans "(no log message)" %} {% endif %} diff --git a/lms/templates/wiki/includes/article_menu.html b/lms/templates/wiki/includes/article_menu.html index 5e2cbaeb054e..e9993eca366a 100644 --- a/lms/templates/wiki/includes/article_menu.html +++ b/lms/templates/wiki/includes/article_menu.html @@ -8,8 +8,8 @@
  • - View - ${_("{span_start}active{span_end}").format(span_start="(", span_end=")") if selected_tab == "view" else ""} + ${_("View")} + ${_("{span_start}(active){span_end}").format(span_start="", span_end="") if selected_tab == "view" else ""}
  • @@ -17,8 +17,8 @@
  • - Edit - ${_("{span_start}active{span_end}").format(span_start="(", span_end=")") if selected_tab == "edit" else ""} + ${_("Edit")} + ${_("{span_start}(active){span_end}").format(span_start="", span_end="") if selected_tab == "edit" else ""}
  • %endif @@ -26,8 +26,8 @@
  • - Changes - ${_("{span_start}active{span_end}").format(span_start="(", span_end=")") if selected_tab == "history" else ""} + ${_("Changes")} + ${_("{span_start}(active){span_end}").format(span_start="", span_end="") if selected_tab == "history" else ""}
  • @@ -37,7 +37,7 @@ ${plugin.article_tab[0]} - ${_("{span_start}active{span_end}").format(span_start="(", span_end=")") if selected_tab == plugin.slug else ""} + ${_("{span_start}(active){span_end}").format(span_start="", span_end="") if selected_tab == plugin.slug else ""} %endif diff --git a/lms/templates/wiki/includes/breadcrumbs.html b/lms/templates/wiki/includes/breadcrumbs.html index 053bc2400e5d..f23916cf4935 100644 --- a/lms/templates/wiki/includes/breadcrumbs.html +++ b/lms/templates/wiki/includes/breadcrumbs.html @@ -1,5 +1,8 @@ ## mako -<%! from django.core.urlresolvers import reverse %> +<%! + from django.core.urlresolvers import reverse + from django.utils.translation import ugettext as _ +%> %if urlpath is not Undefined and urlpath:
    @@ -29,7 +32,7 @@ %if create_article_root: - Add article + ${_("Add article")} %endif diff --git a/lms/templates/wiki/includes/cheatsheet.html b/lms/templates/wiki/includes/cheatsheet.html index 4ac9bbd85adb..6ab8b605328f 100644 --- a/lms/templates/wiki/includes/cheatsheet.html +++ b/lms/templates/wiki/includes/cheatsheet.html @@ -24,7 +24,7 @@

    {% trans "Wiki Syntax Help" %}

    {# Translators: Do not translate "edX" #}

    {% trans "edX Additions:" %}

    circuit-schematic:
    -
    $LaTeX Math Expression$
    +
    $LaTeX {% trans "Math Expression" %}$
    @@ -33,8 +33,8 @@

    {% trans "edX Additions:" %}

    {% trans "Useful examples:" %}

     http://wikipedia.org
    -[Wikipedia](http://wikipedia.org)
    -[edX Wiki](wiki:/edx/)
    +[{% trans "Wikipedia" %}](http://wikipedia.org)
    +[{% trans "edX Wiki" %}](wiki:/edx/)
                   
     {% trans "Huge Header" %}
    diff --git a/lms/templates/wiki/preview_inline.html b/lms/templates/wiki/preview_inline.html
    index 98e2a05ccd9d..decd185b7d3a 100644
    --- a/lms/templates/wiki/preview_inline.html
    +++ b/lms/templates/wiki/preview_inline.html
    @@ -10,17 +10,18 @@
         
    {% if revision %}
    - {% trans "Previewing revision" %}: + {% trans "Previewing revision:" %} {% include "wiki/includes/revision_info.html" %}
    {% endif %} {% if merge %}
    - {% trans "Previewing merge between" %}: - {% include "wiki/includes/revision_info.html" with revision=merge1 %} - {% trans "and" %} - {% include "wiki/includes/revision_info.html" with revision=merge2 %} + {% trans "Previewing a merge between two revisions:" %} +
      +
    1. {% include "wiki/includes/revision_info.html" with revision=merge1 %}
    2. +
    3. {% include "wiki/includes/revision_info.html" with revision=merge2 %}
    4. +
    {% endif %} diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index 61ef87126331..141497c20025 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -9,7 +9,7 @@ # Third-party: -e git+https://github.com/edx/django-staticfiles.git@d89aae2a82f2b#egg=django-staticfiles -e git+https://github.com/edx/django-pipeline.git@88ec8a011e481918fdc9d2682d4017c835acd8be#egg=django-pipeline --e git+https://github.com/edx/django-wiki.git@41815e2ef1b0323f92900f8e60711b0f0c37766b#egg=django-wiki +-e git+https://github.com/edx/django-wiki.git@00424a1290328f60b52c5ad22e4fe22f16a29d12#egg=django-wiki -e git+https://github.com/gabrielfalcao/lettuce.git@cccc3978ad2df82a78b6f9648fe2e9baddd22f88#egg=lettuce -e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev -e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk