diff --git a/.github/workflows/build_assets.yml b/.github/workflows/build_assets.yml index 2889ae5d..ec9258df 100644 --- a/.github/workflows/build_assets.yml +++ b/.github/workflows/build_assets.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v4 - name: Install Packages (pip) - run: pip install -r docs/source/requirements.txt + run: pip install -r docs/requirements.txt - name: Build Assets run: | diff --git a/.gitignore b/.gitignore index fd69c45f..9a71bb71 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,9 @@ i18n/*.qph # Documentation /docs/build/ +/docs/source/locales/**/*.mo /novelwriter/assets/help/ -/novelwriter/assets/manual.pdf +/novelwriter/assets/manual*.pdf *.qch *.qhc .~lock.* diff --git a/docs/source/requirements.txt b/docs/requirements.txt similarity index 88% rename from docs/source/requirements.txt rename to docs/requirements.txt index ad8c84ca..4ccbc91e 100644 --- a/docs/source/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,7 @@ -sphinx-book-theme -sphinx>=5.0 -sphinx-favicon -sphinx-design -pygments>=2.7 docutils>=0.17.1 +pygments>=2.7 +sphinx-book-theme +sphinx-design +sphinx-favicon +sphinx-intl +sphinx>=5.0 diff --git a/docs/source/conf.py b/docs/source/conf.py index 72ddad50..9162893d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -5,15 +5,20 @@ Documentation: http://www.sphinx-doc.org/en/master/config # -- Imports ----------------------------------------------------------------- +import datetime import os import time -import datetime # -- Project Information ----------------------------------------------------- project = "novelWriter" copyright = f"{datetime.date.today().year}" -author = "Veronica Berglyd Olsen" + +tmp_authors = ["Veronica Berglyd Olsen"] +if additional := os.environ.get("SPHINX_I18N_AUTHORS"): + tmp_authors.extend(a.strip() for a in additional.split(",")) + +author = ", ".join(tmp_authors) initFile = os.path.join( os.path.dirname(__file__), os.pardir, os.pardir, @@ -41,6 +46,8 @@ source_suffix = ".rst" master_doc = "index" today_fmt = "%A, %d %B %Y at %H:%M" language = "en" +locale_dirs = ["locales/"] +gettext_compact = False exclude_patterns = [] # -- Options for HTML Output ------------------------------------------------- @@ -80,5 +87,5 @@ latex_elements = { } latex_logo = "_static/novelwriter-pdf.png" latex_documents = [( - master_doc, "manual.tex", "User Guide", author, "manual" + master_doc, "manual.tex", None, author, "manual" )] diff --git a/docs/source/index.rst b/docs/source/index.rst index c10ea5e9..d472746b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,6 +1,6 @@ -###################### -novelWriter User Guide -###################### +########## +User Guide +########## | **Release Version:** |release| | **Updated:** |today| diff --git a/docs/source/locales/authors_fr.conf b/docs/source/locales/authors_fr.conf new file mode 100644 index 00000000..08eaa7d9 --- /dev/null +++ b/docs/source/locales/authors_fr.conf @@ -0,0 +1,2 @@ +# French translation authors, one name per line +Karduin diff --git a/docs/source/tech_source.rst b/docs/source/tech_source.rst index ad3d07c9..93521416 100644 --- a/docs/source/tech_source.rst +++ b/docs/source/tech_source.rst @@ -138,7 +138,7 @@ packages from PyPi: .. code-block:: bash - pip install -r docs/source/requirements.txt + pip install -r docs/requirements.txt The documentation can then be built from the root folder in the source code by running: diff --git a/novelwriter/assets/manual_fr_FR.pdf b/novelwriter/assets/manual_fr_FR.pdf deleted file mode 100644 index b2ee5e21..00000000 Binary files a/novelwriter/assets/manual_fr_FR.pdf and /dev/null differ diff --git a/pkgutils.py b/pkgutils.py index 794ce640..240faa94 100755 --- a/pkgutils.py +++ b/pkgutils.py @@ -202,6 +202,24 @@ if __name__ == "__main__": ) cmdBuildQM.set_defaults(func=utils.assets.buildTranslationAssets) + # Update Docs i18n Sources + cmdUpdateDocsPo = parsers.add_parser( + "docs-lupdate", help=( + "Update translation files for internationalisation of the docs. " + "The langauges to be updated can be added as arguments, " + "or set to all to update all existing translations." + ) + ) + cmdUpdateDocsPo.add_argument("lang", nargs="+") + cmdUpdateDocsPo.set_defaults(func=utils.assets.updateDocsTranslationSources) + + # Build Docs i18n Files + cmdBuildU18nDocs = parsers.add_parser( + "docs-lrelease", help="Build the translated PDF manual files." + ) + cmdBuildU18nDocs.add_argument("lang", nargs="+") + cmdBuildU18nDocs.set_defaults(func=utils.assets.buildDocsTranslationAssets) + # Build Manual cmdBuildManual = parsers.add_parser( "manual", help="Build the help documentation as a PDF (requires LaTeX)." diff --git a/setup/make_pip.sh b/setup/make_pip.sh index 6ddf21bc..0521a7ff 100755 --- a/setup/make_pip.sh +++ b/setup/make_pip.sh @@ -17,7 +17,7 @@ if [ ! -d $ENVPATH ]; then python3 -m venv $ENVPATH fi source $ENVPATH/bin/activate -pip3 install -r docs/source/requirements.txt +pip3 install -r docs/requirements.txt python3 pkgutils.py build-assets deactivate diff --git a/setup/make_release.sh b/setup/make_release.sh index 5dd543ee..b46ec49e 100755 --- a/setup/make_release.sh +++ b/setup/make_release.sh @@ -16,7 +16,7 @@ if [ ! -d $ENVPATH ]; then python3 -m venv $ENVPATH fi source $ENVPATH/bin/activate -pip3 install -r docs/source/requirements.txt +pip3 install -r docs/requirements.txt python3 pkgutils.py build-assets deactivate diff --git a/utils/assets.py b/utils/assets.py index b9512dfc..840160cd 100644 --- a/utils/assets.py +++ b/utils/assets.py @@ -21,12 +21,15 @@ along with this program. If not, see . from __future__ import annotations import argparse +import os import subprocess import sys import zipfile from pathlib import Path +from PyQt6.QtCore import QLocale + from utils.common import ROOT_DIR, writeFile @@ -248,6 +251,82 @@ def buildTranslationAssets(args: argparse.Namespace | None = None) -> None: return +def updateDocsTranslationSources(args: argparse.Namespace) -> None: + """Build the documentation .po files.""" + print("") + print("Building Docs Translation Files") + print("===============================") + print("") + + docsDir = ROOT_DIR / "docs" + locsDir = ROOT_DIR / "docs" / "source" / "locales" + locsDir.mkdir(exist_ok=True) + + print("Generating POT Files") + subprocess.call(["make", "gettext"], cwd=docsDir) + print("") + + lang = args.lang + update = [] + if lang == ["all"]: + update = [i.stem for i in locsDir.iterdir() if i.is_dir()] + else: + update = lang + + print("Generating PO Files") + print("Languages: ", update) + print("") + + for code in update: + subprocess.call(["sphinx-intl", "update", "-p", "build/gettext", "-l", code], cwd=docsDir) + print("") + + print("Done") + print("") + + return + + +def buildDocsTranslationAssets(args: argparse.Namespace | None = None) -> None: + """Build the documentation i18n PDF files.""" + print("") + print("Building Docs Manuals") + print("=====================") + print("") + + docsDir = ROOT_DIR / "docs" + locsDir = ROOT_DIR / "docs" / "source" / "locales" + pdfFile = ROOT_DIR / "docs" / "build" / "latex" / "manual.pdf" + locsDir.mkdir(exist_ok=True) + + lang = args.lang + build = [] + if lang == ["all"]: + build = [i.stem for i in locsDir.iterdir() if i.is_dir()] + else: + build = lang + + for code in build: + data = (locsDir / f"authors_{code}.conf").read_text(encoding="utf-8") + authors = [x for x in data.splitlines() if x and not x.startswith("#")] + env = os.environ.copy() + env["SPHINX_I18N_AUTHORS"] = ", ".join(authors) + exCode = subprocess.call( + f"make -e SPHINXOPTS=\"-D language='{code}'\" clean latexpdf", + cwd=docsDir, env=env, shell=True + ) + if exCode == 0: + print("") + name = f"manual_{QLocale(code).name()}.pdf" + pdfFile.rename(ROOT_DIR / "novelwriter" / "assets" / name) + else: + raise Exception(f"Build returned error code {exCode}") + + print("") + + return + + def cleanBuiltAssets(args: argparse.Namespace | None = None) -> None: """Remove assets built by this script.""" print("")