diff --git a/nw/languages/nw_pt.qm b/i18n/nw_pt.qm similarity index 100% rename from nw/languages/nw_pt.qm rename to i18n/nw_pt.qm diff --git a/nw/languages/nw_pt.ts b/i18n/nw_pt.ts similarity index 100% rename from nw/languages/nw_pt.ts rename to i18n/nw_pt.ts diff --git a/nw/languages/phrases_pt.qph b/i18n/phrases_pt.qph similarity index 100% rename from nw/languages/phrases_pt.qph rename to i18n/phrases_pt.qph diff --git a/novelWriter.pro b/novelWriter.pro index 587eea36..715ae5a4 100644 --- a/novelWriter.pro +++ b/novelWriter.pro @@ -33,4 +33,4 @@ SOURCES += nw/error.py \ nw/gui/wordlist.py \ nw/gui/writingstats.py -TRANSLATIONS += nw/languages/nw_pt.ts +TRANSLATIONS += i18n/nw_pt.ts diff --git a/nw/__init__.py b/nw/__init__.py index 3e362cd5..f658f21a 100644 --- a/nw/__init__.py +++ b/nw/__init__.py @@ -24,13 +24,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ -import os import sys import getopt import logging -import re -from PyQt5.QtCore import QLibraryInfo, QLocale, QTranslator from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QErrorMessage @@ -112,21 +109,6 @@ logger = logging.getLogger(__name__) # Load the main config as a global object CONFIG = Config() -nw_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "languages") -qt_path = QLibraryInfo.location(QLibraryInfo.TranslationsPath) - -translators = {} -def load_translation(app, path, prefix, lang, script = None, country = None): - filename = "_".join(filter(bool, [prefix, - lang and lang.lower(), - script and script.capitalize(), - country and country.upper()])) - if filename not in translators: - translator = QTranslator() - if translator.load(filename, path): - print(filename, path) - app.installTranslator(translator) - translators[filename] = translator def main(sysArgs=None): """Parses command line, sets up logging, and launches main GUI. @@ -302,20 +284,8 @@ def main(sysArgs=None): # Connect the exception handler before making the main GUI sys.excepthook = exceptionHandler - # Load translations - lang, script, country = re.match( - r"^([a-z]{2,3})(?:_([a-z]{4}))?(?:_([a-z]{2,3}))?$", - QLocale.system().name(), re.IGNORECASE).groups() - - for path, prefix in ((qt_path, "qt"), - (qt_path, "qtbase"), - (nw_path, "nw")): - load_translation(nwApp, path, prefix, lang) - load_translation(nwApp, path, prefix, lang, script=script) - load_translation(nwApp, path, prefix, lang, country=country) - load_translation(nwApp, path, prefix, lang, script, country) - # Launch main GUI + CONFIG.initTranslations(nwApp) nwGUI = GuiMain() if not nwGUI.hasProject: nwGUI.showProjectLoadDialog() diff --git a/nw/config.py b/nw/config.py index 58229ea5..8173952a 100644 --- a/nw/config.py +++ b/nw/config.py @@ -30,11 +30,15 @@ import shutil import json import sys import os +import re from time import time from PyQt5.Qt import PYQT_VERSION_STR -from PyQt5.QtCore import QT_VERSION_STR, QStandardPaths, QSysInfo +from PyQt5.QtCore import ( + QT_VERSION_STR, QStandardPaths, QSysInfo, QLocale, QLibraryInfo, + QTranslator +) from nw.constants import nwConst, nwFiles, nwUnicode from nw.common import splitVersionNumber, formatTimeStamp @@ -75,6 +79,9 @@ class Config: self.iconPath = None # The full path to the nw/assets/icons folder self.helpPath = None # The full path to the novelwriter .qhc help file + # Internationalisation + self.qtTrans = {} + # Runtime Settings and Variables self.confChanged = False # True whenever the config has chenged, false after save self.hasHelp = False # True if the Qt help files are present in the assets folder @@ -84,11 +91,11 @@ class Config: self.guiSyntax = "default_light" self.guiIcons = "typicons_colour_light" self.guiDark = False # Load icons for dark backgrounds, if available - self.guiLang = "en" # Hardcoded for now since the GUI is only in English self.guiFont = "" # Defaults to system default font self.guiFontSize = 11 self.guiScale = 1.0 # Set automatically by Theme class self.lastNotes = "0x0" # The latest release notes that have been shown + self.guiLang = QLocale.system().name() ## Sizes self.winGeometry = [1200, 650] @@ -354,6 +361,26 @@ class Config: return True + def initTranslations(self, nwApp): + """Initialise the internationalisation. + """ + lnName, lnScript, lnCountry = re.match( + r"^([a-z]{2,3})(?:_([a-z]{4}))?(?:_([a-z]{2,3}))?$", self.guiLang, re.IGNORECASE + ).groups() + + qtLang = QLibraryInfo.location(QLibraryInfo.TranslationsPath) + nwLang = os.path.join(self.appRoot, "i18n") + loadTrans = [ + (qtLang, "qt"), (qtLang, "qtbase"), (nwLang, "nw") + ] + for lnPath, lnPref in loadTrans: + self._loadTranslation(nwApp, lnPath, lnPref, lnName) + self._loadTranslation(nwApp, lnPath, lnPref, lnName, lnScript=lnScript) + self._loadTranslation(nwApp, lnPath, lnPref, lnName, lnCountry=lnCountry) + self._loadTranslation(nwApp, lnPath, lnPref, lnName, lnScript, lnCountry) + + return + def loadConfig(self): """Load preferences from file and replace default settings. """ @@ -397,6 +424,9 @@ class Config: self.lastNotes = self._parseLine( cnfParse, cnfSec, "lastnotes", self.CNF_STR, self.lastNotes ) + self.guiLang = self._parseLine( + cnfParse, cnfSec, "guilang", self.CNF_STR, self.guiLang + ) ## Sizes cnfSec = "Sizes" @@ -626,6 +656,7 @@ class Config: cnfParse.set(cnfSec, "guifont", str(self.guiFont)) cnfParse.set(cnfSec, "guifontsize", str(self.guiFontSize)) cnfParse.set(cnfSec, "lastnotes", str(self.lastNotes)) + cnfParse.set(cnfSec, "guilang", str(self.guiLang)) ## Sizes cnfSec = "Sizes" @@ -951,6 +982,25 @@ class Config: # Internal Functions ## + def _loadTranslation(self, nwApp, lnPath, lnPref, lnName, lnScript=None, lnCountry=None): + """Load a translator file and create the translation object. + """ + lngFile = "_".join(filter(bool, [ + lnPref, + lnName and lnName.lower(), + lnScript and lnScript.capitalize(), + lnCountry and lnCountry.upper() + ])) + + if lngFile not in self.qtTrans: + qTranslator = QTranslator() + if qTranslator.load(lngFile, lnPath): + logger.debug("Loaded i18n: %s" % os.path.join(lnPath, lngFile)) + nwApp.installTranslator(qTranslator) + self.qtTrans[lngFile] = qTranslator + + return + def _packList(self, inData): """Pack a list of items into a comma-separated string. """ diff --git a/nw/guimain.py b/nw/guimain.py index 50123955..31872d24 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -76,6 +76,7 @@ class GuiMain(QMainWindow): logger.info("Python Version: %s (0x%x)" % ( self.mainConf.verPyString, self.mainConf.verPyHexVal) ) + logger.info("GUI Language: %s" % self.mainConf.guiLang) # Core Classes # ============