Merge branch 'translations' into 'master'
Translations Closes #14 See merge request ynerant/squirrel-battle!31
This commit is contained in:
commit
e5886bbe44
|
@ -23,3 +23,6 @@ save.json
|
||||||
|
|
||||||
# Don't commit docs output
|
# Don't commit docs output
|
||||||
docs/_build
|
docs/_build
|
||||||
|
|
||||||
|
# Don't commit compiled messages
|
||||||
|
*.mo
|
||||||
|
|
|
@ -7,6 +7,7 @@ py37:
|
||||||
stage: test
|
stage: test
|
||||||
image: python:3.7-alpine
|
image: python:3.7-alpine
|
||||||
before_script:
|
before_script:
|
||||||
|
- apk add --no-cache gettext
|
||||||
- pip install tox
|
- pip install tox
|
||||||
script: tox -e py3
|
script: tox -e py3
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ py38:
|
||||||
stage: test
|
stage: test
|
||||||
image: python:3.8-alpine
|
image: python:3.8-alpine
|
||||||
before_script:
|
before_script:
|
||||||
|
- apk add --no-cache gettext
|
||||||
- pip install tox
|
- pip install tox
|
||||||
script: tox -e py3
|
script: tox -e py3
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ py39:
|
||||||
stage: test
|
stage: test
|
||||||
image: python:3.9-alpine
|
image: python:3.9-alpine
|
||||||
before_script:
|
before_script:
|
||||||
|
- apk add --no-cache gettext
|
||||||
- pip install tox
|
- pip install tox
|
||||||
script: tox -e py3
|
script: tox -e py3
|
||||||
|
|
||||||
|
@ -37,7 +40,7 @@ build-deb:
|
||||||
image: debian:buster-slim
|
image: debian:buster-slim
|
||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script:
|
||||||
- apt-get update && apt-get -y --no-install-recommends install build-essential debmake dh-python debhelper python3-all python3-setuptools
|
- apt-get update && apt-get -y --no-install-recommends install build-essential debmake dh-python debhelper gettext python3-all python3-setuptools
|
||||||
script:
|
script:
|
||||||
- dpkg-buildpackage
|
- dpkg-buildpackage
|
||||||
- mkdir build && cp ../*.deb build/
|
- mkdir build && cp ../*.deb build/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
python3-squirrel-battle (3.14) beta; urgency=low
|
python3-squirrel-battle (3.14.1) beta; urgency=low
|
||||||
|
|
||||||
* Some graphical improvements.
|
* Some graphical improvements.
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ Source: python3-squirrel-battle
|
||||||
Section: devel
|
Section: devel
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: ynerant <squirrel-battle@crans.org>
|
Maintainer: ynerant <squirrel-battle@crans.org>
|
||||||
Build-Depends: debhelper (>=10~), dh-python, python3-all, python3-setuptools
|
Build-Depends: debhelper (>=10~), dh-python, gettext, python3-all, python3-setuptools
|
||||||
Depends: fonts-noto-color-emoji
|
Depends: fonts-noto-color-emoji
|
||||||
Standards-Version: 4.1.4
|
Standards-Version: 4.1.4
|
||||||
Homepage: https://gitlab.crans.org/ynerant/squirrel-battle
|
Homepage: https://gitlab.crans.org/ynerant/squirrel-battle
|
||||||
|
|
|
@ -34,6 +34,16 @@ paquet ainsi que des détails à fournir à PyPI :
|
||||||
with open("README.md", "r") as f:
|
with open("README.md", "r") as f:
|
||||||
long_description = f.read()
|
long_description = f.read()
|
||||||
|
|
||||||
|
# Compile messages
|
||||||
|
for language in ["de", "en", "fr"]:
|
||||||
|
args = ["msgfmt", "--check-format",
|
||||||
|
"-o", f"squirrelbattle/locale/{language}/LC_MESSAGES"
|
||||||
|
"/squirrelbattle.mo",
|
||||||
|
f"squirrelbattle/locale/{language}/LC_MESSAGES"
|
||||||
|
"/squirrelbattle.po"]
|
||||||
|
print(f"Compiling {language} messages...")
|
||||||
|
subprocess.Popen(args)
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="squirrel-battle",
|
name="squirrel-battle",
|
||||||
version="3.14.1",
|
version="3.14.1",
|
||||||
|
@ -60,7 +70,7 @@ paquet ainsi que des détails à fournir à PyPI :
|
||||||
],
|
],
|
||||||
python_requires='>=3.6',
|
python_requires='>=3.6',
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
package_data={"squirrelbattle": ["assets/*"]},
|
package_data={"squirrelbattle": ["assets/*", "locale/*/*/*.mo"]},
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"squirrel-battle = squirrelbattle.bootstrap:Bootstrap.run_game",
|
"squirrel-battle = squirrelbattle.bootstrap:Bootstrap.run_game",
|
||||||
|
@ -72,6 +82,8 @@ Ce fichier contient le nom du paquet, sa version, l'auteur et son contact,
|
||||||
sa description en une ligne et sa description longue, le lien d'accueil du projet,
|
sa description en une ligne et sa description longue, le lien d'accueil du projet,
|
||||||
sa licence, ses classificateurs et son exécutable.
|
sa licence, ses classificateurs et son exécutable.
|
||||||
|
|
||||||
|
Il commence tout d'abord par compiler les fichiers de `traduction <translation.html>`_.
|
||||||
|
|
||||||
Le paramètre ``entry_points`` définit un exécutable nommé ``squirrel-battle``,
|
Le paramètre ``entry_points`` définit un exécutable nommé ``squirrel-battle``,
|
||||||
qui permet de lancer le jeu.
|
qui permet de lancer le jeu.
|
||||||
|
|
||||||
|
@ -167,7 +179,7 @@ du dépôt Git. Le fichier ``PKGBUILD`` dispose de cette structure :
|
||||||
url="https://gitlab.crans.org/ynerant/squirrel-battle"
|
url="https://gitlab.crans.org/ynerant/squirrel-battle"
|
||||||
license=('GPLv3')
|
license=('GPLv3')
|
||||||
depends=('python')
|
depends=('python')
|
||||||
makedepends=('python-setuptools')
|
makedepends=('gettext' 'python-setuptools')
|
||||||
depends=('noto-fonts-emoji')
|
depends=('noto-fonts-emoji')
|
||||||
checkdepends=('python-tox')
|
checkdepends=('python-tox')
|
||||||
ssource=("git+https://gitlab.crans.org/ynerant/squirrel-battle.git")
|
ssource=("git+https://gitlab.crans.org/ynerant/squirrel-battle.git")
|
||||||
|
@ -217,7 +229,7 @@ les releases, est plus ou moins similaire :
|
||||||
url="https://gitlab.crans.org/ynerant/squirrel-battle"
|
url="https://gitlab.crans.org/ynerant/squirrel-battle"
|
||||||
license=('GPLv3')
|
license=('GPLv3')
|
||||||
depends=('python')
|
depends=('python')
|
||||||
makedepends=('python-setuptools')
|
makedepends=('gettext' 'python-setuptools')
|
||||||
depends=('noto-fonts-emoji')
|
depends=('noto-fonts-emoji')
|
||||||
checkdepends=('python-tox')
|
checkdepends=('python-tox')
|
||||||
source=("https://gitlab.crans.org/ynerant/squirrel-battle/-/archive/v3.14.1/$pkgbase-v$pkgver.tar.gz")
|
source=("https://gitlab.crans.org/ynerant/squirrel-battle/-/archive/v3.14.1/$pkgbase-v$pkgver.tar.gz")
|
||||||
|
@ -296,7 +308,7 @@ D'abord on installe les paquets nécessaires :
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
apt update
|
apt update
|
||||||
apt --no-install-recommends install build-essential debmake dh-python debhelper python3-all python3-setuptools
|
apt --no-install-recommends install build-essential debmake dh-python debhelper gettext python3-all python3-setuptools
|
||||||
|
|
||||||
On peut ensuite construire le paquet :
|
On peut ensuite construire le paquet :
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ Bienvenue dans la documentation de Squirrel Battle !
|
||||||
install-dev
|
install-dev
|
||||||
tests
|
tests
|
||||||
display/index
|
display/index
|
||||||
|
translation
|
||||||
deployment
|
deployment
|
||||||
documentation
|
documentation
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
Installation d'un environnement de développement
|
Installation d'un environnement de développement
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
Il est toujours préférable de travailler dans un environnement Python isolé du reste de son instalation.
|
Il est toujours préférable de travailler dans un environnement Python isolé du
|
||||||
|
reste de son instalation.
|
||||||
|
|
||||||
1. **Installation des dépendances de la distribution.**
|
1. **Installation des dépendances de la distribution.**
|
||||||
Vous devez déjà installer Python et le module qui permet de créer des environnements virtuels.
|
Vous devez déjà installer Python et le module qui permet de créer des
|
||||||
On donne ci-dessous l'exemple pour une distribution basée sur Debian, mais vous pouvez facilement adapter pour ArchLinux ou autre.
|
environnements virtuels.
|
||||||
|
On donne ci-dessous l'exemple pour une distribution basée sur Debian,
|
||||||
|
mais vous pouvez facilement adapter pour ArchLinux ou autre.
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
$ sudo apt update
|
$ sudo apt update
|
||||||
$ sudo apt install --no-install-recommends -y python3-setuptools python3-venv python3-dev git
|
$ sudo apt install --no-install-recommends -y python3-setuptools python3-venv python3-dev gettext git
|
||||||
|
|
||||||
2. **Clonage du dépot** là où vous voulez :
|
2. **Clonage du dépot** là où vous voulez :
|
||||||
|
|
||||||
|
@ -25,7 +28,13 @@ Il est toujours préférable de travailler dans un environnement Python isolé d
|
||||||
|
|
||||||
$ python3 -m venv env
|
$ python3 -m venv env
|
||||||
$ source env/bin/activate # entrer dans l'environnement
|
$ source env/bin/activate # entrer dans l'environnement
|
||||||
(env)$ pip3 install -r requirements.txt
|
(env) $ pip3 install -r requirements.txt
|
||||||
(env)$ deactivate # sortir de l'environnement
|
(env) $ deactivate # sortir de l'environnement
|
||||||
|
|
||||||
|
4. **Compilation des messages de traduction.**
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
(env) $ python3 main.py --compilemessages
|
||||||
|
|
||||||
Le lancement du jeu se fait en lançant la commande ``python3 main.py``.
|
Le lancement du jeu se fait en lançant la commande ``python3 main.py``.
|
|
@ -0,0 +1,120 @@
|
||||||
|
Traduction
|
||||||
|
==========
|
||||||
|
|
||||||
|
Le jeu Squirrel Battle est entièrement traduit en anglais, en français et en allement.
|
||||||
|
La langue se choisit dans les `paramètres <settings.html>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Utitisation
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Les traductions sont gérées grâce au module natif ``gettext``. Le module
|
||||||
|
``squirrelbattle.translations`` s'occupe d'installer les traductions, et de
|
||||||
|
donner les chaînes traduites.
|
||||||
|
|
||||||
|
Pour choisir la langue, il faut appeler ``Translator.setlocale(language: str)``,
|
||||||
|
où ``language`` correspond au code à 2 lettres de la langue.
|
||||||
|
|
||||||
|
Enfin, le module expose une fonction ``gettext(str) -> str`` qui permet de
|
||||||
|
traduire les chaînes.
|
||||||
|
|
||||||
|
Il est courant et recommandé d'importer cette fonction sous l'alias ``_``,
|
||||||
|
afin de limiter la verbositer et de permettre de rendre facilement une chaîne
|
||||||
|
traduisible.
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from squirrelbattle.translations import gettext as _, Translator
|
||||||
|
|
||||||
|
Translator.setlocale("fr")
|
||||||
|
print(_("I am a translatable string"))
|
||||||
|
print("I am not translatable")
|
||||||
|
|
||||||
|
Si les traductions sont bien faites (voir ci-dessous), cela donnera :
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
Je suis une chaîne traduisible
|
||||||
|
I am not translatable
|
||||||
|
|
||||||
|
À noter que si la chaîne n'est pas traduite, alors par défaut on renvoie la
|
||||||
|
chaîne elle-même.
|
||||||
|
|
||||||
|
|
||||||
|
Extraction des chaînes à traduire
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
L'appel à ``gettext`` ne fait pas que traduire les chaînes : il est possible
|
||||||
|
également d'extraire toutes les chaînes à traduire.
|
||||||
|
|
||||||
|
Il est nécessaire d'installer le paquet Linux ``gettext`` pour cela.
|
||||||
|
|
||||||
|
L'utilitaire ``xgettext`` s'occupe de cette extraction. Il s'utilise de la façon
|
||||||
|
suivante :
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
xgettext --from-code utf-8 -o output_file.po source_1.py ... source_n.py
|
||||||
|
|
||||||
|
Afin de ne pas avoir à sélectionner manuellement chaque fichier, il est possible
|
||||||
|
d'appeler directement ``python3 main.py --makemessages``. Cela a pour effet
|
||||||
|
d'exécuter pour chaque langue ``<LANG>`` :
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
find squirrelbattle -iname '*.py' | xargs xgettext --from-code utf-8
|
||||||
|
--add-comments
|
||||||
|
--package-name=squirrelbattle
|
||||||
|
--package-version=3.14.1
|
||||||
|
"--copyright-holder=ÿnérant, eichhornchen, nicomarg, charlse"
|
||||||
|
--msgid-bugs-address=squirrel-battle@crans.org
|
||||||
|
-o squirrelbattle/locale/<LANG>/LC_MESSAGES/squirrelbattle.po
|
||||||
|
|
||||||
|
Les fichiers de traductions se trouvent alors dans
|
||||||
|
``squirrelbattle/locale/<LANG>/LC_MESSAGES/squirrelbattle.po``.
|
||||||
|
|
||||||
|
|
||||||
|
Traduire les chaînes
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Après extraction des chaînes, les chaînes à traduire se trouvent dans
|
||||||
|
``squirrelbattle/locale/<LANG>/LC_MESSAGES/squirrelbattle.po``, comme indiqué
|
||||||
|
ci-dessus.
|
||||||
|
|
||||||
|
Ce fichier peut-être édité avec un utilitaire tel que ``poedit``, sur
|
||||||
|
l'interface Web sur `<https://translate.ynerant.fr/squirrel-battle/squirrel-battle>`_,
|
||||||
|
mais surtout manuellement avec un éditeur de texte.
|
||||||
|
|
||||||
|
Dans ce fichier, on obtient pour chaque chaîne à traduire un paragraphe de la
|
||||||
|
forme :
|
||||||
|
|
||||||
|
.. code:: po
|
||||||
|
|
||||||
|
#: main.py:4
|
||||||
|
msgid "I am a translatable string"
|
||||||
|
msgstr "Je suis une chaîne traduisible"
|
||||||
|
|
||||||
|
Il sufift de remplir les champs ``msgstr``.
|
||||||
|
|
||||||
|
|
||||||
|
Compilation des chaînes
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Pour gagner en efficacité, les chaînes sont compilées dans un fichier avec
|
||||||
|
l'extension ``.mo``. Ce sont ces fichiers qui sont lus par le module de traduction.
|
||||||
|
|
||||||
|
Pour compiler les traductions, c'est l'utilitaire ``msgfmt`` fourni toujours par
|
||||||
|
le paquet Linux ``gettext`` que nous utilisons. Il s'utilise assez simplement :
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
msgfmt po_file.po -o mo_file.mo
|
||||||
|
|
||||||
|
À nouveau, il est possible de compiler automatiquement les messages en exécutant
|
||||||
|
``python3 main.py --compilemessages``.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
On ne partagera pas dans le dépôt Git les fichiers compilé. En développement,
|
||||||
|
on compilera soi-même les messages, et en production, la construction des
|
||||||
|
paquets se charge de compiler automatiquement les traductions.
|
16
main.py
16
main.py
|
@ -2,8 +2,24 @@
|
||||||
|
|
||||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
from squirrelbattle.bootstrap import Bootstrap
|
from squirrelbattle.bootstrap import Bootstrap
|
||||||
|
from squirrelbattle.translations import Translator
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
parser.add_argument("--makemessages", "-mm", action="store_true",
|
||||||
|
help="Extract translatable strings")
|
||||||
|
parser.add_argument("--compilemessages", "-cm", action="store_true",
|
||||||
|
help="Compile translatable strings")
|
||||||
|
|
||||||
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
if args.makemessages:
|
||||||
|
Translator.makemessages()
|
||||||
|
elif args.compilemessages:
|
||||||
|
Translator.compilemessages()
|
||||||
|
else:
|
||||||
Bootstrap.run_game()
|
Bootstrap.run_game()
|
||||||
|
|
14
setup.py
14
setup.py
|
@ -3,13 +3,23 @@
|
||||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import os
|
import subprocess
|
||||||
|
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
with open("README.md", "r") as f:
|
with open("README.md", "r") as f:
|
||||||
long_description = f.read()
|
long_description = f.read()
|
||||||
|
|
||||||
|
# Compile messages
|
||||||
|
for language in ["de", "en", "fr"]:
|
||||||
|
args = ["msgfmt", "--check-format",
|
||||||
|
"-o", f"squirrelbattle/locale/{language}/LC_MESSAGES"
|
||||||
|
"/squirrelbattle.mo",
|
||||||
|
f"squirrelbattle/locale/{language}/LC_MESSAGES"
|
||||||
|
"/squirrelbattle.po"]
|
||||||
|
print(f"Compiling {language} messages...")
|
||||||
|
subprocess.Popen(args)
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="squirrel-battle",
|
name="squirrel-battle",
|
||||||
version="3.14.1",
|
version="3.14.1",
|
||||||
|
@ -36,7 +46,7 @@ setup(
|
||||||
],
|
],
|
||||||
python_requires='>=3.6',
|
python_requires='>=3.6',
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
package_data={"squirrelbattle": ["assets/*"]},
|
package_data={"squirrelbattle": ["assets/*", "locale/*/*/*.mo"]},
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"squirrel-battle = squirrelbattle.bootstrap:Bootstrap.run_game",
|
"squirrel-battle = squirrelbattle.bootstrap:Bootstrap.run_game",
|
||||||
|
|
|
@ -6,6 +6,7 @@ from typing import List
|
||||||
from squirrelbattle.menus import Menu, MainMenu
|
from squirrelbattle.menus import Menu, MainMenu
|
||||||
from .display import Display, Box
|
from .display import Display, Box
|
||||||
from ..resources import ResourceManager
|
from ..resources import ResourceManager
|
||||||
|
from ..translations import gettext as _
|
||||||
|
|
||||||
|
|
||||||
class MenuDisplay(Display):
|
class MenuDisplay(Display):
|
||||||
|
@ -17,8 +18,6 @@ class MenuDisplay(Display):
|
||||||
|
|
||||||
def update_menu(self, menu: Menu) -> None:
|
def update_menu(self, menu: Menu) -> None:
|
||||||
self.menu = menu
|
self.menu = menu
|
||||||
self.trueheight = len(self.values)
|
|
||||||
self.truewidth = max([len(a) for a in self.values])
|
|
||||||
|
|
||||||
# Menu values are printed in pad
|
# Menu values are printed in pad
|
||||||
self.pad = self.newpad(self.trueheight, self.truewidth + 2)
|
self.pad = self.newpad(self.trueheight, self.truewidth + 2)
|
||||||
|
@ -44,6 +43,14 @@ class MenuDisplay(Display):
|
||||||
self.height - 2 + self.y,
|
self.height - 2 + self.y,
|
||||||
self.width - 2 + self.x)
|
self.width - 2 + self.x)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def truewidth(self) -> int:
|
||||||
|
return max([len(str(a)) for a in self.values])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def trueheight(self) -> int:
|
||||||
|
return len(self.values)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preferred_width(self) -> int:
|
def preferred_width(self) -> int:
|
||||||
return self.truewidth + 6
|
return self.truewidth + 6
|
||||||
|
@ -60,9 +67,10 @@ class MenuDisplay(Display):
|
||||||
class SettingsMenuDisplay(MenuDisplay):
|
class SettingsMenuDisplay(MenuDisplay):
|
||||||
@property
|
@property
|
||||||
def values(self) -> List[str]:
|
def values(self) -> List[str]:
|
||||||
return [a[1][1] + (" : "
|
return [_(a[1][1]) + (" : "
|
||||||
+ ("?" if self.menu.waiting_for_key
|
+ ("?" if self.menu.waiting_for_key
|
||||||
and a == self.menu.validate() else a[1][0])
|
and a == self.menu.validate() else a[1][0]
|
||||||
|
.replace("\n", "\\n"))
|
||||||
if a[1][0] else "") for a in self.menu.values]
|
if a[1][0] else "") for a in self.menu.values]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
import curses
|
import curses
|
||||||
|
|
||||||
|
from ..entities.player import Player
|
||||||
|
from ..translations import gettext as _
|
||||||
from .display import Display
|
from .display import Display
|
||||||
|
|
||||||
from squirrelbattle.entities.player import Player
|
|
||||||
|
|
||||||
|
|
||||||
class StatsDisplay(Display):
|
class StatsDisplay(Display):
|
||||||
player: Player
|
player: Player
|
||||||
|
@ -31,12 +31,12 @@ class StatsDisplay(Display):
|
||||||
self.player.dexterity, self.player.constitution)
|
self.player.dexterity, self.player.constitution)
|
||||||
self.addstr(self.pad, 3, 0, string3)
|
self.addstr(self.pad, 3, 0, string3)
|
||||||
|
|
||||||
inventory_str = "Inventaire : " + "".join(
|
inventory_str = _("Inventory:") + " " + "".join(
|
||||||
self.pack[item.name.upper()] for item in self.player.inventory)
|
self.pack[item.name.upper()] for item in self.player.inventory)
|
||||||
self.addstr(self.pad, 8, 0, inventory_str)
|
self.addstr(self.pad, 8, 0, inventory_str)
|
||||||
|
|
||||||
if self.player.dead:
|
if self.player.dead:
|
||||||
self.addstr(self.pad, 10, 0, "VOUS ÊTES MORT",
|
self.addstr(self.pad, 10, 0, _("YOU ARE DEAD"),
|
||||||
curses.A_BOLD | curses.A_BLINK | curses.A_STANDOUT
|
curses.A_BOLD | curses.A_BLINK | curses.A_STANDOUT
|
||||||
| self.color_pair(3))
|
| self.color_pair(3))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
from random import randint
|
from random import randint
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
@ -13,6 +14,7 @@ from .interfaces import Map, Logs
|
||||||
from .resources import ResourceManager
|
from .resources import ResourceManager
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from . import menus
|
from . import menus
|
||||||
|
from .translations import gettext as _, Translator
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,11 +32,12 @@ class Game:
|
||||||
Init the game.
|
Init the game.
|
||||||
"""
|
"""
|
||||||
self.state = GameMode.MAINMENU
|
self.state = GameMode.MAINMENU
|
||||||
self.main_menu = menus.MainMenu()
|
|
||||||
self.settings_menu = menus.SettingsMenu()
|
|
||||||
self.settings = Settings()
|
self.settings = Settings()
|
||||||
self.settings.load_settings()
|
self.settings.load_settings()
|
||||||
self.settings.write_settings()
|
self.settings.write_settings()
|
||||||
|
Translator.setlocale(self.settings.LOCALE)
|
||||||
|
self.main_menu = menus.MainMenu()
|
||||||
|
self.settings_menu = menus.SettingsMenu()
|
||||||
self.settings_menu.update_values(self.settings)
|
self.settings_menu.update_values(self.settings)
|
||||||
self.logs = Logs()
|
self.logs = Logs()
|
||||||
self.message = None
|
self.message = None
|
||||||
|
@ -142,16 +145,16 @@ class Game:
|
||||||
try:
|
try:
|
||||||
self.map.load_state(d)
|
self.map.load_state(d)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.message = "Some keys are missing in your save file.\n" \
|
self.message = _("Some keys are missing in your save file.\n"
|
||||||
"Your save seems to be corrupt. It got deleted."
|
"Your save seems to be corrupt. It got deleted.")
|
||||||
os.unlink(ResourceManager.get_config_path("save.json"))
|
os.unlink(ResourceManager.get_config_path("save.json"))
|
||||||
self.display_actions(DisplayActions.UPDATE)
|
self.display_actions(DisplayActions.UPDATE)
|
||||||
return
|
return
|
||||||
|
|
||||||
players = self.map.find_entities(Player)
|
players = self.map.find_entities(Player)
|
||||||
if not players:
|
if not players:
|
||||||
self.message = "No player was found on this map!\n" \
|
self.message = _("No player was found on this map!\n"
|
||||||
"Maybe you died?"
|
"Maybe you died?")
|
||||||
self.player.health = 0
|
self.player.health = 0
|
||||||
self.display_actions(DisplayActions.UPDATE)
|
self.display_actions(DisplayActions.UPDATE)
|
||||||
return
|
return
|
||||||
|
@ -170,8 +173,9 @@ class Game:
|
||||||
state = json.loads(f.read())
|
state = json.loads(f.read())
|
||||||
self.load_state(state)
|
self.load_state(state)
|
||||||
except JSONDecodeError:
|
except JSONDecodeError:
|
||||||
self.message = "The JSON file is not correct.\n" \
|
self.message = _("The JSON file is not correct.\n"
|
||||||
"Your save seems corrupted. It got deleted."
|
"Your save seems corrupted. "
|
||||||
|
"It got deleted.")
|
||||||
os.unlink(file_path)
|
os.unlink(file_path)
|
||||||
self.display_actions(DisplayActions.UPDATE)
|
self.display_actions(DisplayActions.UPDATE)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ from math import sqrt
|
||||||
from random import choice, randint
|
from random import choice, randint
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from squirrelbattle.display.texturepack import TexturePack
|
from .display.texturepack import TexturePack
|
||||||
|
from .translations import gettext as _
|
||||||
|
|
||||||
|
|
||||||
class Logs:
|
class Logs:
|
||||||
|
@ -128,7 +129,7 @@ class Map:
|
||||||
"""
|
"""
|
||||||
Put randomly {count} hedgehogs on the map, where it is available.
|
Put randomly {count} hedgehogs on the map, where it is available.
|
||||||
"""
|
"""
|
||||||
for _ in range(count):
|
for ignored in range(count):
|
||||||
y, x = 0, 0
|
y, x = 0, 0
|
||||||
while True:
|
while True:
|
||||||
y, x = randint(0, self.height - 1), randint(0, self.width - 1)
|
y, x = randint(0, self.height - 1), randint(0, self.width - 1)
|
||||||
|
@ -314,6 +315,10 @@ class Entity:
|
||||||
from squirrelbattle.entities.items import Item
|
from squirrelbattle.entities.items import Item
|
||||||
return isinstance(self, Item)
|
return isinstance(self, Item)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def translated_name(self) -> str:
|
||||||
|
return _(self.name.replace("_", " "))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_all_entity_classes():
|
def get_all_entity_classes():
|
||||||
"""
|
"""
|
||||||
|
@ -390,8 +395,10 @@ class FightingEntity(Entity):
|
||||||
"""
|
"""
|
||||||
Deals damage to the opponent, based on the stats
|
Deals damage to the opponent, based on the stats
|
||||||
"""
|
"""
|
||||||
return f"{self.name} hits {opponent.name}. "\
|
return _("{name} hits {opponent}.")\
|
||||||
+ opponent.take_damage(self, self.strength)
|
.format(name=_(self.translated_name.capitalize()),
|
||||||
|
opponent=_(opponent.translated_name)) + " " + \
|
||||||
|
opponent.take_damage(self, self.strength)
|
||||||
|
|
||||||
def take_damage(self, attacker: "Entity", amount: int) -> str:
|
def take_damage(self, attacker: "Entity", amount: int) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -400,8 +407,11 @@ class FightingEntity(Entity):
|
||||||
self.health -= amount
|
self.health -= amount
|
||||||
if self.health <= 0:
|
if self.health <= 0:
|
||||||
self.die()
|
self.die()
|
||||||
return f"{self.name} takes {amount} damage."\
|
return _("{name} takes {amount} damage.")\
|
||||||
+ (f" {self.name} dies." if self.health <= 0 else "")
|
.format(name=self.translated_name.capitalize(), amount=str(amount))\
|
||||||
|
+ (" " + _("{name} dies.")
|
||||||
|
.format(name=self.translated_name.capitalize())
|
||||||
|
if self.health <= 0 else "")
|
||||||
|
|
||||||
def die(self) -> None:
|
def die(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
|
# This file is distributed under the same license as the squirrelbattle package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squirrelbattle 3.14.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
|
||||||
|
"POT-Creation-Date: 2020-11-28 16:03+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/game_test.py:284 squirrelbattle/tests/game_test.py:287
|
||||||
|
#: squirrelbattle/tests/translations_test.py:16
|
||||||
|
msgid "New game"
|
||||||
|
msgstr "Neu Spiel"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:17
|
||||||
|
msgid "Resume"
|
||||||
|
msgstr "Weitergehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:18
|
||||||
|
msgid "Load"
|
||||||
|
msgstr "Laden"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:19
|
||||||
|
msgid "Save"
|
||||||
|
msgstr "Speichern"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:20
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:21
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "Verlassen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:27
|
||||||
|
msgid "Main key to move up"
|
||||||
|
msgstr "Haupttaste zum Obengehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:29
|
||||||
|
msgid "Secondary key to move up"
|
||||||
|
msgstr "Sekundärtaste zum Obengehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:31
|
||||||
|
msgid "Main key to move down"
|
||||||
|
msgstr "Haupttaste zum Untergehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:33
|
||||||
|
msgid "Secondary key to move down"
|
||||||
|
msgstr "Sekundärtaste zum Untergehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:35
|
||||||
|
msgid "Main key to move left"
|
||||||
|
msgstr "Haupttaste zum Linksgehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:37
|
||||||
|
msgid "Secondary key to move left"
|
||||||
|
msgstr "Sekundärtaste zum Linksgehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:39
|
||||||
|
msgid "Main key to move right"
|
||||||
|
msgstr "Haupttaste zum Rechtsgehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:41
|
||||||
|
msgid "Secondary key to move right"
|
||||||
|
msgstr "Sekundärtaste zum Rechtsgehen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:43
|
||||||
|
msgid "Key to validate a menu"
|
||||||
|
msgstr "Menütaste"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:45
|
||||||
|
msgid "Texture pack"
|
||||||
|
msgstr "Textur-Packung"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:46
|
||||||
|
msgid "Language"
|
||||||
|
msgstr "Sprache"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:49
|
||||||
|
msgid "player"
|
||||||
|
msgstr "Spieler"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:51
|
||||||
|
msgid "tiger"
|
||||||
|
msgstr "Tiger"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:52
|
||||||
|
msgid "hedgehog"
|
||||||
|
msgstr "Igel"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:53
|
||||||
|
msgid "rabbit"
|
||||||
|
msgstr "Kanninchen"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:54
|
||||||
|
msgid "teddy bear"
|
||||||
|
msgstr "Teddybär"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:56
|
||||||
|
msgid "bomb"
|
||||||
|
msgstr "Bombe"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:57
|
||||||
|
msgid "heart"
|
||||||
|
msgstr "Herz"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:34
|
||||||
|
msgid "Inventory:"
|
||||||
|
msgstr "Bestand:"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:39
|
||||||
|
msgid "YOU ARE DEAD"
|
||||||
|
msgstr "SIE WURDEN GESTORBEN"
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:398
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} hits {opponent}."
|
||||||
|
msgstr "{name} schlägt {opponent}."
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:410
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} takes {amount} damage."
|
||||||
|
msgstr "{name} nimmt {amount} Schadenspunkte."
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:412
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} dies."
|
||||||
|
msgstr "{name} stirbt."
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:71
|
||||||
|
msgid "Back"
|
||||||
|
msgstr "Zurück"
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:148
|
||||||
|
msgid ""
|
||||||
|
"Some keys are missing in your save file.\n"
|
||||||
|
"Your save seems to be corrupt. It got deleted."
|
||||||
|
msgstr ""
|
||||||
|
"In Ihrer Speicherdatei fehlen einige Schlüssel.\n"
|
||||||
|
"Ihre Speicherung scheint korrupt zu sein. Es wird gelöscht."
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:156
|
||||||
|
msgid ""
|
||||||
|
"No player was found on this map!\n"
|
||||||
|
"Maybe you died?"
|
||||||
|
msgstr ""
|
||||||
|
"Auf dieser Karte wurde kein Spieler gefunden!\n"
|
||||||
|
"Vielleicht sind Sie gestorben?"
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:176
|
||||||
|
msgid ""
|
||||||
|
"The JSON file is not correct.\n"
|
||||||
|
"Your save seems corrupted. It got deleted."
|
||||||
|
msgstr ""
|
||||||
|
"Die JSON-Datei ist nicht korrekt.\n"
|
||||||
|
"Ihre Speicherung scheint korrumpiert. Sie wurde gelöscht."
|
|
@ -0,0 +1,195 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
|
# This file is distributed under the same license as the squirrelbattle package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squirrelbattle 3.14.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
|
||||||
|
"POT-Creation-Date: 2020-11-28 16:03+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:34
|
||||||
|
msgid "Inventory:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:39
|
||||||
|
msgid "YOU ARE DEAD"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:394 squirrelbattle/interfaces.py:398
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} hits {opponent}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:405 squirrelbattle/interfaces.py:410
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} takes {amount} damage."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:45 squirrelbattle/tests/translations_test.py:14
|
||||||
|
#: squirrelbattle/tests/game_test.py:284 squirrelbattle/tests/game_test.py:287
|
||||||
|
#: squirrelbattle/tests/translations_test.py:16
|
||||||
|
msgid "New game"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:46 squirrelbattle/tests/translations_test.py:15
|
||||||
|
#: squirrelbattle/tests/translations_test.py:17
|
||||||
|
msgid "Resume"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:47 squirrelbattle/tests/translations_test.py:17
|
||||||
|
#: squirrelbattle/tests/translations_test.py:19
|
||||||
|
msgid "Save"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:48 squirrelbattle/tests/translations_test.py:16
|
||||||
|
#: squirrelbattle/tests/translations_test.py:18
|
||||||
|
msgid "Load"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:49 squirrelbattle/tests/translations_test.py:18
|
||||||
|
#: squirrelbattle/tests/translations_test.py:20
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:50 squirrelbattle/tests/translations_test.py:19
|
||||||
|
#: squirrelbattle/tests/translations_test.py:21
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:71
|
||||||
|
msgid "Back"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:147 squirrelbattle/game.py:148
|
||||||
|
msgid ""
|
||||||
|
"Some keys are missing in your save file.\n"
|
||||||
|
"Your save seems to be corrupt. It got deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:155 squirrelbattle/game.py:156
|
||||||
|
msgid ""
|
||||||
|
"No player was found on this map!\n"
|
||||||
|
"Maybe you died?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:175 squirrelbattle/game.py:176
|
||||||
|
msgid ""
|
||||||
|
"The JSON file is not correct.\n"
|
||||||
|
"Your save seems corrupted. It got deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:21 squirrelbattle/tests/translations_test.py:21
|
||||||
|
#: squirrelbattle/tests/translations_test.py:25
|
||||||
|
#: squirrelbattle/tests/translations_test.py:27
|
||||||
|
msgid "Main key to move up"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:22 squirrelbattle/tests/translations_test.py:23
|
||||||
|
#: squirrelbattle/tests/translations_test.py:27
|
||||||
|
#: squirrelbattle/tests/translations_test.py:29
|
||||||
|
msgid "Secondary key to move up"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:23 squirrelbattle/tests/translations_test.py:25
|
||||||
|
#: squirrelbattle/tests/translations_test.py:29
|
||||||
|
#: squirrelbattle/tests/translations_test.py:31
|
||||||
|
msgid "Main key to move down"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:24 squirrelbattle/tests/translations_test.py:27
|
||||||
|
#: squirrelbattle/tests/translations_test.py:31
|
||||||
|
#: squirrelbattle/tests/translations_test.py:33
|
||||||
|
msgid "Secondary key to move down"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:25 squirrelbattle/tests/translations_test.py:29
|
||||||
|
#: squirrelbattle/tests/translations_test.py:33
|
||||||
|
#: squirrelbattle/tests/translations_test.py:35
|
||||||
|
msgid "Main key to move left"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:26 squirrelbattle/tests/translations_test.py:31
|
||||||
|
#: squirrelbattle/tests/translations_test.py:35
|
||||||
|
#: squirrelbattle/tests/translations_test.py:37
|
||||||
|
msgid "Secondary key to move left"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:27 squirrelbattle/tests/translations_test.py:33
|
||||||
|
#: squirrelbattle/tests/translations_test.py:37
|
||||||
|
#: squirrelbattle/tests/translations_test.py:39
|
||||||
|
msgid "Main key to move right"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:29 squirrelbattle/tests/translations_test.py:35
|
||||||
|
#: squirrelbattle/tests/translations_test.py:39
|
||||||
|
#: squirrelbattle/tests/translations_test.py:41
|
||||||
|
msgid "Secondary key to move right"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:30 squirrelbattle/tests/translations_test.py:37
|
||||||
|
#: squirrelbattle/tests/translations_test.py:41
|
||||||
|
#: squirrelbattle/tests/translations_test.py:43
|
||||||
|
msgid "Key to validate a menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:31 squirrelbattle/tests/translations_test.py:39
|
||||||
|
#: squirrelbattle/tests/translations_test.py:43
|
||||||
|
#: squirrelbattle/tests/translations_test.py:45
|
||||||
|
msgid "Texture pack"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:32 squirrelbattle/tests/translations_test.py:40
|
||||||
|
#: squirrelbattle/tests/translations_test.py:44
|
||||||
|
#: squirrelbattle/tests/translations_test.py:46
|
||||||
|
msgid "Language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:407 squirrelbattle/interfaces.py:412
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} dies."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:47
|
||||||
|
#: squirrelbattle/tests/translations_test.py:49
|
||||||
|
msgid "player"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:49
|
||||||
|
#: squirrelbattle/tests/translations_test.py:51
|
||||||
|
msgid "tiger"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:50
|
||||||
|
#: squirrelbattle/tests/translations_test.py:52
|
||||||
|
msgid "hedgehog"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:51
|
||||||
|
#: squirrelbattle/tests/translations_test.py:53
|
||||||
|
msgid "rabbit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:52
|
||||||
|
#: squirrelbattle/tests/translations_test.py:54
|
||||||
|
msgid "teddy bear"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:54
|
||||||
|
#: squirrelbattle/tests/translations_test.py:56
|
||||||
|
msgid "bomb"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:55
|
||||||
|
#: squirrelbattle/tests/translations_test.py:57
|
||||||
|
msgid "heart"
|
||||||
|
msgstr ""
|
|
@ -0,0 +1,201 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
|
# This file is distributed under the same license as the squirrelbattle package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squirrelbattle 3.14.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: squirrel-battle@crans.org\n"
|
||||||
|
"POT-Creation-Date: 2020-11-28 16:03+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:34
|
||||||
|
msgid "Inventory:"
|
||||||
|
msgstr "Inventaire :"
|
||||||
|
|
||||||
|
#: squirrelbattle/display/statsdisplay.py:39
|
||||||
|
msgid "YOU ARE DEAD"
|
||||||
|
msgstr "VOUS ÊTES MORT"
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:394 squirrelbattle/interfaces.py:398
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} hits {opponent}."
|
||||||
|
msgstr "{name} frappe {opponent}."
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:405 squirrelbattle/interfaces.py:410
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} takes {amount} damage."
|
||||||
|
msgstr "{name} prend {amount} points de dégât."
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:45 squirrelbattle/tests/translations_test.py:14
|
||||||
|
#: squirrelbattle/tests/game_test.py:284 squirrelbattle/tests/game_test.py:287
|
||||||
|
#: squirrelbattle/tests/translations_test.py:16
|
||||||
|
msgid "New game"
|
||||||
|
msgstr "Nouvelle partie"
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:46 squirrelbattle/tests/translations_test.py:15
|
||||||
|
#: squirrelbattle/tests/translations_test.py:17
|
||||||
|
msgid "Resume"
|
||||||
|
msgstr "Continuer"
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:47 squirrelbattle/tests/translations_test.py:17
|
||||||
|
#: squirrelbattle/tests/translations_test.py:19
|
||||||
|
msgid "Save"
|
||||||
|
msgstr "Sauvegarder"
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:48 squirrelbattle/tests/translations_test.py:16
|
||||||
|
#: squirrelbattle/tests/translations_test.py:18
|
||||||
|
msgid "Load"
|
||||||
|
msgstr "Charger"
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:49 squirrelbattle/tests/translations_test.py:18
|
||||||
|
#: squirrelbattle/tests/translations_test.py:20
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "Paramètres"
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:50 squirrelbattle/tests/translations_test.py:19
|
||||||
|
#: squirrelbattle/tests/translations_test.py:21
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "Quitter"
|
||||||
|
|
||||||
|
#: squirrelbattle/menus.py:71
|
||||||
|
msgid "Back"
|
||||||
|
msgstr "Retour"
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:147 squirrelbattle/game.py:148
|
||||||
|
msgid ""
|
||||||
|
"Some keys are missing in your save file.\n"
|
||||||
|
"Your save seems to be corrupt. It got deleted."
|
||||||
|
msgstr ""
|
||||||
|
"Certaines clés de votre ficher de sauvegarde sont manquantes.\n"
|
||||||
|
"Votre sauvegarde semble corrompue. Elle a été supprimée."
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:155 squirrelbattle/game.py:156
|
||||||
|
msgid ""
|
||||||
|
"No player was found on this map!\n"
|
||||||
|
"Maybe you died?"
|
||||||
|
msgstr ""
|
||||||
|
"Aucun joueur n'a été trouvé sur la carte !\n"
|
||||||
|
"Peut-être êtes-vous mort ?"
|
||||||
|
|
||||||
|
#: squirrelbattle/game.py:175 squirrelbattle/game.py:176
|
||||||
|
msgid ""
|
||||||
|
"The JSON file is not correct.\n"
|
||||||
|
"Your save seems corrupted. It got deleted."
|
||||||
|
msgstr ""
|
||||||
|
"Le fichier JSON de sauvegarde est incorrect.\n"
|
||||||
|
"Votre sauvegarde semble corrompue. Elle a été supprimée."
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:21 squirrelbattle/tests/translations_test.py:21
|
||||||
|
#: squirrelbattle/tests/translations_test.py:25
|
||||||
|
#: squirrelbattle/tests/translations_test.py:27
|
||||||
|
msgid "Main key to move up"
|
||||||
|
msgstr "Touche principale pour aller vers le haut"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:22 squirrelbattle/tests/translations_test.py:23
|
||||||
|
#: squirrelbattle/tests/translations_test.py:27
|
||||||
|
#: squirrelbattle/tests/translations_test.py:29
|
||||||
|
msgid "Secondary key to move up"
|
||||||
|
msgstr "Touche secondaire pour aller vers le haut"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:23 squirrelbattle/tests/translations_test.py:25
|
||||||
|
#: squirrelbattle/tests/translations_test.py:29
|
||||||
|
#: squirrelbattle/tests/translations_test.py:31
|
||||||
|
msgid "Main key to move down"
|
||||||
|
msgstr "Touche principale pour aller vers le bas"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:24 squirrelbattle/tests/translations_test.py:27
|
||||||
|
#: squirrelbattle/tests/translations_test.py:31
|
||||||
|
#: squirrelbattle/tests/translations_test.py:33
|
||||||
|
msgid "Secondary key to move down"
|
||||||
|
msgstr "Touche secondaire pour aller vers le bas"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:25 squirrelbattle/tests/translations_test.py:29
|
||||||
|
#: squirrelbattle/tests/translations_test.py:33
|
||||||
|
#: squirrelbattle/tests/translations_test.py:35
|
||||||
|
msgid "Main key to move left"
|
||||||
|
msgstr "Touche principale pour aller vers la gauche"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:26 squirrelbattle/tests/translations_test.py:31
|
||||||
|
#: squirrelbattle/tests/translations_test.py:35
|
||||||
|
#: squirrelbattle/tests/translations_test.py:37
|
||||||
|
msgid "Secondary key to move left"
|
||||||
|
msgstr "Touche secondaire pour aller vers la gauche"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:27 squirrelbattle/tests/translations_test.py:33
|
||||||
|
#: squirrelbattle/tests/translations_test.py:37
|
||||||
|
#: squirrelbattle/tests/translations_test.py:39
|
||||||
|
msgid "Main key to move right"
|
||||||
|
msgstr "Touche principale pour aller vers la droite"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:29 squirrelbattle/tests/translations_test.py:35
|
||||||
|
#: squirrelbattle/tests/translations_test.py:39
|
||||||
|
#: squirrelbattle/tests/translations_test.py:41
|
||||||
|
msgid "Secondary key to move right"
|
||||||
|
msgstr "Touche secondaire pour aller vers la droite"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:30 squirrelbattle/tests/translations_test.py:37
|
||||||
|
#: squirrelbattle/tests/translations_test.py:41
|
||||||
|
#: squirrelbattle/tests/translations_test.py:43
|
||||||
|
msgid "Key to validate a menu"
|
||||||
|
msgstr "Touche pour valider un menu"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:31 squirrelbattle/tests/translations_test.py:39
|
||||||
|
#: squirrelbattle/tests/translations_test.py:43
|
||||||
|
#: squirrelbattle/tests/translations_test.py:45
|
||||||
|
msgid "Texture pack"
|
||||||
|
msgstr "Pack de textures"
|
||||||
|
|
||||||
|
#: squirrelbattle/settings.py:32 squirrelbattle/tests/translations_test.py:40
|
||||||
|
#: squirrelbattle/tests/translations_test.py:44
|
||||||
|
#: squirrelbattle/tests/translations_test.py:46
|
||||||
|
msgid "Language"
|
||||||
|
msgstr "Langue"
|
||||||
|
|
||||||
|
#: squirrelbattle/interfaces.py:407 squirrelbattle/interfaces.py:412
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "{name} dies."
|
||||||
|
msgstr "{name} meurt."
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:47
|
||||||
|
#: squirrelbattle/tests/translations_test.py:49
|
||||||
|
msgid "player"
|
||||||
|
msgstr "joueur"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:49
|
||||||
|
#: squirrelbattle/tests/translations_test.py:51
|
||||||
|
msgid "tiger"
|
||||||
|
msgstr "tigre"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:50
|
||||||
|
#: squirrelbattle/tests/translations_test.py:52
|
||||||
|
msgid "hedgehog"
|
||||||
|
msgstr "hérisson"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:51
|
||||||
|
#: squirrelbattle/tests/translations_test.py:53
|
||||||
|
msgid "rabbit"
|
||||||
|
msgstr "lapin"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:52
|
||||||
|
#: squirrelbattle/tests/translations_test.py:54
|
||||||
|
msgid "teddy bear"
|
||||||
|
msgstr "nounours"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:54
|
||||||
|
#: squirrelbattle/tests/translations_test.py:56
|
||||||
|
msgid "bomb"
|
||||||
|
msgstr "bombe"
|
||||||
|
|
||||||
|
#: squirrelbattle/tests/translations_test.py:55
|
||||||
|
#: squirrelbattle/tests/translations_test.py:57
|
||||||
|
msgid "heart"
|
||||||
|
msgstr "cœur"
|
|
@ -7,6 +7,7 @@ from typing import Any, Optional
|
||||||
from .display.texturepack import TexturePack
|
from .display.texturepack import TexturePack
|
||||||
from .enums import GameMode, KeyValues, DisplayActions
|
from .enums import GameMode, KeyValues, DisplayActions
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
|
from .translations import gettext as _, Translator
|
||||||
|
|
||||||
|
|
||||||
class Menu:
|
class Menu:
|
||||||
|
@ -41,15 +42,15 @@ class MainMenuValues(Enum):
|
||||||
"""
|
"""
|
||||||
Values of the main menu
|
Values of the main menu
|
||||||
"""
|
"""
|
||||||
START = 'Nouvelle partie'
|
START = "New game"
|
||||||
RESUME = 'Continuer'
|
RESUME = "Resume"
|
||||||
SAVE = 'Sauvegarder'
|
SAVE = "Save"
|
||||||
LOAD = 'Charger'
|
LOAD = "Load"
|
||||||
SETTINGS = 'Paramètres'
|
SETTINGS = "Settings"
|
||||||
EXIT = 'Quitter'
|
EXIT = "Exit"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.value
|
return _(self.value)
|
||||||
|
|
||||||
|
|
||||||
class MainMenu(Menu):
|
class MainMenu(Menu):
|
||||||
|
@ -67,7 +68,7 @@ class SettingsMenu(Menu):
|
||||||
|
|
||||||
def update_values(self, settings: Settings) -> None:
|
def update_values(self, settings: Settings) -> None:
|
||||||
self.values = list(settings.__dict__.items())
|
self.values = list(settings.__dict__.items())
|
||||||
self.values.append(("RETURN", ["", "Retour"]))
|
self.values.append(("RETURN", ["", _("Back")]))
|
||||||
|
|
||||||
def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str,
|
def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str,
|
||||||
game: Any) -> None:
|
game: Any) -> None:
|
||||||
|
@ -95,6 +96,12 @@ class SettingsMenu(Menu):
|
||||||
game.settings.TEXTURE_PACK)
|
game.settings.TEXTURE_PACK)
|
||||||
game.settings.write_settings()
|
game.settings.write_settings()
|
||||||
self.update_values(game.settings)
|
self.update_values(game.settings)
|
||||||
|
elif option == "LOCALE":
|
||||||
|
game.settings.LOCALE = 'fr' if game.settings.LOCALE == 'en'\
|
||||||
|
else 'de' if game.settings.LOCALE == 'fr' else 'en'
|
||||||
|
Translator.setlocale(game.settings.LOCALE)
|
||||||
|
game.settings.write_settings()
|
||||||
|
self.update_values(game.settings)
|
||||||
else:
|
else:
|
||||||
self.waiting_for_key = True
|
self.waiting_for_key = True
|
||||||
self.update_values(game.settings)
|
self.update_values(game.settings)
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import locale
|
||||||
import os
|
import os
|
||||||
from typing import Any, Generator
|
from typing import Any, Generator
|
||||||
|
|
||||||
from .resources import ResourceManager
|
from .resources import ResourceManager
|
||||||
|
from .translations import gettext as _
|
||||||
|
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
|
@ -16,25 +18,17 @@ class Settings:
|
||||||
We can define the setting by simply use settings.TEXTURE_PACK = 'new_key'
|
We can define the setting by simply use settings.TEXTURE_PACK = 'new_key'
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.KEY_UP_PRIMARY = \
|
self.KEY_UP_PRIMARY = ['z', 'Main key to move up']
|
||||||
['z', 'Touche principale pour aller vers le haut']
|
self.KEY_UP_SECONDARY = ['KEY_UP', 'Secondary key to move up']
|
||||||
self.KEY_UP_SECONDARY = \
|
self.KEY_DOWN_PRIMARY = ['s', 'Main key to move down']
|
||||||
['KEY_UP', 'Touche secondaire pour aller vers le haut']
|
self.KEY_DOWN_SECONDARY = ['KEY_DOWN', 'Secondary key to move down']
|
||||||
self.KEY_DOWN_PRIMARY = \
|
self.KEY_LEFT_PRIMARY = ['q', 'Main key to move left']
|
||||||
['s', 'Touche principale pour aller vers le bas']
|
self.KEY_LEFT_SECONDARY = ['KEY_LEFT', 'Secondary key to move left']
|
||||||
self.KEY_DOWN_SECONDARY = \
|
self.KEY_RIGHT_PRIMARY = ['d', 'Main key to move right']
|
||||||
['KEY_DOWN', 'Touche secondaire pour aller vers le bas']
|
self.KEY_RIGHT_SECONDARY = ['KEY_RIGHT', 'Secondary key to move right']
|
||||||
self.KEY_LEFT_PRIMARY = \
|
self.KEY_ENTER = ['\n', 'Key to validate a menu']
|
||||||
['q', 'Touche principale pour aller vers la gauche']
|
self.TEXTURE_PACK = ['ascii', 'Texture pack']
|
||||||
self.KEY_LEFT_SECONDARY = \
|
self.LOCALE = [locale.getlocale()[0][:2], 'Language']
|
||||||
['KEY_LEFT', 'Touche secondaire pour aller vers la gauche']
|
|
||||||
self.KEY_RIGHT_PRIMARY = \
|
|
||||||
['d', 'Touche principale pour aller vers la droite']
|
|
||||||
self.KEY_RIGHT_SECONDARY = \
|
|
||||||
['KEY_RIGHT', 'Touche secondaire pour aller vers la droite']
|
|
||||||
self.KEY_ENTER = \
|
|
||||||
['\n', 'Touche pour valider un menu']
|
|
||||||
self.TEXTURE_PACK = ['ascii', 'Pack de textures utilisé']
|
|
||||||
|
|
||||||
def __getattribute__(self, item: str) -> Any:
|
def __getattribute__(self, item: str) -> Any:
|
||||||
superattribute = super().__getattribute__(item)
|
superattribute = super().__getattribute__(item)
|
||||||
|
@ -53,10 +47,10 @@ class Settings:
|
||||||
Retrieve the comment of a setting.
|
Retrieve the comment of a setting.
|
||||||
"""
|
"""
|
||||||
if item in self.settings_keys:
|
if item in self.settings_keys:
|
||||||
return object.__getattribute__(self, item)[1]
|
return _(object.__getattribute__(self, item)[1])
|
||||||
for key in self.settings_keys:
|
for key in self.settings_keys:
|
||||||
if getattr(self, key) == item:
|
if getattr(self, key) == item:
|
||||||
return object.__getattribute__(self, key)[1]
|
return _(object.__getattribute__(self, key)[1])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def settings_keys(self) -> Generator[str, Any, None]:
|
def settings_keys(self) -> Generator[str, Any, None]:
|
||||||
|
|
|
@ -46,10 +46,10 @@ class TestEntities(unittest.TestCase):
|
||||||
self.assertEqual(entity.strength, 2)
|
self.assertEqual(entity.strength, 2)
|
||||||
for _ in range(9):
|
for _ in range(9):
|
||||||
self.assertEqual(entity.hit(entity),
|
self.assertEqual(entity.hit(entity),
|
||||||
"tiger hits tiger. tiger takes 2 damage.")
|
"Tiger hits tiger. Tiger takes 2 damage.")
|
||||||
self.assertFalse(entity.dead)
|
self.assertFalse(entity.dead)
|
||||||
self.assertEqual(entity.hit(entity), "tiger hits tiger. "
|
self.assertEqual(entity.hit(entity), "Tiger hits tiger. "
|
||||||
+ "tiger takes 2 damage. tiger dies.")
|
+ "Tiger takes 2 damage. Tiger dies.")
|
||||||
self.assertTrue(entity.dead)
|
self.assertTrue(entity.dead)
|
||||||
|
|
||||||
entity = Rabbit()
|
entity = Rabbit()
|
||||||
|
@ -70,8 +70,8 @@ class TestEntities(unittest.TestCase):
|
||||||
self.assertTrue(entity.y == 2 and entity.x == 6)
|
self.assertTrue(entity.y == 2 and entity.x == 6)
|
||||||
self.assertEqual(old_health - entity.strength, self.player.health)
|
self.assertEqual(old_health - entity.strength, self.player.health)
|
||||||
self.assertEqual(self.map.logs.messages[-1],
|
self.assertEqual(self.map.logs.messages[-1],
|
||||||
f"{entity.name} hits {self.player.name}. \
|
f"{entity.name.capitalize()} hits {self.player.name}. \
|
||||||
{self.player.name} takes {entity.strength} damage.")
|
{self.player.name.capitalize()} takes {entity.strength} damage.")
|
||||||
|
|
||||||
# Fight the rabbit
|
# Fight the rabbit
|
||||||
old_health = entity.health
|
old_health = entity.health
|
||||||
|
|
|
@ -4,17 +4,16 @@
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from squirrelbattle.resources import ResourceManager
|
from ..bootstrap import Bootstrap
|
||||||
|
from ..display.display import Display
|
||||||
from squirrelbattle.enums import DisplayActions
|
from ..display.display_manager import DisplayManager
|
||||||
|
from ..entities.player import Player
|
||||||
from squirrelbattle.bootstrap import Bootstrap
|
from ..enums import DisplayActions
|
||||||
from squirrelbattle.display.display import Display
|
from ..game import Game, KeyValues, GameMode
|
||||||
from squirrelbattle.display.display_manager import DisplayManager
|
from ..menus import MainMenuValues
|
||||||
from squirrelbattle.entities.player import Player
|
from ..resources import ResourceManager
|
||||||
from squirrelbattle.game import Game, KeyValues, GameMode
|
from ..settings import Settings
|
||||||
from squirrelbattle.menus import MainMenuValues
|
from ..translations import gettext as _, Translator
|
||||||
from squirrelbattle.settings import Settings
|
|
||||||
|
|
||||||
|
|
||||||
class TestGame(unittest.TestCase):
|
class TestGame(unittest.TestCase):
|
||||||
|
@ -275,12 +274,23 @@ class TestGame(unittest.TestCase):
|
||||||
self.game.handle_key_pressed(KeyValues.ENTER)
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii")
|
self.assertEqual(self.game.settings.TEXTURE_PACK, "ascii")
|
||||||
|
|
||||||
|
# Change language
|
||||||
|
Translator.compilemessages()
|
||||||
|
Translator.refresh_translations()
|
||||||
|
self.game.settings.LOCALE = "en"
|
||||||
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
|
self.assertEqual(self.game.settings.LOCALE, "fr")
|
||||||
|
self.assertEqual(_("New game"), "Nouvelle partie")
|
||||||
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
|
self.assertEqual(self.game.settings.LOCALE, "de")
|
||||||
|
self.assertEqual(_("New game"), "Neu Spiel")
|
||||||
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
|
self.assertEqual(self.game.settings.LOCALE, "en")
|
||||||
|
self.assertEqual(_("New game"), "New game")
|
||||||
|
|
||||||
# Navigate to "back" button
|
# Navigate to "back" button
|
||||||
self.game.handle_key_pressed(KeyValues.DOWN)
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
||||||
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
||||||
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
||||||
self.game.handle_key_pressed(KeyValues.DOWN)
|
|
||||||
|
|
||||||
self.game.handle_key_pressed(KeyValues.ENTER)
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
||||||
|
|
|
@ -24,7 +24,7 @@ class TestSettings(unittest.TestCase):
|
||||||
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
|
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
|
||||||
settings.get_comment('TEXTURE_PACK'))
|
settings.get_comment('TEXTURE_PACK'))
|
||||||
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
|
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
|
||||||
'Pack de textures utilisé')
|
'Texture pack')
|
||||||
|
|
||||||
settings.TEXTURE_PACK = 'squirrel'
|
settings.TEXTURE_PACK = 'squirrel'
|
||||||
self.assertEqual(settings.TEXTURE_PACK, 'squirrel')
|
self.assertEqual(settings.TEXTURE_PACK, 'squirrel')
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from squirrelbattle.translations import gettext as _, Translator
|
||||||
|
|
||||||
|
|
||||||
|
class TestTranslations(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
Translator.compilemessages()
|
||||||
|
Translator.refresh_translations()
|
||||||
|
Translator.setlocale("fr")
|
||||||
|
|
||||||
|
def test_main_menu_translation(self) -> None:
|
||||||
|
"""
|
||||||
|
Ensure that the main menu is translated.
|
||||||
|
"""
|
||||||
|
self.assertEqual(_("New game"), "Nouvelle partie")
|
||||||
|
self.assertEqual(_("Resume"), "Continuer")
|
||||||
|
self.assertEqual(_("Load"), "Charger")
|
||||||
|
self.assertEqual(_("Save"), "Sauvegarder")
|
||||||
|
self.assertEqual(_("Settings"), "Paramètres")
|
||||||
|
self.assertEqual(_("Exit"), "Quitter")
|
||||||
|
|
||||||
|
def test_settings_menu_translation(self) -> None:
|
||||||
|
"""
|
||||||
|
Ensure that the settings menu is translated.
|
||||||
|
"""
|
||||||
|
self.assertEqual(_("Main key to move up"),
|
||||||
|
"Touche principale pour aller vers le haut")
|
||||||
|
self.assertEqual(_("Secondary key to move up"),
|
||||||
|
"Touche secondaire pour aller vers le haut")
|
||||||
|
self.assertEqual(_("Main key to move down"),
|
||||||
|
"Touche principale pour aller vers le bas")
|
||||||
|
self.assertEqual(_("Secondary key to move down"),
|
||||||
|
"Touche secondaire pour aller vers le bas")
|
||||||
|
self.assertEqual(_("Main key to move left"),
|
||||||
|
"Touche principale pour aller vers la gauche")
|
||||||
|
self.assertEqual(_("Secondary key to move left"),
|
||||||
|
"Touche secondaire pour aller vers la gauche")
|
||||||
|
self.assertEqual(_("Main key to move right"),
|
||||||
|
"Touche principale pour aller vers la droite")
|
||||||
|
self.assertEqual(_("Secondary key to move right"),
|
||||||
|
"Touche secondaire pour aller vers la droite")
|
||||||
|
self.assertEqual(_("Key to validate a menu"),
|
||||||
|
"Touche pour valider un menu")
|
||||||
|
self.assertEqual(_("Texture pack"), "Pack de textures")
|
||||||
|
self.assertEqual(_("Language"), "Langue")
|
||||||
|
|
||||||
|
def test_entities_translation(self) -> None:
|
||||||
|
self.assertEqual(_("player"), "joueur")
|
||||||
|
|
||||||
|
self.assertEqual(_("tiger"), "tigre")
|
||||||
|
self.assertEqual(_("hedgehog"), "hérisson")
|
||||||
|
self.assertEqual(_("rabbit"), "lapin")
|
||||||
|
self.assertEqual(_("teddy bear"), "nounours")
|
||||||
|
|
||||||
|
self.assertEqual(_("bomb"), "bombe")
|
||||||
|
self.assertEqual(_("heart"), "cœur")
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
import gettext as gt
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
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 message.
|
||||||
|
"""
|
||||||
|
SUPPORTED_LOCALES: List[str] = ["de", "en", "fr"]
|
||||||
|
locale: str = "en"
|
||||||
|
translators: dict = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def refresh_translations(cls) -> None:
|
||||||
|
"""
|
||||||
|
Load 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],
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setlocale(cls, lang: str) -> None:
|
||||||
|
"""
|
||||||
|
Define the language used to translate the game.
|
||||||
|
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())
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def makemessages(cls) -> None: # pragma: no cover
|
||||||
|
"""
|
||||||
|
Analyse all strings in the project and extract them.
|
||||||
|
"""
|
||||||
|
for language in cls.SUPPORTED_LOCALES:
|
||||||
|
file_name = Path(__file__).parent / "locale" / language \
|
||||||
|
/ "LC_MESSAGES" / "squirrelbattle.po"
|
||||||
|
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",
|
||||||
|
"--package-version=3.14.1",
|
||||||
|
"--copyright-holder=ÿnérant, eichhornchen, "
|
||||||
|
"nicomarg, charlse",
|
||||||
|
"--msgid-bugs-address=squirrel-battle@crans.org",
|
||||||
|
"-o", file_name]
|
||||||
|
if file_name.is_file():
|
||||||
|
args.append("--join-existing")
|
||||||
|
print(f"Make {language} messages...")
|
||||||
|
subprocess.Popen(args, stdin=find.stdout).wait()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def compilemessages(cls) -> None:
|
||||||
|
"""
|
||||||
|
Compile translation messages from source files.
|
||||||
|
"""
|
||||||
|
for language in cls.SUPPORTED_LOCALES:
|
||||||
|
args = ["msgfmt", "--check-format",
|
||||||
|
"-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()
|
||||||
|
|
||||||
|
|
||||||
|
def gettext(message: str) -> str:
|
||||||
|
"""
|
||||||
|
Translate a message.
|
||||||
|
"""
|
||||||
|
return Translator.get_translator().gettext(message)
|
||||||
|
|
||||||
|
|
||||||
|
Translator.refresh_translations()
|
Loading…
Reference in New Issue