Commit 55dd0fc8 by Steve Strassmann

workaround for gettext parser bug

parent 22e147b2
[main]
host = https://www.transifex.com
[edx-studio.django-partial]
file_filter = conf/locale/<lang>/LC_MESSAGES/django-partial.po
source_file = conf/locale/en/LC_MESSAGES/django-partial.po
source_lang = en
type = PO
[edx-studio.djangojs]
file_filter = conf/locale/<lang>/LC_MESSAGES/djangojs.po
source_file = conf/locale/en/LC_MESSAGES/djangojs.po
source_lang = en
type = PO
[edx-studio.mako]
file_filter = conf/locale/<lang>/LC_MESSAGES/mako.po
source_file = conf/locale/en/LC_MESSAGES/mako.po
source_lang = en
type = PO
[edx-studio.messages]
file_filter = conf/locale/<lang>/LC_MESSAGES/messages.po
source_file = conf/locale/en/LC_MESSAGES/messages.po
source_lang = en
type = PO
{"locales" : ["en"]} {"locales" : ["en", "fr", "es"]}
...@@ -50,14 +50,29 @@ def execute (command, working_directory=BASE_DIR, log=LOG): ...@@ -50,14 +50,29 @@ def execute (command, working_directory=BASE_DIR, log=LOG):
""" """
Executes shell command in a given working_directory. Executes shell command in a given working_directory.
Command is a string to pass to the shell. Command is a string to pass to the shell.
Output is logged to log. The command is logged to log, output is ignored.
""" """
if log:
log.info(command) log.info(command)
subprocess.call(command.split(' '), cwd=working_directory) subprocess.call(command.split(' '), cwd=working_directory)
def call(command, working_directory=BASE_DIR, log=LOG):
"""
Executes shell command in a given working_directory.
Command is a string to pass to the shell.
Returns a tuple of two strings: (stdout, stderr)
"""
if log:
log.info(command)
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=working_directory)
out, err = p.communicate()
return (out, err)
def get_config(): def get_config():
"""Returns data found in config file, or returns None if file not found""" """Returns data found in config file, or returns None if file not found"""
config_path = os.path.abspath(CONFIG_FILENAME) config_path = os.path.normpath(CONFIG_FILENAME)
if not os.path.exists(config_path): if not os.path.exists(config_path):
log.warn("Configuration file cannot be found: %s" % \ log.warn("Configuration file cannot be found: %s" % \
os.path.relpath(config_path, BASE_DIR)) os.path.relpath(config_path, BASE_DIR))
......
...@@ -79,6 +79,7 @@ def fix_header(po): ...@@ -79,6 +79,7 @@ def fix_header(po):
""" """
Replace default headers with edX headers Replace default headers with edX headers
""" """
po.metadata_is_fuzzy = [] # remove [u'fuzzy']
header = po.header header = po.header
fixes = ( fixes = (
('SOME DESCRIPTIVE TITLE', 'edX translation file'), ('SOME DESCRIPTIVE TITLE', 'edX translation file'),
...@@ -119,10 +120,9 @@ def fix_metadata(po): ...@@ -119,10 +120,9 @@ def fix_metadata(po):
'Report-Msgid-Bugs-To': 'translation_team@edx.org', 'Report-Msgid-Bugs-To': 'translation_team@edx.org',
'Project-Id-Version': '0.1a', 'Project-Id-Version': '0.1a',
'Language' : 'en', 'Language' : 'en',
'Last-Translator' : '',
'Language-Team': 'translation team <translation_team@edx.org>', 'Language-Team': 'translation team <translation_team@edx.org>',
} }
if po.metadata.has_key('Last-Translator'):
del po.metadata['Last-Translator']
po.metadata.update(fixes) po.metadata.update(fixes)
def strip_key_strings(po): def strip_key_strings(po):
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
""" """
import os import os
from polib import pofile
from execute import execute, get_config, messages_dir, remove_file, \ from execute import execute, get_config, messages_dir, remove_file, \
BASE_DIR, LOG, SOURCE_LOCALE BASE_DIR, LOG, SOURCE_LOCALE
...@@ -30,11 +32,23 @@ def merge(locale, target='django.po'): ...@@ -30,11 +32,23 @@ def merge(locale, target='django.po'):
merge_cmd = 'msgcat -o merged.po ' + ' '.join(files_to_merge) merge_cmd = 'msgcat -o merged.po ' + ' '.join(files_to_merge)
execute(merge_cmd, working_directory=locale_directory) execute(merge_cmd, working_directory=locale_directory)
# rename merged.po -> django.po (default) # clean up redunancies in the metadata
merged_filename = os.path.join(locale_directory, 'merged.po') merged_filename = os.path.join(locale_directory, 'merged.po')
clean_metadata(merged_filename)
# rename merged.po -> django.po (default)
django_filename = os.path.join(locale_directory, target) django_filename = os.path.join(locale_directory, target)
os.rename(merged_filename, django_filename) # can't overwrite file on Windows os.rename(merged_filename, django_filename) # can't overwrite file on Windows
def clean_metadata(file):
"""
Clean up redundancies in the metadata caused by merging.
This reads in a PO file and simply saves it back out again.
"""
po = pofile(file)
po.save()
def validate_files(dir, files_to_merge): def validate_files(dir, files_to_merge):
""" """
Asserts that the given files exist. Asserts that the given files exist.
......
...@@ -10,15 +10,15 @@ ...@@ -10,15 +10,15 @@
# #
# $ ./make_dummy.py <sourcefile> # $ ./make_dummy.py <sourcefile>
# #
# $ ./make_dummy.py mitx/conf/locale/en/LC_MESSAGES/django.po # $ ./make_dummy.py ../conf/locale/en/LC_MESSAGES/django.po
# #
# generates output to # generates output to
# mitx/conf/locale/vr/LC_MESSAGES/django.po # mitx/conf/locale/fr/LC_MESSAGES/django.po
import os, sys import os, sys
import polib import polib
from dummy import Dummy from dummy import Dummy
from execute import create_dir_if_necessary from execute import get_logger, create_dir_if_necessary
def main(file, locale): def main(file, locale):
""" """
...@@ -41,11 +41,11 @@ def new_filename(original_filename, new_locale): ...@@ -41,11 +41,11 @@ def new_filename(original_filename, new_locale):
orig_dir = os.path.dirname(original_filename) orig_dir = os.path.dirname(original_filename)
msgs_dir = os.path.basename(orig_dir) msgs_dir = os.path.basename(orig_dir)
orig_file = os.path.basename(original_filename) orig_file = os.path.basename(original_filename)
return os.path.join(orig_dir, return os.path.abspath(os.path.join(orig_dir,
'/../..', '../..',
new_locale, new_locale,
msgs_dir, msgs_dir,
orig_file) orig_file))
# Dummy language # Dummy language
...@@ -60,7 +60,7 @@ DEFAULT_LOCALE = 'fr' ...@@ -60,7 +60,7 @@ DEFAULT_LOCALE = 'fr'
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv)<2: if len(sys.argv)<2:
raise Exception("missing file argument") raise Exception("missing file argument")
if len(sys.argv)<2: if len(sys.argv)<3:
locale = DEFAULT_LOCALE locale = DEFAULT_LOCALE
else: else:
locale = sys.argv[2] locale = sys.argv[2]
......
...@@ -2,3 +2,5 @@ from test_extract import TestExtract ...@@ -2,3 +2,5 @@ from test_extract import TestExtract
from test_generate import TestGenerate from test_generate import TestGenerate
from test_converter import TestConverter from test_converter import TestConverter
from test_dummy import TestDummy from test_dummy import TestDummy
from test_validate import TestValidate
import os
from unittest import TestCase
from nose.plugins.skip import SkipTest
from execute import call, LOCALE_DIR, LOG
class TestValidate(TestCase):
"""
Call GNU msgfmt -c on each .po file to validate its format.
"""
def test_validate(self):
# Skip this test for now because it's very noisy
raise SkipTest()
for file in self.get_po_files():
# Use relative paths to make output less noisy.
rfile = os.path.relpath(file, LOCALE_DIR)
(out, err) = call(['msgfmt','-c', rfile], log=None, working_directory=LOCALE_DIR)
if err != '':
LOG.warn('\n'+err)
def get_po_files(self, root=LOCALE_DIR):
"""
This is a generator. It yields all of the .po files under root.
"""
for (dirpath, dirnames, filenames) in os.walk(root):
for name in filenames:
(base, ext) = os.path.splitext(name)
if ext.lower() == '.po':
yield os.path.join(dirpath, name)
...@@ -337,12 +337,6 @@ task :migrate, [:env] do |t, args| ...@@ -337,12 +337,6 @@ task :migrate, [:env] do |t, args|
sh(django_admin(:lms, args.env, 'migrate')) sh(django_admin(:lms, args.env, 'migrate'))
end end
desc "Run tests for the internationalization library"
task :test_i18n do
test = File.join(REPO_ROOT, "i18n", "tests")
sh("nosetests #{test}")
end
Dir["common/lib/*"].select{|lib| File.directory?(lib)}.each do |lib| Dir["common/lib/*"].select{|lib| File.directory?(lib)}.each do |lib|
task_name = "test_#{lib}" task_name = "test_#{lib}"
...@@ -516,27 +510,49 @@ end ...@@ -516,27 +510,49 @@ end
# --- Internationalization tasks # --- Internationalization tasks
desc "Extract localizable strings from sources" namespace :i18n do
task :extract_dev_strings do
desc "Extract localizable strings from sources"
task :extract do
sh(File.join(REPO_ROOT, "i18n", "extract.py")) sh(File.join(REPO_ROOT, "i18n", "extract.py"))
end end
desc "Compile localizable strings from sources. With optional flag 'extract', will extract strings first." desc "Compile localizable strings from sources. With optional flag 'extract', will extract strings first."
task :generate_i18n do task :generate do
if ARGV.last.downcase == 'extract' if ARGV.last.downcase == 'extract'
Rake::Task["extract_dev_strings"].execute Rake::Task["i18n:extract"].execute
end end
sh(File.join(REPO_ROOT, "i18n", "generate.py")) sh(File.join(REPO_ROOT, "i18n", "generate.py"))
end end
desc "Simulate international translation by generating dummy strings corresponding to source strings." desc "Simulate international translation by generating dummy strings corresponding to source strings."
task :dummy_i18n do task :dummy do
source_files = Dir["#{REPO_ROOT}/conf/locale/en/LC_MESSAGES/*.po"] source_files = Dir["#{REPO_ROOT}/conf/locale/en/LC_MESSAGES/*.po"]
dummy_locale = 'fr' dummy_locale = 'fr'
cmd = File.join(REPO_ROOT, "i18n", "make_dummy.py") cmd = File.join(REPO_ROOT, "i18n", "make_dummy.py")
for file in source_files do for file in source_files do
sh("#{cmd} #{file} #{dummy_locale}") sh("#{cmd} #{file} #{dummy_locale}")
end end
end
namespace :transifex do
desc "Push source strings to Transifex for translation"
task :push do
sh("tx push -s")
end
desc "Pull transated strings from Transifex"
task :pull do
sh("tx pull")
end
end
desc "Run tests for the internationalization library"
task :test do
test = File.join(REPO_ROOT, "i18n", "tests")
sh("nosetests #{test}")
end
end end
# --- Develop and public documentation --- # --- Develop and public documentation ---
......
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