Merge branch 'translations' into 'master'
Translations Closes #14 See merge request ynerant/squirrel-battle!31
This commit was merged in pull request #112.
	This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -23,3 +23,6 @@ save.json
 | 
			
		||||
 | 
			
		||||
# Don't commit docs output
 | 
			
		||||
docs/_build
 | 
			
		||||
 | 
			
		||||
# Don't commit compiled messages
 | 
			
		||||
*.mo
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ py37:
 | 
			
		||||
  stage: test
 | 
			
		||||
  image: python:3.7-alpine
 | 
			
		||||
  before_script:
 | 
			
		||||
    - apk add --no-cache gettext
 | 
			
		||||
    - pip install tox
 | 
			
		||||
  script: tox -e py3
 | 
			
		||||
 | 
			
		||||
@@ -14,6 +15,7 @@ py38:
 | 
			
		||||
  stage: test
 | 
			
		||||
  image: python:3.8-alpine
 | 
			
		||||
  before_script:
 | 
			
		||||
    - apk add --no-cache gettext
 | 
			
		||||
    - pip install tox
 | 
			
		||||
  script: tox -e py3
 | 
			
		||||
 | 
			
		||||
@@ -22,6 +24,7 @@ py39:
 | 
			
		||||
  stage: test
 | 
			
		||||
  image: python:3.9-alpine
 | 
			
		||||
  before_script:
 | 
			
		||||
    - apk add --no-cache gettext
 | 
			
		||||
    - pip install tox
 | 
			
		||||
  script: tox -e py3
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +40,7 @@ build-deb:
 | 
			
		||||
  image: debian:buster-slim
 | 
			
		||||
  stage: build
 | 
			
		||||
  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:
 | 
			
		||||
    - dpkg-buildpackage
 | 
			
		||||
    - mkdir build && cp ../*.deb build/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
python3-squirrel-battle (3.14) beta; urgency=low
 | 
			
		||||
python3-squirrel-battle (3.14.1) beta; urgency=low
 | 
			
		||||
 | 
			
		||||
  * Some graphical improvements.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@ Source: python3-squirrel-battle
 | 
			
		||||
Section: devel
 | 
			
		||||
Priority: optional
 | 
			
		||||
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
 | 
			
		||||
Standards-Version: 4.1.4
 | 
			
		||||
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:
 | 
			
		||||
        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(
 | 
			
		||||
        name="squirrel-battle",
 | 
			
		||||
        version="3.14.1",
 | 
			
		||||
@@ -60,7 +70,7 @@ paquet ainsi que des détails à fournir à PyPI :
 | 
			
		||||
        ],
 | 
			
		||||
        python_requires='>=3.6',
 | 
			
		||||
        include_package_data=True,
 | 
			
		||||
        package_data={"squirrelbattle": ["assets/*"]},
 | 
			
		||||
        package_data={"squirrelbattle": ["assets/*", "locale/*/*/*.mo"]},
 | 
			
		||||
        entry_points={
 | 
			
		||||
            "console_scripts": [
 | 
			
		||||
                "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 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``,
 | 
			
		||||
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"
 | 
			
		||||
    license=('GPLv3')
 | 
			
		||||
    depends=('python')
 | 
			
		||||
    makedepends=('python-setuptools')
 | 
			
		||||
    makedepends=('gettext' 'python-setuptools')
 | 
			
		||||
    depends=('noto-fonts-emoji')
 | 
			
		||||
    checkdepends=('python-tox')
 | 
			
		||||
    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"
 | 
			
		||||
    license=('GPLv3')
 | 
			
		||||
    depends=('python')
 | 
			
		||||
    makedepends=('python-setuptools')
 | 
			
		||||
    makedepends=('gettext' 'python-setuptools')
 | 
			
		||||
    depends=('noto-fonts-emoji')
 | 
			
		||||
    checkdepends=('python-tox')
 | 
			
		||||
    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::
 | 
			
		||||
 | 
			
		||||
  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 :
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ Bienvenue dans la documentation de Squirrel Battle !
 | 
			
		||||
   install-dev
 | 
			
		||||
   tests
 | 
			
		||||
   display/index
 | 
			
		||||
   translation
 | 
			
		||||
   deployment
 | 
			
		||||
   documentation
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,19 @@
 | 
			
		||||
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.**
 | 
			
		||||
    Vous devez déjà installer Python et le module qui permet de créer des environnements virtuels.
 | 
			
		||||
    On donne ci-dessous l'exemple pour une distribution basée sur Debian, mais vous pouvez facilement adapter pour ArchLinux ou autre.
 | 
			
		||||
    Vous devez déjà installer Python et le module qui permet de créer des
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    $ 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 :
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +28,13 @@ Il est toujours préférable de travailler dans un environnement Python isolé d
 | 
			
		||||
 | 
			
		||||
    $ python3 -m venv env
 | 
			
		||||
    $ source env/bin/activate  # entrer dans l'environnement
 | 
			
		||||
    (env)$ pip3 install -r requirements.txt
 | 
			
		||||
    (env)$ deactivate  # sortir de l'environnement
 | 
			
		||||
    (env) $ pip3 install -r requirements.txt
 | 
			
		||||
    (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``.
 | 
			
		||||
							
								
								
									
										120
									
								
								docs/translation.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								docs/translation.rst
									
									
									
									
									
										Normal file
									
								
							@@ -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.
 | 
			
		||||
							
								
								
									
										18
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								main.py
									
									
									
									
									
								
							@@ -2,8 +2,24 @@
 | 
			
		||||
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
import argparse
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.bootstrap import Bootstrap
 | 
			
		||||
from squirrelbattle.translations import Translator
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    Bootstrap.run_game()
 | 
			
		||||
    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()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								setup.py
									
									
									
									
									
								
							@@ -3,13 +3,23 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
from setuptools import find_packages, setup
 | 
			
		||||
 | 
			
		||||
with open("README.md", "r") as f:
 | 
			
		||||
    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(
 | 
			
		||||
    name="squirrel-battle",
 | 
			
		||||
    version="3.14.1",
 | 
			
		||||
@@ -36,7 +46,7 @@ setup(
 | 
			
		||||
    ],
 | 
			
		||||
    python_requires='>=3.6',
 | 
			
		||||
    include_package_data=True,
 | 
			
		||||
    package_data={"squirrelbattle": ["assets/*"]},
 | 
			
		||||
    package_data={"squirrelbattle": ["assets/*", "locale/*/*/*.mo"]},
 | 
			
		||||
    entry_points={
 | 
			
		||||
        "console_scripts": [
 | 
			
		||||
            "squirrel-battle = squirrelbattle.bootstrap:Bootstrap.run_game",
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ from typing import List
 | 
			
		||||
from squirrelbattle.menus import Menu, MainMenu
 | 
			
		||||
from .display import Display, Box
 | 
			
		||||
from ..resources import ResourceManager
 | 
			
		||||
from ..translations import gettext as _
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MenuDisplay(Display):
 | 
			
		||||
@@ -17,8 +18,6 @@ class MenuDisplay(Display):
 | 
			
		||||
 | 
			
		||||
    def update_menu(self, menu: Menu) -> None:
 | 
			
		||||
        self.menu = menu
 | 
			
		||||
        self.trueheight = len(self.values)
 | 
			
		||||
        self.truewidth = max([len(a) for a in self.values])
 | 
			
		||||
 | 
			
		||||
        # Menu values are printed in pad
 | 
			
		||||
        self.pad = self.newpad(self.trueheight, self.truewidth + 2)
 | 
			
		||||
@@ -44,6 +43,14 @@ class MenuDisplay(Display):
 | 
			
		||||
                         self.height - 2 + self.y,
 | 
			
		||||
                         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
 | 
			
		||||
    def preferred_width(self) -> int:
 | 
			
		||||
        return self.truewidth + 6
 | 
			
		||||
@@ -60,9 +67,10 @@ class MenuDisplay(Display):
 | 
			
		||||
class SettingsMenuDisplay(MenuDisplay):
 | 
			
		||||
    @property
 | 
			
		||||
    def values(self) -> List[str]:
 | 
			
		||||
        return [a[1][1] + (" : "
 | 
			
		||||
        return [_(a[1][1]) + (" : "
 | 
			
		||||
                + ("?" 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]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,10 @@
 | 
			
		||||
 | 
			
		||||
import curses
 | 
			
		||||
 | 
			
		||||
from ..entities.player import Player
 | 
			
		||||
from ..translations import gettext as _
 | 
			
		||||
from .display import Display
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.entities.player import Player
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class StatsDisplay(Display):
 | 
			
		||||
    player: Player
 | 
			
		||||
@@ -31,12 +31,12 @@ class StatsDisplay(Display):
 | 
			
		||||
                    self.player.dexterity, self.player.constitution)
 | 
			
		||||
        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.addstr(self.pad, 8, 0, inventory_str)
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
                        | self.color_pair(3))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from json import JSONDecodeError
 | 
			
		||||
from random import randint
 | 
			
		||||
from typing import Any, Optional
 | 
			
		||||
@@ -13,6 +14,7 @@ from .interfaces import Map, Logs
 | 
			
		||||
from .resources import ResourceManager
 | 
			
		||||
from .settings import Settings
 | 
			
		||||
from . import menus
 | 
			
		||||
from .translations import gettext as _, Translator
 | 
			
		||||
from typing import Callable
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -30,11 +32,12 @@ class Game:
 | 
			
		||||
        Init the game.
 | 
			
		||||
        """
 | 
			
		||||
        self.state = GameMode.MAINMENU
 | 
			
		||||
        self.main_menu = menus.MainMenu()
 | 
			
		||||
        self.settings_menu = menus.SettingsMenu()
 | 
			
		||||
        self.settings = Settings()
 | 
			
		||||
        self.settings.load_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.logs = Logs()
 | 
			
		||||
        self.message = None
 | 
			
		||||
@@ -142,16 +145,16 @@ class Game:
 | 
			
		||||
        try:
 | 
			
		||||
            self.map.load_state(d)
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            self.message = "Some keys are missing in your save file.\n" \
 | 
			
		||||
                           "Your save seems to be corrupt. It got deleted."
 | 
			
		||||
            self.message = _("Some keys are missing in your save file.\n"
 | 
			
		||||
                             "Your save seems to be corrupt. It got deleted.")
 | 
			
		||||
            os.unlink(ResourceManager.get_config_path("save.json"))
 | 
			
		||||
            self.display_actions(DisplayActions.UPDATE)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        players = self.map.find_entities(Player)
 | 
			
		||||
        if not players:
 | 
			
		||||
            self.message = "No player was found on this map!\n" \
 | 
			
		||||
                           "Maybe you died?"
 | 
			
		||||
            self.message = _("No player was found on this map!\n"
 | 
			
		||||
                             "Maybe you died?")
 | 
			
		||||
            self.player.health = 0
 | 
			
		||||
            self.display_actions(DisplayActions.UPDATE)
 | 
			
		||||
            return
 | 
			
		||||
@@ -170,8 +173,9 @@ class Game:
 | 
			
		||||
                    state = json.loads(f.read())
 | 
			
		||||
                    self.load_state(state)
 | 
			
		||||
                except JSONDecodeError:
 | 
			
		||||
                    self.message = "The JSON file is not correct.\n" \
 | 
			
		||||
                                   "Your save seems corrupted. It got deleted."
 | 
			
		||||
                    self.message = _("The JSON file is not correct.\n"
 | 
			
		||||
                                     "Your save seems corrupted. "
 | 
			
		||||
                                     "It got deleted.")
 | 
			
		||||
                    os.unlink(file_path)
 | 
			
		||||
                    self.display_actions(DisplayActions.UPDATE)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,8 @@ from math import sqrt
 | 
			
		||||
from random import choice, randint
 | 
			
		||||
from typing import List, Optional
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.display.texturepack import TexturePack
 | 
			
		||||
from .display.texturepack import TexturePack
 | 
			
		||||
from .translations import gettext as _
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Logs:
 | 
			
		||||
@@ -128,7 +129,7 @@ class Map:
 | 
			
		||||
        """
 | 
			
		||||
        Put randomly {count} hedgehogs on the map, where it is available.
 | 
			
		||||
        """
 | 
			
		||||
        for _ in range(count):
 | 
			
		||||
        for ignored in range(count):
 | 
			
		||||
            y, x = 0, 0
 | 
			
		||||
            while True:
 | 
			
		||||
                y, x = randint(0, self.height - 1), randint(0, self.width - 1)
 | 
			
		||||
@@ -314,6 +315,10 @@ class Entity:
 | 
			
		||||
        from squirrelbattle.entities.items import Item
 | 
			
		||||
        return isinstance(self, Item)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def translated_name(self) -> str:
 | 
			
		||||
        return _(self.name.replace("_", " "))
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_all_entity_classes():
 | 
			
		||||
        """
 | 
			
		||||
@@ -390,8 +395,10 @@ class FightingEntity(Entity):
 | 
			
		||||
        """
 | 
			
		||||
        Deals damage to the opponent, based on the stats
 | 
			
		||||
        """
 | 
			
		||||
        return f"{self.name} hits {opponent.name}. "\
 | 
			
		||||
            + opponent.take_damage(self, self.strength)
 | 
			
		||||
        return _("{name} hits {opponent}.")\
 | 
			
		||||
            .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:
 | 
			
		||||
        """
 | 
			
		||||
@@ -400,8 +407,11 @@ class FightingEntity(Entity):
 | 
			
		||||
        self.health -= amount
 | 
			
		||||
        if self.health <= 0:
 | 
			
		||||
            self.die()
 | 
			
		||||
        return f"{self.name} takes {amount} damage."\
 | 
			
		||||
            + (f" {self.name} dies." if self.health <= 0 else "")
 | 
			
		||||
        return _("{name} takes {amount} damage.")\
 | 
			
		||||
            .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:
 | 
			
		||||
        """
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										166
									
								
								squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								squirrelbattle/locale/de/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							@@ -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."
 | 
			
		||||
							
								
								
									
										195
									
								
								squirrelbattle/locale/en/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								squirrelbattle/locale/en/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							@@ -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 ""
 | 
			
		||||
							
								
								
									
										201
									
								
								squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								squirrelbattle/locale/fr/LC_MESSAGES/squirrelbattle.po
									
									
									
									
									
										Normal file
									
								
							@@ -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 .enums import GameMode, KeyValues, DisplayActions
 | 
			
		||||
from .settings import Settings
 | 
			
		||||
from .translations import gettext as _, Translator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Menu:
 | 
			
		||||
@@ -41,15 +42,15 @@ class MainMenuValues(Enum):
 | 
			
		||||
    """
 | 
			
		||||
    Values of the main menu
 | 
			
		||||
    """
 | 
			
		||||
    START = 'Nouvelle partie'
 | 
			
		||||
    RESUME = 'Continuer'
 | 
			
		||||
    SAVE = 'Sauvegarder'
 | 
			
		||||
    LOAD = 'Charger'
 | 
			
		||||
    SETTINGS = 'Paramètres'
 | 
			
		||||
    EXIT = 'Quitter'
 | 
			
		||||
    START = "New game"
 | 
			
		||||
    RESUME = "Resume"
 | 
			
		||||
    SAVE = "Save"
 | 
			
		||||
    LOAD = "Load"
 | 
			
		||||
    SETTINGS = "Settings"
 | 
			
		||||
    EXIT = "Exit"
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.value
 | 
			
		||||
        return _(self.value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MainMenu(Menu):
 | 
			
		||||
@@ -67,7 +68,7 @@ class SettingsMenu(Menu):
 | 
			
		||||
 | 
			
		||||
    def update_values(self, settings: Settings) -> None:
 | 
			
		||||
        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,
 | 
			
		||||
                           game: Any) -> None:
 | 
			
		||||
@@ -95,6 +96,12 @@ class SettingsMenu(Menu):
 | 
			
		||||
                            game.settings.TEXTURE_PACK)
 | 
			
		||||
                    game.settings.write_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:
 | 
			
		||||
                    self.waiting_for_key = True
 | 
			
		||||
                    self.update_values(game.settings)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,12 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
import locale
 | 
			
		||||
import os
 | 
			
		||||
from typing import Any, Generator
 | 
			
		||||
 | 
			
		||||
from .resources import ResourceManager
 | 
			
		||||
from .translations import gettext as _
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Settings:
 | 
			
		||||
@@ -16,25 +18,17 @@ class Settings:
 | 
			
		||||
    We can define the setting by simply use settings.TEXTURE_PACK = 'new_key'
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.KEY_UP_PRIMARY = \
 | 
			
		||||
            ['z', 'Touche principale pour aller vers le haut']
 | 
			
		||||
        self.KEY_UP_SECONDARY = \
 | 
			
		||||
            ['KEY_UP', 'Touche secondaire pour aller vers le haut']
 | 
			
		||||
        self.KEY_DOWN_PRIMARY = \
 | 
			
		||||
            ['s', 'Touche principale pour aller vers le bas']
 | 
			
		||||
        self.KEY_DOWN_SECONDARY = \
 | 
			
		||||
            ['KEY_DOWN', 'Touche secondaire pour aller vers le bas']
 | 
			
		||||
        self.KEY_LEFT_PRIMARY = \
 | 
			
		||||
            ['q', 'Touche principale pour aller vers la gauche']
 | 
			
		||||
        self.KEY_LEFT_SECONDARY = \
 | 
			
		||||
            ['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é']
 | 
			
		||||
        self.KEY_UP_PRIMARY = ['z', 'Main key to move up']
 | 
			
		||||
        self.KEY_UP_SECONDARY = ['KEY_UP', 'Secondary key to move up']
 | 
			
		||||
        self.KEY_DOWN_PRIMARY = ['s', 'Main key to move down']
 | 
			
		||||
        self.KEY_DOWN_SECONDARY = ['KEY_DOWN', 'Secondary key to move down']
 | 
			
		||||
        self.KEY_LEFT_PRIMARY = ['q', 'Main key to move left']
 | 
			
		||||
        self.KEY_LEFT_SECONDARY = ['KEY_LEFT', 'Secondary key to move left']
 | 
			
		||||
        self.KEY_RIGHT_PRIMARY = ['d', 'Main key to move right']
 | 
			
		||||
        self.KEY_RIGHT_SECONDARY = ['KEY_RIGHT', 'Secondary key to move right']
 | 
			
		||||
        self.KEY_ENTER = ['\n', 'Key to validate a menu']
 | 
			
		||||
        self.TEXTURE_PACK = ['ascii', 'Texture pack']
 | 
			
		||||
        self.LOCALE = [locale.getlocale()[0][:2], 'Language']
 | 
			
		||||
 | 
			
		||||
    def __getattribute__(self, item: str) -> Any:
 | 
			
		||||
        superattribute = super().__getattribute__(item)
 | 
			
		||||
@@ -53,10 +47,10 @@ class Settings:
 | 
			
		||||
        Retrieve the comment of a setting.
 | 
			
		||||
        """
 | 
			
		||||
        if item in self.settings_keys:
 | 
			
		||||
            return object.__getattribute__(self, item)[1]
 | 
			
		||||
            return _(object.__getattribute__(self, item)[1])
 | 
			
		||||
        for key in self.settings_keys:
 | 
			
		||||
            if getattr(self, key) == item:
 | 
			
		||||
                return object.__getattribute__(self, key)[1]
 | 
			
		||||
                return _(object.__getattribute__(self, key)[1])
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def settings_keys(self) -> Generator[str, Any, None]:
 | 
			
		||||
 
 | 
			
		||||
@@ -46,10 +46,10 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(entity.strength, 2)
 | 
			
		||||
        for _ in range(9):
 | 
			
		||||
            self.assertEqual(entity.hit(entity),
 | 
			
		||||
                             "tiger hits tiger. tiger takes 2 damage.")
 | 
			
		||||
                             "Tiger hits tiger. Tiger takes 2 damage.")
 | 
			
		||||
            self.assertFalse(entity.dead)
 | 
			
		||||
        self.assertEqual(entity.hit(entity), "tiger hits tiger. "
 | 
			
		||||
                         + "tiger takes 2 damage. tiger dies.")
 | 
			
		||||
        self.assertEqual(entity.hit(entity), "Tiger hits tiger. "
 | 
			
		||||
                         + "Tiger takes 2 damage. Tiger dies.")
 | 
			
		||||
        self.assertTrue(entity.dead)
 | 
			
		||||
 | 
			
		||||
        entity = Rabbit()
 | 
			
		||||
@@ -70,8 +70,8 @@ class TestEntities(unittest.TestCase):
 | 
			
		||||
        self.assertTrue(entity.y == 2 and entity.x == 6)
 | 
			
		||||
        self.assertEqual(old_health - entity.strength, self.player.health)
 | 
			
		||||
        self.assertEqual(self.map.logs.messages[-1],
 | 
			
		||||
                         f"{entity.name} hits {self.player.name}. \
 | 
			
		||||
{self.player.name} takes {entity.strength} damage.")
 | 
			
		||||
                         f"{entity.name.capitalize()} hits {self.player.name}. \
 | 
			
		||||
{self.player.name.capitalize()} takes {entity.strength} damage.")
 | 
			
		||||
 | 
			
		||||
        # Fight the rabbit
 | 
			
		||||
        old_health = entity.health
 | 
			
		||||
 
 | 
			
		||||
@@ -4,17 +4,16 @@
 | 
			
		||||
import os
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.resources import ResourceManager
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.enums import DisplayActions
 | 
			
		||||
 | 
			
		||||
from squirrelbattle.bootstrap import Bootstrap
 | 
			
		||||
from squirrelbattle.display.display import Display
 | 
			
		||||
from squirrelbattle.display.display_manager import DisplayManager
 | 
			
		||||
from squirrelbattle.entities.player import Player
 | 
			
		||||
from squirrelbattle.game import Game, KeyValues, GameMode
 | 
			
		||||
from squirrelbattle.menus import MainMenuValues
 | 
			
		||||
from squirrelbattle.settings import Settings
 | 
			
		||||
from ..bootstrap import Bootstrap
 | 
			
		||||
from ..display.display import Display
 | 
			
		||||
from ..display.display_manager import DisplayManager
 | 
			
		||||
from ..entities.player import Player
 | 
			
		||||
from ..enums import DisplayActions
 | 
			
		||||
from ..game import Game, KeyValues, GameMode
 | 
			
		||||
from ..menus import MainMenuValues
 | 
			
		||||
from ..resources import ResourceManager
 | 
			
		||||
from ..settings import Settings
 | 
			
		||||
from ..translations import gettext as _, Translator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestGame(unittest.TestCase):
 | 
			
		||||
@@ -275,12 +274,23 @@ class TestGame(unittest.TestCase):
 | 
			
		||||
        self.game.handle_key_pressed(KeyValues.ENTER)
 | 
			
		||||
        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
 | 
			
		||||
        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.assertEqual(self.game.state, GameMode.MAINMENU)
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ class TestSettings(unittest.TestCase):
 | 
			
		||||
        self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
 | 
			
		||||
                         settings.get_comment('TEXTURE_PACK'))
 | 
			
		||||
        self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
 | 
			
		||||
                         'Pack de textures utilisé')
 | 
			
		||||
                         'Texture pack')
 | 
			
		||||
 | 
			
		||||
        settings.TEXTURE_PACK = 'squirrel'
 | 
			
		||||
        self.assertEqual(settings.TEXTURE_PACK, 'squirrel')
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								squirrelbattle/tests/translations_test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								squirrelbattle/tests/translations_test.py
									
									
									
									
									
										Normal file
									
								
							@@ -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")
 | 
			
		||||
							
								
								
									
										96
									
								
								squirrelbattle/translations.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								squirrelbattle/translations.py
									
									
									
									
									
										Normal file
									
								
							@@ -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()
 | 
			
		||||
		Reference in New Issue
	
	Block a user