SVGHMI: i18n: now loads PO filesand match translation against catalog. Refactored a bit to move i18n related code in i18n.py
--- a/svghmi/i18n.py Tue Jan 19 11:57:13 2021 +0100
+++ b/svghmi/i18n.py Thu Jan 21 05:04:23 2021 +0100
@@ -7,9 +7,11 @@
# See COPYING file for copyrights details.
from __future__ import absolute_import
+import os
import sys
import subprocess
import time
+import ast
import wx
def open_pofile(pofile):
@@ -36,6 +38,66 @@
else:
subprocess.Popen([poedit_path,pofile])
+def EtreeToMessages(msgs):
+ """ Converts XML tree from 'extract_i18n' templates into a list of tuples """
+ messages = []
+
+ for msg in msgs:
+ messages.append((
+ "\n".join([line.text.encode("utf-8") for line in msg]),
+ msg.get("label"), msg.get("id")))
+
+ return messages
+
+def SaveCatalog(fname, messages):
+ """ Save messages given as list of tupple (msg,label,id) in POT file """
+ w = POTWriter()
+ w.ImportMessages(messages)
+
+ with open(fname, 'w') as POT_file:
+ w.write(POT_file)
+
+def ReadTranslations(dirpath):
+ """ Read all PO files from a directory and return a list of (lang, translation_dict) tuples """
+
+ po_files = [fname for fname in os.listdir(dirpath) if fname.endswith(".po")]
+
+ translations = []
+ for po_fname in po_files:
+ r = POReader()
+ with open(os.path.join(dirpath, po_fname), 'r') as PO_file:
+ r.read(PO_file)
+ translations.append((po_fname[:-3], r.get_messages()))
+ return translations
+
+def MatchTranslations(translations, messages, errcallback):
+ """
+ Matches translations against original message catalog,
+ warn about inconsistancies,
+ returns list of langs, and a list of (msgid, [translations]) tuples
+ """
+ translated_messages = []
+ for msgid,label,svgid in messages:
+ translated_message = []
+ for lang,translation in translations:
+ msg = translation.pop(msgid, None)
+ if msg is None:
+ errcallback(_('{}: Missing translation for "{}" (label:{}, id:{})').format(lang,msgid,label,svgid))
+ translated_message.append(msg)
+ translated_messages.append((msgid,translated_message))
+ langs = []
+ for lang,translation in translations:
+ langs.append(lang)
+ for msgid, msg in translation.iteritems():
+ errcallback(_('{}: Unused translation "{}":"{}"').format(lang,msgid,msg))
+
+ return langs,translated_messages
+
+
+def TranslationToEtree(langs,translated_messages):
+ pass
+
+
locpfx = '#:svghmi.svg:'
pot_header = '''\
@@ -51,8 +113,8 @@
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
"Language-Team: LANGUAGE <LL@li.org>\\n"
"MIME-Version: 1.0\\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
+"Content-Type: text/plain; charset=UTF-8\\n"
+"Content-Transfer-Encoding: 8bit\\n"
"Generated-By: SVGHMI 1.0\\n"
'''
@@ -111,11 +173,10 @@
def ImportMessages(self, msgs):
for msg in msgs:
- self.addentry("\n".join([line.text.encode("utf-8") for line in msg]), msg.get("label"), msg.get("id"))
+ self.addentry(*msg)
def addentry(self, msg, label, svgid):
entry = (label, svgid)
- print(entry)
self.__messages.setdefault(msg, set()).add(entry)
def write(self, fp):
@@ -153,7 +214,10 @@
def __init__(self):
self.__messages = {}
- def add(msgid, msgstr, fuzzy):
+ def get_messages(self):
+ return self.__messages
+
+ def add(self, msgid, msgstr, fuzzy):
"Add a non-fuzzy translation to the dictionary."
if not fuzzy and msgstr:
self.__messages[msgid] = msgstr
--- a/svghmi/svghmi.py Tue Jan 19 11:57:13 2021 +0100
+++ b/svghmi/svghmi.py Thu Jan 21 05:04:23 2021 +0100
@@ -30,7 +30,7 @@
import targets
from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
from XSLTransform import XSLTransform
-from svghmi.i18n import POTWriter, POReader, open_pofile
+from svghmi.i18n import EtreeToMessages, SaveCatalog, ReadTranslations, MatchTranslations, TranslationToEtree
HMI_TYPES_DESC = {
"HMI_NODE":{},
@@ -530,18 +530,18 @@
return res
def GetTranslations(self, _context, msgs):
-
- w = POTWriter()
- w.ImportMessages(msgs)
-
- with open(self._getPOTpath(), 'w') as POT_file:
- w.write(POT_file)
-
- # XXX scan existing PO files
- # XXX read PO files
-
- r = POReader()
- return None # XXX return all langs from all POs
+ messages = EtreeToMessages(msgs)
+
+ SaveCatalog(self._getPOTpath(), messages)
+
+ translations = ReadTranslations(self.CTNPath())
+
+ langs,translated_messages = MatchTranslations(translations, messages,
+ errcallback=self.GetCTRoot().logger.write_warning)
+
+ print(langs,translated_messages)
+
+ return TranslationToEtree(langs,translated_messages)
def CTNGenerate_C(self, buildpath, locations):
@@ -699,7 +699,7 @@
if dialog.ShowModal() == wx.ID_OK:
POFile = dialog.GetPath()
if os.path.isfile(POFile):
- if os.path.dirname(POFile) == project_path:
+ if os.path.relpath(POFile, project_path) == os.path.basename(POFile):
self._StartPOEdit(POFile)
else:
self.GetCTRoot().logger.write_error(_("PO file misplaced: %s is not in %s\n") % (POFile,project_path))