diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py index d5f4edfc..0bb8184a 100644 --- a/nw/core/tokenizer.py +++ b/nw/core/tokenizer.py @@ -151,6 +151,10 @@ class Tokenizer(): self._trComment = self.tr("Comment") self._trNotes = self.tr("Notes") + self._spellLang = self.theProject.projLang + if self._spellLang is None: + self._spellLang = self.theParent.mainConf.spellLanguage + return ## @@ -664,7 +668,7 @@ class Tokenizer(): theTitle = theTitle.replace(r"%sc%", str(self.numChScene)) theTitle = theTitle.replace(r"%sca%", str(self.numAbsScene)) if r"%chw%" in theTitle: - theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter, "en")) + theTitle = theTitle.replace(r"%chw%", numberToWord(self.numChapter, self._spellLang)) if r"%chi%" in theTitle: theTitle = theTitle.replace(r"%chi%", numberToRoman(self.numChapter, True)) if r"%chI%" in theTitle: diff --git a/nw/core/tools.py b/nw/core/tools.py index 91b59c93..7e538d6d 100644 --- a/nw/core/tools.py +++ b/nw/core/tools.py @@ -120,35 +120,40 @@ def numberToRoman(numVal, isLower=False): return romNum.lower() if isLower else romNum # =============================================================================================== # -# Convert an Integer to a Word Number +# Convert an Integer to a Number String # =============================================================================================== # -def numberToWord(numVal, theLanguage): +def numberToWord(numVal, theLang): """Wrapper for converting numbers to words for chapter headings. """ + if not isinstance(numVal, int): + return "[NaN]" + + if numVal < 0: + return "[<0]" + + if numVal > 999: + return "[>999]" + numWord = "" - if theLanguage == "en": # TODO: I18N - numWord = _numberToWordEN(numVal) + theCode = theLang.split("_")[0] + if theCode == "en": + numWord = _numberToWord_EN(numVal) + elif theCode in ("nb", "nn"): + numWord = _numberToWord_NO(numVal, theCode) else: - numWord = _numberToWordEN(numVal) + # Default to return the number as a string + numWord = str(numVal) + return numWord -def _numberToWordEN(numVal): +def _numberToWord_EN(numVal): """Convert numbers to English words. """ oneWord = "" tenWord = "" hunWord = "" - if not isinstance(numVal, int): - return "[NaN]" - - if numVal < 0: - return "[Negative]" - - if numVal > 999: - return "[Out of Range]" - if numVal == 0: return "Zero" @@ -156,38 +161,83 @@ def _numberToWordEN(numVal): tenVal = (numVal - oneVal) % 100 hunVal = (numVal - tenVal - oneVal) % 1000 - theHundreds = { - 100: "One Hundred", 200: "Two Hundred", 300: "Three Hundred", - 400: "Four Hundred", 500: "Five Hundred", 600: "Six Hundred", - 700: "Seven Hundred", 800: "Eight Hundred", 900: "Nine Hundred", - } - theTens = { - 20: "Twenty", 30: "Thirty", 40: "Forty", 50: "Fifty", - 60: "Sixty", 70: "Seventy", 80: "Eighty", 90: "Ninety", - } - theTeens = { - 0: "Ten", 1: "Eleven", 2: "Twelve", 3: "Thirteen", 4: "Fourteen", - 5: "Fifteen", 6: "Sixteen", 7: "Seventeen", 8: "Eighteen", 9: "Nineteen", - } - theOnes = { - 0: "", 1: "One", 2: "Two", 3: "Three", 4: "Four", - 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", + theWords = { + 0: "", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five", + 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", 10: "Ten", + 11: "Eleven", 12: "Twelve", 13: "Thirteen", 14: "Fourteen", + 15: "Fifteen", 16: "Sixteen", 17: "Seventeen", 18: "Eighteen", + 19: "Nineteen", 20: "Twenty", 30: "Thirty", 40: "Forty", + 50: "Fifty", 60: "Sixty", 70: "Seventy", 80: "Eighty", + 90: "Ninety", 100: "One Hundred", 200: "Two Hundred", + 300: "Three Hundred", 400: "Four Hundred", 500: "Five Hundred", + 600: "Six Hundred", 700: "Seven Hundred", 800: "Eight Hundred", + 900: "Nine Hundred", } - retVale = "" - hunWord = theHundreds.get(hunVal, "") + retVal = "" + hunWord = theWords.get(hunVal, "") if tenVal == 10: - oneWord = theTeens.get(oneVal, "") - retVale = f"{hunWord} {oneWord}".strip() + oneWord = theWords.get(oneVal+10, "") + retVal = f"{hunWord} {oneWord}".strip() else: - oneWord = theOnes.get(oneVal, "") + oneWord = theWords.get(oneVal, "") if tenVal == 0: - retVale = f"{hunWord} {oneWord}".strip() + retVal = f"{hunWord} {oneWord}".strip() else: - tenWord = theTens.get(tenVal, "") + tenWord = theWords.get(tenVal, "") if oneVal == 0: - retVale = f"{hunWord} {tenWord}".strip() + retVal = f"{hunWord} {tenWord}".strip() else: - retVale = f"{hunWord} {tenWord}-{oneWord}".strip() + retVal = f"{hunWord} {tenWord}-{oneWord}".strip() - return retVale + return retVal + +def _numberToWord_NO(numVal, theCode): + """Convert numbers to Norwegian words. + """ + oneWord = "" + tenWord = "" + hunWord = "" + + if numVal == 0: + return "null" + + oneVal = numVal % 10 + tenVal = (numVal - oneVal) % 100 + hunVal = (numVal - tenVal - oneVal) % 1000 + + theWords = { + 0: "", 1: "én", 2: "to", 3: "tre", 4: "fire", 5: "fem", 6: "seks", + 7: "sju", 8: "åtte", 9: "ni", 10: "ti", 11: "elleve", 12: "tolv", + 13: "tretten", 14: "fjorten", 15: "femten", 16: "seksten", 17: "sytten", + 18: "atten", 19: "nitten", 20: "tjue", 30: "tretti", 40: "førti", + 50: "femti", 60: "seksti", 70: "sytti", 80: "åtti", 90: "nitti", + 100: "ett hundre", 200: "to hundre", 300: "tre hundre", 400: "fire hundre", + 500: "fem hundre", 600: "seks hundre", 700: "sju hundre", + 800: "åtte hundre", 900: "ni hundre", + } + + if theCode == "nn": + theWords[1] = "ein" + theWords[100] = "eitt hundre" + + retVal = "" + hunWord = theWords.get(hunVal, "") + if tenVal == 10: + oneWord = theWords.get(oneVal+10, "") + sepVal = " og " if hunWord and oneWord else " " + retVal = f"{hunWord}{sepVal}{oneWord}" + else: + oneWord = theWords.get(oneVal, "") + if tenVal == 0: + sepVal = " og " if hunWord and oneWord else " " + retVal = f"{hunWord}{sepVal}{oneWord}".strip() + else: + tenWord = theWords.get(tenVal, "") + sepVal = " og " if hunWord and tenWord else " " + if oneVal == 0: + retVal = f"{hunWord}{sepVal}{tenWord}".strip() + else: + retVal = f"{hunWord}{sepVal}{tenWord}{oneWord}".strip() + + return retVal.strip() diff --git a/nw/gui/build.py b/nw/gui/build.py index 0d11674b..4615c9ff 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -331,24 +331,13 @@ class GuiBuildNovel(QDialog): self.fileGroup.setLayout(self.fileForm) self.novelFiles = QSwitch(width=wS, height=hS) - self.novelFiles.setToolTip(self.tr("Include files with layouts {0}.").format( - self.locale().createSeparatedList([ - self.locale().quoteString(self.tr('Book')), - self.locale().quoteString(self.tr('Page')), - self.locale().quoteString(self.tr('Partition')), - self.locale().quoteString(self.tr('Chapter')), - self.locale().quoteString(self.tr('Unnumbered')), - self.locale().quoteString(self.tr('Scene')), - ]) - )) + self.novelFiles.setToolTip(self.tr("Include files with layouts other than 'Note'.")) self.novelFiles.setChecked( self.optState.getBool("GuiBuildNovel", "addNovel", True) ) self.noteFiles = QSwitch(width=wS, height=hS) - self.noteFiles.setToolTip(self.tr("Include files with layout {0}.").format( - self.locale().quoteString(self.tr("Note")) - )) + self.noteFiles.setToolTip(self.tr("Include files with layout 'Note'.")) self.noteFiles.setChecked( self.optState.getBool("GuiBuildNovel", "addNotes", False) ) diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index 5502d79c..a2a8b4c1 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -147,20 +147,20 @@ class GuiMainStatus(QStatusBar): qApp.processEvents() return - def setLanguage(self, theLang, theProvider=""): + def setLanguage(self, theLanguage, theProvider=""): """Set the language code for the spell checker. """ - if theLang is None: + if theLanguage is None: self.langText.setText(self.tr("None")) self.langText.setToolTip("") else: - qLocal = QLocale(theLang) + qLocal = QLocale(theLanguage) spLang = qLocal.nativeLanguageName().title() self.langText.setText(spLang) if theProvider: - self.langText.setToolTip("%s (%s)" % (theLang, theProvider)) + self.langText.setToolTip("%s (%s)" % (theLanguage, theProvider)) else: - self.langText.setToolTip(theLang) + self.langText.setToolTip(theLanguage) return diff --git a/tests/test_core/test_core_tools.py b/tests/test_core/test_core_tools.py index d49ebf15..802eb94f 100644 --- a/tests/test_core/test_core_tools.py +++ b/tests/test_core/test_core_tools.py @@ -86,6 +86,7 @@ def testCoreTools_RomanNumbers(): def testCoreTools_NumberWords(): """Test the conversion of integer to English words. """ + # English assert numberToWord(0, "en") == "Zero" assert numberToWord(1, "en") == "One" assert numberToWord(2, "en") == "Two" @@ -114,14 +115,46 @@ def testCoreTools_NumberWords(): assert numberToWord(142, "en") == "One Hundred Forty-Two" assert numberToWord(999, "en") == "Nine Hundred Ninety-Nine" + # Norwegian + assert numberToWord(0, "nb") == "null" + assert numberToWord(1, "nb") == "én" + assert numberToWord(10, "nb") == "ti" + assert numberToWord(20, "nb") == "tjue" + assert numberToWord(21, "nb") == "tjueén" + assert numberToWord(29, "nb") == "tjueni" + assert numberToWord(42, "nb") == "førtito" + assert numberToWord(60, "nb") == "seksti" + assert numberToWord(100, "nb") == "ett hundre" + assert numberToWord(114, "nb") == "ett hundre og fjorten" + assert numberToWord(142, "nb") == "ett hundre og førtito" + assert numberToWord(999, "nb") == "ni hundre og nittini" + + assert numberToWord(0, "nn") == "null" + assert numberToWord(1, "nn") == "ein" + assert numberToWord(10, "nn") == "ti" + assert numberToWord(20, "nn") == "tjue" + assert numberToWord(21, "nn") == "tjueein" + assert numberToWord(29, "nn") == "tjueni" + assert numberToWord(42, "nn") == "førtito" + assert numberToWord(60, "nn") == "seksti" + assert numberToWord(100, "nn") == "eitt hundre" + assert numberToWord(114, "nn") == "eitt hundre og fjorten" + assert numberToWord(142, "nn") == "eitt hundre og førtito" + assert numberToWord(999, "nn") == "ni hundre og nittini" + + # Check complex language setting + assert numberToWord(1, "en_GB") == "One" + assert numberToWord(2, "en_GB") == "Two" + assert numberToWord(3, "en_GB") == "Three" + # Check a few with a nonsense language setting - assert numberToWord(1, "foo") == "One" - assert numberToWord(2, "foo") == "Two" - assert numberToWord(3, "foo") == "Three" + assert numberToWord(1, "foo") == "1" + assert numberToWord(2, "foo") == "2" + assert numberToWord(3, "foo") == "3" # Test out of range values - assert numberToWord(12345, "en") == "[Out of Range]" - assert numberToWord(-2345, "en") == "[Negative]" + assert numberToWord(12345, "en") == "[>999]" + assert numberToWord(-2345, "en") == "[<0]" assert numberToWord("234", "en") == "[NaN]" # END Test testCoreTools_NumberWords