From b393bb157bae77187433b4acd7df1935147870d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Wed, 18 Nov 2020 20:16:46 +0100
Subject: [PATCH 1/2] add support for translation when used as a django app
 (#43082)

---
 debian/control           |  1 +
 eopayment/common.py      | 11 +++++++++++
 eopayment/dummy.py       | 23 ++++++++++-------------
 eopayment/keyware.py     |  6 ++----
 eopayment/mollie.py      |  2 +-
 eopayment/ogone.py       | 27 ++++++++++++---------------
 eopayment/paybox.py      | 17 ++++++++---------
 eopayment/payfip_ws.py   |  4 +---
 eopayment/sips2.py       |  3 +--
 eopayment/systempayv2.py | 33 ++++++++++++++++-----------------
 eopayment/tipi.py        |  3 +--
 setup.py                 | 37 +++++++++++++++++++++++++++++++++++++
 12 files changed, 101 insertions(+), 66 deletions(-)

diff --git a/debian/control b/debian/control
index 8eeffc6..a86f060 100644
--- a/debian/control
+++ b/debian/control
@@ -5,6 +5,7 @@ Maintainer: Frederic Peters <fpeters@debian.org>
 Build-Depends: debhelper (>= 9),
                python-all (>= 2.6),
                python-crypto,
+               python-django-common,
                python-requests,
                python-setuptools (>= 0.6b3),
                python-six,
diff --git a/eopayment/common.py b/eopayment/common.py
index 4d59229..13af15e 100644
--- a/eopayment/common.py
+++ b/eopayment/common.py
@@ -17,6 +17,7 @@
 import os.path
 import os
 import random
+import sys
 import logging
 from datetime import date
 from decimal import ROUND_DOWN, Decimal
@@ -28,6 +29,16 @@ if six.PY3:
 else:
     import cgi
 
+
+from gettext import gettext as _
+
+try:
+    if 'django' in sys.modules:
+        from django.utils.translation import ugettext_lazy as _
+except ImportError:
+    pass
+
+
 __all__ = ['PaymentCommon', 'URL', 'HTML', 'RANDOM', 'RECEIVED', 'ACCEPTED',
            'PAID', 'ERROR', 'WAITING']
 
diff --git a/eopayment/dummy.py b/eopayment/dummy.py
index 3128a68..48b4053 100644
--- a/eopayment/dummy.py
+++ b/eopayment/dummy.py
@@ -26,16 +26,13 @@ from .common import (
     ResponseError,
     URL,
     PAID, ERROR, WAITING,
-    force_text
+    force_text,
+    _
 )
 
 __all__ = ['Payment']
 
 
-def N_(message):
-    return message
-
-
 SERVICE_URL = 'http://dummy-payment.demo.entrouvert.com/'
 LOGGER = logging.getLogger(__name__)
 
@@ -65,31 +62,31 @@ class Payment(PaymentCommon):
         'parameters': [
             {
                 'name': 'normal_return_url',
-                'caption': N_('Normal return URL'),
+                'caption': _('Normal return URL'),
                 'default': '',
                 'required': True,
             },
             {
                 'name': 'automatic_return_url',
-                'caption': N_('Automatic return URL'),
+                'caption': _('Automatic return URL'),
                 'required': False,
             },
             {
                 'name': 'dummy_service_url',
-                'caption': 'URL of the dummy payment service',
+                'caption': _('URL of the dummy payment service'),
                 'default': SERVICE_URL,
                 'type': str,
             },
             {
                 'name': 'origin',
-                'caption': 'name of the requesting service, '
-                           'to present in the user interface',
+                'caption': _('name of the requesting service, '
+                           'to present in the user interface'),
                 'type': str,
                 'default': 'origin',
             },
             {
                 'name': 'consider_all_response_signed',
-                'caption': (
+                'caption': _(
                     'All response will be considered as signed '
                     '(to test payment locally for example, as you '
                     'cannot received the signed callback)'
@@ -115,13 +112,13 @@ class Payment(PaymentCommon):
             },
             {
                 'name': 'direct_notification_url',
-                'caption': 'direct notification url (replaced by automatic_return_url)',
+                'caption': _('direct notification url (replaced by automatic_return_url)'),
                 'type': str,
                 'deprecated': True,
             },
             {
                 'name': 'next_url (replaced by normal_return_url)',
-                'caption': 'Return URL for the user',
+                'caption': _('Return URL for the user'),
                 'type': str,
                 'deprecated': True,
             },
diff --git a/eopayment/keyware.py b/eopayment/keyware.py
index 6a4ff1f..034adee 100644
--- a/eopayment/keyware.py
+++ b/eopayment/keyware.py
@@ -14,13 +14,11 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from gettext import gettext as _
-
 import requests
 from six.moves.urllib.parse import parse_qs, urljoin
 
 from .common import (CANCELLED, ERROR, PAID, URL, WAITING, PaymentCommon,
-                     PaymentException, PaymentResponse, ResponseError)
+                     PaymentException, PaymentResponse, ResponseError, _)
 
 __all__ = ['Payment']
 
@@ -30,7 +28,7 @@ class Payment(PaymentCommon):
     service_url = 'https://api.online.emspay.eu/v1/'
 
     description = {
-        'caption': 'Keyware payment backend',
+        'caption': _('Keyware payment backend'),
         'parameters': [
             {
                 'name': 'normal_return_url',
diff --git a/eopayment/mollie.py b/eopayment/mollie.py
index 5395a1b..c6d205e 100644
--- a/eopayment/mollie.py
+++ b/eopayment/mollie.py
@@ -14,7 +14,7 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from gettext import gettext as _
+from .common import _
 
 import requests
 from six.moves.urllib.parse import parse_qs, urljoin
diff --git a/eopayment/ogone.py b/eopayment/ogone.py
index 9d759ef..369c199 100644
--- a/eopayment/ogone.py
+++ b/eopayment/ogone.py
@@ -24,13 +24,10 @@ from decimal import Decimal, ROUND_HALF_UP
 from .common import (
     PaymentCommon, PaymentResponse, FORM, CANCELLED, PAID,
     ERROR, Form, DENIED, ACCEPTED, ORDERID_TRANSACTION_SEPARATOR,
-    WAITING, ResponseError, force_byte, force_text
+    WAITING, ResponseError, force_byte, force_text, _
 )
 
 
-def N_(message):
-    return message
-
 ENVIRONMENT_TEST = 'TEST'
 ENVIRONMENT_TEST_URL = 'https://secure.ogone.com/ncol/test/orderstandard.asp'
 ENVIRONMENT_PROD = 'PROD'
@@ -434,54 +431,54 @@ VC
 class Payment(PaymentCommon):
     # See http://payment-services.ingenico.com/fr/fr/ogone/support/guides/integration%20guides/e-commerce
     description = {
-        'caption': N_('Système de paiement Ogone / Ingenico Payment System e-Commerce'),
+        'caption': _('Ogone / Ingenico Payment System e-Commerce'),
         'parameters': [
             {
                 'name': 'normal_return_url',
-                'caption': N_('Normal return URL'),
+                'caption': _('Normal return URL'),
                 'default': '',
                 'required': True,
             },
             {
                 'name': 'automatic_return_url',
-                'caption': N_('Automatic return URL (ignored, must be set in Ogone backoffice)'),
+                'caption': _('Automatic return URL (ignored, must be set in Ogone backoffice)'),
                 'required': False,
             },
             {
                 'name': 'environment',
                 'default': ENVIRONMENT_TEST,
-                'caption': N_(u'Environnement'),
+                'caption': 'Environnement',
                 'choices': ENVIRONMENT,
             },
             {
                 'name': 'pspid',
-                'caption': N_(u"Nom d'affiliation dans le système"),
+                'caption': "Nom d'affiliation dans le système",
                 'required': True,
             },
             {
                 'name': 'language',
-                'caption': N_(u'Langage'),
+                'caption': _(u'Language'),
                 'default': 'fr_FR',
-                'choices': (('fr_FR', N_('français')),),
+                'choices': (('fr_FR', 'français'),),
             },
             {
                 'name': 'hash_algorithm',
-                'caption': N_(u'Algorithme de hachage'),
+                'caption': 'Algorithme de hachage',
                 'default': 'sha1',
             },
             {
                 'name': 'sha_in',
-                'caption': N_(u'Clé SHA-IN'),
+                'caption': 'Clé SHA-IN',
                 'required': True,
             },
             {
                 'name': 'sha_out',
-                'caption': N_(u'Clé SHA-OUT'),
+                'caption': 'Clé SHA-OUT',
                 'required': True,
             },
             {
                 'name': 'currency',
-                'caption': N_(u'Monnaie'),
+                'caption': 'Monnaie',
                 'default': 'EUR',
                 'choices': ('EUR',),
             },
diff --git a/eopayment/paybox.py b/eopayment/paybox.py
index fdb7322..f839061 100644
--- a/eopayment/paybox.py
+++ b/eopayment/paybox.py
@@ -36,12 +36,11 @@ from six.moves.urllib import parse as urlparse
 from six.moves.urllib import parse as urllib
 
 import base64
-from gettext import gettext as _
 import warnings
 
 from .common import (PaymentCommon, PaymentResponse, FORM, PAID, CANCELLED,
                      DENIED, ERROR, Form, ResponseError, force_text,
-                     force_byte)
+                     force_byte, _)
 from . import cb
 
 __all__ = ['sign', 'Payment']
@@ -214,7 +213,7 @@ class Payment(PaymentCommon):
             },
             {
                 'name': 'platform',
-                'caption': _('Plateforme cible'),
+                'caption': 'Plateforme cible',
                 'default': 'test',
                 'choices': (
                     ('test', 'Test'),
@@ -224,7 +223,7 @@ class Payment(PaymentCommon):
             },
             {
                 'name': 'site',
-                'caption': _('Numéro de site'),
+                'caption': 'Numéro de site',
                 'required': True,
                 'validation': lambda x: isinstance(x, six.string_types)
                 and x.isdigit() and len(x) == 7,
@@ -237,28 +236,28 @@ class Payment(PaymentCommon):
             },
             {
                 'name': 'rang',
-                'caption': _('Numéro de rang'),
+                'caption': 'Numéro de rang',
                 'required': True,
                 'validation': lambda x: isinstance(x, six.string_types)
                 and x.isdigit() and len(x) == 2,
             },
             {
                 'name': 'identifiant',
-                'caption': _('Identifiant'),
+                'caption': 'Identifiant',
                 'required': True,
                 'validation': lambda x: isinstance(x, six.string_types)
                 and x.isdigit() and (0 < len(x) < 10),
             },
             {
                 'name': 'shared_secret',
-                'caption': _('Secret partagé (clé HMAC)'),
+                'caption': 'Secret partagé (clé HMAC)',
                 'validation': lambda x: isinstance(x, str)
                 and all(a.lower() in '0123456789abcdef' for a in x),
                 'required': True,
             },
             {
                 'name': 'devise',
-                'caption': _('Devise'),
+                'caption': 'Devise',
                 'default': '978',
                 'choices': (
                     ('978', 'Euro'),
@@ -271,7 +270,7 @@ class Payment(PaymentCommon):
             },
             {
                 'name': 'capture_day',
-                'caption': _('Nombre de jours pour un paiement différé'),
+                'caption': 'Nombre de jours pour un paiement différé',
                 'default': '',
                 'required': False,
                 'validation': lambda x: isinstance(x, six.string_types)
diff --git a/eopayment/payfip_ws.py b/eopayment/payfip_ws.py
index e2163c3..a7754bd 100644
--- a/eopayment/payfip_ws.py
+++ b/eopayment/payfip_ws.py
@@ -25,8 +25,6 @@ import re
 import unicodedata
 import xml.etree.ElementTree as ET
 
-from gettext import gettext as _
-
 import pytz
 
 import six
@@ -38,7 +36,7 @@ import zeep.exceptions
 from .systempayv2 import isonow
 from .common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED,
                      CANCELLED, ERROR, ResponseError, PaymentException,
-                     WAITING, EXPIRED, force_text)
+                     WAITING, EXPIRED, force_text, _)
 
 WSDL_URL = 'https://www.tipi.budget.gouv.fr/tpa/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService?wsdl'  # noqa: E501
 
diff --git a/eopayment/sips2.py b/eopayment/sips2.py
index 8e7291d..6e319e9 100644
--- a/eopayment/sips2.py
+++ b/eopayment/sips2.py
@@ -16,7 +16,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import datetime
-from gettext import gettext as _
 import collections
 import hashlib
 import hmac
@@ -31,7 +30,7 @@ import requests
 import pytz
 
 from .common import (PaymentCommon, FORM, Form, PaymentResponse, PAID, ERROR,
-                     CANCELED, ResponseError, force_text)
+                     CANCELED, ResponseError, force_text, _)
 
 __all__ = ['Payment']
 
diff --git a/eopayment/systempayv2.py b/eopayment/systempayv2.py
index f503976..2fd0eb2 100644
--- a/eopayment/systempayv2.py
+++ b/eopayment/systempayv2.py
@@ -26,10 +26,9 @@ import string
 import six
 from six.moves.urllib import parse as urlparse
 import warnings
-from gettext import gettext as _
 
 from .common import (PaymentCommon, PaymentResponse, PAID, DENIED, CANCELLED,
-                     ERROR, FORM, Form, ResponseError, force_text, force_byte)
+                     ERROR, FORM, Form, ResponseError, force_text, force_byte, _)
 from .cb import translate_cb_error_code
 
 __all__ = ['Payment']
@@ -135,20 +134,20 @@ PARAMETERS = [
     Parameter('vads_language', 'a', 12, length=2, default='fr'),
     Parameter('vads_order_id', 'an-', 13, max_length=32),
     Parameter('vads_order_info', 'an', 14, max_length=255,
-              description=_(u"Complément d'information 1")),
+              description="Complément d'information 1"),
     Parameter('vads_order_info2', 'an', 14, max_length=255,
-              description=_(u"Complément d'information 2")),
+              description="Complément d'information 2"),
     Parameter('vads_order_info3', 'an', 14, max_length=255,
-              description=_(u"Complément d'information 3")),
+              description="Complément d'information 3"),
     Parameter('vads_page_action', None, 46, needed=True, default='PAYMENT',
               choices=('PAYMENT',)),
     Parameter('vads_payment_cards', 'an;', 8, max_length=127, default='',
-              description=_(u'Liste des cartes de paiement acceptées'),
-              help_text=_(u'vide ou des valeurs sépareés par un point-virgule '
-                          'parmi AMEX, AURORE-MULTI, BUYSTER, CB, COFINOGA, '
-                          'E-CARTEBLEUE, MASTERCARD, JCB, MAESTRO, ONEY, '
-                          'ONEY_SANDBOX, PAYPAL, PAYPAL_SB, PAYSAFECARD, '
-                          'VISA')),
+              description='Liste des cartes de paiement acceptées',
+              help_text='vide ou des valeurs sépareés par un point-virgule '
+                        'parmi AMEX, AURORE-MULTI, BUYSTER, CB, COFINOGA, '
+                        'E-CARTEBLEUE, MASTERCARD, JCB, MAESTRO, ONEY, '
+                        'ONEY_SANDBOX, PAYPAL, PAYPAL_SB, PAYSAFECARD, '
+                        'VISA'),
     # must be SINGLE or MULTI with parameters
     Parameter('vads_payment_config', '', 7, default='SINGLE',
               choices=('SINGLE', 'MULTI'), needed=True),
@@ -156,7 +155,7 @@ PARAMETERS = [
               choices=('', 'NONE', 'POST', 'GET')),
     Parameter('signature', 'an', None, length=40),
     Parameter('vads_site_id', 'n', 2, length=8, needed=True,
-              description=_(u'Identifiant de la boutique')),
+              description='Identifiant de la boutique'),
     Parameter('vads_theme_config', 'ans', 32, max_length=255),
     Parameter(VADS_TRANS_DATE, 'n', 4, length=14, needed=True,
               default=isonow),
@@ -244,19 +243,19 @@ class Payment(PaymentCommon):
             },
             {'name': 'service_url',
                 'default': service_url,
-                'caption': _(u'URL du service de paiment'),
-                'help_text': _(u'ne pas modifier si vous ne savez pas'),
+                'caption': 'URL du service de paiment',
+                'help_text': 'ne pas modifier si vous ne savez pas',
                 'validation': lambda x: x.startswith('http'),
                 'required': True, },
             {'name': 'secret_test',
-                'caption': _(u'Secret pour la configuration de TEST'),
+                'caption': 'Secret pour la configuration de TEST',
                 'validation': lambda value: str.isalnum(value),
                 'required': True, },
             {'name': 'secret_production',
-                'caption': _(u'Secret pour la configuration de PRODUCTION'),
+                'caption': 'Secret pour la configuration de PRODUCTION',
                 'validation': lambda value: str.isalnum(value), },
             {'name': 'signature_algo',
-                'caption': _(u'Algorithme de signature'),
+                'caption': 'Algorithme de signature',
                 'default': 'sha1',
                 'choices': (
                     ('sha1', 'SHA-1'),
diff --git a/eopayment/tipi.py b/eopayment/tipi.py
index c231b59..6a17230 100644
--- a/eopayment/tipi.py
+++ b/eopayment/tipi.py
@@ -21,10 +21,9 @@ import random
 import pytz
 
 from .common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED,
-                     CANCELLED, ERROR, ResponseError)
+                     CANCELLED, ERROR, ResponseError, _)
 from six.moves.urllib.parse import urlencode, parse_qs
 
