squirrel-battle/squirrelbattle/translations.py

108 lines
3.8 KiB
Python
Raw Permalink Normal View History

2021-01-10 09:46:17 +00:00
# Copyright (C) 2020-2021 by ÿnérant, eichhornchen, nicomarg, charlse
2020-11-27 19:32:40 +00:00
# SPDX-License-Identifier: GPL-3.0-or-later
2020-11-28 00:59:52 +00:00
import gettext as gt
2020-11-28 02:21:20 +00:00
import os
2021-01-10 10:25:53 +00:00
from pathlib import Path
import re
import subprocess
2020-11-28 00:59:52 +00:00
from typing import Any, List
class Translator:
"""
This module uses gettext to translate strings.
Translator.setlocale defines the language of the strings,
then gettext() translates the messages.
2020-11-28 00:59:52 +00:00
"""
2020-12-07 00:01:39 +00:00
SUPPORTED_LOCALES: List[str] = ["de", "en", "es", "fr"]
2020-11-28 00:59:52 +00:00
locale: str = "en"
translators: dict = {}
@classmethod
def refresh_translations(cls) -> None:
"""
Loads compiled translations.
"""
for language in cls.SUPPORTED_LOCALES:
rep = Path(__file__).parent / "locale" / language / "LC_MESSAGES"
rep.mkdir(parents=True) if not rep.is_dir() else None
if os.path.isfile(rep / "squirrelbattle.mo"):
cls.translators[language] = gt.translation(
"squirrelbattle",
localedir=Path(__file__).parent / "locale",
languages=[language],
)
2020-11-28 00:59:52 +00:00
@classmethod
def setlocale(cls, lang: str) -> None:
"""
Defines the language used to translate the game.
2020-11-28 00:59:52 +00:00
The language must be supported, otherwise nothing is done.
"""
lang = lang[:2]
if lang in cls.SUPPORTED_LOCALES:
cls.locale = lang
@classmethod
def get_translator(cls) -> Any:
return cls.translators.get(cls.locale, gt.NullTranslations())
2020-11-27 19:32:40 +00:00
@classmethod
2020-11-28 02:04:28 +00:00
def makemessages(cls) -> None: # pragma: no cover
"""
Analyses all strings in the project and extracts them.
"""
for language in cls.SUPPORTED_LOCALES:
if language == "en":
# Don't translate the main language
continue
2020-11-28 02:21:20 +00:00
file_name = Path(__file__).parent / "locale" / language \
/ "LC_MESSAGES" / "squirrelbattle.po"
2020-11-28 02:04:28 +00:00
args = ["find", "squirrelbattle", "-iname", "*.py"]
find = subprocess.Popen(args, cwd=Path(__file__).parent.parent,
stdout=subprocess.PIPE)
args = ["xargs", "xgettext", "--from-code", "utf-8",
"--add-comments",
"--package-name=squirrelbattle",
2021-01-10 22:57:39 +00:00
"--package-version=23.14",
"--copyright-holder=ÿnérant, eichhornchen, "
2020-12-07 00:01:39 +00:00
"nicomarg, charlse, ifugao",
"--msgid-bugs-address=squirrel-battle@crans.org",
"--sort-by-file",
2020-11-28 02:21:20 +00:00
"-o", file_name]
if file_name.is_file():
args.append("--join-existing")
with open(file_name, "r") as f:
content = f.read()
with open(file_name, "w") as f:
f.write(re.sub("#:.*\n", "", content))
print(f"Make {language} messages...")
subprocess.Popen(args, stdin=find.stdout).wait()
@classmethod
def compilemessages(cls) -> None:
"""
Compiles translation messages from source files.
"""
for language in cls.SUPPORTED_LOCALES:
if language == "en":
continue
args = ["msgfmt", "--check-format",
2020-11-28 02:04:28 +00:00
"-o", Path(__file__).parent / "locale" / language
/ "LC_MESSAGES" / "squirrelbattle.mo",
Path(__file__).parent / "locale" / language
/ "LC_MESSAGES" / "squirrelbattle.po"]
print(f"Compiling {language} messages...")
subprocess.Popen(args).wait()
2020-11-27 19:32:40 +00:00
def gettext(message: str) -> str:
2020-11-28 00:59:52 +00:00
"""
Translates a message.
2020-11-28 00:59:52 +00:00
"""
return Translator.get_translator().gettext(message)
Translator.refresh_translations()