[extensions-web] i18n: added damned-lies compatible translation workflow support.
- From: Yuri Konotopov <ykonotopov src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [extensions-web] i18n: added damned-lies compatible translation workflow support.
- Date: Tue, 22 Jan 2019 03:49:06 +0000 (UTC)
commit 5cd432e4eb380b4ee23ed48e989cd4cd3fdc01cb
Author: Yuri Konotopov <ykonotopov gnome org>
Date: Tue Jan 22 07:45:55 2019 +0400
i18n: added damned-lies compatible translation workflow support.
1. Implemented damned-lies compatible translation workflow with single
gettext template in the "po" directory"
2. Implemented Mustache templates strings extraction in makemessages.
3. Implemented Django-compatible compilation of translations from single
gettext template to "django.po" and "djangojs.po"
See-Also: https://gitlab.gnome.org/Infrastructure/extensions-web/merge_requests/9
README.rst | 1 +
openshift/docker/Dockerfile | 7 +-
requirements.txt | 1 +
sweettooth/core/__init__.py | 0
sweettooth/core/management/__init__.py | 0
sweettooth/core/management/commands/__init__.py | 25 ++
.../core/management/commands/compilemessages.py | 55 +++++
.../core/management/commands/makemessages.py | 125 ++++++++++
sweettooth/locale/en/LC_MESSAGES/django.po | 255 ---------------------
sweettooth/locale/en/LC_MESSAGES/djangojs.po | 42 ----
sweettooth/settings.py | 3 +-
11 files changed, 214 insertions(+), 300 deletions(-)
---
diff --git a/README.rst b/README.rst
index 6e37028..40d06dc 100644
--- a/README.rst
+++ b/README.rst
@@ -99,6 +99,7 @@ Once you've done that, proceed with the database migrations:
::
$ python manage.py migrate
+ $ python manage.py compilemessages
$ python mange.py createsuperuser --username=joe --email=joe email com
After above steps your database should be initialized and almost ready to run.
diff --git a/openshift/docker/Dockerfile b/openshift/docker/Dockerfile
index 7fec13d..376b633 100644
--- a/openshift/docker/Dockerfile
+++ b/openshift/docker/Dockerfile
@@ -7,6 +7,10 @@ ENV PYTHONUNBUFFERED=1 \
GPG_KEY=08E2400FF7FE8FEDE3ACB52818147B073BAD2B07
RUN set -ex \
+ && apt-get update \
+ && apt-get install --no-install-recommends --no-install-suggests -y \
+ gettext \
+ && rm -r /var/lib/apt/lists/* \
&& pip install Sphinx \
&& wget -O xapian-core.tar.xz
"https://oligarchy.co.uk/xapian/$XAPIAN_VERSION/xapian-core-$XAPIAN_VERSION.tar.xz" \
&& wget -O xapian-core.tar.xz.asc
"https://oligarchy.co.uk/xapian/$XAPIAN_VERSION/xapian-core-$XAPIAN_VERSION.tar.xz.asc" \
@@ -68,4 +72,5 @@ RUN set -ex \
&& chown www-data:root /extensions-web/wsgi.ini \
&& pip install -r requirements.txt \
&& pip install mysqlclient \
- && pip install uWSGI
+ && pip install uWSGI \
+ && EGO_SECRET_KEY=- python manage.py compilemessages
diff --git a/requirements.txt b/requirements.txt
index dcdf708..bd47ef1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,6 +4,7 @@ django-contrib-comments == 1.9.0
django-registration == 2.5.2
Pygments >= 1.4
pillow >= 2.0.0
+polib >= 1.1.0
chardet >= 2.2.1
dj-database-url
dj-email-url
diff --git a/sweettooth/core/__init__.py b/sweettooth/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/sweettooth/core/management/__init__.py b/sweettooth/core/management/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/sweettooth/core/management/commands/__init__.py b/sweettooth/core/management/commands/__init__.py
new file mode 100644
index 0000000..073c63b
--- /dev/null
+++ b/sweettooth/core/management/commands/__init__.py
@@ -0,0 +1,25 @@
+"""
+ GNOME Shell extensions repository
+ Copyright (C) 2019 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
+
+from django.conf import settings
+from pathlib import Path
+
+class MessagesCommand:
+ metadata_domain_prefix = 'extensions-web-domain-'
+ po_path = Path(settings.BASE_DIR).joinpath('po')
+ linguas_path = Path(po_path).joinpath('LINGUAS')
+ locale_path = Path(settings.SITE_ROOT).joinpath("locale")
+
+ def check_po_directory(self):
+ Path(self.po_path).mkdir(parents=True, exist_ok=True)
+ Path(self.linguas_path).touch(exist_ok=True)
+
+ def create_locale_directory(self):
+ self.locale_path.mkdir(parents=True, exist_ok=True)
diff --git a/sweettooth/core/management/commands/compilemessages.py
b/sweettooth/core/management/commands/compilemessages.py
new file mode 100644
index 0000000..e65fba4
--- /dev/null
+++ b/sweettooth/core/management/commands/compilemessages.py
@@ -0,0 +1,55 @@
+"""
+ GNOME Shell extensions repository
+ Copyright (C) 2019 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
+
+from django.core.management.commands.compilemessages import Command as CompileMessagesCommand
+from sweettooth.core.management.commands import MessagesCommand
+from pathlib import Path
+import polib
+
+class Command(CompileMessagesCommand, MessagesCommand):
+ def handle(self, *args, **options):
+ self.check_po_directory()
+ self.create_locale_directory()
+ self.copy_translations()
+
+ super().handle(*args, **options)
+
+ def copy_translations(self):
+ with open(self.linguas_path, 'r') as file:
+ for line in file:
+ lang = line.strip()
+
+ po_path = Path(self.po_path, lang + '.po')
+ if not lang or not po_path.is_file():
+ continue
+
+ self.stdout.write('processing language %s\n' % lang)
+ source = polib.pofile(po_path)
+ django = polib.POFile()
+ djangojs = polib.POFile()
+
+ django.metadata = source.metadata
+ djangojs.metadata = source.metadata
+
+ for entry in source:
+ for occurrence, line in entry.occurrences:
+ if occurrence.startswith(self.metadata_domain_prefix):
+ domain = occurrence[len(self.metadata_domain_prefix):]
+
+ if domain == 'django':
+ django.append(entry)
+ elif domain == 'djangojs':
+ djangojs.append(entry)
+
+ lang_path = self.locale_path.joinpath(lang, 'LC_MESSAGES')
+ lang_path.mkdir(parents=True, exist_ok=True)
+
+ django.save(str(lang_path.joinpath("django.po")))
+ djangojs.save(str(lang_path.joinpath("djangojs.po")))
diff --git a/sweettooth/core/management/commands/makemessages.py
b/sweettooth/core/management/commands/makemessages.py
new file mode 100644
index 0000000..0b92a04
--- /dev/null
+++ b/sweettooth/core/management/commands/makemessages.py
@@ -0,0 +1,125 @@
+"""
+ GNOME Shell extensions repository
+ Copyright (C) 2019 Yuri Konotopov <ykonotopov gnome org>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+"""
+
+from datetime import datetime
+from django.conf import settings
+from django.core.management.commands.makemessages import Command as MakeMessagesCommand
+from html.parser import HTMLParser
+from pathlib import Path
+import polib
+import pytz
+
+from sweettooth.core.management.commands import MessagesCommand
+
+class GettextParser(HTMLParser):
+ in_gettext = False
+ po = None
+ file = None
+
+ def __init__(self, po):
+ super().__init__(convert_charrefs=True)
+ self.po = po
+
+ def set_file(self, file):
+ self.file = file
+
+ def handle_starttag(self, tag, attrs):
+ if tag.lower() == 'x-gettext':
+ self.in_gettext = True
+ else:
+ self.in_gettext = False
+
+ def handle_endtag(self, tag):
+ self.in_gettext = False
+
+ def handle_data(self, data):
+ if self.in_gettext:
+ (line, offset) = self.getpos()
+ self.po.append(polib.POEntry(msgid=data, occurrences=[(self.file, line)]))
+
+
+class Command(MakeMessagesCommand, MessagesCommand):
+ def handle(self, *args, **options):
+ options['keep_pot'] = True
+
+ self.check_po_directory()
+ self.create_locale_directory()
+
+ for domain in ('django', 'djangojs'):
+ self.locale_paths = []
+ options['domain'] = domain
+ super().handle(*args, **options)
+
+ self.create_po_template()
+
+ for domain in ('django', 'djangojs'):
+ self.domain = domain
+ self.remove_potfiles()
+
+ def build_potfiles(self):
+ potfiles = super().build_potfiles()
+ if self.domain == 'djangojs':
+ if len(potfiles) > 1:
+ # We do not support multiple locale dirs
+ raise NotImplementedError("Multiple locale dirs are not supported")
+
+ po = polib.pofile(potfiles[0], check_for_duplicates = True)
+
+ self.search_mustache_texts(po)
+
+ po.sort()
+ po.save(potfiles[0])
+
+ return potfiles
+
+ def search_mustache_texts(self, po):
+ extensions = self.extensions
+ self.extensions = {'.mst'}
+
+ parser = GettextParser(po)
+ file_list = self.find_files(Path(settings.SITE_ROOT).joinpath('static', 'js'))
+ for translatable_file in file_list:
+ with open(translatable_file.path, 'r') as file:
+ parser.set_file(translatable_file.path.replace(settings.BASE_DIR, '').lstrip('/'))
+ parser.feed(file.read())
+ parser.reset()
+
+ self.extensions = extensions
+
+ def create_po_template(self):
+ django = polib.pofile(str(Path(self.locale_paths[0]).joinpath('django.pot')), check_for_duplicates =
True)
+ djangojs = polib.pofile(str(Path(self.locale_paths[0]).joinpath('djangojs.pot')),
check_for_duplicates = True)
+
+ self.add_po_domain(django, 'django')
+ self.add_po_domain(djangojs, 'djangojs')
+
+ for entry in djangojs:
+ django.append(entry)
+
+ django.header = "\nGNOME Shell extensions repository\n"
+ django.header += "\n"
+ django.header += "DO NOT EDIT!\n"
+ django.header += "This file is auto generated with manage.py makemessages."
+ django.header += "\n"
+
+ django.metadata = {
+ 'Project-Id-Version': '1.0',
+ 'Report-Msgid-Bugs-To': 'ykonotopov gnome org',
+ 'POT-Creation-Date': datetime.now(pytz.utc).strftime('%Y-%m-%d %H:%M%z'),
+ 'MIME-Version': '1.0',
+ 'Content-Type': 'text/plain; charset=utf-8',
+ 'Content-Transfer-Encoding': '8bit',
+ }
+ django.sort()
+ django.save(Path(self.po_path).joinpath("extensions-web.pot"))
+
+ def add_po_domain(self, po, domain):
+ for entry in po:
+ entry.occurrences.append((self.metadata_domain_prefix + domain, 1))
diff --git a/sweettooth/settings.py b/sweettooth/settings.py
index 44c7c3f..6a2f809 100644
--- a/sweettooth/settings.py
+++ b/sweettooth/settings.py
@@ -48,6 +48,7 @@ INSTALLED_APPS = (
'sweettooth.extensions',
'sweettooth.auth',
+ 'sweettooth.core',
'sweettooth.review',
'sweettooth.errorreports',
'sweettooth.templates',
@@ -110,8 +111,6 @@ DATABASES = {
LANGUAGE_CODE = 'en-us'
-LOCALE_PATHS = [os.path.join(BASE_DIR, 'sweettooth', 'locale')]
-
TIME_ZONE = 'UTC'
USE_I18N = True
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]