-from gettext import gettext as _
 import logging
 import warnings
 
diff --git a/setup.py b/setup.py
index 1287044..baf0421 100755
--- a/setup.py
+++ b/setup.py
@@ -6,10 +6,17 @@ Setup script for eopayment
 
 import io
 import subprocess
+
 import distutils
 import distutils.core
+from distutils.command.build import build as _build
+from distutils.cmd import Command
+from distutils.spawn import find_executable
+
 import setuptools
 from setuptools.command.sdist import sdist
+from setuptools.command.install_lib import install_lib as _install_lib
+
 from glob import glob
 from os.path import splitext, basename, join as pjoin
 import os
@@ -91,6 +98,33 @@ def get_version():
 
     return '0.0.0'
 
+
+class compile_translations(Command):
+    description = 'compile message catalogs to MO files via django compilemessages'
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        django_admin = find_executable('django-admin')
+        if django_admin:
+            subprocess.check_call([django_admin, 'compilemessages'])
+
+
+class build(_build):
+    sub_commands = [('compile_translations', None)] + _build.sub_commands
+
+
+class install_lib(_install_lib):
+    def run(self):
+        self.run_command('compile_translations')
+        _install_lib.run(self)
+
+
 setuptools.setup(
     name='eopayment',
     version=get_version(),
@@ -128,6 +162,9 @@ setuptools.setup(
         'zeep >= 2.5',
     ],
     cmdclass={
+        'build': build,
+        'compile_translations': compile_translations,
+        'install_lib': install_lib,
         'sdist': eo_sdist,
     }
 )
-- 
2.29.2

