Commit 5e244b1c by Ned Batchelder

Minor style changes to the i18n directory.

parent 7547c540
......@@ -11,7 +11,7 @@ BASE_DIR = path(__file__).abspath().dirname().joinpath('..').normpath()
LOCALE_DIR = BASE_DIR.joinpath('conf', 'locale')
class Configuration:
class Configuration(object):
"""
# Reads localization configuration in json format
......
import re
import itertools
class Converter:
class Converter(object):
"""Converter is an abstract class that transforms strings.
It hides embedded tags (HTML or Python sequences) from transformation
To implement Converter, provide implementation for inner_convert_string()
Strategy:
......@@ -16,7 +16,7 @@ class Converter:
3. re-insert the extracted tags
"""
# matches tags like these:
# HTML: <B>, </B>, <BR/>, <textformat leading="10">
# Python: %(date)s, %(name)s
......@@ -25,7 +25,7 @@ class Converter:
def convert(self, string):
"""Returns: a converted tagged string
param: string (contains html tags)
Don't replace characters inside tags
"""
(string, tags) = self.detag_string(string)
......@@ -35,7 +35,7 @@ class Converter:
def detag_string(self, string):
"""Extracts tags from string.
returns (string, list) where
string: string has tags replaced by indices (<BR>... => <0>, <1>, <2>, etc.)
list: list of the removed tags ('<BR>', '<I>', '</I>')
......@@ -62,4 +62,3 @@ class Converter:
def inner_convert_string(self, string):
return string # do nothing by default
......@@ -54,49 +54,47 @@ LOREM = ' Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed ' \
PAD_FACTOR = 1.3
class Dummy (Converter):
class Dummy(Converter):
"""
A string converter that generates dummy strings with fake accents
and lorem ipsum padding.
"""
"""
def convert(self, string):
result = Converter.convert(self, string)
return self.pad(result)
def inner_convert_string(self, string):
for (k,v) in TABLE.items():
for k, v in TABLE.items():
string = string.replace(k, v)
return string
def pad(self, string):
"""add some lorem ipsum text to the end of string"""
size = len(string)
if size < 7:
target = size*3
target = size * 3
else:
target = int(size*PAD_FACTOR)
return string + self.terminate(LOREM[:(target-size)])
def terminate(self, string):
"""replaces the final char of string with #"""
return string[:-1]+'#'
return string[:-1] + '#'
def init_msgs(self, msgs):
"""
Make sure the first msg in msgs has a plural property.
msgs is list of instances of polib.POEntry
"""
if len(msgs)==0:
if not msgs:
return
headers = msgs[0].get_property('msgstr')
has_plural = len([header for header in headers if header.find('Plural-Forms:') == 0])>0
has_plural = any(header.startswith('Plural-Forms:') for header in headers)
if not has_plural:
# Apply declaration for English pluralization rules
plural = "Plural-Forms: nplurals=2; plural=(n != 1);\\n"
headers.append(plural)
def convert_msg(self, msg):
"""
......@@ -104,19 +102,18 @@ class Dummy (Converter):
msg is an instance of polib.POEntry
"""
source = msg.msgid
if len(source)==0:
if not source:
# don't translate empty string
return
plural = msg.msgid_plural
if len(plural)>0:
if plural:
# translate singular and plural
foreign_single = self.convert(source)
foreign_plural = self.convert(plural)
plural = {'0': self.final_newline(source, foreign_single),
'1': self.final_newline(plural, foreign_plural)}
msg.msgstr_plural = plural
return
else:
foreign = self.convert(source)
msg.msgstr = self.final_newline(source, foreign)
......@@ -126,7 +123,7 @@ class Dummy (Converter):
If last char of original is a newline, make sure translation
has a newline too.
"""
if len(original)>1:
if original[-1]=='\n' and translated[-1]!='\n':
return translated + '\n'
if original:
if original[-1] == '\n' and translated[-1] != '\n':
translated += '\n'
return translated
......@@ -17,7 +17,7 @@ def execute(command, working_directory=BASE_DIR):
def call(command, working_directory=BASE_DIR):
"""
Executes shell command in a given working_directory.
Command is a string to pass to the shell.
Command is a list of strings to execute as a command line.
Returns a tuple of two strings: (stdout, stderr)
"""
......@@ -25,7 +25,8 @@ def call(command, working_directory=BASE_DIR):
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=working_directory)
out, err = p.communicate()
return (out, err)
def create_dir_if_necessary(pathname):
dirname = os.path.dirname(pathname)
if not os.path.exists(dirname):
......
#!/usr/bin/env python
"""
See https://edx-wiki.atlassian.net/wiki/display/ENG/PO+File+workflow
This task extracts all English strings from all source code
and produces three human-readable files:
This task extracts all English strings from all source code
and produces three human-readable files:
conf/locale/en/LC_MESSAGES/django-partial.po
conf/locale/en/LC_MESSAGES/djangojs.po
conf/locale/en/LC_MESSAGES/mako.po
This task will clobber any existing django.po file.
This is because django-admin.py makemessages hardcodes this filename
and it cannot be overridden.
This task will clobber any existing django.po file.
This is because django-admin.py makemessages hardcodes this filename
and it cannot be overridden.
"""
import os, sys, logging
......@@ -34,7 +34,7 @@ SOURCE_WARN = 'This English source file is machine-generated. Do not check it in
LOG = logging.getLogger(__name__)
def main ():
def main():
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
create_dir_if_necessary(LOCALE_DIR)
source_msgs_dir = CONFIGURATION.source_messages_dir
......@@ -44,23 +44,28 @@ def main ():
for filename in generated_files:
remove_file(source_msgs_dir.joinpath(filename))
# Extract strings from mako templates
# Extract strings from mako templates.
babel_mako_cmd = 'pybabel extract -F %s -c "TRANSLATORS:" . -o %s' % (BABEL_CONFIG, BABEL_OUT)
# Extract strings from django source files
make_django_cmd = 'django-admin.py makemessages -l en --ignore=src/* --ignore=i18n/* ' \
+ '--extension html'
# Extract strings from javascript source files
make_djangojs_cmd = 'django-admin.py makemessages -l en -d djangojs --ignore=src/* ' \
+ '--ignore=i18n/* --extension js'
# Extract strings from django source files.
make_django_cmd = (
'django-admin.py makemessages -l en --ignore=src/* --ignore=i18n/* '
'--extension html'
)
# Extract strings from Javascript source files.
make_djangojs_cmd = (
'django-admin.py makemessages -l en --ignore=src/* --ignore=i18n/* '
'-d djangojs --extension js'
)
execute(babel_mako_cmd, working_directory=BASE_DIR)
execute(make_django_cmd, working_directory=BASE_DIR)
# makemessages creates 'django.po'. This filename is hardcoded.
# Rename it to django-partial.po to enable merging into django.po later.
os.rename(source_msgs_dir.joinpath('django.po'),
source_msgs_dir.joinpath('django-partial.po'))
os.rename(
source_msgs_dir.joinpath('django.po'),
source_msgs_dir.joinpath('django-partial.po')
)
execute(make_djangojs_cmd, working_directory=BASE_DIR)
for filename in generated_files:
......@@ -101,7 +106,7 @@ def fix_header(po):
('FIRST AUTHOR <EMAIL@ADDRESS>',
'EdX Team <info@edx.org>')
)
for (src, dest) in fixes:
for src, dest in fixes:
header = header.replace(src, dest)
po.header = header
......@@ -112,12 +117,12 @@ def fix_header(po):
u'Content-Transfer-Encoding': u'8bit',
u'Project-Id-Version': u'PACKAGE VERSION',
u'Report-Msgid-Bugs-To': u'',
u'Last-Translator': u'FULL NAME <EMAIL@ADDRESS>',
u'Last-Translator': u'FULL NAME <EMAIL@ADDRESS>',
u'Language-Team': u'LANGUAGE <LL@li.org>',
u'POT-Creation-Date': u'2013-04-25 14:14-0400',
u'Content-Type': u'text/plain; charset=UTF-8',
u'MIME-Version': u'1.0'}
"""
"""
def fix_metadata(po):
"""
......@@ -146,7 +151,7 @@ def is_key_string(string):
returns True if string is a key string.
Key strings begin with underscore.
"""
return len(string)>1 and string[0]=='_'
return len(string) > 1 and string[0] == '_'
if __name__ == '__main__':
main()
#!/usr/bin/env python
"""
See https://edx-wiki.atlassian.net/wiki/display/ENG/PO+File+workflow
See https://edx-wiki.atlassian.net/wiki/display/ENG/PO+File+workflow
This task merges and compiles the human-readable .po files on the
local filesystem into machine-readable .mo files. This is typically
necessary as part of the build process since these .mo files are
needed by Django when serving the web app.
This task merges and compiles the human-readable .pofiles on the
local filesystem into machine-readable .mofiles. This is typically
necessary as part of the build process since these .mofiles are
needed by Django when serving the web app.
The configuration file (in edx-platform/conf/locale/config) specifies which
languages to generate.
The configuration file (in edx-platform/conf/locale/config) specifies which
languages to generate.
"""
import os, sys, logging
......@@ -26,10 +26,13 @@ def merge(locale, target='django.po', fail_if_missing=True):
"""
For the given locale, merge django-partial.po, messages.po, mako.po -> django.po
target is the resulting filename
If fail_if_missing is True, and the files to be merged are missing,
throw an Exception.
If fail_if_missing is False, and the files to be merged are missing,
If fail_if_missing is true, and the files to be merged are missing,
throw an Exception, otherwise return silently.
If fail_if_missing is false, and the files to be merged are missing,
just return silently.
"""
LOG.info('Merging locale={0}'.format(locale))
locale_directory = CONFIGURATION.get_messages_dir(locale)
......
......@@ -51,11 +51,7 @@ def new_filename(original_filename, new_locale):
orig_dir = os.path.dirname(original_filename)
msgs_dir = os.path.basename(orig_dir)
orig_file = os.path.basename(original_filename)
return os.path.abspath(os.path.join(orig_dir,
'../..',
new_locale,
msgs_dir,
orig_file))
return os.path.abspath(os.path.join(orig_dir, '../..', new_locale, msgs_dir, orig_file))
if __name__ == '__main__':
# required arg: file
......
......@@ -17,7 +17,7 @@ class TestConfiguration(TestCase):
config_filename = os.path.normpath(os.path.join(LOCALE_DIR, 'no_such_file'))
with self.assertRaises(Exception):
Configuration(config_filename)
def test_valid_configuration(self):
"""
Make sure we have a valid configuration file,
......
......@@ -3,7 +3,7 @@ from unittest import TestCase
import converter
class UpcaseConverter (converter.Converter):
class UpcaseConverter(converter.Converter):
"""
Converts a string to uppercase. Just used for testing.
"""
......
......@@ -4,14 +4,14 @@ from nose.plugins.skip import SkipTest
from config import LOCALE_DIR
from execute import call
def test_po_files(root=LOCALE_DIR):
"""
This is a generator. It yields all of the .po files under root, and tests each one.
"""
log = logging.getLogger(__name__)
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
for (dirpath, dirnames, filenames) in os.walk(root):
for name in filenames:
(base, ext) = os.path.splitext(name)
......
......@@ -27,7 +27,7 @@ def clean_translated_locales():
for locale in CONFIGURATION.locales:
if locale != CONFIGURATION.source_locale:
clean_locale(locale)
def clean_locale(locale):
"""
Strips out the warning from all of a locale's translated po files
......@@ -58,7 +58,7 @@ def get_new_header(po):
return TRANSIFEX_HEADER % team
if __name__ == '__main__':
if len(sys.argv)<2:
if len(sys.argv) < 2:
raise Exception("missing argument: push or pull")
arg = sys.argv[1]
if arg == 'push':
......@@ -67,4 +67,3 @@ if __name__ == '__main__':
pull()
else:
raise Exception("unknown argument: (%s)" % arg)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment