From c00d71d422c27e84992b2eb157941b3375b44951 Mon Sep 17 00:00:00 2001 From: Steve Strassmann <steve@strassmann.com> Date: Mon, 29 Apr 2013 11:32:22 -0400 Subject: [PATCH] integrate dummy string tools; added rake tasks and unit tests --- i18n/dummy.py | 6 +-- i18n/make_dummy.py | 49 +++++++++---------- i18n/test/__init__.py | 2 + i18n/update.py | 110 ------------------------------------------ rakefile | 10 ++++ requirements.txt | 5 +- 6 files changed, 43 insertions(+), 139 deletions(-) delete mode 100755 i18n/update.py diff --git a/i18n/dummy.py b/i18n/dummy.py index 798ee525b5d..78bfdc3b58f 100644 --- a/i18n/dummy.py +++ b/i18n/dummy.py @@ -86,7 +86,7 @@ class Dummy (Converter): def init_msgs(self, msgs): """ Make sure the first msg in msgs has a plural property. - msgs is list of instances of pofile.Msg + msgs is list of instances of polib.POEntry """ if len(msgs)==0: return @@ -100,8 +100,8 @@ class Dummy (Converter): def convert_msg(self, msg): """ - Takes one Msg object and converts it (adds a dummy translation to it) - msg is an instance of pofile.Msg + Takes one POEntry object and converts it (adds a dummy translation to it) + msg is an instance of polib.POEntry """ source = msg.msgid if len(source)==0: diff --git a/i18n/make_dummy.py b/i18n/make_dummy.py index 4ccfb0d5f17..c8dcde861a7 100755 --- a/i18n/make_dummy.py +++ b/i18n/make_dummy.py @@ -18,20 +18,12 @@ import os, sys import polib from dummy import Dummy +from execute import create_dir_if_necessary -# Dummy language -# two letter language codes reference: -# see http://www.loc.gov/standards/iso639-2/php/code_list.php -# -# Django will not localize in languages that django itself has not been -# localized for. So we are using a well-known language: 'fr'. - -OUT_LANG = 'fr' - -def main(file): +def main(file, locale): """ Takes a source po file, reads it, and writes out a new po file - containing a dummy translation. + in :param locale: containing a dummy translation. """ if not os.path.exists(file): raise IOError('File does not exist: %s' % file) @@ -40,29 +32,36 @@ def main(file): converter.init_msgs(pofile.translated_entries()) for msg in pofile: converter.convert_msg(msg) - new_file = new_filename(file, OUT_LANG) + new_file = new_filename(file, locale) create_dir_if_necessary(new_file) pofile.save(new_file) - - -def new_filename(original_filename, new_lang): - """Returns a filename derived from original_filename, using new_lang as the locale""" +def new_filename(original_filename, new_locale): + """Returns a filename derived from original_filename, using new_locale as the locale""" orig_dir = os.path.dirname(original_filename) msgs_dir = os.path.basename(orig_dir) orig_file = os.path.basename(original_filename) - return '%s/%s/%s/%s' % (os.path.abspath(orig_dir + '/../..'), - new_lang, - msgs_dir, - orig_file) + return os.path.join(orig_dir, + '/../..', + new_locale, + msgs_dir, + orig_file) -def create_dir_if_necessary(pathname): - dirname = os.path.dirname(pathname) - if not os.path.exists(dirname): - os.makedirs(dirname) +# Dummy language +# two letter language codes reference: +# see http://www.loc.gov/standards/iso639-2/php/code_list.php +# +# Django will not localize in languages that django itself has not been +# localized for. So we are using a well-known language: 'fr'. + +DEFAULT_LOCALE = 'fr' if __name__ == '__main__': if len(sys.argv)<2: raise Exception("missing file argument") - main(sys.argv[1]) + if len(sys.argv)<2: + locale = DEFAULT_LOCALE + else: + locale = sys.argv[2] + main(sys.argv[1], locale) diff --git a/i18n/test/__init__.py b/i18n/test/__init__.py index 65100a18d99..d60515c7125 100644 --- a/i18n/test/__init__.py +++ b/i18n/test/__init__.py @@ -1,2 +1,4 @@ from test_extract import TestExtract from test_generate import TestGenerate +from test_converter import TestConverter +from test_dummy import TestDummy diff --git a/i18n/update.py b/i18n/update.py deleted file mode 100755 index 447dcf71d5a..00000000000 --- a/i18n/update.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/python - -import os, subprocess, logging, json -from make_dummy import create_dir_if_necessary, main as dummy_main - -''' -Generate or update all translation files - Usage: - $ update.py - - - 1. extracts files from mako templates - 2. extracts files from django templates and python source files - 3. extracts files from django javascript files - 4. generates dummy text translations - 5. compiles po files to mo files - - Configuration (e.g. known languages) declared in mitx/conf/locale/config -''' - -# ----------------------------------- -# BASE_DIR is the working directory to execute django-admin commands from. -# Typically this should be the 'mitx' directory. -BASE_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))+'/..') - -# LOCALE_DIR contains the locale files. -# Typically this should be 'mitx/conf/locale' -LOCALE_DIR = BASE_DIR + '/conf/locale' - -# MSGS_DIR contains the English po files -MSGS_DIR = LOCALE_DIR + '/en/LC_MESSAGES' - -# CONFIG_FILENAME contains localization configuration in json format -CONFIG_FILENAME = LOCALE_DIR + '/config' - -# BABEL_CONFIG contains declarations for Babel to extract strings from mako template files -BABEL_CONFIG = LOCALE_DIR + '/babel.cfg' - -# Strings from mako template files are written to BABEL_OUT -BABEL_OUT = MSGS_DIR + '/mako.po' - -# These are the shell commands invoked by main() -COMMANDS = { - 'babel_mako': 'pybabel extract -F %s -c "TRANSLATORS:" . -o %s' % (BABEL_CONFIG, BABEL_OUT), - 'make_django': 'django-admin.py makemessages --all --ignore=src/* --extension html -l en', - 'make_djangojs': 'django-admin.py makemessages --all -d djangojs --ignore=src/* --extension js -l en', - 'msgcat' : 'msgcat -o merged.po django.po %s' % BABEL_OUT, - 'rename_django' : 'mv django.po django_old.po', - 'rename_merged' : 'mv merged.po django.po', - 'compile': 'django-admin.py compilemessages' - - } - -def execute (command_kwd, log, working_directory=BASE_DIR): - ''' - Executes command_kwd, which references a shell command in COMMANDS. - ''' - full_cmd = COMMANDS[command_kwd] - log.info('%s' % full_cmd) - subprocess.call(full_cmd.split(' '), cwd=working_directory) - -def make_log (): - '''returns a logger''' - log = logging.getLogger(__name__) - log.setLevel(logging.INFO) - log_handler = logging.StreamHandler() - log_handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')) - log.addHandler(log_handler) - return log - -def get_config (): - '''Returns data found in config file, or returns None if file not found''' - config_path = os.path.abspath(CONFIG_FILENAME) - if not os.path.exists(config_path): - return None - with open(config_path) as stream: - return json.load(stream) - -def main (): - log = make_log() - create_dir_if_necessary(LOCALE_DIR) - log.info('Executing all commands from %s' % BASE_DIR) - - remove_files = ['django.po', 'djangojs.po', 'nonesuch'] - for filename in remove_files: - path = MSGS_DIR + '/' + filename - log.info('Deleting file %s' % path) - if not os.path.exists(path): - log.warn("File does not exist: %s" % path) - else: - os.remove(path) - - # Generate or update human-readable .po files from all source code. - execute('babel_mako', log=log) - execute('make_django', log=log) - execute('make_djangojs', log=log) - execute('msgcat', log=log, working_directory=MSGS_DIR) - execute('rename_django', log=log, working_directory=MSGS_DIR) - execute('rename_merged', log=log, working_directory=MSGS_DIR) - - # Generate dummy text files from the English .po files - log.info('Generating dummy text.') - dummy_main(LOCALE_DIR + '/en/LC_MESSAGES/django.po') - dummy_main(LOCALE_DIR + '/en/LC_MESSAGES/djangojs.po') - - # Generate machine-readable .mo files - execute('compile', log) - -if __name__ == '__main__': - main() diff --git a/rakefile b/rakefile index 537a081471b..61fc1b26980 100644 --- a/rakefile +++ b/rakefile @@ -516,6 +516,16 @@ task :generate_i18n do sh(File.join(REPO_ROOT, "i18n", "generate.py")) end +desc "Simulate international translation by generating dummy strings corresponding to source strings." +task :dummy_i18n do + source_files = Dir["#{REPO_ROOT}/conf/locale/en/LC_MESSAGES/*.po"] + dummy_locale = 'fr' + cmd = File.join(REPO_ROOT, "i18n", "make_dummy.py") + for file in source_files do + sh("#{cmd} #{file} #{dummy_locale}") + end +end + # --- Develop and public documentation --- desc "Invoke sphinx 'make build' to generate docs." task :builddocs, [:options] do |t, args| diff --git a/requirements.txt b/requirements.txt index 77239a4d502..d3fdd46b816 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -r repo-requirements.txt -Babel==0.9.6 beautifulsoup4==4.1.3 beautifulsoup==3.2.1 boto==2.6.0 @@ -62,6 +61,10 @@ newrelic==1.8.0.13 # Used for documentation gathering sphinx==1.1.3 +# Used for Internationalization and localization +Babel==0.9.6 +transifex-client==0.8 + # Used for testing coverage==3.6 factory_boy==2.0.2 -- GitLab