From f6214ae36d382edaca6a548eb8e5a9e6f0614531 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 3 Jun 2025 19:53:00 +0200 Subject: [PATCH 01/19] Build AppImage with Python 3.11 again --- .github/workflows/build_linux.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 56b0f8ea..8a926afc 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -10,13 +10,13 @@ jobs: needs: buildAssets runs-on: ubuntu-latest env: - PYTHON_VERSION: "3.13" + PYTHON_VERSION: "3.11" LINUX_TAG: "manylinux_2_28_x86_64" steps: - name: Python Setup uses: actions/setup-python@v5 with: - python-version: "3.13" + python-version: "3.11" architecture: x64 - name: Install Packages (pip) From 53784b310eb8d993dcf01e59d914d53341034695 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 6 Jun 2025 18:39:21 +0200 Subject: [PATCH 02/19] Close instead of hide auto-complete menu when inactive (#2386) --- novelwriter/gui/doceditor.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 0892bb71..8d1c42c1 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -1090,11 +1090,14 @@ class GuiDocEditor(QPlainTextEdit): show = self._completer.updateMetaText(text, bPos) else: show = self._completer.updateCommentText(text, bPos) - point = self.cursorRect().bottomRight() - self._completer.move(viewport.mapToGlobal(point)) - self._completer.setVisible(show) + if show: + point = self.cursorRect().bottomRight() + self._completer.move(viewport.mapToGlobal(point)) + self._completer.show() + else: + self._completer.close() else: - self._completer.setVisible(False) + self._completer.close() if self._doReplace and added == 1: cursor = self.textCursor() From bf1067a346314cd7d6b900b0fe4f1dce62772b2c Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:07:32 +0200 Subject: [PATCH 03/19] Make sure project items in inactive classes are removed from the index (#2387) --- novelwriter/core/index.py | 16 ++++++++++------ novelwriter/core/item.py | 2 +- tests/test_core/test_core_index.py | 29 ++++++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/novelwriter/core/index.py b/novelwriter/core/index.py index fb357842..ee108ad3 100644 --- a/novelwriter/core/index.py +++ b/novelwriter/core/index.py @@ -131,12 +131,6 @@ class Index: self._novelExtra = extra return - def setItemClass(self, tHandle: str, itemClass: nwItemClass) -> None: - """Update the class for all tags of a handle.""" - logger.info("Updating class for '%s'", tHandle) - self._tagsIndex.updateClass(tHandle, itemClass.name) - return - ## # Public Methods ## @@ -183,6 +177,16 @@ class Index: self.scanText(tHandle, self._project.storage.getDocumentText(tHandle)) return + def refreshHandle(self, tHandle: str) -> None: + """Update the class for all tags of a handle.""" + if item := self._project.tree[tHandle]: + logger.info("Updating class for '%s'", tHandle) + if item.isInactiveClass(): + self.deleteHandle(tHandle) + else: + self._tagsIndex.updateClass(tHandle, item.itemClass.name) + return + def indexChangedSince(self, checkTime: int | float) -> bool: """Check if the index has changed since a given time.""" return self._indexChange > float(checkTime) diff --git a/novelwriter/core/item.py b/novelwriter/core/item.py index a8f2fbbd..a6b92734 100644 --- a/novelwriter/core/item.py +++ b/novelwriter/core/item.py @@ -439,7 +439,7 @@ class NWItem: self.setClass(itemClass) if self._type == nwItemType.FILE: # Notify the index of the class change - self._project.index.setItemClass(self._handle, itemClass) + self._project.index.refreshHandle(self._handle) if self._layout == nwItemLayout.NO_LAYOUT: # If no layout is set, pick one diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index 990a2206..bc9bef2c 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -95,12 +95,35 @@ def testCoreIndex_LoadSave(qtbot, monkeypatch, prjLipsum, nwGUI, tstPaths): tagIndex = str(index._tagsIndex.packData()) itemsIndex = str(index._itemIndex.packData()) + # Update item class + bHandle = "4c4f28287af27" + bItem = project.tree[bHandle] + assert bItem is not None + + tagsBod = index._tagsIndex["Bod"] + assert tagsBod is not None + assert tagsBod["handle"] == bHandle + assert tagsBod["class"] == "CHARACTER" + + bItem.setClass(nwItemClass.CUSTOM) + index.refreshHandle(bHandle) + assert tagsBod is not None + assert tagsBod["handle"] == bHandle + assert tagsBod["class"] == "CUSTOM" + + # Update item class to inactive + bItem.setClass(nwItemClass.TRASH) + index.refreshHandle(bHandle) + assert "Bod" not in index._tagsIndex + bItem.setClass(nwItemClass.CHARACTER) + index.reIndexHandle(bHandle) + # Delete a handle assert index._tagsIndex["Bod"] is not None - assert index._itemIndex["4c4f28287af27"] is not None - index.deleteHandle("4c4f28287af27") + assert index._itemIndex[bHandle] is not None + index.deleteHandle(bHandle) assert index._tagsIndex["Bod"] is None - assert index._itemIndex["4c4f28287af27"] is None + assert index._itemIndex[bHandle] is None # Clear the index index.clear() From 53355dbcc64480ca4280b7484a99b8cf32d42323 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:16:59 +0200 Subject: [PATCH 04/19] Don't remove tags for the tag keyword (#2386) --- novelwriter/constants.py | 4 ++++ novelwriter/core/index.py | 10 ++++++---- novelwriter/gui/doceditor.py | 4 +--- tests/test_core/test_core_index.py | 11 ++++++----- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/novelwriter/constants.py b/novelwriter/constants.py index c20b9c47..4fde6f38 100644 --- a/novelwriter/constants.py +++ b/novelwriter/constants.py @@ -184,6 +184,10 @@ class nwKeyWords: POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY, OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, ] + CAN_LOOKUP: Final[list[str]] = [ + POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY, + OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, STORY_KEY, MENTION_KEY, + ] # Set of Valid Keys VALID_KEYS: Final[set[str]] = set(ALL_KEYS) diff --git a/novelwriter/core/index.py b/novelwriter/core/index.py index ee108ad3..d8e9c8e4 100644 --- a/novelwriter/core/index.py +++ b/novelwriter/core/index.py @@ -757,10 +757,12 @@ class Index: """Return all tags used by a specific document.""" return self._itemIndex.allItemTags(tHandle) if tHandle else [] - def getClassTags(self, itemClass: nwItemClass | None) -> list[str]: - """Return all tags based on itemClass.""" - name = None if itemClass is None else itemClass.name - return self._tagsIndex.filterTagNames(name) + def getKeyWordTags(self, keyWord: str) -> list[str]: + """Return all tags usable for a specific keyword.""" + if keyWord in nwKeyWords.CAN_LOOKUP: + itemClass = nwKeyWords.KEY_CLASS.get(keyWord) + return self._tagsIndex.filterTagNames(itemClass.name if itemClass else None) + return [] def getTagsData( self, activeOnly: bool = True diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 8d1c42c1..846b6317 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -2116,9 +2116,7 @@ class CommandCompleter(QMenu): length = len(lookup) suffix = "" options = sorted(filter( - lambda x: lookup in x.lower(), SHARED.project.index.getClassTags( - nwKeyWords.KEY_CLASS.get(kw.strip()) - ) + lambda x: lookup in x.lower(), SHARED.project.index.getKeyWordTags(kw.strip()) ))[:15] if not options: diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index bc9bef2c..dca4575a 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -789,11 +789,12 @@ def testCoreIndex_ExtractData(nwGUI, fncPath, mockRnd): assert index.getDocumentTags(cHandle) == ["jane"] assert index.getDocumentTags(None) == [] - # getClassTags - # ============ - assert index.getClassTags(None) == ["Jane", "John"] - assert index.getClassTags(nwItemClass.CHARACTER) == ["Jane", "John"] - assert index.getClassTags(nwItemClass.PLOT) == [] + # getKeyWordTags + # ============== + assert index.getKeyWordTags("@mention") == ["Jane", "John"] + assert index.getKeyWordTags("@char") == ["Jane", "John"] + assert index.getKeyWordTags("@plot") == [] + assert index.getKeyWordTags("@tag") == [] # getTagsData # =========== From 2bffa83d625a6a6f01aff51e8274eb006630a0f9 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 15:46:17 +0200 Subject: [PATCH 05/19] Update app description --- pyproject.toml | 2 +- setup/appimage_launcher.sh | 2 +- setup/data/novelwriter.desktop | 2 +- setup/debian/control | 8 +------- setup/macos/Info.plist.template | 2 +- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ece574a8..0fb42595 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "novelWriter" authors = [ {name = "Veronica Berglyd Olsen", email = "code@vkbo.net"}, ] -description = "A markdown-like text editor for planning and writing novels" +description = "A plain text editor for planning and writing novels" readme = {file = "setup/description_pypi.md", content-type = "text/markdown"} license = {text = "GNU General Public License v3"} classifiers = [ diff --git a/setup/appimage_launcher.sh b/setup/appimage_launcher.sh index fc0aa9e9..81bd9b63 100755 --- a/setup/appimage_launcher.sh +++ b/setup/appimage_launcher.sh @@ -24,7 +24,7 @@ cat > $HOME/.local/share/applications/novelWriter.desktop <= 3.10 Package: novelwriter Architecture: all Depends: ${misc:Depends}, ${python3:Depends}, python3 (>=3.10), python3-pyqt6 (>= 6.4), python3-pyqt6.qtsvg (>= 6.4), python3-enchant (>= 2.0) -Description: A markdown-like text editor for planning and writing novels - novelWriter is a plain text editor designed for writing novels assembled from - many smaller text documents. It uses a minimal formatting syntax inspired by - Markdown, and adds a meta data syntax for comments, synopsis, and - cross-referencing. It's designed to be a simple text editor that allows for - easy organisation of text and notes, using human readable text files as - storage for robustness. +Description: A plain text editor for planning and writing novels diff --git a/setup/macos/Info.plist.template b/setup/macos/Info.plist.template index d239a050..348acff7 100644 --- a/setup/macos/Info.plist.template +++ b/setup/macos/Info.plist.template @@ -11,7 +11,7 @@ CFBundleExecutable novelWriter CFBundleGetInfoString - novelWriter: A markdown-like text editor for planning and writing novels. + novelWriter: A plain text editor for planning and writing novels. CFBundleIconFile novelwriter.icns CFBundleIdentifier From dd7c8162acef8893ea9f37cc9595f19111d573b3 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:38:53 +0200 Subject: [PATCH 06/19] Update appimage build --- .github/workflows/build_linux.yml | 14 +++- pkgutils.py | 24 ++---- setup/icons/novelwriter.png | Bin 0 -> 9228 bytes setup/icons/x-novelwriter-project.png | Bin 0 -> 8843 bytes utils/build_appimage.py | 112 ++++++++++---------------- utils/common.py | 37 +++++++-- 6 files changed, 86 insertions(+), 101 deletions(-) create mode 100644 setup/icons/novelwriter.png create mode 100644 setup/icons/x-novelwriter-project.png diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 8a926afc..ca073f1f 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -10,15 +10,21 @@ jobs: needs: buildAssets runs-on: ubuntu-latest env: - PYTHON_VERSION: "3.11" - LINUX_TAG: "manylinux_2_28_x86_64" + PYTHON_VERSION: "3.13" + LINUX_TAG: "manylinux_2_28" + LINUX_ARCH: "x86_64" steps: - name: Python Setup uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.13" architecture: x64 + - name: Install Packages (apt) + run: | + sudo apt update + sudo apt install libxcb-cursor0 + - name: Install Packages (pip) run: pip install python-appimage setuptools @@ -35,7 +41,7 @@ jobs: id: build run: | echo "BUILD_VERSION=$(python pkgutils.py version)" >> $GITHUB_OUTPUT - python pkgutils.py build-appimage --linux-tag $LINUX_TAG --python-version $PYTHON_VERSION + python pkgutils.py build-appimage $LINUX_TAG $LINUX_ARCH $PYTHON_VERSION - name: Upload Artifacts uses: actions/upload-artifact@v4 diff --git a/pkgutils.py b/pkgutils.py index fc30b985..beb5fece 100755 --- a/pkgutils.py +++ b/pkgutils.py @@ -272,24 +272,12 @@ if __name__ == "__main__": cmdBuildUbuntu.set_defaults(func=utils.build_debian.launchpad) # Build AppImage - cmdBuildAppImage = parsers.add_parser( - "build-appimage", help=( - "Build an AppImage. " - "Argument --linux-tag defaults manylinux_2_28_x86_64, and --python-version to 3.13." - ) - ) - cmdBuildAppImage.add_argument( - "--linux-tag", - default="manylinux_2_28_x86_64", - help=( - "Linux compatibility tag (e.g. manylinux_2_28_x86_64) " - "see https://python-appimage.readthedocs.io/en/latest/#available-python-appimages " - "and https://github.com/pypa/manylinux for a list of valid tags." - ), - ) - cmdBuildAppImage.add_argument( - "--python-version", default="3.13", help="Python version (e.g. 3.13)" - ) + # See https://github.com/pypa/manylinux + # See https://python-appimage.readthedocs.io/en/latest/#available-python-appimages + cmdBuildAppImage = parsers.add_parser("build-appimage", help="Build an AppImage.") + cmdBuildAppImage.add_argument("linux", help="Manylinux version, e.g. manylinux_2_28.") + cmdBuildAppImage.add_argument("arch", help="Architecture, e.g. x86_64.") + cmdBuildAppImage.add_argument("python", help="Python version, e.g. 3.13.") cmdBuildAppImage.set_defaults(func=utils.build_appimage.appImage) # Build Windows Inno Setup Installer diff --git a/setup/icons/novelwriter.png b/setup/icons/novelwriter.png new file mode 100644 index 0000000000000000000000000000000000000000..a9ec557a12a6a78155e501a2bf039348d3ae04f9 GIT binary patch literal 9228 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 LtgTcIw~F{5k2VKv literal 0 HcmV?d00001 diff --git a/setup/icons/x-novelwriter-project.png b/setup/icons/x-novelwriter-project.png new file mode 100644 index 0000000000000000000000000000000000000000..9186479b30c170e27977aa4d0fd277ac0d80e6f2 GIT binary patch literal 8843 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 Xy5&$|MUj+%u|dzCsw$MrnT7l>1rdiP literal 0 HcmV?d00001 diff --git a/utils/build_appimage.py b/utils/build_appimage.py index ea784269..57b44413 100644 --- a/utils/build_appimage.py +++ b/utils/build_appimage.py @@ -22,13 +22,15 @@ from __future__ import annotations import argparse import datetime +import os import shutil -import subprocess import sys +from pathlib import Path + from utils.common import ( ROOT_DIR, SETUP_DIR, appdataXml, copyPackageFiles, copySourceCode, - extractVersion, makeCheckSum, toUpload, writeFile + extractVersion, freshFolder, makeCheckSum, systemCall, toUpload, writeFile ) @@ -49,115 +51,83 @@ def appImage(args: argparse.Namespace) -> None: print("") print("Build AppImage") - print("==============") - print("") + print("="*120) - linuxTag = args.linux_tag - pythonVer = args.python_version + mLinux = args.linux + mArch = args.arch + pyVer = args.python # Version Info - # ============ - pkgVers, _, relDate = extractVersion() relDate = datetime.datetime.strptime(relDate, "%Y-%m-%d") - print("") # Set Up Folder - # ============= - bldDir = ROOT_DIR / "dist_appimage" - bldPkg = f"novelwriter_{pkgVers}" + bldPkg = f"novelwriter-{pkgVers}-{mArch}" + bldImg = f"{bldPkg}.AppImage" outDir = bldDir / bldPkg imgDir = bldDir / "appimage" - - # Set Up Folders - # ============== + appDir = bldDir / f"novelWriter-{mArch}" bldDir.mkdir(exist_ok=True) - - if outDir.exists(): - print("Removing old build files ...") - print("") - shutil.rmtree(outDir) - - outDir.mkdir() - - if imgDir.exists(): - print("Removing old build metadata files ...") - print("") - shutil.rmtree(imgDir) - - imgDir.mkdir() + freshFolder(outDir) + freshFolder(imgDir) + freshFolder(appDir) # Remove old AppImages if images := bldDir.glob("*.AppImage"): print("Removing old AppImages") - print("") for image in images: image.unlink() # Copy novelWriter Source - # ======================= - print("Copying novelWriter source ...") - print("") - copySourceCode(outDir) - print("") print("Copying or generating additional files ...") - print("") - copyPackageFiles(outDir) # Write Metadata - # ============== - writeFile(imgDir / "novelwriter.appdata.xml", appdataXml()) - print("Wrote: novelwriter.appdata.xml") - + writeFile(imgDir / "requirements.txt", str(outDir)) writeFile(imgDir / "entrypoint.sh", ( - '#! /bin/bash \n' + f"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{APPDIR}}/usr/lib/{mArch}-linux-gnu/\n" '{{ python-executable }} -sE ${APPDIR}/opt/python{{ python-version }}/bin/novelwriter "$@"' )) - print("Wrote: entrypoint.sh") - - writeFile(imgDir / "requirements.txt", str(outDir)) - print("Wrote: requirements.txt") shutil.copyfile(SETUP_DIR / "data" / "novelwriter.desktop", imgDir / "novelwriter.desktop") print("Copied: novelwriter.desktop") - shutil.copyfile(SETUP_DIR / "icons" / "novelwriter.svg", imgDir / "novelwriter.svg") - print("Copied: novelwriter.svg") - - shutil.copyfile( - SETUP_DIR / "data" / "hicolor" / "256x256" / "apps" / "novelwriter.png", - imgDir / "novelwriter.png" - ) + shutil.copyfile(SETUP_DIR / "icons" / "novelwriter.png", imgDir / "novelwriter.png") print("Copied: novelwriter.png") - # Build AppImage - # ============== + # Build AppDir + systemCall([ + sys.executable, "-m", "python_appimage", "build", "app", "--no-packaging", + "-l", f"{mLinux}_{mArch}", "-p", pyVer, "appimage" + ], cwd=bldDir) - try: - subprocess.call([ - sys.executable, "-m", "python_appimage", "build", "app", - "-l", linuxTag, "-p", pythonVer, "appimage" - ], cwd=bldDir) - except Exception as exc: - print("AppImage build: FAILED") - print("") - print(str(exc)) - print("") - sys.exit(1) + # Copy Libraries + libPath = Path(f"/usr/lib/{mArch}-linux-gnu") + appLibs = appDir / "usr" / "lib" / f"{mArch}-linux-gnu" + appLibs.mkdir(exist_ok=True) + shutil.copyfile(libPath / "libxcb-cursor.so.0", appLibs / "libxcb-cursor.so.0") - bldFile = list(bldDir.glob("*.AppImage"))[0] - outFile = bldDir / f"novelWriter-{pkgVers}.AppImage" - bldFile.rename(outFile) - shaFile = makeCheckSum(outFile.name, cwd=bldDir) + # Build Image + env = os.environ.copy() + env["ARCH"] = mArch + systemCall([ + "appimagetool", "--no-appstream", "--updateinformation", + f"gh-releases-zsync|vkbo|novelwriter|latest|novelwriter-*-{mArch}.AppImage.zsync", + str(appDir), bldImg + ], cwd=bldDir, env=env) - toUpload(outFile) + updFile = bldDir / f"{bldImg}.zsync" + bldFile = bldDir / bldImg + shaFile = makeCheckSum(bldFile.name, cwd=bldDir) + + toUpload(bldFile) + toUpload(updFile) toUpload(shaFile) return diff --git a/utils/common.py b/utils/common.py index 6eda3841..2c986480 100644 --- a/utils/common.py +++ b/utils/common.py @@ -22,6 +22,7 @@ from __future__ import annotations import shutil import subprocess +import sys from pathlib import Path @@ -77,16 +78,16 @@ def copySourceCode(dst: Path) -> None: for item in src.glob("**/*"): relSrc = item.relative_to(ROOT_DIR) if item.suffix in (".pyc", ".pyo"): - print(f"Ignore: {relSrc}") + print("Ignored:", relSrc) continue if item.parent.is_dir() and item.parent.name != "__pycache__": dstDir = dst / relSrc.parent if not dstDir.exists(): dstDir.mkdir(parents=True) - print(f"Folder: {dstDir}") + print("Created:", dstDir.relative_to(ROOT_DIR)) if item.is_file(): shutil.copyfile(item, dst / relSrc) - print(f"Copied: {dst / relSrc}") + print("Copied:", relSrc) return @@ -95,26 +96,23 @@ def copyPackageFiles(dst: Path, setupPy: bool = False) -> None: copyFiles = ["LICENSE.md", "CREDITS.md", "pyproject.toml"] for copyFile in copyFiles: shutil.copyfile(copyFile, dst / copyFile) - print(f"Copied: {copyFile}") + print("Copied:", copyFile) writeFile(dst / "MANIFEST.in", ( "include LICENSE.md\n" "include CREDITS.md\n" "recursive-include novelwriter/assets *\n" )) - print("Wrote: MANIFEST.in") if setupPy: writeFile(dst / "setup.py", ( "import setuptools\n" "setuptools.setup()\n" )) - print("Wrote: setup.py") text = readFile(ROOT_DIR / "pyproject.toml") text = text.replace("setup/description_pypi.md", "data/description_short.txt") writeFile(dst / "pyproject.toml", text) - print("Wrote: pyproject.toml") return @@ -188,4 +186,27 @@ def readFile(file: Path) -> str: def writeFile(file: Path, text: str) -> int: """Write string to file.""" - return file.write_text(text, encoding="utf-8") + result = file.write_text(text, encoding="utf-8") + print("Wrote:", file.relative_to(ROOT_DIR)) + return result + + +def freshFolder(path: Path) -> None: + """Make sure a folder exists and is empty.""" + if path.exists(): + print("Removing:", str(path)) + shutil.rmtree(path) + path.mkdir() + return + + +def systemCall(cmd: list, cwd: Path | str | None = None, env: dict | None = None) -> None: + """Make a system call using subprocess.""" + if isinstance(cwd, Path): + cwd = str(cwd) + try: + subprocess.call([str(c) for c in cmd], cwd=cwd, env=env) + except Exception as exc: + print("ERROR:", str(exc)) + sys.exit(1) + return From a534e30467043eb3bed9adc70e22415e101ad287 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:51:49 +0200 Subject: [PATCH 07/19] Add the appimagetool exec --- .github/workflows/build_linux.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index ca073f1f..9cb3daf3 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -40,6 +40,9 @@ jobs: - name: Build AppImage id: build run: | + wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$LINUX_ARCH.AppImage + chmod +x appimagetool-$LINUX_ARCH.AppImage + ln -sfv appimagetool-$LINUX_ARCH.AppImage appimagetool echo "BUILD_VERSION=$(python pkgutils.py version)" >> $GITHUB_OUTPUT python pkgutils.py build-appimage $LINUX_TAG $LINUX_ARCH $PYTHON_VERSION From 910723bbcdaf1101eb1f540e5e502505e0c5bd53 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 19:02:53 +0200 Subject: [PATCH 08/19] Add symlink --- .github/workflows/build_linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 9cb3daf3..1083c082 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -42,7 +42,7 @@ jobs: run: | wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$LINUX_ARCH.AppImage chmod +x appimagetool-$LINUX_ARCH.AppImage - ln -sfv appimagetool-$LINUX_ARCH.AppImage appimagetool + ln -sfv appimagetool-$LINUX_ARCH.AppImage ~/.local/bin/appimagetool echo "BUILD_VERSION=$(python pkgutils.py version)" >> $GITHUB_OUTPUT python pkgutils.py build-appimage $LINUX_TAG $LINUX_ARCH $PYTHON_VERSION From e6befda1460c63cbbfe8a4602f90f75b5544f0ed Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 19:08:19 +0200 Subject: [PATCH 09/19] Use env var for appimagetool --- .github/workflows/build_linux.yml | 2 +- utils/build_appimage.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 1083c082..cbca61c8 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -42,7 +42,7 @@ jobs: run: | wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$LINUX_ARCH.AppImage chmod +x appimagetool-$LINUX_ARCH.AppImage - ln -sfv appimagetool-$LINUX_ARCH.AppImage ~/.local/bin/appimagetool + export APPIMAGE_TOOL_EXEC="$(pwd)/appimagetool-$LINUX_ARCH.AppImage" echo "BUILD_VERSION=$(python pkgutils.py version)" >> $GITHUB_OUTPUT python pkgutils.py build-appimage $LINUX_TAG $LINUX_ARCH $PYTHON_VERSION diff --git a/utils/build_appimage.py b/utils/build_appimage.py index 57b44413..d051f51c 100644 --- a/utils/build_appimage.py +++ b/utils/build_appimage.py @@ -114,10 +114,11 @@ def appImage(args: argparse.Namespace) -> None: shutil.copyfile(libPath / "libxcb-cursor.so.0", appLibs / "libxcb-cursor.so.0") # Build Image + appToolExec = os.environ.get("APPIMAGE_TOOL_EXEC", "appimagetool") env = os.environ.copy() env["ARCH"] = mArch systemCall([ - "appimagetool", "--no-appstream", "--updateinformation", + appToolExec, "--no-appstream", "--updateinformation", f"gh-releases-zsync|vkbo|novelwriter|latest|novelwriter-*-{mArch}.AppImage.zsync", str(appDir), bldImg ], cwd=bldDir, env=env) From 28c45719e2f9254279c015b34df189904ee4db49 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 19:36:39 +0200 Subject: [PATCH 10/19] Move libxcb-cursor --- utils/build_appimage.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/build_appimage.py b/utils/build_appimage.py index d051f51c..3b3bf4f8 100644 --- a/utils/build_appimage.py +++ b/utils/build_appimage.py @@ -91,7 +91,7 @@ def appImage(args: argparse.Namespace) -> None: writeFile(imgDir / "novelwriter.appdata.xml", appdataXml()) writeFile(imgDir / "requirements.txt", str(outDir)) writeFile(imgDir / "entrypoint.sh", ( - f"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{APPDIR}}/usr/lib/{mArch}-linux-gnu/\n" + # f"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{APPDIR}}/usr/lib/{mArch}-linux-gnu/\n" '{{ python-executable }} -sE ${APPDIR}/opt/python{{ python-version }}/bin/novelwriter "$@"' )) @@ -109,9 +109,9 @@ def appImage(args: argparse.Namespace) -> None: # Copy Libraries libPath = Path(f"/usr/lib/{mArch}-linux-gnu") - appLibs = appDir / "usr" / "lib" / f"{mArch}-linux-gnu" - appLibs.mkdir(exist_ok=True) - shutil.copyfile(libPath / "libxcb-cursor.so.0", appLibs / "libxcb-cursor.so.0") + siteDir = appDir / "opt" / f"python{pyVer}" / "lib" / f"python{pyVer}" / "site-packages" + qt6Lib = siteDir / "PyQt6" / "Qt6" / "lib" + shutil.copyfile(libPath / "libxcb-cursor.so.0", qt6Lib / "libxcb-cursor.so.0") # Build Image appToolExec = os.environ.get("APPIMAGE_TOOL_EXEC", "appimagetool") From d153d8059528bdbb40a3644a38be59b4e4484842 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:01:22 +0200 Subject: [PATCH 11/19] Use lower case for release names --- setup/macos/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/macos/build.sh b/setup/macos/build.sh index 878a09b0..67b94c46 100755 --- a/setup/macos/build.sh +++ b/setup/macos/build.sh @@ -206,10 +206,10 @@ brew install create-dmg create-dmg --volname "novelWriter $VERSION" --volicon $SRC_DIR/setup/macos/novelwriter.icns \ --window-pos 200 120 --window-size 800 400 --icon-size 100 \ --icon novelWriter.app 200 190 --hide-extension novelWriter.app \ - --app-drop-link 600 185 $RLS_DIR/novelWriter-"${VERSION}"-$ARCH.dmg "$BUILD_DIR"/ + --app-drop-link 600 185 $RLS_DIR/novelwriter-"${VERSION}"-$ARCH.dmg "$BUILD_DIR"/ pushd $RLS_DIR || exit 1 -shasum -a 256 novelWriter-"${VERSION}"-$ARCH.dmg | tee novelWriter-"${VERSION}"-$ARCH.dmg.sha256 +shasum -a 256 novelwriter-"${VERSION}"-$ARCH.dmg | tee novelwriter-"${VERSION}"-$ARCH.dmg.sha256 popd || exit 1 rm -r $CONDA_PATH From 6379f031c2966206180d315052245ea22c4e43d3 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:49:00 +0200 Subject: [PATCH 12/19] Prune the AppImage a little, and prune Windows installer less --- setup/macos/build.sh | 4 +- utils/build_appimage.py | 6 ++- utils/build_windows.py | 84 ++--------------------------------------- utils/common.py | 66 ++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 83 deletions(-) diff --git a/setup/macos/build.sh b/setup/macos/build.sh index 67b94c46..ca475fa1 100755 --- a/setup/macos/build.sh +++ b/setup/macos/build.sh @@ -174,7 +174,7 @@ rm lib/python3.*/site-packages/PyQt6/QtWebEngine* || true rm -r lib/python3.*/site-packages/PyQt6/Qt6/translations/qtwebengine* || true rm -r lib/python3.*/site-packages/PyQt6/Qt6/plugins/webview/libqtwebview* || true -# Remove unneeded QtQuick/Decaritive components +# Remove unneeded QtQuick/Declarative components rm lib/python3.*/site-packages/PyQt6/QtQml* || true rm lib/python3.*/site-packages/PyQt6/QtQuick* || true rm lib/python3.*/site-packages/PyQt6/WebChannel* || true @@ -200,7 +200,7 @@ mkdir -p $RLS_DIR # --- Create DMG -------------------------------------------------------------------------------- # # Generate .dmg -echo "Packageing DMG ..." +echo "Packaging DMG ..." brew install create-dmg create-dmg --volname "novelWriter $VERSION" --volicon $SRC_DIR/setup/macos/novelwriter.icns \ diff --git a/utils/build_appimage.py b/utils/build_appimage.py index 3b3bf4f8..d32a377e 100644 --- a/utils/build_appimage.py +++ b/utils/build_appimage.py @@ -30,7 +30,8 @@ from pathlib import Path from utils.common import ( ROOT_DIR, SETUP_DIR, appdataXml, copyPackageFiles, copySourceCode, - extractVersion, freshFolder, makeCheckSum, systemCall, toUpload, writeFile + extractVersion, freshFolder, makeCheckSum, removeRedundantQt, systemCall, + toUpload, writeFile ) @@ -113,6 +114,9 @@ def appImage(args: argparse.Namespace) -> None: qt6Lib = siteDir / "PyQt6" / "Qt6" / "lib" shutil.copyfile(libPath / "libxcb-cursor.so.0", qt6Lib / "libxcb-cursor.so.0") + # Remove Redundant + removeRedundantQt(siteDir) + # Build Image appToolExec = os.environ.get("APPIMAGE_TOOL_EXEC", "appimagetool") env = os.environ.copy() diff --git a/utils/build_windows.py b/utils/build_windows.py index a4f0e866..98d5e8c2 100644 --- a/utils/build_windows.py +++ b/utils/build_windows.py @@ -30,7 +30,10 @@ import zipfile from pathlib import Path -from utils.common import ROOT_DIR, SETUP_DIR, copySourceCode, extractVersion, readFile, writeFile +from utils.common import ( + ROOT_DIR, SETUP_DIR, copySourceCode, extractVersion, readFile, + removeRedundantQt, writeFile +) def prepareCode(outDir: Path) -> None: @@ -103,85 +106,6 @@ def installRequirements(libDir: Path) -> None: return -def removeRedundantQt(libDir: Path) -> None: - """Delete Qt files that are not needed""" - - def unlinkIfFound(file: Path) -> None: - if file.is_file(): - file.unlink() - print(f"Deleted: {file}") - - def deleteFolder(folder: Path) -> None: - if folder.is_dir(): - shutil.rmtree(folder) - print(f"Deleted: {folder}") - - def unlinkIfPrefix(folder: Path, prefix: tuple[str, ...]) -> None: - if folder.is_dir(): - for item in folder.iterdir(): - if item.name.startswith(prefix): - if item.is_file(): - unlinkIfFound(item) - elif item.is_dir(): - deleteFolder(item) - - print("Deleting Redundant Files") - print("========================") - print("") - - pyQt6Dir = libDir / "PyQt6" - bindDir = libDir / "PyQt6" / "bindings" - qt6Dir = libDir / "PyQt6" / "Qt6" - binDir = libDir / "PyQt6" / "Qt6" / "bin" - plugDir = libDir / "PyQt6" / "Qt6" / "plugins" - qmDir = libDir / "PyQt6" / "Qt6" / "translations" - dictDir = libDir / "enchant" / "data" / "mingw64" / "share" / "enchant" / "hunspell" - - for item in dictDir.iterdir(): - if not item.name.startswith(("en_GB", "en_US")): - unlinkIfFound(item) - - for item in qmDir.iterdir(): - if not item.name.startswith("qtbase"): - unlinkIfFound(item) - - bulkDel = ("QtQml", "Qt6Qml", "QtQuick", "Qt6Quick") - unlinkIfPrefix(pyQt6Dir, bulkDel) - unlinkIfPrefix(bindDir, bulkDel) - unlinkIfPrefix(binDir, bulkDel) - - delQt6 = [ - "Qt6Bluetooth", "Qt6DBus", "Qt6Designer", "Qt6Help", "Qt6Multimedia", - "Qt6MultimediaWidgets", "Qt6Network", "Qt6Nfc", "Qt6OpenGL", "Qt6Positioning", - "Qt6PositioningQuick", "Qt6Sensors", "Qt6SerialPort", "Qt6Sql", "Qt6Test", - "Qt6TextToSpeech", "Qt6WebChannel", "Qt6WebSockets", "Qt6Xml", - ] - for item in delQt6: - qtItem = item.replace("Qt6", "Qt") - unlinkIfFound(binDir / f"{item}.dll") - unlinkIfFound(pyQt6Dir / f"{qtItem}.pyd") - unlinkIfFound(pyQt6Dir / f"{qtItem}.pyi") - deleteFolder(bindDir / qtItem) - - delList = [ - binDir / "opengl32sw.dll", - qt6Dir / "qml", - plugDir / "renderers", - plugDir / "sensors", - plugDir / "sqldrivers", - plugDir / "texttospeech", - plugDir / "webview", - ] - for item in delList: - unlinkIfFound(item) - deleteFolder(item) - - print("Done") - print("") - - return - - def main(args: argparse.Namespace) -> None: """Set up a package with embedded Python and dependencies for Windows installation. diff --git a/utils/common.py b/utils/common.py index 2c986480..4ba82e00 100644 --- a/utils/common.py +++ b/utils/common.py @@ -210,3 +210,69 @@ def systemCall(cmd: list, cwd: Path | str | None = None, env: dict | None = None print("ERROR:", str(exc)) sys.exit(1) return + + +def removeRedundantQt(qtBase: Path) -> None: + """Delete Qt files that are not needed""" + + def unlinkIfFound(file: Path) -> None: + if file.is_file(): + file.unlink() + print("Deleted:", file.relative_to(ROOT_DIR)) + + def deleteFolder(folder: Path) -> None: + if folder.is_dir(): + shutil.rmtree(folder) + print("Deleted:", folder.relative_to(ROOT_DIR)) + + def unlinkIfPrefix(folder: Path, prefix: tuple[str, ...]) -> None: + if folder.is_dir(): + for item in folder.iterdir(): + if item.name.startswith(prefix): + if item.is_file(): + unlinkIfFound(item) + elif item.is_dir(): + deleteFolder(item) + + print("Deleting redundant files ...") + + pyQt6Dir = qtBase / "PyQt6" + bindDir = qtBase / "PyQt6" / "bindings" + qt6Dir = qtBase / "PyQt6" / "Qt6" + binDir = qtBase / "PyQt6" / "Qt6" / "bin" + libDir = qtBase / "PyQt6" / "Qt6" / "lib" + plugDir = qtBase / "PyQt6" / "Qt6" / "plugins" + qmDir = qtBase / "PyQt6" / "Qt6" / "translations" + dictDir = qtBase / "enchant" / "data" / "mingw64" / "share" / "enchant" / "hunspell" + + # Prune Dictionaries + if dictDir.exists(): + for item in dictDir.iterdir(): + if not item.name.startswith(("en_GB", "en_US")): + unlinkIfFound(item) + + # Prune Translations + for item in qmDir.iterdir(): + if not item.name.startswith("qtbase"): + unlinkIfFound(item) + + # Delete Modules + modules = [ + "Qt6Qml", "Qt6Quick", "Qt6Bluetooth", "Qt6Nfc", + "Qt6Sensors", "Qt6SerialPort", "Qt6Test", + ] + modules.extend([x.replace("Qt6", "Qt") for x in modules]) + modules.extend([f"lib{x}" for x in modules]) + modules = tuple(modules) + + unlinkIfPrefix(pyQt6Dir, modules) + unlinkIfPrefix(bindDir, modules) + unlinkIfPrefix(binDir, modules) + unlinkIfPrefix(libDir, modules) + + # Other Files + deleteFolder(qt6Dir / "qml") + deleteFolder(plugDir / "qmlls") + deleteFolder(plugDir / "qmllint") + + return From 5d1e781d20c2d42825f4cbd651a30a73842f5d5a Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:57:33 +0200 Subject: [PATCH 13/19] Bump version to 2.7.1 --- novelwriter/__init__.py | 6 +++--- sample/nwProject.nwx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index 7e526b72..dcabc0b6 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -49,9 +49,9 @@ __license__ = "GPLv3" __author__ = "Veronica Berglyd Olsen" __maintainer__ = "Veronica Berglyd Olsen" __email__ = "code@vkbo.net" -__version__ = "2.7" -__hexversion__ = "0x020700f0" -__date__ = "2025-06-01" +__version__ = "2.7.1" +__hexversion__ = "0x020701f0" +__date__ = "2025-06-10" __status__ = "Stable" __domain__ = "novelwriter.io" diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index ec7fe909..ae0fee4d 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,6 +1,6 @@ - - + + Sample Project Jane Smith From f08078bd0864f349a8be57246d5128ac85cfae6f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:00:41 +0200 Subject: [PATCH 14/19] Update Czech translation --- i18n/nw_base.ts | 368 ++++++++-------- i18n/nw_cs_CZ.ts | 470 ++++++++++----------- i18n/nw_de_DE.ts | 368 ++++++++-------- i18n/nw_en_US.ts | 368 ++++++++-------- i18n/nw_it_IT.ts | 368 ++++++++-------- i18n/nw_ja_JP.ts | 368 ++++++++-------- i18n/nw_nb_NO.ts | 368 ++++++++-------- i18n/nw_pl_PL.ts | 368 ++++++++-------- i18n/nw_pt_BR.ts | 368 ++++++++-------- i18n/nw_zh_CN.ts | 368 ++++++++-------- novelwriter/assets/i18n/project_cs_CZ.json | 2 + 11 files changed, 1893 insertions(+), 1891 deletions(-) diff --git a/i18n/nw_base.ts b/i18n/nw_base.ts index 9cad99a2..5a56f47d 100644 --- a/i18n/nw_base.ts +++ b/i18n/nw_base.ts @@ -365,7 +365,7 @@ Constant - + Title @@ -401,571 +401,571 @@ - - - - + + + + None - + Novel - - + + Plot - - + + Characters - - + + Locations - - + + Timeline - - + + Objects - - + + Entities - - - + + + Custom - + Archive - + Templates - + Trash - - + + Novel Document - - + + Project Note - + Root Folder - + Folder - + Novel Title Page - + Novel Chapter - + Novel Scene - + Novel Section - + Active - + Inactive - + Tag - + Point of View - - + + Focus - + Story - + Mentions - + Level - + Document - + Line - + Status - + Chars - + Words - + Pars - + POV - + Synopsis - + Open Document (.odt) - + Flat Open Document (.fodt) - + Microsoft Word Document (.docx) - + HTML 5 (.html) - + novelWriter Markup (.txt) - + Standard Markdown (.md) - + Extended Markdown (.md) - + Portable Document Format (.pdf) - + JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) - + Square - + Triangle - + Nabla - + Diamond - + Pentagon - + Hexagon - + Star - + Pacman - + 1/4 Circle - + Half Circle - + 3/4 Circle - + Full Circle - + 1 Bar - + 2 Bars - + 3 Bars - + 4 Bars - + 1 Block - + 2 Blocks - + 3 Blocks - + 4 Blocks - + Text files - + Markdown files - + novelWriter files - + CSV files - + All files - + Millimetres - + Centimetres - + Inches - + A4 - + A5 - + A6 - + US Legal - + US Letter - + Theme Colours - + Foreground Colour - + Faded Colour - + Red - + Orange - + Yellow - + Green - + Aqua - + Blue - + Purple - + Straight single quotation mark - + Straight double quotation mark - + Left single quotation mark - + Right single quotation mark - + Single low-9 quotation mark - + Single high-reversed-9 quotation mark - + Left double quotation mark - + Right double quotation mark - + Double low-9 quotation mark - + Double high-reversed-9 quotation mark - + Double low-reversed-9 quotation mark - + Single left-pointing angle quotation mark - + Single right-pointing angle quotation mark - + Double left-pointing angle quotation mark - + Double right-pointing angle quotation mark - + Left corner bracket - + Right corner bracket - + Left white corner bracket - + Right white corner bracket - + Short dash - + Long dash - + Horizontal bar @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) - + Selected: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar - + Outline - + Search - + Toggle Focus Mode - + Close @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for - + Replace with - + Search - + Case Sensitive - + Whole Words Only - + RegEx Mode - + Loop Search - + Search Next File - + Preserve Case - + Close Search - + Find in current document - + Find and replace in current document @@ -1232,82 +1232,82 @@ - + Set as Document Name - + Open URL - + Follow Tag - + Create Note for Tag - + Cut - + Copy - + Paste - + Select All - + Select Word - + Select Paragraph - + Spelling Suggestion(s) - + No Suggestions - + Ignore Word - + Add Word to Dictionary - + Please select some text before calling replace quotes. - + Do you want to create a new project note for the tag '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold - + Markdown Italic - + Markdown Strikethrough - + Shortcode Bold - + Shortcode Italic - + Shortcode Strikethrough - + Shortcode Underline - + Shortcode Highlight - + Shortcode Superscript - + Shortcode Subscript @@ -4281,67 +4281,67 @@ Stats - + Characters - + Characters in Text - + Characters in Headings - + Paragraphs - + Headings - + Characters, No Spaces - + Characters in Text, No Spaces - + Characters in Headings, No Spaces - + Words - + Words in Text - + Words in Headings - + Characters: {0} ({1}) - + Words: {0} ({1}) diff --git a/i18n/nw_cs_CZ.ts b/i18n/nw_cs_CZ.ts index 4d60fab4..15a35eea 100644 --- a/i18n/nw_cs_CZ.ts +++ b/i18n/nw_cs_CZ.ts @@ -96,12 +96,12 @@ Include Story Structure - + Zahrnout strukturu příběhu Include Manuscript Notes - + Zahrnout poznámky Manuscriptu @@ -365,7 +365,7 @@ Constant - + Title Název @@ -401,573 +401,573 @@ Oddělovač scén - - - - + + + + None Žádný - + Novel Román - - + + Plot Zápletka - - + + Characters Postavy - - + + Locations Lokality - - + + Timeline Časová osa - - + + Objects Objekty - - + + Entities Subjekty - - - + + + Custom Vlastní - + Archive Archiv - + Templates Šablony - + Trash Koš - - + + Novel Document Dokument románu - - + + Project Note Poznámka projektu - + Root Folder Kořenová složka - + Folder Složky - + Novel Title Page Titulní stránka románu - + Novel Chapter Kapitola románu - + Novel Scene Scéna románu - + Novel Section Sekce románu - + Active Aktivní - + Inactive Neaktivní - + Tag Štítek - + Point of View Úhel pohledu - - + + Focus Zaměření - + Story Příběh - + Mentions Zmínky - + Level Úroveň - + Document Dokument - + Line Řádek - + Status Stav - + Chars Znaky - + Words Slova - + Pars Pars - + POV POV - + Synopsis Synopse - + Open Document (.odt) Open Dokument (.odt) - + Flat Open Document (.fodt) Flat Open Dokument (.fodt) - + Microsoft Word Document (.docx) Dokument Microsoft Word (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter Markup (.txt) - + Standard Markdown (.md) Standard Markdown (.md) - + Extended Markdown (.md) Extended Markdown (.md) - + Portable Document Format (.pdf) Portable Document Format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter Markup (.json) - + Square Čtverec - + Triangle Trojúhelník - + Nabla Nabla - + Diamond Kosočtverec - + Pentagon Pětiúhelník - + Hexagon Šestiúhelník - + Star Hvězdička - + Pacman Pacman - + 1/4 Circle 1/4 kružnice - + Half Circle Půlkruh - + 3/4 Circle 3/4 kružnice - + Full Circle Úplný kruh - + 1 Bar 1 čára - + 2 Bars 2 čáry - + 3 Bars 3 čáry - + 4 Bars 4 čáry - + 1 Block 1 blok - + 2 Blocks 2 bloky - + 3 Blocks 3 bloky - + 4 Blocks 4 bloky - + Text files Textový soubor - + Markdown files Soubory Markdown - + novelWriter files novelWriter soubory - + CSV files CSV soubory - + All files Všechny soubory - + Millimetres Milimetry - + Centimetres Centimetry - + Inches Palce - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US Legal - + US Letter US Letter - - - Theme Colours - - - - - Foreground Colour - - - - - Faded Colour - - - - - Red - - - Orange - + Theme Colours + Barvy šablony - Yellow - + Foreground Colour + Barva popředí - Green - + Faded Colour + Vybledlá barva - Aqua - + Red + Červená - Blue - + Orange + Oranžová - Purple - + Yellow + Žlutá - + + Green + Zelená + + + + Aqua + Aqua + + + + Blue + Modrý + + + + Purple + Fialová + + + Straight single quotation mark Jednoduchá uvozovka - + Straight double quotation mark Dvojitá uvozovka - + Left single quotation mark Levá jednoduchá uvozovka - + Right single quotation mark Pravá jednoduchá uvozovka - + Single low-9 quotation mark Jednoduchá uvozovka s nízkými hodnotami - + Single high-reversed-9 quotation mark Jednoduchá uvozovka s vysokými hodnotami - + Left double quotation mark Levá dvojitá uvozovka - + Right double quotation mark Pravá dvojitá uvozovka - + Double low-9 quotation mark Dvojítá uvzozovka s nízkými hodnotami - + Double high-reversed-9 quotation mark Dvojítá uvozovka s vysokými hodnotami - + Double low-reversed-9 quotation mark Dvojítá uvozovka s nízkými hodnotami - + Single left-pointing angle quotation mark Jednoduchá úhlová uvozovka směřující vlevo - + Single right-pointing angle quotation mark Jednoduchá úhlová uvozovka směřující vpravo - + Double left-pointing angle quotation mark Dvojitá úhlová uvozovka směřující vlevo - + Double right-pointing angle quotation mark Dvojitá úhlová uvozovka směřující vpravo - + Left corner bracket Levý roh závorky - + Right corner bracket Pravý roh závorky - + Left white corner bracket Levý bílý roh závorky - + Right white corner bracket Pravý bílý roh závorky - + Short dash - + Krátká pomlčka - + Long dash - + Dlouhá pomlčka - + Horizontal bar - + Horizontální lišta @@ -1024,7 +1024,7 @@ Do you want to save your changes to '{0}'? - + Chcete uložit své změny do '{0}'? @@ -1078,40 +1078,40 @@ GuiDocEditFooter - + Line: {0} ({1}) Řádek: {0} ({1}) - + Selected: {0} - + Vybráno: {0} GuiDocEditHeader - + Toggle Tool Bar Přepnout nástrojovou lištu - + Outline Podtržený - + Search Hledat - + Toggle Focus Mode Přepnout režim soustředění - + Close Zavřít @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Najít - + Replace with Nahradit - + Search Hledat - + Case Sensitive Rozlišovat velká a malá písmena - + Whole Words Only Pouze celá slova - + RegEx Mode RegEx režim - + Loop Search Hledání ve smyčce - + Search Next File Hledat další soubor - + Preserve Case Preserve Case - + Close Search Ukončit hledání - + Find in current document Najít v aktuálním dokumentu - + Find and replace in current document Najít a nahradit v aktuálním dokumentu @@ -1232,82 +1232,82 @@ Umístění souboru: {0} - + Set as Document Name Nastavit jako název dokumentu - + Open URL Otevřít URL - + Follow Tag Sledovat štítek - + Create Note for Tag Vytvořit poznámku pro štítek - + Cut Vyjmout - + Copy Kopírovat - + Paste Vložit - + Select All Vybrat vše - + Select Word Vybrat slovo - + Select Paragraph Vybrat odstavec - + Spelling Suggestion(s) Návrhy opravy - + No Suggestions Žádné návrhy - + Ignore Word Ignorovat slovo - + Add Word to Dictionary Přidat slovo do slovníku - + Please select some text before calling replace quotes. Vyberte prosím nějaký text před voláním nahrazujících uvozovek. - + Do you want to create a new project note for the tag '{0}'? Chcete vytvořit novou poznámku projektu pro značku '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Markdown Tučně - + Markdown Italic Markdown Kurzíva - + Markdown Strikethrough Markdown Přeškrtnuté - + Shortcode Bold Shortcode Tučně - + Shortcode Italic Shortcode Kurzíva - + Shortcode Strikethrough Shortcode Přeškrtnuté - + Shortcode Underline Shortcode Podtržené - + Shortcode Highlight Shortcode Zvýraznění - + Shortcode Superscript Shortcode Horní index - + Shortcode Subscript Shortcode Dolní index @@ -2336,7 +2336,7 @@ About Qt - + O Qt @@ -2390,12 +2390,12 @@ Total character count (session change) - + Celkový počet znaků (změna relace) Total word count (session change) - + Počet slov v románu (změna relace) @@ -2474,7 +2474,7 @@ Delete build '{0}'? - + Smazat sestavení '{0}'? @@ -2747,17 +2747,17 @@ User interface colour theme. - + Barevné téma uživatelského rozhraní. Icon theme - + Motiv ikon User interface icon theme. - + Téma ikon uživatelského rozhraní. @@ -2793,12 +2793,12 @@ Prefer character count over word count - + Preferovat počet znaků před počtem slov Display character count instead where available. - + Kde je to možné, zobrazit počet znaků. @@ -2845,27 +2845,27 @@ Project View - + Zobrazení projektu Project tree icon colours - + Barvy ikon stromu projektu Override colours for project icons. - + Přepsat barvy pro ikony projektu. Keep theme colours on documents - + Ponechat barvy motivů v dokumentech Only override icon colours for folders. - + Přepsat pouze barvy ikon pro složky. @@ -3086,12 +3086,12 @@ Cursor width - + Šířka kurzoru The width of the text cursor of the editor. - + Šířka textového kurzoru editoru. @@ -3111,7 +3111,7 @@ Scroll past the end of the document - + Posunutí za konec dokumentu @@ -3496,7 +3496,7 @@ New Part - + Nová část @@ -4041,7 +4041,7 @@ Author Name - + Jméno autora @@ -4051,7 +4051,7 @@ Address Line - + Adresní řádek @@ -4281,69 +4281,69 @@ Stats - + Characters Znaky - + Characters in Text Znaky v textu - + Characters in Headings Znaky v nadpisech - + Paragraphs Odstavce - + Headings Nadpisy - + Characters, No Spaces Znaky, žádné mezery - + Characters in Text, No Spaces Znaky v textu, bez mezer - + Characters in Headings, No Spaces Znaky v nadpisech, žádné mezery - + Words Slova - + Words in Text Slova v textu - + Words in Headings Slova v nadpisech - + Characters: {0} ({1}) - + Znaky: {0} ({1}) - + Words: {0} ({1}) - Slova: {0} ({1}) + Slova: {0} ({1}) diff --git a/i18n/nw_de_DE.ts b/i18n/nw_de_DE.ts index 49f78378..2b2a41b5 100644 --- a/i18n/nw_de_DE.ts +++ b/i18n/nw_de_DE.ts @@ -365,7 +365,7 @@ Constant - + Title Titel @@ -401,571 +401,571 @@ Szenentrenner - - - - + + + + None Ohne - + Novel Roman - - + + Plot Handlung - - + + Characters Charaktere - - + + Locations Schauplätze - - + + Timeline Zeitleiste - - + + Objects Objekte - - + + Entities Organisationen - - - + + + Custom Benutzerdefiniert - + Archive Archiv - + Templates Vorlagen - + Trash Papierkorb - - + + Novel Document Romandokument - - + + Project Note Projektnotiz - + Root Folder Hauptordner - + Folder Ordner - + Novel Title Page Romantitel - + Novel Chapter Kapitel - + Novel Scene Szene - + Novel Section Romanabschnitt - + Active Aktiv - + Inactive Inaktiv - + Tag Schlagwort - + Point of View Perspektive - - + + Focus Fokus - + Story Geschichte - + Mentions Erwähnungen - + Level Ebene - + Document Dokument - + Line Zeile - + Status Status - + Chars Zeichen - + Words Wörter - + Pars Absätze - + POV Perspektive - + Synopsis Zusammenfassung - + Open Document (.odt) Open Document (.odt) - + Flat Open Document (.fodt) Flat Open Document (.fodt) - + Microsoft Word Document (.docx) Microsoft-Word-Dokument (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter-Markup (.txt) - + Standard Markdown (.md) Standard-Markdown (.md) - + Extended Markdown (.md) Erweitertes Markdown (.md) - + Portable Document Format (.pdf) Portable Document Format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter-Markup (.json) - + Square Quadrat - + Triangle Dreieck - + Nabla Nabla - + Diamond Raute - + Pentagon Fünfeck - + Hexagon Sechseck - + Star Stern - + Pacman Pacman - + 1/4 Circle 1/4-Kreis - + Half Circle Halbkreis - + 3/4 Circle 3/4-Kreis - + Full Circle Voller Kreis - + 1 Bar 1 Balken - + 2 Bars 2 Balken - + 3 Bars 3 Balken - + 4 Bars 4 Balken - + 1 Block 1 Block - + 2 Blocks 2 Blöcke - + 3 Blocks 3 Blöcke - + 4 Blocks 4 Blöcke - + Text files Textdateien - + Markdown files Markdown-Dateien - + novelWriter files novelWriter-Dateien - + CSV files CSV-Dateien - + All files Alle Dateien - + Millimetres Millimeter - + Centimetres Zentimeter - + Inches Zoll - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US Legal - + US Letter US Letter - + Theme Colours Farbschema (Anwendung) - + Foreground Colour Vordergrundfarbe - + Faded Colour Grau - + Red Rot - + Orange Orange - + Yellow Gelb - + Green Grün - + Aqua Türkis - + Blue Blau - + Purple Violett - + Straight single quotation mark Einfaches gerades Anführungszeichen - + Straight double quotation mark Doppeltes gerades Anführungszeichen - + Left single quotation mark Einfaches Anführungszeichen 6 oben - + Right single quotation mark Einfaches Anführungszeichen 9 oben - + Single low-9 quotation mark Einfaches Anführungszeichen 9 unten - + Single high-reversed-9 quotation mark Einfaches Anführungszeichen gespiegelte 9 oben - + Left double quotation mark Doppeltes Anführungszeichen 6 oben - + Right double quotation mark Doppeltes Anführungszeichen 9 oben - + Double low-9 quotation mark Doppeltes Anführungszeichen 9 unten - + Double high-reversed-9 quotation mark Doppeltes Anführungszeichen gespiegelte 9 oben - + Double low-reversed-9 quotation mark Doppeltes Anführungszeichen gespiegelte 9 unten - + Single left-pointing angle quotation mark Einfaches Guillemet linkszeigend - + Single right-pointing angle quotation mark Einfaches Guillemet rechtszeigend - + Double left-pointing angle quotation mark Doppeltes Guillemet linkszeigend - + Double right-pointing angle quotation mark Doppeltes Guillemet rechtszeigend - + Left corner bracket Linke Eckklammer - + Right corner bracket Rechte Eckklammer - + Left white corner bracket Linke weiße Eckklammer - + Right white corner bracket Rechte weiße Eckklammer - + Short dash Gedankenstrich - + Long dash Spiegelstrich - + Horizontal bar Horizontaler Balken @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) Zeile: {0} ({1}) - + Selected: {0} Markiert: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar Werkzeugleiste ein/aus - + Outline Gliederung - + Search Suche - + Toggle Focus Mode Ablenkungsfrei ein/aus - + Close Schließen @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Suchen nach - + Replace with Ersetzen durch - + Search Suchen - + Case Sensitive Groß-/Kleinschreibung beachten - + Whole Words Only Nur ganze Wörter - + RegEx Mode RegEx-Modus - + Loop Search Suche am Anfang fortsetzen - + Search Next File Nächstes Dokument durchsuchen - + Preserve Case Groß-/Kleinschreibung beibehalten - + Close Search Suche schließen - + Find in current document Im geöffneten Dokument suchen - + Find and replace in current document Im geöffneten Dokument suchen und ersetzen @@ -1232,82 +1232,82 @@ Dateispeicherort: {0} - + Set as Document Name Als Dokumentname verwenden - + Open URL URL öffnen - + Follow Tag Schlagwort öffnen - + Create Note for Tag Notiz für Schlagwort erstellen - + Cut Ausschneiden - + Copy Kopieren - + Paste Einfügen - + Select All Alles markieren - + Select Word Wort markieren - + Select Paragraph Absatz markieren - + Spelling Suggestion(s) Korrekturvorschläge - + No Suggestions Keine Vorschläge - + Ignore Word Wort ignorieren - + Add Word to Dictionary Zum Wörterbuch hinzufügen - + Please select some text before calling replace quotes. Bitte markieren Sie den Text, in dem die Anführungszeichen ersetzt werden sollen. - + Do you want to create a new project note for the tag '{0}'? Möchten Sie für das Schlagwort „{0}“ eine neue Projektnotiz erstellen? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Fett mit Markdown - + Markdown Italic Kursiv mit Markdown - + Markdown Strikethrough Durchgestrichen mit Markdown - + Shortcode Bold Fett mit Shortcode - + Shortcode Italic Kursiv mit Shortcode - + Shortcode Strikethrough Durchgestrichen mit Shortcode - + Shortcode Underline Unterstrichen mit Shortcode - + Shortcode Highlight Hervorheben mit Shortcode - + Shortcode Superscript Hochgestellt mit Shortcode - + Shortcode Subscript Tiefgestellt mit Shortcode @@ -4281,67 +4281,67 @@ Stats - + Characters Zeichen - + Characters in Text Zeichen im Text - + Characters in Headings Zeichen in Überschriften - + Paragraphs Absätze - + Headings Überschriften - + Characters, No Spaces Zeichen ohne Leerzeichen - + Characters in Text, No Spaces Zeichen im Text ohne Leerzeichen - + Characters in Headings, No Spaces Zeichen in Überschriften ohne Leerzeichen - + Words Wörter - + Words in Text Wörter im Text - + Words in Headings Wörter in Überschriften - + Characters: {0} ({1}) Zeichen: {0} ({1}) - + Words: {0} ({1}) Wörter: {0} ({1}) diff --git a/i18n/nw_en_US.ts b/i18n/nw_en_US.ts index e6151082..f151b882 100644 --- a/i18n/nw_en_US.ts +++ b/i18n/nw_en_US.ts @@ -365,7 +365,7 @@ Constant - + Title Title @@ -401,571 +401,571 @@ Scene Separator - - - - + + + + None None - + Novel Novel - - + + Plot Plot - - + + Characters Characters - - + + Locations Locations - - + + Timeline Timeline - - + + Objects Objects - - + + Entities Entities - - - + + + Custom Custom - + Archive Archive - + Templates Templates - + Trash Trash - - + + Novel Document Novel Document - - + + Project Note Project Note - + Root Folder Root Folder - + Folder Folder - + Novel Title Page Novel Title Page - + Novel Chapter Novel Chapter - + Novel Scene Novel Scene - + Novel Section Novel Section - + Active Active - + Inactive Inactive - + Tag Tag - + Point of View Point of View - - + + Focus Focus - + Story Story - + Mentions Mentions - + Level Level - + Document Document - + Line Line - + Status Status - + Chars Chars - + Words Words - + Pars Pars - + POV POV - + Synopsis Synopsis - + Open Document (.odt) Open Document (.odt) - + Flat Open Document (.fodt) Flat Open Document (.fodt) - + Microsoft Word Document (.docx) Microsoft Word Document (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter Markup (.txt) - + Standard Markdown (.md) Standard Markdown (.md) - + Extended Markdown (.md) Extended Markdown (.md) - + Portable Document Format (.pdf) Portable Document Format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter Markup (.json) - + Square Square - + Triangle Triangle - + Nabla Nabla - + Diamond Diamond - + Pentagon Pentagon - + Hexagon Hexagon - + Star Star - + Pacman Pacman - + 1/4 Circle 1/4 Circle - + Half Circle Half Circle - + 3/4 Circle 3/4 Circle - + Full Circle Full Circle - + 1 Bar 1 Bar - + 2 Bars 2 Bars - + 3 Bars 3 Bars - + 4 Bars 4 Bars - + 1 Block 1 Block - + 2 Blocks 2 Blocks - + 3 Blocks 3 Blocks - + 4 Blocks 4 Blocks - + Text files Text files - + Markdown files Markdown files - + novelWriter files novelWriter files - + CSV files CSV files - + All files All files - + Millimetres Millimeters - + Centimetres Centimeters - + Inches Inches - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US Legal - + US Letter US Letter - + Theme Colours Theme Colors - + Foreground Colour Foreground Color - + Faded Colour Faded Color - + Red Red - + Orange Orange - + Yellow Yellow - + Green Green - + Aqua Aqua - + Blue Blue - + Purple Purple - + Straight single quotation mark Straight single quotation mark - + Straight double quotation mark Straight double quotation mark - + Left single quotation mark Left single quotation mark - + Right single quotation mark Right single quotation mark - + Single low-9 quotation mark Single low-9 quotation mark - + Single high-reversed-9 quotation mark Single high-reversed-9 quotation mark - + Left double quotation mark Left double quotation mark - + Right double quotation mark Right double quotation mark - + Double low-9 quotation mark Double low-9 quotation mark - + Double high-reversed-9 quotation mark Double high-reversed-9 quotation mark - + Double low-reversed-9 quotation mark Double low-reversed-9 quotation mark - + Single left-pointing angle quotation mark Single left-pointing angle quotation mark - + Single right-pointing angle quotation mark Single right-pointing angle quotation mark - + Double left-pointing angle quotation mark Double left-pointing angle quotation mark - + Double right-pointing angle quotation mark Double right-pointing angle quotation mark - + Left corner bracket Left corner bracket - + Right corner bracket Right corner bracket - + Left white corner bracket Left white corner bracket - + Right white corner bracket Right white corner bracket - + Short dash Short dash - + Long dash Long dash - + Horizontal bar Horizontal bar @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) Line: {0} ({1}) - + Selected: {0} Selected: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar Toggle Tool Bar - + Outline Outline - + Search Search - + Toggle Focus Mode Toggle Focus Mode - + Close Close @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Search for - + Replace with Replace with - + Search Search - + Case Sensitive Case Sensitive - + Whole Words Only Whole Words Only - + RegEx Mode RegEx Mode - + Loop Search Loop Search - + Search Next File Search Next File - + Preserve Case Preserve Case - + Close Search Close Search - + Find in current document Find in current document - + Find and replace in current document Find and replace in current document @@ -1232,82 +1232,82 @@ File Location: {0} - + Set as Document Name Set as Document Name - + Open URL Open URL - + Follow Tag Follow Tag - + Create Note for Tag Create Note for Tag - + Cut Cut - + Copy Copy - + Paste Paste - + Select All Select All - + Select Word Select Word - + Select Paragraph Select Paragraph - + Spelling Suggestion(s) Spelling Suggestion(s) - + No Suggestions No Suggestions - + Ignore Word Ignore Word - + Add Word to Dictionary Add Word to Dictionary - + Please select some text before calling replace quotes. Please select some text before calling replace quotes. - + Do you want to create a new project note for the tag '{0}'? Do you want to create a new project note for the tag '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Markdown Bold - + Markdown Italic Markdown Italic - + Markdown Strikethrough Markdown Strikethrough - + Shortcode Bold Shortcode Bold - + Shortcode Italic Shortcode Italic - + Shortcode Strikethrough Shortcode Strikethrough - + Shortcode Underline Shortcode Underline - + Shortcode Highlight Shortcode Highlight - + Shortcode Superscript Shortcode Superscript - + Shortcode Subscript Shortcode Subscript @@ -4281,67 +4281,67 @@ Stats - + Characters Characters - + Characters in Text Characters in Text - + Characters in Headings Characters in Headings - + Paragraphs Paragraphs - + Headings Headings - + Characters, No Spaces Characters, No Spaces - + Characters in Text, No Spaces Characters in Text, No Spaces - + Characters in Headings, No Spaces Characters in Headings, No Spaces - + Words Words - + Words in Text Words in Text - + Words in Headings Words in Headings - + Characters: {0} ({1}) Characters: {0} ({1}) - + Words: {0} ({1}) Words: {0} ({1}) diff --git a/i18n/nw_it_IT.ts b/i18n/nw_it_IT.ts index d21d1922..57a69b3a 100644 --- a/i18n/nw_it_IT.ts +++ b/i18n/nw_it_IT.ts @@ -365,7 +365,7 @@ Constant - + Title Titolo @@ -401,571 +401,571 @@ Separatore di scena - - - - + + + + None Nessuno - + Novel Romanzo - - + + Plot Trama - - + + Characters Personaggi - - + + Locations Luoghi - - + + Timeline Sequenza temporale - - + + Objects Oggetti - - + + Entities Entità - - - + + + Custom Personalizzato - + Archive Archivio - + Templates Modelli - + Trash Cestino - - + + Novel Document Documento del romanzo - - + + Project Note Nota del progetto - + Root Folder Cartella principale - + Folder Cartella - + Novel Title Page Pagina del titolo del romanzo - + Novel Chapter Capitolo del romanzo - + Novel Scene Scena del romanzo - + Novel Section Sezione del romanzo - + Active Attivo - + Inactive Inattivo - + Tag Etichetta - + Point of View Punto di vista - - + + Focus Focus - + Story Storia - + Mentions Menzioni - + Level Livello - + Document Documento - + Line Righe - + Status Stato - + Chars Caratteri - + Words Parole - + Pars Paragrafi - + POV POV - + Synopsis Sommario - + Open Document (.odt) Documento Aperto (.odt) - + Flat Open Document (.fodt) Apri documento piatto (.fodt) - + Microsoft Word Document (.docx) Documento Microsoft Word (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter Markup (.txt) - + Standard Markdown (.md) Standard Markdown (.md) - + Extended Markdown (.md) Extended Markdown (.md) - + Portable Document Format (.pdf) Portable Document Format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter Markup (.json) - + Square Quadrato - + Triangle Triangolo - + Nabla Triangolo capovolto - + Diamond Diamante - + Pentagon Pentagono - + Hexagon Esagono - + Star Stella - + Pacman Pacman - + 1/4 Circle 1/4 di cerchio - + Half Circle Mezzo cerchio - + 3/4 Circle 3/4 di cerchio - + Full Circle Cerchio intero - + 1 Bar 1 barra - + 2 Bars 2 barre - + 3 Bars 3 barre - + 4 Bars 4 barre - + 1 Block 1 blocco - + 2 Blocks 2 blocchi - + 3 Blocks 3 blocchi - + 4 Blocks 4 blocchi - + Text files File di testo - + Markdown files File Markdown - + novelWriter files File di novelWriter - + CSV files File CSV - + All files Tutti i file - + Millimetres Millimetri - + Centimetres Centimetri - + Inches Pollici - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US Legale - + US Letter US Lettera - + Theme Colours Colori del tema - + Foreground Colour Colore del primo piano - + Faded Colour Colore sfumato - + Red Rosso - + Orange Arancione - + Yellow Giallo - + Green Verde - + Aqua Acqua - + Blue Blu - + Purple Viola - + Straight single quotation mark Virgoletta singola diritta - + Straight double quotation mark Virgolette doppie diritte - + Left single quotation mark Virgoletta singola a sinistra - + Right single quotation mark Virgoletta singola a destra - + Single low-9 quotation mark Singola virgoletta bassa 9 - + Single high-reversed-9 quotation mark Singola virgoletta alta inversa-9 - + Left double quotation mark Virgolette doppie a sinistra - + Right double quotation mark Virgolette doppie a destra - + Double low-9 quotation mark Doppie virgolette basse 9 - + Double high-reversed-9 quotation mark Doppie virgolette alte inverse 9 - + Double low-reversed-9 quotation mark Doppie virgolette basse inverse 9 - + Single left-pointing angle quotation mark Virgoletta singola ad angolo sinistro (<) - + Single right-pointing angle quotation mark Virgoletta singola ad angolo destro (>) - + Double left-pointing angle quotation mark Virgolette doppie ad angolo sinistro (<<) - + Double right-pointing angle quotation mark Virgolette doppie ad angolo destro (>>) - + Left corner bracket Staffa angolare sinistra - + Right corner bracket Staffa angolare destra - + Left white corner bracket Staffa angolare bianca sinistra - + Right white corner bracket Staffa angolare bianca destra - + Short dash Trattino breve - + Long dash Trattino lungo - + Horizontal bar Barra orizzontale @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) Riga: {0} ({1}) - + Selected: {0} Selezionato: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar Attiva/disattiva la Barra degli strumenti - + Outline Struttura - + Search Cerca - + Toggle Focus Mode Attiva/Disattiva modalità Focus - + Close Chiudi @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Ricerca - + Replace with Sostituisci con - + Search Cerca - + Case Sensitive Considera maiuscole/minuscole - + Whole Words Only Solo parole intere - + RegEx Mode Modalità RegEx - + Loop Search Ricerca a ciclo continuo - + Search Next File Cerca nel file successivo - + Preserve Case Non considerare maiuscole/minuscole - + Close Search Chiudi ricerca - + Find in current document Trova nel documento corrente - + Find and replace in current document Trova e sostituisci nel documento corrente @@ -1232,82 +1232,82 @@ Posizione del file: {0} - + Set as Document Name Imposta come nome del documento - + Open URL Apri URL - + Follow Tag Segui i Tag - + Create Note for Tag Crea una nota per il Tag - + Cut Taglia - + Copy Copia - + Paste Incolla - + Select All Seleziona tutto - + Select Word Seleziona parola - + Select Paragraph Seleziona paragrafo - + Spelling Suggestion(s) Suggerimento(i) ortografico(i) - + No Suggestions Nessun suggerimento - + Ignore Word Ignora parola - + Add Word to Dictionary Aggiungi parola al dizionario - + Please select some text before calling replace quotes. Per favore seleziona del testo prima di chiedere il cambio di virgolette. - + Do you want to create a new project note for the tag '{0}'? Vuoi creare una nuova nota di progetto per il tag '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Markdown grassetto - + Markdown Italic Markdown corsivo - + Markdown Strikethrough Markdown barrato - + Shortcode Bold Shortcode grassetto - + Shortcode Italic Shortcode corsivo - + Shortcode Strikethrough Shortcode barrato - + Shortcode Underline Shortcode sottolineato - + Shortcode Highlight Evidenziazione - + Shortcode Superscript Shortcode apice - + Shortcode Subscript Shortcode pendice @@ -4281,67 +4281,67 @@ Stats - + Characters Caratteri - + Characters in Text Caratteri nel testo - + Characters in Headings Caratteri nelle intestazioni - + Paragraphs Paragrafi - + Headings Intestazioni - + Characters, No Spaces Caratteri, esclusi gli spazi - + Characters in Text, No Spaces Caratteri nel testo, esclusi gli spazi - + Characters in Headings, No Spaces Caratteri nelle intestazioni, esclusi gli spazi - + Words Parole - + Words in Text Parole nel testo - + Words in Headings Parole nelle intestazioni - + Characters: {0} ({1}) Caratteri: {0} ({1}) - + Words: {0} ({1}) Parole: {0} ({1}) diff --git a/i18n/nw_ja_JP.ts b/i18n/nw_ja_JP.ts index a4f7a65f..594f0cd9 100644 --- a/i18n/nw_ja_JP.ts +++ b/i18n/nw_ja_JP.ts @@ -365,7 +365,7 @@ Constant - + Title タイトル @@ -401,571 +401,571 @@ シーンセパレーター - - - - + + + + None なし - + Novel 小説 - - + + Plot プロット - - + + Characters 登場人物 - - + + Locations 場所 - - + + Timeline タイムライン - - + + Objects オブジェクト - - + + Entities エンティティ - - - + + + Custom カスタム - + Archive アーカイブ - + Templates テンプレート - + Trash ごみ箱 - - + + Novel Document 小説のドキュメント - - + + Project Note プロジェクトノート - + Root Folder ルートフォルダー - + Folder フォルダー - + Novel Title Page 小説のタイトルページ - + Novel Chapter 小説のチャプター - + Novel Scene 小説のシーン - + Novel Section 小説のセクション - + Active アクティブ - + Inactive 非アクティブ - + Tag タグ - + Point of View 視点 - - + + Focus 焦点 - + Story ストーリー - + Mentions メンション - + Level 階層 - + Document ドキュメント - + Line - + Status ステータス - + Chars 文字 - + Words 単語 - + Pars 段落 - + POV 視点 - + Synopsis あらすじ - + Open Document (.odt) オープンドキュメント (.odt) - + Flat Open Document (.fodt) フラットオープンドキュメント (.fodt) - + Microsoft Word Document (.docx) Microsoft Word 文書 (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriterマークアップ (.txt) - + Standard Markdown (.md) 標準マークダウン (.md) - + Extended Markdown (.md) 拡張マークダウン (.md) - + Portable Document Format (.pdf) ポータブルドキュメントフォーマット (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter マークアップ (.json) - + Square 正方形 - + Triangle 三角形 - + Nabla 逆三角形 - + Diamond 菱形 - + Pentagon 五角形 - + Hexagon 六角形 - + Star - + Pacman パックマン - + 1/4 Circle 1/4の円 - + Half Circle 半円 - + 3/4 Circle 3/4の円 - + Full Circle 全円 - + 1 Bar 1バー - + 2 Bars 2バー - + 3 Bars 3バー - + 4 Bars 4バー - + 1 Block 1ブロック - + 2 Blocks 2ブロック - + 3 Blocks 3ブロック - + 4 Blocks 4ブロック - + Text files テキストファイル - + Markdown files マークダウンファイル - + novelWriter files novelWriterファイル - + CSV files CSVファイル - + All files すべてのファイル - + Millimetres ミリメートル - + Centimetres センチメートル - + Inches インチ - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US リーガル - + US Letter US レター - + Theme Colours テーマカラー - + Foreground Colour 前景色 - + Faded Colour 色あせた色 - + Red - + Orange オレンジ - + Yellow 黄色 - + Green - + Aqua 水色 - + Blue - + Purple - + Straight single quotation mark 直線形シングルクォーテーション - + Straight double quotation mark 直線形ダブルクォーテーション - + Left single quotation mark 左シングルクォーテーション - + Right single quotation mark 右シングルクォーテーション - + Single low-9 quotation mark シングルローナインクォーテーション - + Single high-reversed-9 quotation mark 上反転シングルローナインクォーテーション - + Left double quotation mark 左ダブルクォーテーション - + Right double quotation mark 右ダブルクォーテーション - + Double low-9 quotation mark ダブルローナインクォーテーション - + Double high-reversed-9 quotation mark 上反転ダブルローナインクォーテーション - + Double low-reversed-9 quotation mark 下反転ダブルローナインクォーテーション - + Single left-pointing angle quotation mark 左フレンチシングルクォーテーション - + Single right-pointing angle quotation mark 右フレンチシングルクォーテーション - + Double left-pointing angle quotation mark 左フレンチダブルクォーテーション - + Double right-pointing angle quotation mark 右フレンチダブルクォーテーション - + Left corner bracket 左鉤括弧 - + Right corner bracket 右鉤括弧 - + Left white corner bracket 左二重鉤括弧 - + Right white corner bracket 右二重鉤括弧 - + Short dash enダッシュ - + Long dash emダッシュ - + Horizontal bar 水平線 @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) 行: {0} ({1}) - + Selected: {0} 選択済み: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar ツールバーの切り替え - + Outline アウトライン - + Search 検索 - + Toggle Focus Mode フォーカスモードの切り替え - + Close 閉じる @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for 検索 - + Replace with 置換候補 - + Search 検索 - + Case Sensitive 大文字と小文字を区別 - + Whole Words Only 完全一致のみ - + RegEx Mode 正規表現モード - + Loop Search ループ検索 - + Search Next File 次のファイルを検索 - + Preserve Case 大文字と小文字を保持 - + Close Search 検索を閉じる - + Find in current document 現在のドキュメント内を検索 - + Find and replace in current document 現在のドキュメント内を検索して置き換え @@ -1232,82 +1232,82 @@ ファイル場所: {0} - + Set as Document Name ドキュメント名として設定 - + Open URL URLを開く - + Follow Tag タグをフォロー - + Create Note for Tag タグのメモを作成 - + Cut 切り取り - + Copy コピー - + Paste 貼り付け - + Select All すべて選択 - + Select Word 単語を選択 - + Select Paragraph 段落を選択 - + Spelling Suggestion(s) スペルの提案 - + No Suggestions 候補なし - + Ignore Word 単語を無視 - + Add Word to Dictionary 単語を辞書に追加 - + Please select some text before calling replace quotes. 置き換え引用符を呼び出す前にテキストを選択してください。 - + Do you want to create a new project note for the tag '{0}'? タグ '{0}' の新規プロジェクトノートを作成しますか? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold マークダウン 太字 - + Markdown Italic マークダウン 斜体 - + Markdown Strikethrough マークダウン 取り消し線 - + Shortcode Bold ショートコード 太字 - + Shortcode Italic ショートコード 斜体 - + Shortcode Strikethrough ショートコード 取り消し線 - + Shortcode Underline ショートコード 下線 - + Shortcode Highlight ショートコードハイライト - + Shortcode Superscript ショートコード 上付き文字 - + Shortcode Subscript ショートコード 下付き文字 @@ -4281,67 +4281,67 @@ Stats - + Characters 文字数 - + Characters in Text テキスト内の文字数 - + Characters in Headings 見出し内の文字数 - + Paragraphs 段落 - + Headings 見出し - + Characters, No Spaces スペースなし文字数 - + Characters in Text, No Spaces テキスト内のスペースなし文字数 - + Characters in Headings, No Spaces 見出し内のスペースなし文字数 - + Words 単語数 - + Words in Text テキスト内の単語数 - + Words in Headings 見出し内の単語数 - + Characters: {0} ({1}) 文字: {0} ({1}) - + Words: {0} ({1}) 単語: {0} ({1}) diff --git a/i18n/nw_nb_NO.ts b/i18n/nw_nb_NO.ts index 3b408970..f01969f1 100644 --- a/i18n/nw_nb_NO.ts +++ b/i18n/nw_nb_NO.ts @@ -365,7 +365,7 @@ Constant - + Title Tittel @@ -401,571 +401,571 @@ Scene-separator - - - - + + + + None Ingen - + Novel Roman - - + + Plot Plott - - + + Characters Karakterer - - + + Locations Lokasjoner - - + + Timeline Tidslinje - - + + Objects Objekter - - + + Entities Enheter - - - + + + Custom Annet - + Archive Arkiv - + Templates Maler - + Trash Søppel - - + + Novel Document Romandokument - - + + Project Note Prosjektnotat - + Root Folder Hovedmappe - + Folder Mappe - + Novel Title Page Tittelside - + Novel Chapter Kapittel - + Novel Scene Scene - + Novel Section Seksjon - + Active Aktiv - + Inactive Inaktiv - + Tag Knagg - + Point of View Perspektiv - - + + Focus Fokus - + Story Fortelling - + Mentions Nevnt - + Level Nivå - + Document Dokument - + Line Linje - + Status Status - + Chars Tegn - + Words Ord - + Pars Avsnitt - + POV Persp. - + Synopsis Sammendrag - + Open Document (.odt) Open Document (.odt) - + Flat Open Document (.fodt) Flat Open Document (.fodt) - + Microsoft Word Document (.docx) Microsoft Word-dokument (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter Markup (.txt) - + Standard Markdown (.md) Standard Markdown (.md) - + Extended Markdown (.md) Utvidet Markdown (.md) - + Portable Document Format (.pdf) Portabelt dokument-format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter Markup (.json) - + Square Firkant - + Triangle Trekant - + Nabla Nabla - + Diamond Diamant - + Pentagon Pentagon - + Hexagon Heksagon - + Star Stjerne - + Pacman Pacman - + 1/4 Circle 1/4 sirkel - + Half Circle Halvsirkel - + 3/4 Circle 3/4 sirkel - + Full Circle Helsirkel - + 1 Bar 1 strek - + 2 Bars 2 streker - + 3 Bars 3 streker - + 4 Bars 4 streker - + 1 Block 1 kloss - + 2 Blocks 2 klosser - + 3 Blocks 3 klosser - + 4 Blocks 4 klosser - + Text files Tekstfiler - + Markdown files Markdown-filer - + novelWriter files novelWriter-filer - + CSV files CSV-filer - + All files Alle filer - + Millimetres Millimeter - + Centimetres Centimeter - + Inches Tommer - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US Legal - + US Letter US Letter - + Theme Colours Tema-farger - + Foreground Colour Tekstfarge - + Faded Colour Grå - + Red Rød - + Orange Oransje - + Yellow Gul - + Green Grønn - + Aqua Akvamarin - + Blue Blå - + Purple Lilla - + Straight single quotation mark Rett, enkelt sitattegn - + Straight double quotation mark Rett, dobbelt sitattegn - + Left single quotation mark Venstre, enkelt sitattegn - + Right single quotation mark Høyre, enkelt sitattegn - + Single low-9 quotation mark Enkelt, lavt-9 sitattegn - + Single high-reversed-9 quotation mark Enkelt, høyt, reversert-9 sitattegn - + Left double quotation mark Venstre, dobbelt sitattegn - + Right double quotation mark Høyre, dobbelt sitattegn - + Double low-9 quotation mark Dobbelt, lavt-9 sitattegn - + Double high-reversed-9 quotation mark Dobbelt, høyt, reversert-9 sitattegn - + Double low-reversed-9 quotation mark Dobbelt, lavt, reversert-9 sitattegn - + Single left-pointing angle quotation mark Enkelt, venstre, angulært sitattegn - + Single right-pointing angle quotation mark Enkelt, høyre, angulært sitattegn - + Double left-pointing angle quotation mark Dobbelt, venstre, angulært sitattegn - + Double right-pointing angle quotation mark Dobbelt, høyre, angulært sitattegn - + Left corner bracket Venstre hjørnevinkel - + Right corner bracket Høyre hjørnevinkel - + Left white corner bracket Venstre, hvit hjørnevinkel - + Right white corner bracket Høyre, hvit hjørnevinkel - + Short dash Kort bindestrek - + Long dash Lang bindestrek - + Horizontal bar Horisontal strek @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) Linje: {0} ({1}) - + Selected: {0} Utvalg: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar Vis/skjul verktøylinje - + Outline Disposisjon - + Search Søk - + Toggle Focus Mode Slå av/på "Fokus-modus" - + Close Lukk @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Søketekst - + Replace with Erstatt med - + Search Søk - + Case Sensitive Skill store/små bokstaver - + Whole Words Only Kun hele ord - + RegEx Mode RegEx-modus - + Loop Search Søk rundt - + Search Next File Søk i neste file - + Preserve Case Behold store/små bokstaver - + Close Search Lukk søk - + Find in current document Søk i det åpne dokumentet - + Find and replace in current document Søk og erstatt i det åpne dokumentet @@ -1232,82 +1232,82 @@ Filplassering: {0} - + Set as Document Name Sett som dokumentnavn - + Open URL Åpne lenke - + Follow Tag Følg knagg - + Create Note for Tag Opprett notat for knagg - + Cut Klipp - + Copy Kopier - + Paste Lim inn - + Select All Velg hele teksten - + Select Word Velg hele ordet - + Select Paragraph Velg hele avsnittet - + Spelling Suggestion(s) Forslag fra stavekontrollen - + No Suggestions Ingen forslag - + Ignore Word Ignorer ord - + Add Word to Dictionary Legg til ord i ordbok - + Please select some text before calling replace quotes. Venligst velg en del av teksten før du velger å erstatte sitattegn. - + Do you want to create a new project note for the tag '{0}'? Vil du opprette et nytt prosjektnotat for knaggen '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Fet skrift med Markdown - + Markdown Italic Kursiv med Markdown - + Markdown Strikethrough Gjennomstrek med Markdown - + Shortcode Bold Fet skrift med kortkode - + Shortcode Italic Kursiv med kortkode - + Shortcode Strikethrough Gjennomstrek med kortkode - + Shortcode Underline Understrek med kortkode - + Shortcode Highlight Tekstutheving med kortkode - + Shortcode Superscript Hevet skrift med kortkode - + Shortcode Subscript Senket skrift med kortkode @@ -4281,67 +4281,67 @@ Stats - + Characters Tegn - + Characters in Text Tegn i tekst - + Characters in Headings Tegn i overskrifter - + Paragraphs Avsnitt - + Headings Overskrifter - + Characters, No Spaces Tegn, utenom mellomrom - + Characters in Text, No Spaces Tegn i tekst, utenom mellomrom - + Characters in Headings, No Spaces Tegn i overskrifter, utenom mellomrom - + Words Ord - + Words in Text Ord i tekst - + Words in Headings Ord i overskrifter - + Characters: {0} ({1}) Tegn: {0} ({1}) - + Words: {0} ({1}) Ord: {0} ({1}) diff --git a/i18n/nw_pl_PL.ts b/i18n/nw_pl_PL.ts index a70f332a..fec9560c 100644 --- a/i18n/nw_pl_PL.ts +++ b/i18n/nw_pl_PL.ts @@ -365,7 +365,7 @@ Constant - + Title Tytuł @@ -401,571 +401,571 @@ Odstęp między scenami - - - - + + + + None NIC - + Novel Powieść - - + + Plot Fabuła - - + + Characters Postacie - - + + Locations Miejsca - - + + Timeline Linia czasu - - + + Objects Obiekty - - + + Entities Podmioty - - - + + + Custom Różne - + Archive Archiwum - + Templates Szablony - + Trash Kosz - - + + Novel Document Dokument powieści - - + + Project Note Notatka projektu - + Root Folder Katalog bazowy - + Folder Katalog - + Novel Title Page Strona tytułowa powieści - + Novel Chapter Rozdział powieści - + Novel Scene Scena - + Novel Section Sekcja - + Active Aktywny - + Inactive Nieaktywny - + Tag Znacznik - + Point of View Punkt widzenia - - + + Focus Skupienie - + Story Historia - + Mentions Wzmianka - + Level Poziom - + Document Dokument - + Line Wiersz - + Status Status - + Chars Znaki - + Words Słowa - + Pars Akapity - + POV Punkt widzenia - + Synopsis Streszczenie - + Open Document (.odt) Open Document (.odt) - + Flat Open Document (.fodt) Flat Open Document (.fodt) - + Microsoft Word Document (.docx) Dokument Word Microsoft (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter Markup (.txt) - + Standard Markdown (.md) Standard Markdown (.md) - + Extended Markdown (.md) Extended Markdown (.md) - + Portable Document Format (.pdf) Portable Document Format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + novelWriter Markup (.json) - + Square Kwadrat - + Triangle Trójkąt - + Nabla Nabla - + Diamond Diament - + Pentagon Pięciokąt - + Hexagon Sześciokąt - + Star Gwiazda - + Pacman Pacman - + 1/4 Circle Ćwierć koła - + Half Circle Pół koła - + 3/4 Circle 3/4 koła - + Full Circle Pełne koło - + 1 Bar 1 pasek - + 2 Bars 2 paski - + 3 Bars 3 paski - + 4 Bars 4 paski - + 1 Block 1 bloczek - + 2 Blocks 2 bloczki - + 3 Blocks 3 bloczki - + 4 Blocks 4 bloczki - + Text files Pliki tekstowe - + Markdown files Pliki Markdown - + novelWriter files Pliki novelWriter - + CSV files Pliki CSV - + All files Wszystkie pliki - + Millimetres Milimetry - + Centimetres Centymetry - + Inches Cale - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal US Legal - + US Letter US Letter - + Theme Colours Kolory motywu - + Foreground Colour Kolor tła - + Faded Colour Zgaszony kolor - + Red Czerwony - + Orange Pomarańczowy - + Yellow Żółty - + Green Zielone - + Aqua Turkusowy - + Blue Niebieski - + Purple Fioletowy - + Straight single quotation mark Amerykański cudzysłów pojedynczy - + Straight double quotation mark Amerykański cudzysłów podwójny - + Left single quotation mark Cudzysłów definicyjny lewy - + Right single quotation mark Cudzysłów definicyjny prawy - + Single low-9 quotation mark Polski cudzysłów pojedynczy lewy - + Single high-reversed-9 quotation mark Polski cudzysłów definicyjny lewy - + Left double quotation mark Cudzysłów amerykański lewy - + Right double quotation mark Cudzysłów apostrofowy prawy - + Double low-9 quotation mark Cudzysłów apostrofowy lewy - + Double high-reversed-9 quotation mark Podwójny odwrócony cudzysłów górny - + Double low-reversed-9 quotation mark Podwójny odwrócony cudzysłów dolny - + Single left-pointing angle quotation mark Pojedynczy cudzysłów ostrokątny lewy - + Single right-pointing angle quotation mark Pojedynczy cudzysłów ostrokątny prawy - + Double left-pointing angle quotation mark Podwójny cudzysłów ostrokątny lewy - + Double right-pointing angle quotation mark Podwójny cudzysłów ostrokątny prawy - + Left corner bracket Lewy nawias narożnikowy - + Right corner bracket Prawy nawias narożnikowy - + Left white corner bracket Lewy nawias narożnikowy biały - + Right white corner bracket Prawy nawias narożnikowy biały - + Short dash Półpauza - + Long dash Pauza - + Horizontal bar Długa pauza @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) Wiersz: {0} ({1}) - + Selected: {0} Wybrane: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar Przełącz pasek narzędzi - + Outline Zarys - + Search Szukaj - + Toggle Focus Mode Przełącz tryb skupienia - + Close Zamknij @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Wyszukaj - + Replace with Zastąp przez - + Search Szukaj - + Case Sensitive Wielkość znaków - + Whole Words Only Tylko pełne słowa - + RegEx Mode Wyrażenia regularne - + Loop Search Wyszukiwanie w pętli - + Search Next File Przeszukuj następny plik - + Preserve Case Zachowaj wielkość liter - + Close Search Zamknij wyszukiwanie - + Find in current document Znajdź w bieżącym dokumencie - + Find and replace in current document Znajdź i zastąp w bieżącym dokumencie @@ -1232,82 +1232,82 @@ Lokalizacja pliku: {0} - + Set as Document Name Ustaw jako nazwę dokumentu - + Open URL Otwórz adres URL - + Follow Tag Podążaj za znacznikiem - + Create Note for Tag Stwórz notatkę dla znacznika - + Cut Wytnij - + Copy Kopiuj - + Paste Wklej - + Select All Zaznacz wszystko - + Select Word Zaznacz słowo - + Select Paragraph Zaznacz akapit - + Spelling Suggestion(s) Podpowiedzi pisowni - + No Suggestions Brak podpowiedzi - + Ignore Word Ignoruj słowo - + Add Word to Dictionary Dodaj słowo do słownika - + Please select some text before calling replace quotes. Zaznacz tekst przed wywołaniem zastępowania cudzysłowów. - + Do you want to create a new project note for the tag '{0}'? Czy chcesz stworzyć nową notatkę dla znacznika '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Pogrubienie Markdown - + Markdown Italic Kursywa Markdown - + Markdown Strikethrough Przekreślenie Markdown - + Shortcode Bold Pogrubienie Shortcode - + Shortcode Italic Kursywa Shortcode - + Shortcode Strikethrough Przekreślenie Shortcode - + Shortcode Underline Podkreślenie Shortcode - + Shortcode Highlight Podświetlenie Shortcode - + Shortcode Superscript Indeks górny Shortcode - + Shortcode Subscript Indeks dolny Shortcode @@ -4281,67 +4281,67 @@ Stats - + Characters Znaki - + Characters in Text Znaki w tekście - + Characters in Headings Znaki w nagłówkach - + Paragraphs Akapity - + Headings Nagłówki - + Characters, No Spaces Znaki bez spacji - + Characters in Text, No Spaces Znaki w tekście bez spacji - + Characters in Headings, No Spaces Znaki w nagłówkach bez spacji - + Words Słowa - + Words in Text Słowa w tekście - + Words in Headings Słowa w nagłówkach - + Characters: {0} ({1}) Znaki: {0} ({1}) - + Words: {0} ({1}) Słowa: {0} ({1}) diff --git a/i18n/nw_pt_BR.ts b/i18n/nw_pt_BR.ts index 8b840827..6c7d368a 100644 --- a/i18n/nw_pt_BR.ts +++ b/i18n/nw_pt_BR.ts @@ -365,7 +365,7 @@ Constant - + Title Título @@ -401,571 +401,571 @@ Separador de cena - - - - + + + + None Nenhum - + Novel Livro - - + + Plot Enredo - - + + Characters Personagens - - + + Locations Lugares - - + + Timeline Linha do tempo - - + + Objects Objetos - - + + Entities Entidades - - - + + + Custom Outros - + Archive Arquivados - + Templates Modelos - + Trash Lixeira - - + + Novel Document Documento do livro - - + + Project Note Notas do projeto - + Root Folder Diretório-raiz - + Folder Diretório - + Novel Title Page Folha de rosto do livro - + Novel Chapter Capítulo do livro - + Novel Scene Cena do livro - + Novel Section Seção do livro - + Active Ativo - + Inactive Inativo - + Tag Etiqueta - + Point of View Ponto de vista - - + + Focus Foco - + Story História - + Mentions Menções - + Level Nível - + Document Documento - + Line Linha - + Status Estado - + Chars Caracteres - + Words Palavras - + Pars Parágrafos - + POV Ponto de vista - + Synopsis Sinopse - + Open Document (.odt) Open Document (.odt) - + Flat Open Document (.fodt) Flat Open Document (.fodt) - + Microsoft Word Document (.docx) Documento do Microsoft Word (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) Markup do novelWriter (.txt) - + Standard Markdown (.md) Markdown padrão (.md) - + Extended Markdown (.md) Markdown estendido (.md) - + Portable Document Format (.pdf) Portable Document Format (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + Markup do novelWriter (.json) - + Square Quadrado - + Triangle Triângulo - + Nabla Nabla - + Diamond Diamante - + Pentagon Pentágono - + Hexagon Hexágono - + Star Estrela - + Pacman Pacman - + 1/4 Circle 1/4 de círculo - + Half Circle Meio círculo - + 3/4 Circle 3/4 de círculo - + Full Circle Círculo completo - + 1 Bar 1 barra - + 2 Bars 2 barras - + 3 Bars 3 barras - + 4 Bars 4 barras - + 1 Block 1 bloco - + 2 Blocks 2 blocos - + 3 Blocks 3 blocos - + 4 Blocks 4 blocos - + Text files Arquivos de texto - + Markdown files Arquivos Markdown - + novelWriter files Arquivos do novelWriter - + CSV files Arquivos CSV - + All files Todos os arquivos - + Millimetres Milímetros - + Centimetres Centímetros - + Inches Polegadas - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal Ofício - + US Letter Carta - + Theme Colours Cores do tema - + Foreground Colour Cor do texto - + Faded Colour Cor atenuada - + Red Vermelho - + Orange Laranja - + Yellow Amarelo - + Green Verde - + Aqua Verde-água - + Blue Azul - + Purple Lilás - + Straight single quotation mark Aspas simples retas - + Straight double quotation mark Aspas duplas retas - + Left single quotation mark Aspas simples à esquerda - + Right single quotation mark Aspas simples à direita - + Single low-9 quotation mark Aspas 9-baixo simples - + Single high-reversed-9 quotation mark Aspas 9-alto-invertido simples - + Left double quotation mark Aspas duplas à esquerda - + Right double quotation mark Aspas duplas à direita - + Double low-9 quotation mark Aspas 9-baixo duplas - + Double high-reversed-9 quotation mark Aspas 9-alto-invertido duplas - + Double low-reversed-9 quotation mark Aspas 9-baixo-invertido duplas - + Single left-pointing angle quotation mark Aspas angulares simples à esquerda - + Single right-pointing angle quotation mark Aspas angulares simples à direita - + Double left-pointing angle quotation mark Aspas angulares duplas apontando à esquerda - + Double right-pointing angle quotation mark Aspas angulares duplas apontando à direita - + Left corner bracket Colchete de canto à esquerda - + Right corner bracket Right corner bracket - + Left white corner bracket Colchete branco de canto à esquerda - + Right white corner bracket Colchete branco de canto à direita - + Short dash Meia-risca (en dash) - + Long dash Travessão (em dash) - + Horizontal bar Barra horizontal @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) Linha: {0} ({1}) - + Selected: {0} Selecionado: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar Exibir/ocultar barra de ferramentas - + Outline Estrutura - + Search Pesquisa - + Toggle Focus Mode Alternar o modo de foco - + Close Fechar @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for Pesquisar por - + Replace with Substituir por - + Search Pesquisa - + Case Sensitive Diferenciar maiúsculas e minúsculas - + Whole Words Only Apenas palavras inteiras - + RegEx Mode Expressão regular - + Loop Search Pesquisa iterativa - + Search Next File Pesquisar no documento seguinte - + Preserve Case Preservar maiúsculas e minúsculas - + Close Search Fechar pesquisa - + Find in current document Encontrar no documento atual - + Find and replace in current document Encontrar e substituir no documento atual @@ -1232,82 +1232,82 @@ Caminho do arquivo: {0} - + Set as Document Name Definir como nome do documento - + Open URL Abrir URL - + Follow Tag Seguir etiqueta - + Create Note for Tag Criar nota para a etiqueta - + Cut Recortar - + Copy Copiar - + Paste Colar - + Select All Selecionar tudo - + Select Word Selecionar palavra - + Select Paragraph Selecionar parágrafo - + Spelling Suggestion(s) Sugestão(ões) de ortografia - + No Suggestions Sem sugestões - + Ignore Word Ignorar palavra - + Add Word to Dictionary Adicionar palavra ao dicionário - + Please select some text before calling replace quotes. Por favor, selecione algum texto antes de usar a substituição de aspas. - + Do you want to create a new project note for the tag '{0}'? Deseja criar uma nova nota de projeto para a etiqueta '{0}'? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Negrito (em Markdown) - + Markdown Italic Itálico (em Markdown) - + Markdown Strikethrough Tachado (em Markdown) - + Shortcode Bold Negrito (código) - + Shortcode Italic Itálico (código) - + Shortcode Strikethrough Tachado (código) - + Shortcode Underline Sublinhado (código) - + Shortcode Highlight Destaque (em código) - + Shortcode Superscript Sobrescrito (código) - + Shortcode Subscript Subscrito (código) @@ -4281,67 +4281,67 @@ Stats - + Characters Caracteres - + Characters in Text Caracteres no texto - + Characters in Headings Caracteres em cabeçalhos - + Paragraphs Parágrafos - + Headings Cabeçalhos - + Characters, No Spaces Caracteres, sem espaços - + Characters in Text, No Spaces Caracteres no texto, sem espaços - + Characters in Headings, No Spaces Caracteres em cabeçalhos, sem espaços - + Words Palavras - + Words in Text Palavras no texto - + Words in Headings Palavras em cabeçalhos - + Characters: {0} ({1}) Caracteres: {0} ({1}) - + Words: {0} ({1}) Palavras: {0} ({1}) diff --git a/i18n/nw_zh_CN.ts b/i18n/nw_zh_CN.ts index 967500d8..234814ab 100644 --- a/i18n/nw_zh_CN.ts +++ b/i18n/nw_zh_CN.ts @@ -365,7 +365,7 @@ Constant - + Title 标题 @@ -401,571 +401,571 @@ 场景分隔符 - - - - + + + + None - + Novel 小说 - - + + Plot 情节 - - + + Characters 角色 - - + + Locations 位置 - - + + Timeline 时间线 - - + + Objects 物品 - - + + Entities 条目 - - - + + + Custom 自定义 - + Archive 归档 - + Templates 模板 - + Trash 回收站 - - + + Novel Document 小说文档 - - + + Project Note 项目笔记 - + Root Folder 根文件夹 - + Folder 文件夹 - + Novel Title Page 小说标题页 - + Novel Chapter 小说章节 - + Novel Scene 小说场景 - + Novel Section 小说章节 - + Active 活跃 - + Inactive 非活跃 - + Tag 标签 - + Point of View 视角 - - + + Focus 聚焦 - + Story 故事 - + Mentions 提及 - + Level 登记 - + Document 文档 - + Line - + Status 状态 - + Chars 字母 - + Words 单词 - + Pars 段落 - + POV 视角 - + Synopsis 概要 - + Open Document (.odt) 打开文档 (.odt) - + Flat Open Document (.fodt) Flat Open Document (.fodt) - + Microsoft Word Document (.docx) Microsoft Word 文档 (.docx) - + HTML 5 (.html) HTML 5 (.html) - + novelWriter Markup (.txt) novelWriter Markdown (.nwd) - + Standard Markdown (.md) Standard Markdown (.md) - + Extended Markdown (.md) Standard Markdown (.md) - + Portable Document Format (.pdf) 便携文档格式 (.pdf) - + JSON + HTML 5 (.json) JSON + HTML 5 (.json) - + JSON + novelWriter Markup (.json) JSON + NovelWriter Markdown (.json) - + Square 正方形 - + Triangle 三角形 - + Nabla 倒三角形 - + Diamond 菱形 - + Pentagon 五边形 - + Hexagon 六边形 - + Star 星形 - + Pacman 吃豆人形 - + 1/4 Circle 1/4 圆 - + Half Circle 半圆 - + 3/4 Circle 3/4 圈 - + Full Circle 圆形 - + 1 Bar 1 条 - + 2 Bars 2 条 - + 3 Bars 3 条 - + 4 Bars 4 条 - + 1 Block 1 块 - + 2 Blocks 2 块 - + 3 Blocks 3 块 - + 4 Blocks 4 块 - + Text files 文本文件 - + Markdown files Markdown 文件 - + novelWriter files novelWriter 文件 - + CSV files CSV 文件 - + All files 所有文件 - + Millimetres 毫米 - + Centimetres 厘米 - + Inches 英寸 - + A4 A4 - + A5 A5 - + A6 A6 - + US Legal 美国法律格式 - + US Letter 美国信件 - + Theme Colours 主题颜色 - + Foreground Colour 前景颜色 - + Faded Colour 淡出颜色 - + Red 红色 - + Orange 橙色 - + Yellow 黄色 - + Green 绿色 - + Aqua 青色 - + Blue 蓝色 - + Purple 紫色 - + Straight single quotation mark 单引号 - + Straight double quotation mark 双引号 - + Left single quotation mark 左单引号标记 - + Right single quotation mark 右单引号标记 - + Single low-9 quotation mark 低单引号 - + Single high-reversed-9 quotation mark 反转的高单引号 - + Left double quotation mark 左双引号标记 - + Right double quotation mark 右双引号标记 - + Double low-9 quotation mark 低双引号 - + Double high-reversed-9 quotation mark 反转的高双引号 - + Double low-reversed-9 quotation mark 反转的低双引号 - + Single left-pointing angle quotation mark 左单角引号 - + Single right-pointing angle quotation mark 右单角引号 - + Double left-pointing angle quotation mark 左双角引号 - + Double right-pointing angle quotation mark 右双角引号 - + Left corner bracket 左角括号 - + Right corner bracket 右角括号 - + Left white corner bracket 白色左角括号 - + Right white corner bracket 白色右角括号 - + Short dash 短横杠线 - + Long dash 长横杠线 - + Horizontal bar 水平栏 @@ -1078,12 +1078,12 @@ GuiDocEditFooter - + Line: {0} ({1}) 行数: {0} ({1}) - + Selected: {0} 已选中: {0} @@ -1091,27 +1091,27 @@ GuiDocEditHeader - + Toggle Tool Bar 切换工具栏 - + Outline 提纲 - + Search 搜索 - + Toggle Focus Mode 切换聚焦模式 - + Close 关闭 @@ -1119,62 +1119,62 @@ GuiDocEditSearch - + Search for 搜索 - + Replace with 替换为 - + Search 搜索 - + Case Sensitive 大小写敏感 - + Whole Words Only 匹配整个单词 - + RegEx Mode 正则表达式模式 - + Loop Search 循环搜索 - + Search Next File 搜索下一个文件 - + Preserve Case 保留大小写 - + Close Search 关闭搜索 - + Find in current document 在当前文档中查找 - + Find and replace in current document 在当前文档中查找和替换 @@ -1232,82 +1232,82 @@ 文件位置 - + Set as Document Name 设置为文档名称 - + Open URL 打开 URL - + Follow Tag 跟随标签 - + Create Note for Tag 为标签创建笔记 - + Cut 剪贴 - + Copy 复制 - + Paste 粘贴 - + Select All 全选 - + Select Word 选定单词 - + Select Paragraph 选定段落 - + Spelling Suggestion(s) 拼写建议 - + No Suggestions 无建议 - + Ignore Word 忽略单词 - + Add Word to Dictionary 向字典中添加单词 - + Please select some text before calling replace quotes. 在替换引号之前请选择文本。 - + Do you want to create a new project note for the tag '{0}'? 您想要为标记为'{0}'创建一个新的项目说明吗? @@ -1391,52 +1391,52 @@ GuiDocToolBar - + Markdown Bold Markdown加粗 - + Markdown Italic Markdown斜体 - + Markdown Strikethrough Markdown 删除线 - + Shortcode Bold Shortcode 加粗 - + Shortcode Italic Shortcode斜体 - + Shortcode Strikethrough Shortcode删除线 - + Shortcode Underline Shortcode下划线 - + Shortcode Highlight 短代码高亮 - + Shortcode Superscript Shortcode上标 - + Shortcode Subscript Shortcode下标 @@ -4281,67 +4281,67 @@ Stats - + Characters 字符数 - + Characters in Text 文本中的字符 - + Characters in Headings 标题中的字符 - + Paragraphs 段落 - + Headings 标题 - + Characters, No Spaces 字符,无空格 - + Characters in Text, No Spaces 文本中的字符,无空格 - + Characters in Headings, No Spaces 标题中的字符,无空格 - + Words 单词 - + Words in Text 文本中的单词 - + Words in Headings 标题中的单词 - + Characters: {0} ({1}) 字符: {0} ({1}) - + Words: {0} ({1}) 单词: {0} ({1}) diff --git a/novelwriter/assets/i18n/project_cs_CZ.json b/novelwriter/assets/i18n/project_cs_CZ.json index 9281da8f..207a8432 100644 --- a/novelwriter/assets/i18n/project_cs_CZ.json +++ b/novelwriter/assets/i18n/project_cs_CZ.json @@ -3,6 +3,8 @@ "Short Description": "Krátký popis", "Footnotes": "Poznámky pod čarou", "Comment": "Komentář", + "Story Structure": "Struktura příběhu", + "Note": "Poznámka", "Notes": "Poznámka", "Tag": "Štítek", "Point of View": "Úhel pohledu", From e3981aad60f4a433d17d8597070eadab71182754 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:06:14 +0200 Subject: [PATCH 15/19] Update changelog --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b578fb..14397c74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # novelWriter Changelog +## Version 2.7.1 [2025-06-10] + +### Release Notes + +This is a patch release that fixes some issues with tags and references, and issue with the +auto-complete menu on Windows, and issues with the AppImage on Linux. The Czech translation for +2.7 has been completed. + +### Detailed Changelog + +**Bugfixes** + +* Fix a bug where tags would be listed in the auto-complete menu for mentions even if the file + defining it had been moved to Archive or Trash. Issue #2387. PR #2389. +* Fixed a bug that seems to only have occurred on Windows where the auto-complete menu would hold + on to the return and arrow keys even when it was hidden. Issue #2386. PR #2389. + +**Improvements** + +* The auto-complete menu in the editor no longer shows any suggestions when defining the tag. + This never made sense anyway. PR #2389. + +**Packaging** + +* Fixed an issue with the AppImage release where on some platforms `libxcb-cursor0` was missing. + The library is now included in the AppImage. Issue #2374. PR #2392. + +---- + ## Version 2.7 [2025-06-01] ### Release Notes From 7d53c4a06b29f585bc18b1a802615209d4a58c84 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:08:09 +0200 Subject: [PATCH 16/19] Extend changelog and fix release date --- CHANGELOG.md | 6 +++++- novelwriter/__init__.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14397c74..7c4e22f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # novelWriter Changelog -## Version 2.7.1 [2025-06-10] +## Version 2.7.1 [2025-06-09] ### Release Notes @@ -22,6 +22,10 @@ auto-complete menu on Windows, and issues with the AppImage on Linux. The Czech * The auto-complete menu in the editor no longer shows any suggestions when defining the tag. This never made sense anyway. PR #2389. +**Internationalisation** + +* Updated the Czech. PR #2393. + **Packaging** * Fixed an issue with the AppImage release where on some platforms `libxcb-cursor0` was missing. diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index dcabc0b6..594dc30c 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -51,7 +51,7 @@ __maintainer__ = "Veronica Berglyd Olsen" __email__ = "code@vkbo.net" __version__ = "2.7.1" __hexversion__ = "0x020701f0" -__date__ = "2025-06-10" +__date__ = "2025-06-09" __status__ = "Stable" __domain__ = "novelwriter.io" From 635493f1c18de03791a6682fe09a4e1614a864ba Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:42:34 +0200 Subject: [PATCH 17/19] Post release updates and AppImage fix --- .github/workflows/build_linux.yml | 2 +- CHANGELOG.md | 6 +++--- utils/build_debian.py | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index cbca61c8..9c38f29e 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -8,7 +8,7 @@ jobs: buildLinux-AppImage: needs: buildAssets - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 env: PYTHON_VERSION: "3.13" LINUX_TAG: "manylinux_2_28" diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c4e22f3..455d9449 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,9 @@ ### Release Notes -This is a patch release that fixes some issues with tags and references, and issue with the -auto-complete menu on Windows, and issues with the AppImage on Linux. The Czech translation for -2.7 has been completed. +This is a patch release that fixes some issues with tags and references, an issue with the +auto-complete menu on Windows, and some issues with the AppImage on Linux. The Czech translation +for 2.7 has also been completed. ### Detailed Changelog diff --git a/utils/build_debian.py b/utils/build_debian.py index ea08e705..35b3603f 100644 --- a/utils/build_debian.py +++ b/utils/build_debian.py @@ -185,6 +185,7 @@ def launchpad(args: argparse.Namespace) -> None: ("24.04", "noble"), ("24.10", "oracular"), ("25.04", "plucky"), + ("25.10", "questing"), ] print("Building Ubuntu packages for:") From d61329a4f343bd8bb5c125846179b2475e4e36c0 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 10 Jun 2025 00:08:48 +0200 Subject: [PATCH 18/19] Improve build code --- .github/workflows/build_linux.yml | 2 ++ utils/build_debian.py | 7 +++--- utils/build_windows.py | 25 ++++-------------- utils/common.py | 42 +++++++++++++++---------------- utils/docs.py | 6 ++--- 5 files changed, 34 insertions(+), 48 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 9c38f29e..64f13d21 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -8,6 +8,8 @@ jobs: buildLinux-AppImage: needs: buildAssets + # Needs to stay on 22.04 as long as we're using manylinux_2_28 + # as libxcb-cursor0 in 22.04 supports glibc >= 2.17 runs-on: ubuntu-22.04 env: PYTHON_VERSION: "3.13" diff --git a/utils/build_debian.py b/utils/build_debian.py index 35b3603f..4835ec86 100644 --- a/utils/build_debian.py +++ b/utils/build_debian.py @@ -24,12 +24,11 @@ import argparse import datetime import email.utils import shutil -import subprocess import sys from utils.common import ( ROOT_DIR, SETUP_DIR, checkAssetsExist, copyPackageFiles, copySourceCode, - extractVersion, makeCheckSum, toUpload, writeFile + extractVersion, makeCheckSum, systemCall, toUpload, writeFile ) SIGN_KEY = "D6A9F6B8F227CF7C6F6D1EE84DBBE4B734B0BD08" @@ -134,10 +133,10 @@ def makeDebianPackage( signArgs = [f"-k{signKey}"] if sourceBuild: - subprocess.call(["debuild", "-S", *signArgs], cwd=outDir) + systemCall(["debuild", "-S", *signArgs], cwd=outDir) toUpload(bldDir / f"{bldPkg}.tar.xz") else: - subprocess.call(["dpkg-buildpackage", *signArgs], cwd=outDir) + systemCall(["dpkg-buildpackage", *signArgs], cwd=outDir) shutil.copyfile(bldDir / f"{bldPkg}.tar.xz", bldDir / f"{bldPkg}.debian.tar.xz") toUpload(bldDir / f"{bldPkg}.debian.tar.xz") toUpload(bldDir / f"{bldPkg}_all.deb") diff --git a/utils/build_windows.py b/utils/build_windows.py index 98d5e8c2..76fdc281 100644 --- a/utils/build_windows.py +++ b/utils/build_windows.py @@ -23,7 +23,6 @@ from __future__ import annotations import argparse import compileall import shutil -import subprocess import sys import urllib.request import zipfile @@ -32,7 +31,7 @@ from pathlib import Path from utils.common import ( ROOT_DIR, SETUP_DIR, copySourceCode, extractVersion, readFile, - removeRedundantQt, writeFile + removeRedundantQt, systemCall, writeFile ) @@ -89,20 +88,11 @@ def embedPython(bldDir: Path, outDir: Path) -> None: def installRequirements(libDir: Path) -> None: """Install dependencies.""" print("Install dependencies ...") - - try: - subprocess.call([ - sys.executable, "-m", - "pip", "install", "-r", "requirements.txt", "--target", str(libDir) - ]) - except Exception as exc: - print("Failed with error:") - print(str(exc)) - sys.exit(1) - + systemCall([ + sys.executable, "-m", "pip", "install", "-r", "requirements.txt", "--target", libDir + ]) print("Done") print("") - return @@ -162,12 +152,7 @@ def main(args: argparse.Namespace) -> None: writeFile(ROOT_DIR / "setup.iss", issData) print("") - try: - subprocess.call(["iscc", "setup.iss"]) - except Exception as exc: - print("Inno Setup failed with error:") - print(str(exc)) - sys.exit(1) + systemCall(["iscc", "setup.iss"]) print("") print("Done") diff --git a/utils/common.py b/utils/common.py index 4ba82e00..1784ed01 100644 --- a/utils/common.py +++ b/utils/common.py @@ -51,11 +51,11 @@ def extractVersion(beQuiet: bool = False) -> tuple[str, str, str]: if aLine.startswith("__date__"): relDate = getValue(aLine) except Exception as exc: - print(f"Could not read file: {initFile}") - print(str(exc)) + print(f"Could not read file: {initFile}", flush=True) + print(str(exc), flush=True) if not beQuiet: - print(f"novelWriter version: {numVers} ({hexVers}) at {relDate}") + print(f"novelWriter version: {numVers} ({hexVers}) at {relDate}", flush=True) return numVers, hexVers, relDate @@ -78,16 +78,16 @@ def copySourceCode(dst: Path) -> None: for item in src.glob("**/*"): relSrc = item.relative_to(ROOT_DIR) if item.suffix in (".pyc", ".pyo"): - print("Ignored:", relSrc) + print("Ignored:", relSrc, flush=True) continue if item.parent.is_dir() and item.parent.name != "__pycache__": dstDir = dst / relSrc.parent if not dstDir.exists(): dstDir.mkdir(parents=True) - print("Created:", dstDir.relative_to(ROOT_DIR)) + print("Created:", dstDir.relative_to(ROOT_DIR), flush=True) if item.is_file(): shutil.copyfile(item, dst / relSrc) - print("Copied:", relSrc) + print("Copied:", relSrc, flush=True) return @@ -96,7 +96,7 @@ def copyPackageFiles(dst: Path, setupPy: bool = False) -> None: copyFiles = ["LICENSE.md", "CREDITS.md", "pyproject.toml"] for copyFile in copyFiles: shutil.copyfile(copyFile, dst / copyFile) - print("Copied:", copyFile) + print("Copied:", copyFile, flush=True) writeFile(dst / "MANIFEST.in", ( "include LICENSE.md\n" @@ -137,10 +137,10 @@ def makeCheckSum(sumFile: str, cwd: Path | None = None) -> str: shaFile = cwd / f"{sumFile}.sha256" with open(shaFile, mode="w", encoding="utf-8") as fOut: subprocess.call(["shasum", "-a", "256", sumFile], stdout=fOut, cwd=cwd) - print(f"SHA256 Sum: {shaFile}") + print(f"SHA256 Sum: {shaFile}", flush=True) except Exception as exc: - print("Could not generate sha256 file") - print(str(exc)) + print("Could not generate sha256 file", flush=True) + print(str(exc), flush=True) return "" return str(shaFile) @@ -154,17 +154,17 @@ def checkAssetsExist() -> bool: sampleZip = ROOT_DIR / "novelwriter" / "assets" / "sample.zip" if sampleZip.is_file(): - print(f"Found: {sampleZip}") + print(f"Found: {sampleZip}", flush=True) hasSample = True pdfManual = ROOT_DIR / "novelwriter" / "assets" / "manual.pdf" if pdfManual.is_file(): - print(f"Found: {pdfManual}") + print(f"Found: {pdfManual}", flush=True) hasManual = True i18nAssets = ROOT_DIR / "novelwriter" / "assets" / "i18n" if len(list(i18nAssets.glob("*.qm"))) > 0: - print(f"Found: {i18nAssets}/*.qm") + print(f"Found: {i18nAssets}/*.qm", flush=True) hasQmData = True return hasSample and hasManual and hasQmData @@ -187,29 +187,29 @@ def readFile(file: Path) -> str: def writeFile(file: Path, text: str) -> int: """Write string to file.""" result = file.write_text(text, encoding="utf-8") - print("Wrote:", file.relative_to(ROOT_DIR)) + print("Wrote:", file.relative_to(ROOT_DIR), flush=True) return result def freshFolder(path: Path) -> None: """Make sure a folder exists and is empty.""" if path.exists(): - print("Removing:", str(path)) + print("Removing:", str(path), flush=True) shutil.rmtree(path) path.mkdir() return -def systemCall(cmd: list, cwd: Path | str | None = None, env: dict | None = None) -> None: +def systemCall(cmd: list, cwd: Path | str | None = None, env: dict | None = None) -> int: """Make a system call using subprocess.""" if isinstance(cwd, Path): cwd = str(cwd) try: - subprocess.call([str(c) for c in cmd], cwd=cwd, env=env) + code = subprocess.call([str(c) for c in cmd], cwd=cwd, env=env) except Exception as exc: - print("ERROR:", str(exc)) + print("ERROR:", str(exc), flush=True) sys.exit(1) - return + return code def removeRedundantQt(qtBase: Path) -> None: @@ -218,12 +218,12 @@ def removeRedundantQt(qtBase: Path) -> None: def unlinkIfFound(file: Path) -> None: if file.is_file(): file.unlink() - print("Deleted:", file.relative_to(ROOT_DIR)) + print("Deleted:", file.relative_to(ROOT_DIR), flush=True) def deleteFolder(folder: Path) -> None: if folder.is_dir(): shutil.rmtree(folder) - print("Deleted:", folder.relative_to(ROOT_DIR)) + print("Deleted:", folder.relative_to(ROOT_DIR), flush=True) def unlinkIfPrefix(folder: Path, prefix: tuple[str, ...]) -> None: if folder.is_dir(): diff --git a/utils/docs.py b/utils/docs.py index c43d3f37..7a4de94b 100644 --- a/utils/docs.py +++ b/utils/docs.py @@ -25,7 +25,7 @@ import os import shutil import subprocess -from utils.common import ROOT_DIR +from utils.common import ROOT_DIR, systemCall def updateDocsTranslationSources(args: argparse.Namespace) -> None: @@ -40,7 +40,7 @@ def updateDocsTranslationSources(args: argparse.Namespace) -> None: locsDir.mkdir(exist_ok=True) print("Generating POT Files") - subprocess.call(["make", "gettext"], cwd=docsDir) + systemCall(["make", "gettext"], cwd=docsDir) print("") lang = args.lang @@ -55,7 +55,7 @@ def updateDocsTranslationSources(args: argparse.Namespace) -> None: print("") for code in update: - subprocess.call(["sphinx-intl", "update", "-p", "build/gettext", "-l", code], cwd=docsDir) + systemCall(["sphinx-intl", "update", "-p", "build/gettext", "-l", code], cwd=docsDir) print("") print("Done") From 8c38bece3a62941db2f5df42bd877d1116df641d Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 10 Jun 2025 00:09:04 +0200 Subject: [PATCH 19/19] Update license setting in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0fb42595..8375e9b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ ] description = "A plain text editor for planning and writing novels" readme = {file = "setup/description_pypi.md", content-type = "text/markdown"} -license = {text = "GNU General Public License v3"} +license = "GPL-3.0" classifiers = [ "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10",