diff --git a/VERSIONS.LST b/VERSIONS.LST
index 3e6f316..e784c3f 100644
--- a/VERSIONS.LST
+++ b/VERSIONS.LST
@@ -1,2 +1,2 @@
-# ver|url|checksum, and | as separator, one version per ||
-
+# ver|url|checksum, and | as separator, one version per ||
+3.1.2|https://github.com/neox95/CNIRevelator/releases/download/3.1.1/CNIRevelator.zip|cb2f4999e7265297008074e0e2beacbb2943a004||
\ No newline at end of file
diff --git a/src/CNIRevelator.py b/src/CNIRevelator.py
index 3fe7fb0..308d41c 100644
--- a/src/CNIRevelator.py
+++ b/src/CNIRevelator.py
@@ -23,22 +23,26 @@
* along with CNIRevelator. If not, see . *
********************************************************************************
"""
-
-import sys
+# Import critical files
import os
-import subprocess
import threading
-import traceback
-import psutil
-import launcher # launcher.py"
-import updater # updater.py
-import globs # globs.py
-import pytesseract # pytesseract.py
+import lang # lang.py
import logger # logger.py
+import globs # globs.py
+import critical # critical.py
+# Import all other files and crash if necessary
+try:
-from main import * # main.py
+ import launcher # launcher.py"
+ import updater # updater.py
+ import pytesseract # pytesseract.py
+ import ihm # ihm.py
+ from tkinter.messagebox import *
+ from tkinter import *
+except:
+ critical.crashCNIR()
# Global handler
logfile = logger.logCur
@@ -59,15 +63,17 @@ def main():
text = 'Tesseract version ' + str(tesser_version) + ' Licensed Apache 2004 successfully initiated\n'
mainw.logOnTerm(text)
- mainw.logOnTerm('\n\nEntrez la première ligne de MRZ svp \n')
+ mainw.logOnTerm('\n\n{} \n'.format(lang.all[globs.CNIRlang]["Please type a MRZ or open a scan"]))
+ # changelog
if globs.CNIRNewVersion:
- showinfo('Changelog : résumé de mise à jour', ('Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n' + globs.changelog), parent=mainw)
+ mainw.after_idle(mainw.showChangeLog)
+
logfile.printdbg('main() : **** Launching App_main() ****')
try:
mainw.mainloop()
except Exception as e:
- showerror("CNIRevelator Fatal Error", "An error has occured : {}".format(e), parent=mainw)
+ showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Error"], "{} : {}".format(lang.all[globs.CNIRlang]["An error has occured"],e), parent=mainw)
logfile.printdbg('main() : **** Ending App_main() ****')
logfile.printdbg('*** CNIRevelator LOGFILE. Goodbye World ! ***')
@@ -75,30 +81,45 @@ def main():
## BOOTSTRAP OF CNIREVELATOR
-
try:
- launcherThread = threading.Thread(target=updater.umain, daemon=False)
- launcher.lmain(launcherThread)
-except Exception:
- updater.exitProcess(1)
-if updater.UPDATE_IS_MADE:
- # Launch app !
- args = updater.UPATH + '\\CNIRevelator.exe ' + globs.CNIRFolder
- cd = updater.UPATH
- for i in range(0,3):
- try:
- updater.spawnProcess(args, cd)
- except:
- time.sleep(3)
- continue
- break
- updater.exitProcess(0)
+ try:
+ # LANGUAGE
+ lang.readLang()
+ except:
+ critical.crashCNIR()
+ updater.exitProcess(1)
-# Here we go !
-try:
- main()
-except Exception as e:
- traceback.print_exc(file=sys.stdout)
+ from main import * # main.py
+ # GO
+ try:
+ launcherThread = threading.Thread(target=updater.umain, daemon=False)
+ launcher.lmain(launcherThread)
+ except Exception:
+ critical.crashCNIR()
+ updater.exitProcess(1)
+
+ if updater.UPDATE_IS_MADE:
+ # Launch app !
+ args = updater.UPATH + '\\CNIRevelator.exe' + " DELETE " + globs.CNIRFolder
+ cd = updater.UPATH
+ for i in range(0,3):
+ try:
+ updater.spawnProcess(args, cd)
+ except:
+ time.sleep(3)
+ continue
+ break
+ updater.exitProcess(0)
+
+ # Here we go !
+ try:
+ main()
+ except Exception as e:
+ critical.crashCNIR()
+ updater.exitProcess(1)
+
+except:
+ critical.crashCNIR()
updater.exitProcess(0)
\ No newline at end of file
diff --git a/src/critical.py b/src/critical.py
new file mode 100644
index 0000000..e44639e
--- /dev/null
+++ b/src/critical.py
@@ -0,0 +1,66 @@
+"""
+********************************************************************************
+* CNIRevelator *
+* *
+* Desc: Critical Stuff for CNIRevelator *
+* *
+* Copyright © 2018-2019 Adrien Bourmault (neox95) *
+* *
+* This file is part of CNIRevelator. *
+* *
+* CNIRevelator is free software: you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation, either version 3 of the License, or *
+* any later version. *
+* *
+* CNIRevelator is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY*without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with CNIRevelator. If not, see . *
+********************************************************************************
+"""
+from tkinter.messagebox import *
+from importlib import reload
+from tkinter import *
+import webbrowser
+import traceback
+import psutil
+import os
+
+import lang # lang.py
+import logger # logger.py
+import globs # globs.py
+
+def crashCNIR(shutdown=True):
+ """
+ very last solution
+ """
+
+ try:
+ root = Tk()
+ root.withdraw()
+ logfile = logger.logCur
+ logfile.printerr("FATAL ERROR : see traceback below.\n{}".format(traceback.format_exc()))
+ showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github"], parent=root)
+ res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open the log file ?"], parent=root)
+ if res == "yes":
+ webbrowser.open_new(globs.CNIRErrLog)
+ res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open an issue on Github to report this bug ?"], parent=root)
+ if res == "yes":
+ webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
+ root.destroy()
+
+ # Quit ?
+ if not shutdown:
+ return
+
+ # Quit totally without remain in memory
+ for process in psutil.process_iter():
+ if process.pid == os.getpid():
+ process.terminate()
+ sys.exit(arg)
+ except:
+ traceback.print_exc()
\ No newline at end of file
diff --git a/src/downloader.py b/src/downloader.py
index c10a7e2..3faa243 100644
--- a/src/downloader.py
+++ b/src/downloader.py
@@ -32,9 +32,11 @@ from Crypto.Cipher import AES
from requests import Session
from time import time
+import critical # critical.py
import logger # logger.py
import globs # globs.py
import ihm # ihm.py
+import lang # lang.py
class AESCipher(object):
@@ -184,8 +186,8 @@ class newdownload:
reducedFilename = filename.split("\\")[-1]
- launcherWindow.printmsg('Downloading {}'.format(title))
- logfile.printdbg('Requesting download of {}'.format(reducedFilename))
+ launcherWindow.printmsg('{} {}'.format(lang.all[globs.CNIRlang]["Downloading"], title))
+ logfile.printdbg('{} {}'.format("Downloading", reducedFilename))
try:
os.remove(filename)
@@ -201,12 +203,12 @@ class newdownload:
launcherWindow.progressBar.stop()
launcherWindow.progressBar.configure(mode='determinate', value=(int(Percent)), maximum=100)
- launcherWindow.printmsg('Downloading {}'.format(title) + ' : {:4.2f} %'.format(Percent))
+ launcherWindow.printmsg('{} {}'.format(lang.all[globs.CNIRlang]["Downloading"], title) + ' : {:4.2f} %'.format(Percent))
launcherWindow.progressBar.configure(mode='indeterminate', value=0, maximum=20)
launcherWindow.progressBar.start()
- logfile.printdbg('Successful retrieved {}'.format(filename))
+ logfile.printdbg('{} {}'.format(lang.all[globs.CNIRlang]["Successful retrieved"], filename))
return filename
diff --git a/src/globs.py b/src/globs.py
index 42b1e6c..f3b0852 100644
--- a/src/globs.py
+++ b/src/globs.py
@@ -26,12 +26,9 @@ import os
# CNIRevelator version
verType = "final release"
-version = [3, 1, 0]
+version = [3, 1, 1]
verstring_full = "{}.{}.{} {}".format(version[0], version[1], version[2], verType)
verstring = "{}.{}".format(version[0], version[1])
-debug = True
-
-changelog = "Version 3.1.0 \nMise-à-jour majeure avec les progressions suivantes :\n- Modifications cosmétiques de l'interface utilisateur\n- Stabilisation des changements effectués sur la version mineure 3.0 : interface utilisateur, OCR, VISA A et B, logging"
CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
CNIRFolder = os.getcwd()
@@ -47,3 +44,28 @@ CNIRMainLog = CNIRFolder + '\\logs\\main.log'
CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
CNIREnv = CNIRFolder + '\\Data\\'
+
+
+CNIRTesserHash = '5b58db27f7bc08c58a2cb33d01533b034b067cf8'
+CNIRFolder = os.path.dirname(os.path.realpath(__file__))
+CNIRLColor = "#006699"
+CNIRName = "CNIRevelator {}".format(verstring)
+CNIRCryptoKey = '82Xh!efX3#@P~2eG'
+
+CNIRLangFile = CNIRFolder + '\\config\\lang.ig'
+CNIRlang = "fr"
+
+CNIRConfig = CNIRFolder + '\\config\\conf.ig'
+CNIRTesser = CNIRFolder + '\\Tesseract-OCR4\\'
+CNIRErrLog = CNIRFolder + '\\logs\\error.log'
+CNIRMainLog = CNIRFolder + '\\logs\\main.log'
+CNIRUrlConfig = CNIRFolder + '\\config\\urlconf.ig'
+CNIRVerStock = CNIRFolder + '\\downloads\\versions.lst'
+CNIREnv = CNIRFolder + '\\Data\\'
+
+CNIRBetaURL = "https://raw.githubusercontent.com/neox95/CNIRevelator/v3.1/VERSIONS.LST"
+CNIRDefaultURL = "https://raw.githubusercontent.com/neox95/CNIRevelator/master/VERSIONS.LST"
+
+CNIRNewVersion = False
+CNIROpenFile = False
+debug = True
\ No newline at end of file
diff --git a/src/ihm.py b/src/ihm.py
index 1c7d153..d6fb8ca 100644
--- a/src/ihm.py
+++ b/src/ihm.py
@@ -1,4 +1,4 @@
-"""
+"""
********************************************************************************
* CNIRevelator *
* *
@@ -23,19 +23,22 @@
********************************************************************************
"""
-from tkinter import *
-import webbrowser
from tkinter.messagebox import *
+from tkinter import *
from tkinter import filedialog
from tkinter import ttk
-import cv2
import PIL.Image, PIL.ImageTk
import traceback
+import webbrowser
+import cv2
+import critical # critical.py
import logger # logger.py
import globs # globs.py
import lang # lang.py
+import updater # updater.py
+import critical # critical.py
controlKeys = ["Escape", "Right", "Left", "Up", "Down", "Home", "End", "BackSpace", "Delete", "Inser", "Shift_L", "Shift_R", "Control_R", "Control_L"]
@@ -117,21 +120,22 @@ class LoginDialog(Toplevel):
self.login = ''
super().__init__(parent)
self.title(lang.all[globs.CNIRlang]["Connection"])
- Label(self, text='IPN : ').pack()
- self.entry_login = Entry(self)
+ self["background"] = "white"
+ Label(self, text='IPN : ', bg="white").pack(fill=Y)
+ self.entry_login = ttk.Entry(self)
self.entry_login.insert(0, '')
self.entry_login.pack()
- Label(self, text='{} : '.format(lang.all[globs.CNIRlang]["Password"])).pack()
- self.entry_pass = Entry(self, show='*')
+ Label(self, text='{} : '.format(lang.all[globs.CNIRlang]["Password"]), bg="white").pack(fill=Y)
+ self.entry_pass = ttk.Entry(self, show='*')
self.entry_pass.insert(0, '')
- self.entry_pass.pack()
- Button(self, text=lang.all[globs.CNIRlang]["Connection"], command=(self.connecti)).pack()
+ self.entry_pass.pack(fill=Y)
+ ttk.Button(self, text=lang.all[globs.CNIRlang]["Connection"], command=(self.connecti)).pack(fill=Y, pady=10)
+ self.update()
self.resizable(width=False, height=False)
ws = self.winfo_screenwidth()
hs = self.winfo_screenheight()
- w = hs / 10
- h = ws / 18
- self.update()
+ w = self.winfo_reqwidth() + 5
+ h = self.winfo_reqheight()
if getattr(sys, 'frozen', False):
self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
else:
@@ -146,6 +150,124 @@ class LoginDialog(Toplevel):
self.key = self.entry_pass.get().strip()
self.destroy()
+class ChangelogDialog(Toplevel):
+
+ def __init__(self, parent, text):
+ super().__init__(parent)
+
+ self.title(lang.all[globs.CNIRlang]["Show Changelog"])
+ self["background"] = "white"
+
+ self.grid_columnconfigure(0, weight=1)
+ self.grid_rowconfigure(0, weight=1)
+
+ self.text = Text(self, wrap='word', width=55, height=15, borderwidth=0, font="TkDefaultFont", bg="white")
+ self.text.grid(column=0, row=0, sticky='EWNS', padx=5, pady=5)
+
+ ttk.Button(self, text="OK", command=(self.oki)).grid(column=0, row=1, pady=5)
+
+ self.scrollb = ttk.Scrollbar(self, command=(self.text.yview))
+ self.scrollb.grid(column=1, row=0, sticky='EWNS', padx=5, pady=5)
+ self.text['yscrollcommand'] = self.scrollb.set
+
+ self.text.insert('end', text)
+ self.text['state'] = 'disabled'
+
+ self.update()
+ self.resizable(width=False, height=False)
+ ws = self.winfo_screenwidth()
+ hs = self.winfo_screenheight()
+ w = self.winfo_reqwidth() + 5
+ h = self.winfo_reqheight()
+ if getattr(sys, 'frozen', False):
+ self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
+ else:
+ self.iconbitmap('id-card.ico')
+ x = ws / 2 - w / 2
+ y = hs / 2 - h / 2
+ self.geometry('%dx%d+%d+%d' % (w, h, x, y))
+ self.bind("", self.oki)
+
+ def oki(self, event=None):
+ self.destroy()
+
+class langDialog(Toplevel):
+
+ def __init__(self, parent):
+ super().__init__(parent)
+
+ self.title(lang.all[globs.CNIRlang]["Language"])
+
+ Label(self, text=lang.all[globs.CNIRlang]["Please choose your language : "]).pack(fill=Y)
+
+ vals = [i for i in lang.all]
+ for i in range(len(lang.all)):
+ ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
+
+ ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
+
+ self.update()
+ self.resizable(width=False, height=False)
+ ws = self.winfo_screenwidth()
+ hs = self.winfo_screenheight()
+ w = self.winfo_reqwidth() + 5
+ h = self.winfo_reqheight()
+ if getattr(sys, 'frozen', False):
+ self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
+ else:
+ self.iconbitmap('id-card.ico')
+ x = ws / 2 - w / 2
+ y = hs / 2 - h / 2
+ self.geometry('%dx%d+%d+%d' % (w, h, x, y))
+ self.bind("", self.oki)
+
+ def oki(self, event=None):
+ self.destroy()
+
+ def createRegister(self, i):
+ def register():
+ lang.updateLang([j for j in lang.all][i])
+ return register
+
+class updateSetDialog(Toplevel):
+
+ def __init__(self, parent):
+ super().__init__(parent)
+
+ self.title(lang.all[globs.CNIRlang]["Update options"])
+
+ Label(self, text=lang.all[globs.CNIRlang]["Please choose your update channel : "]).pack(fill=Y)
+
+ self.vals = ["Stable", "Beta"]
+ vals = self.vals
+ for i in range(len(vals)):
+ ttk.Radiobutton(self, text=vals[i], command=self.createRegister(i), value=vals[i]).pack(fill=Y)
+
+ ttk.Button(self, text="OK", command=(self.oki)).pack(fill=Y, pady=5)
+
+ self.update()
+ self.resizable(width=False, height=False)
+ ws = self.winfo_screenwidth()
+ hs = self.winfo_screenheight()
+ w = self.winfo_reqwidth() + 5
+ h = self.winfo_reqheight()
+ if getattr(sys, 'frozen', False):
+ self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
+ else:
+ self.iconbitmap('id-card.ico')
+ x = ws / 2 - w / 2
+ y = hs / 2 - h / 2
+ self.geometry('%dx%d+%d+%d' % (w, h, x, y))
+ self.bind("", self.oki)
+
+ def oki(self, event=None):
+ self.destroy()
+
+ def createRegister(self, i):
+ def register():
+ updater.updateChannel(self.vals[i])
+ return register
+
class LauncherWindow(Tk):
def __init__(self):
@@ -153,6 +275,12 @@ class LauncherWindow(Tk):
Tk.__init__(self)
self.resizable(width=False, height=False)
+ # icon
+ if getattr(sys, 'frozen', False):
+ self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
+ else:
+ self.iconbitmap('id-card.ico')
+
# Setting up the geometry
ws = self.winfo_screenwidth()
hs = self.winfo_screenheight()
@@ -201,11 +329,6 @@ class LauncherWindow(Tk):
self.update()
self.progressBar.grid(row=1, sticky='S')
-
- if getattr(sys, 'frozen', False):
- self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
- else:
- self.iconbitmap('id-card.ico')
logfile = logger.logCur
logfile.printdbg('Launcher IHM successful')
self.protocol('WM_DELETE_WINDOW', lambda : 0)
@@ -233,22 +356,20 @@ class ResizeableCanvas(Canvas):
# rescale all the objects tagged with the "all" tag
self.scale("all",0,0,wscale,hscale)
-def crashCNIR():
- """
- last solution
- """
- # Global handler
- logfile = logger.logCur
- # hide main window
- root = Tk()
- root.withdraw()
- logfile.printerr("FATAL ERROR : see traceback below.\n{}".format(traceback.format_exc()))
- showerror(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github"])
- res = askquestion(lang.all[globs.CNIRlang]["CNIRevelator Fatal Eror"], lang.all[globs.CNIRlang]["Would you like to open an issue on Github to report this bug ?"])
- if res == "yes":
- webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
- root.destroy()
+class StatusBar(Frame):
+ def __init__(self, master):
+ Frame.__init__(self, master)
+ self.label = Label(self, bd=1, relief=SUNKEN, anchor=W)
+ self.label.pack(fill=X)
+
+ def set(self, text):
+ self.label.config(text="Document : " + text.lower())
+ self.label.update_idletasks()
+
+ def clear(self):
+ self.label.config(text="")
+ self.label.update_idletasks()
## Global Handler
launcherWindowCur = LauncherWindow()
diff --git a/src/lang.py b/src/lang.py
new file mode 100644
index 0000000..7c2c166
--- /dev/null
+++ b/src/lang.py
@@ -0,0 +1,1465 @@
+"""
+********************************************************************************
+* CNIRevelator *
+* *
+* Desc: Application langage file *
+* *
+* Copyright © 2018-2019 Adrien Bourmault (neox95) *
+* *
+* This file is part of CNIRevelator. *
+* *
+* CNIRevelator is free software: you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation, either version 3 of the License, or *
+* any later version. *
+* *
+* CNIRevelator is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY*without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with CNIRevelator. If not, see . *
+********************************************************************************
+"""
+import os
+
+import globs # globs.py
+import critical # critical.py
+
+## FRENCH LANGUAGE
+french = \
+{
+"Please type a MRZ or open a scan" : "Veuillez taper une MRZ ou ouvrir un scan svp",
+"Changelog : update summary" : "Changelog : résumé de mise à jour",
+"Program version" : "Version du logiciel",
+"CNIRevelator Fatal Error" : "Erreur fatale de CNIRevelator",
+"An error has occured" : "Une erreur s'est produite",
+"Downloading" : "Téléchargement de",
+"Successful retrieved" : "Réussite du téléchargement de",
+"Choose the identity document" : "Choisir le document d'identité",
+"OCR Detection Validation" : "Validation de la MRZ détectée par OCR",
+"Validate" : "Valider",
+"Validation Error" : "Erreur de validation",
+"The submitted MRZ contains invalid "
+ "characters" : "La MRZ soumise contient des caractères invalides",
+"Connection" : "Connexion",
+"Password" : "Mot de passe",
+"Booting up..." : "Démarrage",
+"CNIRevelator Fatal Eror" : "Erreur Fatale de CNIRevelator",
+"CNIRevelator crashed because a "
+"fatal error occured. View log for "
+"more infos and please open "
+"an issue on Github" : "CNIRevelator s'est arrêté car une erreur fatale s'est produite. Consultez le journal pour plus d'informations et ouvrez s'il vous plaît un ticket sur Github.",
+"Would you like to open the "
+"log file ?" : "Souhaitez-vous ouvrir le fichier de log ?",
+"Would you like to open an issue "
+"on Github to report this bug ?" : "Souhaitez-vous ouvrir un ticket sur Github pour signaler ce bogue?",
+"Starting..." : "Lancement...",
+"Informations about the current "
+"document" : "Informations sur la pièce d'identité",
+"IDLE" : "EN ATTENTE",
+"Status" : "Statut",
+"Name" : "Nom",
+"Birth date" : "Date de naissance",
+"Issue date" : "Date de délivrance",
+"Expiration date" : "Date d'expiration",
+"Sex" : "Sexe",
+"Issuing country" : "Pays émetteur",
+"Nationality" : "Nationalité",
+"Registration" : "Immatriculation",
+"Document number" : "N° de document",
+"Unknown" : "Inconnu(e)",
+"Display and processing of "
+"documents" : "Affichage et traitement de documents",
+"Complete MRZ capture terminal" : "Terminal de saisie de MRZ complète",
+"Quick entry terminal (731)" : "Terminal de saisie rapide (731)",
+"Monitor" : "Moniteur",
+"New" : "Nouveau",
+"Open scan..." : "Ouvrir scan...",
+"Quit" : "Quitter",
+"File" : "Fichier",
+"Settings" : "Paramètres",
+"Keyboard commands" : "Commandes au clavier",
+"Report a bug" : "Signaler un problème",
+"About CNIRevelator" : "A propos de CNIRevelator",
+"Help" : "Aide",
+"OCR module error" : "Erreur du module OCR",
+"The OCR module located at {} "
+"can not be found or corrupted. "
+"It will be reinstalled at "
+"the next run" : "Le module OCR localisé en {} est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution",
+"The Tesseract module "
+"encountered a problem: {}" : "Le module Tesseract a rencontré un problème : {}",
+"Tesseract error : {}. "
+"Will be reinstallated" : "Erreur de Tesseract : {}. Le module sera réinstallé",
+"Document detected: {}\n" : "Document detecté : {}\n",
+"Document detected again: {}\n" : "Document re-detecté : {}\n",
+"Character not accepted !\n" : "Caractère non accepté !\n",
+"Open a scan of document..." : "Ouvrir un scan de document...",
+"OpenCV error (image processing)" : "Erreur OpenCV (traitement d'images)",
+"A critical error has occurred in "
+"the OpenCV image processing "
+"manager used by CNIRevelator, the "
+"application will reset itself" : "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser",
+"ABOUT" : 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n'
+ "Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
+ "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer "
+ "dans les termes de la GNU General Public License telle que publiée par "
+ "la Free Software Foundation, dans sa version 3 ou "
+ "ultérieure. " + "\n\n"
+ "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois "
+ "impliquer une quelconque garantie de "
+ "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la "
+ "GNU General Public License pour plus de détails à ce sujet. "
+ "\n\n"
+ "Vous devriez avoir reçu une copie de la GNU General Public License "
+ "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à . "
+ "\n\n"
+ "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004."
+ "\n\n"
+ "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019."
+ "\n\n"
+ "Le code source de ce programme est disponible sur Github à l'adresse .\n"
+ "Son fonctionnement est conforme aux normes et directives du document 9303 de l'OACI régissant les documents de voyages et d'identité." + '\n\n'
+ " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !\n\n",
+
+"KEYBHELP" : "Terminal de saisie rapide (731) : \n\n"
+ "Caractères autorisés : Alphanumériques en majuscule et le caractère '<'. Pas de minuscules ni caractères spéciaux, autrement la somme est mise à zéro \n\n"
+ "Calculer résultat :\t\t\tTouche Ctrl droite \n"
+ "Copier :\t\t\t\tCtrl-C \n"
+ "Coller :\t\t\t\tCtrl-V \n"
+ "\n\n"
+ "Terminal de saisie MRZ complète : \n\n"
+ "Caractères autorisés : Alphanumériques en majuscule et le caractère '<'. Pas de minuscules ni caractères spéciaux, autrement la somme est mise à zéro \n\n"
+ "Calculer résultat :\t\t\tTouche Ctrl droite \n"
+ "Compléter champ :\t\t\tTouche Tab \n"
+ "Copier :\t\t\t\tCtrl-C \n"
+ "Coller :\t\t\t\tCtrl-V \n"
+ "Forcer une nouvelle détection du document :\tEchap\n",
+
+"CHANGELOG" : "Version 3.1.1 \nMise-à-jour mineure avec les progressions suivantes :\n- Correction d'un bug sévère du système de mise à jour\n\n" + \
+"Version 3.1.0 \nMise-à-jour majeure avec les progressions suivantes :\n- Modifications cosmétiques de l'interface utilisateur\n- Stabilisation des changements effectués sur la version mineure 3.0 : interface utilisateur, OCR, VISA A et B, logging\n- Rationalisation du système de langues\n- Ajout des canaux de mise-à-jour\n\n" + \
+"Version 3.0.8 finale\nCorrectif : bug du système de mise-à-jour'\n\n" + \
+"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \
+"Version 3.0.7 finale\nMise-à-jour majeure avec les corrections suivantes :\n- Refonte de l'interface utilisateur\n- Fonction OCR intégrée à l'application avec support des TIFF et JPEG\n- Corrections d'erreurs sur le traitement des VISA de type A et B, ainsi que les titres de séjour\n\n" + \
+"Version 3.0.6 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'apparence du launcher de l'application\n- Améliorations de l'interface, notamment de la stabilité\n- Ajout de la signature numérique de l'exécutable\n\n" + \
+"Version 3.0.5 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement de l'icône de l'exécutable afin de refléter le changement de version majeur accompli en 3.0\n\n" + \
+"Version 3.0.4 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le système de mise-à-jour\n\n" + \
+"Version 3.0.3 \nMise-à-jour mineure avec les corrections suivantes :\n- Correction d'un bug affectant le changelog\n- Correction d'une erreur avec la touche Suppr Arrière et Suppr causant une perte de données\n\n" + \
+"Version 3.0.2 \nMise-à-jour mineure avec les corrections suivantes :\n- Changement d'icône de l'exécutable\n- Correction d'un bug affectant le logging\n- Correction d'un bug affectant la détection de documents\n- Et autres modifications mineures\n\n" + \
+"Version 3.0.1 \nMise-à-jour majeure avec les corrections suivantes :\n- Renouvellement de la signature numérique de l'exécutable\n- Amélioration de présentation du log en cas d'erreur\n- Refonte totale du code source et désobfuscation\n- Téléchargements en HTTPS fiables avec somme de contrôle\n- Nouveaux terminaux d'entrées : un rapide (731) et un complet\n- Détection des documents améliorée, possibilité de choix plus fin\nEt les regressions suivantes :\n- Suppression temporaire de la fonction de lecture OCR. Retour planifié pour une prochaine version",
+
+"Document Review: {}\n\n" : "Examen du document : {}\n\n",
+"Calculated {} [facultative]\n" : "Checksum position {}: Lu {} VS Calculé {} [facultatif]\n",
+"Checksum position {}: Lu {} VS "
+"Calculated {}\n" : "Checksum position {}: Lu {} VS Calculé {}\n",
+"COMPLIANT" : "CONFORME",
+"IMPROPER" : "NON CONFORME",
+"Installing the updates" : "Installation des mises-à-jour",
+"Verifying download..." : "Vérification du téléchargement ...",
+"Preparing installation..." : "Préparation de l'installation",
+"Success !" : "Installation terminée !",
+"Launching the new version..." : "Lancement de la nouvelle version...",
+"Credentials Error. No effective "
+"update !" : "Identifiants incorrects. Pas de mise-à-jour !",
+"Deleting old version" : "Suppression de l'ancienne version",
+'Software is up-to-date !' : "Logiciel à jour !",
+"An error occured. "
+"No effective update !" : "Une erreur s'est produite. Pas de mise-à-jour !",
+"Shortcut creation" : "Création de raccourci",
+"Would you like to create/update "
+"the shortcut for CNIRevelator "
+"on your desktop ?" : "Souhaitez vous créer/mettre à jour le raccourci pour CNIRevelator sur votre bureau ?",
+"The file you provided is "
+"not found : {}" : "Fichier transmis non trouvé : {}",
+"Update options" : "Options de mise-à-jour",
+"Language" : "Langue",
+"Show Changelog" : "Résumé de mise-à-jour",
+"Please choose your language : " : "Merci de choisir votre langue : ",
+"Please choose your update "
+"channel : " : "Merci de choisir votre canal de mise-à-jour : ",
+"Passeport" : "Passeport",
+"Carte-passeport" : "Carte-passeport",
+"Titre d'identité/de voyage" : "Titre d'identité/de voyage",
+"Certificat de membre d'équipage" : "Certificat de membre d'équipage",
+"Visa de type A" : "Visa de type A",
+"Visa de type B" : "Visa de type B",
+"Carte de séjour" : "Carte de séjour",
+"Pièce d'identité/de voyage" : "Pièce d'identité/de voyage",
+"Pièce d'identité FR" : "Pièce d'identité FR",
+"Permis de conduire" : "Permis de conduire",
+
+"LANDCODE2" : {
+ 'AW': 'Aruba',
+ 'AF': 'Afghanistan',
+ 'AO': 'Angola',
+ 'AI': 'Anguilla',
+ 'AL': 'Albanie',
+ 'AD': 'Andorre',
+ 'AE': 'Emirats arabes unis',
+ 'AR': 'Argentine',
+ 'AM': 'Arménie',
+ 'AS': 'Samoa américaines',
+ 'AQ': 'Antarctique',
+ 'TF': 'Terres australes et antarctiques françaises',
+ 'AG': 'Antigua-et-Barbuda',
+ 'AU': 'Australie',
+ 'AT': 'Autriche',
+ 'AZ': 'Azerbaidjan',
+ 'BI': 'Burundi',
+ 'BE': 'Belgique',
+ 'BJ': 'Benin',
+ 'BQ': 'Pays-Bas caribéens',
+ 'BF': 'Burkina Faso',
+ 'BD': 'Bangladesh',
+ 'BG': 'Bulgarie',
+ 'BH': 'Bahrein',
+ 'BS': 'Bahamas',
+ 'BA': 'Bosnie-Herzegovine',
+ 'BL': 'Saint-Barthélemy',
+ 'BY': 'Bielorussie',
+ 'BZ': 'Belize',
+ 'BM': 'Bermudes',
+ 'BO': 'Bolivie',
+ 'BR': 'Brésil',
+ 'BB': 'Barbade',
+ 'BN': 'Brunei',
+ 'BT': 'Bhoutan',
+ 'BW': 'Botswana',
+ 'CF': 'République Centrafricaine',
+ 'CA': 'Canada',
+ 'CC': 'Îles Cocos',
+ 'CH': 'Suisse',
+ 'CL': 'Chili',
+ 'CN': 'Chine',
+ 'CI': "Côte d'Ivoire",
+ 'CM': 'Cameroun',
+ 'CD': 'Congo (République démocratique)',
+ 'CG': 'Congo (République)',
+ 'CK': 'Îles Cook',
+ 'CO': 'Colombie',
+ 'KM': 'Comores',
+ 'CV': 'Cap-Vert',
+ 'CR': 'Costa Rica',
+ 'CU': 'Cuba',
+ 'CW': 'Curaçao',
+ 'CX': 'Île Christmas',
+ 'KY': 'Caimans',
+ 'CY': 'Chypre',
+ 'CZ': 'Tchéquie',
+ 'DE': 'Allemagne',
+ 'DJ': 'Djibouti',
+ 'DM': 'Dominique',
+ 'DK': 'Danemark',
+ 'DO': 'République dominicaine',
+ 'DZ': 'Algérie',
+ 'EC': 'Equateur',
+ 'EG': 'Egypte',
+ 'ER': 'Erythrée',
+ 'EH': 'Sahara occidental',
+ 'ES': 'Espagne',
+ 'EE': 'Estonie',
+ 'ET': 'Ethiopie',
+ 'FI': 'Finlande',
+ 'FJ': 'Fidji',
+ 'FK': 'Îles Malouines',
+ 'FR': 'France',
+ 'FO': 'Féroé',
+ 'FM': 'Micronésie',
+ 'GA': 'Gabon',
+ 'GB': 'Royaume-Uni',
+ 'GE': 'Géorgie',
+ 'GG': 'Guernesey',
+ 'GH': 'Ghana',
+ 'GI': 'Gibraltar',
+ 'GN': 'Guinée',
+ 'GP': 'Guadeloupe',
+ 'GM': 'Gambie',
+ 'GW': 'Guinée-Bissau',
+ 'GQ': 'Guinée équatoriale',
+ 'GR': 'Grèce',
+ 'GD': 'Grenade',
+ 'GL': 'Groenland',
+ 'GT': 'Guatemala',
+ 'GF': 'Guyane',
+ 'GU': 'Guam',
+ 'GY': 'Guyana',
+ 'HK': 'Hong Kong',
+ 'HN': 'Honduras',
+ 'HR': 'Croatie',
+ 'HT': 'Haïti',
+ 'HU': 'Hongrie',
+ 'ID': 'Indonésie',
+ 'IM': 'Île de Man',
+ 'IN': 'Inde',
+ 'IO': "Territoire britannique de l'océan Indien",
+ 'IE': 'Irlande',
+ 'IR': 'Irak',
+ 'IQ': 'Iran',
+ 'IS': 'Islande',
+ 'IL': 'Israël',
+ 'IT': 'Italie',
+ 'JM': 'Jamaïque',
+ 'JE': 'Jersey',
+ 'JO': 'Jordanie',
+ 'JP': 'Japon',
+ 'KZ': 'Kazakhstan',
+ 'KE': 'Kenya',
+ 'KG': 'Kirghizistan',
+ 'KH': 'Cambodge',
+ 'KI': 'Kiribati',
+ 'KN': 'Saint-Christophe-et-Niévès',
+ 'KR': 'Corée du Sud',
+ 'KW': 'Koweït',
+ 'LA': 'Laos',
+ 'LB': 'Liban',
+ 'LR': 'Liberia',
+ 'LY': 'Libye',
+ 'LC': 'Sainte-Lucie',
+ 'LI': 'Liechtenstein',
+ 'LK': 'Sri Lanka',
+ 'LS': 'Lesotho',
+ 'LT': 'Lituanie',
+ 'LU': 'Luxembourg',
+ 'LV': 'Lettonie',
+ 'MO': 'Macao',
+ 'MF': 'Sint-Maarten',
+ 'MA': 'Maroc',
+ 'MC': 'Monaco',
+ 'MD': 'Moldavie',
+ 'MG': 'Madagascar',
+ 'MV': 'Maldives',
+ 'MX': 'Mexique',
+ 'MH': 'Marshall',
+ 'MK': 'Macedoine',
+ 'ML': 'Mali',
+ 'MT': 'Malte',
+ 'MM': 'Birmanie',
+ 'ME': 'Monténégro',
+ 'MN': 'Mongolie',
+ 'MP': 'Îles Mariannes du Nord',
+ 'MZ': 'Mozambique',
+ 'MR': 'Mauritanie',
+ 'MS': 'Montserrat',
+ 'MQ': 'Martinique',
+ 'MU': 'Maurice',
+ 'MW': 'Malawi',
+ 'MY': 'Malaisie',
+ 'YT': 'Mayotte',
+ 'NA': 'Namibie',
+ 'NC': 'Nouvelle-Calédonie',
+ 'NE': 'Niger',
+ 'NF': 'Île Norfolk',
+ 'NG': 'Nigeria',
+ 'NI': 'Nicaragua',
+ 'NU': 'Niue',
+ 'NL': 'Pays-Bas',
+ 'NO': 'Norvège',
+ 'NP': 'Nepal',
+ 'NR': 'Nauru',
+ 'NZ': 'Nouvelle-Zélande',
+ 'OM': 'Oman',
+ 'PK': 'Pakistan',
+ 'PA': 'Panama',
+ 'PN': 'Îles Pitcairn',
+ 'PE': 'Pérou',
+ 'PH': 'Philippines',
+ 'PW': 'Palaos',
+ 'PG': 'Papouasie-Nouvelle-Guinée',
+ 'PL': 'Pologne',
+ 'PR': 'Porto Rico',
+ 'KP': 'Corée du Nord',
+ 'PT': 'Portugal',
+ 'PY': 'Paraguay',
+ 'PS': 'Palestine',
+ 'PF': 'Polynésie française',
+ 'QA': 'Qatar',
+ 'RE': 'Réunion',
+ 'RO': 'Roumanie',
+ 'RU': 'Russie',
+ 'RW': 'Rwanda',
+ 'SA': 'Arabie saoudite',
+ 'SD': 'Soudan',
+ 'SN': 'Sénégal',
+ 'SG': 'Singapour',
+ 'GS': 'Georgie du Sud-et-les iles Sandwich du Sud',
+ 'SH': 'Sainte-Hélène, Ascension et Tristan da Cunha',
+ 'SJ': 'Svalbard et île Jan Mayen',
+ 'SB': 'Salomon',
+ 'SL': 'Sierra Leone',
+ 'SV': 'Salvador',
+ 'SM': 'Saint-Marin',
+ 'SO': 'Somalie',
+ 'PM': 'Saint-Pierre-et-Miquelon',
+ 'RS': 'Serbie',
+ 'SS': 'Soudan du Sud',
+ 'ST': 'Sao Tomé-et-Principe',
+ 'SR': 'Suriname',
+ 'SK': 'Slovaquie',
+ 'SI': 'Slovénie',
+ 'SE': 'Suède',
+ 'SZ': 'eSwatani',
+ 'SX': 'Saint-Martin ',
+ 'SC': 'Seychelles',
+ 'SY': 'Syrie',
+ 'TC': 'Îles Turques-et-Caïques',
+ 'TD': 'Tchad',
+ 'TG': 'Togo',
+ 'TH': 'Thaïlande',
+ 'TJ': 'Tadjikistan',
+ 'TK': 'Tokelau',
+ 'TM': 'Turkmenistan',
+ 'TL': 'Timor oriental',
+ 'TO': 'Tonga',
+ 'TT': 'Trinité-et-Tobago',
+ 'TN': 'Tunisie',
+ 'TR': 'Turquie',
+ 'TV': 'Tuvalu',
+ 'TW': 'Taiwan',
+ 'TZ': 'Tanzanie',
+ 'UG': 'Ouganda',
+ 'UA': 'Ukraine',
+ 'UY': 'Uruguay',
+ 'US': 'Etats-Unis',
+ 'UZ': 'Ouzbékistan',
+ 'VA': 'Saint-Siège (État de la Cité du Vatican)',
+ 'VC': 'Saint-Vincent-et-les-Grenadines',
+ 'VE': 'Venezuela',
+ 'VG': 'Îles Vierges britanniques',
+ 'VI': 'Îles Vierges des États-Unis',
+ 'VN': 'Viêt Nam',
+ 'VU': 'Vanuatu',
+ 'WF': 'Wallis-et-Futuna',
+ 'WS': 'Samoa',
+ 'XK': 'Kosovo',
+ 'YE': 'Yémen',
+ 'ZA': 'Afrique du Sud',
+ 'ZM': 'Zambie',
+ 'ZW': 'Zimbabwe'
+ },
+
+"LANDCODE3" : {
+ 'ABW': 'Aruba',
+ 'AFG': 'Afghanistan',
+ 'AGO': 'Angola',
+ 'AIA': 'Anguilla',
+ 'ALB': 'Albanie',
+ 'AND': 'Andorre',
+ 'ARE': 'Emirats arabes unis',
+ 'ARG': 'Argentine',
+ 'ARM': 'Arménie',
+ 'ASM': 'Samoa américaines',
+ 'ATA': 'Antarctique',
+ 'ATF': 'Terres australes et antarctiques françaises',
+ 'ATG': 'Antigua-et-Barbuda',
+ 'AUS': 'Australie',
+ 'AUT': 'Autriche',
+ 'AZE': 'Azerbaidjan',
+ 'BDI': 'Burundi',
+ 'BEL': 'Belgique',
+ 'BEN': 'Benin',
+ 'BES': 'Pays-Bas caribéens',
+ 'BFA': 'Burkina Faso',
+ 'BGD': 'Bangladesh',
+ 'BGR': 'Bulgarie',
+ 'BHR': 'Bahrein',
+ 'BHS': 'Bahamas',
+ 'BIH': 'Bosnie-Herzegovine',
+ 'BLM': 'Saint-Barthélemy',
+ 'BLR': 'Bielorussie',
+ 'BLZ': 'Belize',
+ 'BMU': 'Bermudes',
+ 'BOL': 'Bolivie',
+ 'BRA': 'Brésil',
+ 'BRB': 'Barbade',
+ 'BRN': 'Brunei',
+ 'BTN': 'Bhoutan',
+ 'BWA': 'Botswana',
+ 'CAF': 'République Centrafricaine',
+ 'CAN': 'Canada',
+ 'CCK': 'Îles Cocos',
+ 'CHE': 'Suisse',
+ 'CHL': 'Chili',
+ 'CHN': 'Chine',
+ 'CIV': "Côte d'Ivoire",
+ 'CMR': 'Cameroun',
+ 'COD': 'Congo (République démocratique)',
+ 'COG': 'Congo (République)',
+ 'COK': 'Îles Cook',
+ 'COL': 'Colombie',
+ 'COM': 'Comores',
+ 'CPV': 'Cap-Vert',
+ 'CRI': 'Costa Rica',
+ 'CUB': 'Cuba',
+ 'CUW': 'Curaçao',
+ 'CXR': 'Île Christmas',
+ 'CYM': 'Caimans',
+ 'CYP': 'Chypre',
+ 'CZE': 'Tchéquie',
+ 'DEU': 'Allemagne',
+ 'DJI': 'Djibouti',
+ 'DMA': 'Dominique',
+ 'DNK': 'Danemark',
+ 'DOM': 'République dominicaine',
+ 'DZA': 'Algérie',
+ 'ECU': 'Equateur',
+ 'EGY': 'Egypte',
+ 'ERI': 'Erythrée',
+ 'ESH': 'Sahara occidental',
+ 'ESP': 'Espagne',
+ 'EST': 'Estonie',
+ 'ETH': 'Ethiopie',
+ 'FIN': 'Finlande',
+ 'FJI': 'Fidji',
+ 'FLK': 'Îles Malouines',
+ 'FRA': 'France',
+ 'FRO': 'Féroé',
+ 'FSM': 'Micronésie',
+ 'GAB': 'Gabon',
+ 'GBR': 'Royaume-Uni',
+ 'GEO': 'Géorgie',
+ 'GGY': 'Guernesey',
+ 'GHA': 'Ghana',
+ 'GIB': 'Gibraltar',
+ 'GIN': 'Guinée',
+ 'GLP': 'Guadeloupe',
+ 'GMB': 'Gambie',
+ 'GNB': 'Guinée-Bissau',
+ 'GNQ': 'Guinée équatoriale',
+ 'GRC': 'Grèce',
+ 'GRD': 'Grenade',
+ 'GRL': 'Groenland',
+ 'GTM': 'Guatemala',
+ 'GUF': 'Guyane',
+ 'GUM': 'Guam',
+ 'GUY': 'Guyana',
+ 'HKG': 'Hong Kong',
+ 'HND': 'Honduras',
+ 'HRV': 'Croatie',
+ 'HTI': 'Haïti',
+ 'HUN': 'Hongrie',
+ 'IDN': 'Indonésie',
+ 'IMN': 'Île de Man',
+ 'IND': 'Inde',
+ 'IOT': "Territoire britannique de l'océan Indien",
+ 'IRL': 'Irlande',
+ 'IRN': 'Irak',
+ 'IRQ': 'Iran',
+ 'ISL': 'Islande',
+ 'ISR': 'Israël',
+ 'ITA': 'Italie',
+ 'JAM': 'Jamaïque',
+ 'JEY': 'Jersey',
+ 'JOR': 'Jordanie',
+ 'JPN': 'Japon',
+ 'KAZ': 'Kazakhstan',
+ 'KEN': 'Kenya',
+ 'KGZ': 'Kirghizistan',
+ 'KHM': 'Cambodge',
+ 'KIR': 'Kiribati',
+ 'KNA': 'Saint-Christophe-et-Niévès',
+ 'KOR': 'Corée du Sud',
+ 'KWT': 'Koweït',
+ 'LAO': 'Laos',
+ 'LBN': 'Liban',
+ 'LBR': 'Liberia',
+ 'LBY': 'Libye',
+ 'LCA': 'Sainte-Lucie',
+ 'LIE': 'Liechtenstein',
+ 'LKA': 'Sri Lanka',
+ 'LSO': 'Lesotho',
+ 'LTU': 'Lituanie',
+ 'LUX': 'Luxembourg',
+ 'LVA': 'Lettonie',
+ 'MAC': 'Macao',
+ 'MAF': 'Sint-Maarten',
+ 'MAR': 'Maroc',
+ 'MCO': 'Monaco',
+ 'MDA': 'Moldavie',
+ 'MDG': 'Madagascar',
+ 'MDV': 'Maldives',
+ 'MEX': 'Mexique',
+ 'MHL': 'Marshall',
+ 'MKD': 'Macedoine',
+ 'MLI': 'Mali',
+ 'MLT': 'Malte',
+ 'MMR': 'Birmanie',
+ 'MNE': 'Monténégro',
+ 'MNG': 'Mongolie',
+ 'MNP': 'Îles Mariannes du Nord',
+ 'MOZ': 'Mozambique',
+ 'MRT': 'Mauritanie',
+ 'MSR': 'Montserrat',
+ 'MTQ': 'Martinique',
+ 'MUS': 'Maurice',
+ 'MWI': 'Malawi',
+ 'MYS': 'Malaisie',
+ 'MYT': 'Mayotte',
+ 'NAM': 'Namibie',
+ 'NCL': 'Nouvelle-Calédonie',
+ 'NER': 'Niger',
+ 'NFK': 'Île Norfolk',
+ 'NGA': 'Nigeria',
+ 'NIC': 'Nicaragua',
+ 'NIU': 'Niue',
+ 'NLD': 'Pays-Bas',
+ 'NOR': 'Norvège',
+ 'NPL': 'Nepal',
+ 'NRU': 'Nauru',
+ 'NZL': 'Nouvelle-Zélande',
+ 'OMN': 'Oman',
+ 'PAK': 'Pakistan',
+ 'PAN': 'Panama',
+ 'PCN': 'Îles Pitcairn',
+ 'PER': 'Pérou',
+ 'PHL': 'Philippines',
+ 'PLW': 'Palaos',
+ 'PNG': 'Papouasie-Nouvelle-Guinée',
+ 'POL': 'Pologne',
+ 'PRI': 'Porto Rico',
+ 'PRK': 'Corée du Nord',
+ 'PRT': 'Portugal',
+ 'PRY': 'Paraguay',
+ 'PSE': 'Palestine',
+ 'PYF': 'Polynésie française',
+ 'QAT': 'Qatar',
+ 'REU': 'Réunion',
+ 'ROU': 'Roumanie',
+ 'RUS': 'Russie',
+ 'RWA': 'Rwanda',
+ 'SAU': 'Arabie saoudite',
+ 'SDN': 'Soudan',
+ 'SEN': 'Sénégal',
+ 'SGP': 'Singapour',
+ 'SGS': 'Georgie du Sud-et-les iles Sandwich du Sud',
+ 'SHN': 'Sainte-Hélène, Ascension et Tristan da Cunha',
+ 'SJM': 'Svalbard et île Jan Mayen',
+ 'SLB': 'Salomon',
+ 'SLE': 'Sierra Leone',
+ 'SLV': 'Salvador',
+ 'SMR': 'Saint-Marin',
+ 'SOM': 'Somalie',
+ 'SPM': 'Saint-Pierre-et-Miquelon',
+ 'SRB': 'Serbie',
+ 'SSD': 'Soudan du Sud',
+ 'STP': 'Sao Tomé-et-Principe',
+ 'SUR': 'Suriname',
+ 'SVK': 'Slovaquie',
+ 'SVN': 'Slovénie',
+ 'SWE': 'Suède',
+ 'SWZ': 'eSwatani',
+ 'SXM': 'Saint-Martin ',
+ 'SYC': 'Seychelles',
+ 'SYR': 'Syrie',
+ 'TCA': 'Îles Turques-et-Caïques',
+ 'TCD': 'Tchad',
+ 'TGO': 'Togo',
+ 'THA': 'Thaïlande',
+ 'TJK': 'Tadjikistan',
+ 'TKL': 'Tokelau',
+ 'TKM': 'Turkmenistan',
+ 'TLS': 'Timor oriental',
+ 'TON': 'Tonga',
+ 'TTO': 'Trinité-et-Tobago',
+ 'TUN': 'Tunisie',
+ 'TUR': 'Turquie',
+ 'TUV': 'Tuvalu',
+ 'TWN': 'Taiwan',
+ 'TZA': 'Tanzanie',
+ 'UGA': 'Ouganda',
+ 'UKR': 'Ukraine',
+ 'URY': 'Uruguay',
+ 'USA': 'Etats-Unis',
+ 'UZB': 'Ouzbékistan',
+ 'VAT': 'Saint-Siège (État de la Cité du Vatican)',
+ 'VCT': 'Saint-Vincent-et-les-Grenadines',
+ 'VEN': 'Venezuela',
+ 'VGB': 'Îles Vierges britanniques',
+ 'VIR': 'Îles Vierges des États-Unis',
+ 'VNM': 'Viêt Nam',
+ 'VUT': 'Vanuatu',
+ 'WLF': 'Wallis-et-Futuna',
+ 'WSM': 'Samoa',
+ 'XKX': 'Kosovo',
+ 'YEM': 'Yémen',
+ 'ZAF': 'Afrique du Sud',
+ 'ZMB': 'Zambie',
+ 'ZWE': 'Zimbabwe',
+ 'NTZ': 'Zone neutre',
+ 'UNO': 'Fonctionnaire des Nations Unies',
+ 'UNA': "Fonctionnaire d'une organisation affiliée aux Nations Unies",
+ 'UNK': 'Représentant des Nations Unies au Kosovo',
+ 'XXA': 'Apatride Convention 1954',
+ 'XXB': 'Réfugié Convention 1954',
+ 'XXC': 'Réfugié autre',
+ 'XXX': 'Résident Légal de Nationalité Inconnue',
+ 'D': 'Allemagne',
+ 'EUE': 'Union Européenne',
+ 'GBD': "Citoyen Britannique d'Outre-mer (BOTC)",
+ 'GBN': 'British National (Overseas)',
+ 'GBO': 'British Overseas Citizen',
+ 'GBP': 'British Protected Person',
+ 'GBS': 'British Subject',
+ 'XBA': 'Banque Africaine de Développement',
+ 'XIM': "Banque Africaine d'Export–Import",
+ 'XCC': 'Caribbean Community or one of its emissaries',
+ 'XCO': 'Common Market for Eastern and Southern Africa',
+ 'XEC': 'Economic Community of West African States',
+ 'XPO': 'International Criminal Police Organization',
+ 'XOM': 'Sovereign Military Order of Malta',
+ 'RKS': 'Kosovo',
+ 'WSA': 'World Service Authority World Passport'
+ }
+}
+
+## ENGLISH LANGUAGE
+
+english = \
+{
+"Please type a MRZ or open a scan" : "Please type a MRZ or open a scan",
+"Changelog : update summary" : "Changelog : update summary",
+"Program version" : "Program version",
+"CNIRevelator Fatal Error" : "CNIRevelator Fatal Error" ,
+"An error has occured" : "An error has occured",
+"Downloading" : "Downloading",
+"Successful retrieved" : "Successful retrieved",
+"Choose the identity document" : "Choose the identity document" ,
+"OCR Detection Validation" : "OCR Detection Validation",
+"Validate" : "Validate",
+"Validation Error" : "Validation Error",
+"The submitted MRZ contains invalid "
+ "characters" : "The submitted MRZ contains invalid characters",
+"Connection" : "Connection",
+"Password" : "Password",
+"Booting up..." : "Booting up...",
+"CNIRevelator Fatal Eror" : "CNIRevelator Fatal Eror",
+"CNIRevelator crashed because a "
+"fatal error occured. View log for "
+"more infos and please open "
+"an issue on Github" : "CNIRevelator crashed because a fatal error occured. View log for more infos and please open an issue on Github",
+"Would you like to open an issue "
+"on Github to report this bug ?" : "Would you like to open an issue on Github to report this bug ?",
+"Would you like to open the "
+"log file ?" : "Would you like to open the log file ?",
+"Starting..." : "Starting...",
+"Informations about the current "
+"document" : "Informations about the current document",
+"IDLE" : "IDLE",
+"Status" : "Status",
+"Name" : "Name",
+"Birth date" : "Birth date",
+"Issue date" : "Issue date",
+"Expiration date" : "Issue date",
+"Sex" : "Sex",
+"Issuing country" : "Issuing country",
+"Nationality" : "Nationality",
+"Registration" : "Registration",
+"Document number" : "Document number",
+"Unknown" : "Unknown",
+"Display and processing of "
+"documents" : "Display and processing of documents",
+"Complete MRZ capture terminal" : "Complete MRZ capture terminal",
+"Quick entry terminal (731)" : "Quick entry terminal (731)",
+"Monitor" : "Monitor",
+"New" : "New",
+"Open scan..." : "Open scan...",
+"Quit" : "Quit",
+"File" : "File",
+"Settings" : "Settings",
+"Keyboard commands" : "Keyboard commands",
+"Report a bug" : "Report a bug",
+"About CNIRevelator" : "About CNIRevelator",
+"Help" : "Help",
+"OCR module error" : "OCR module error",
+"The OCR module located at {} "
+"can not be found or corrupted. "
+"It will be reinstalled at "
+"the next run" : "The OCR module located at {} can not be found or corrupted. It will be reinstalled at the next run",
+"The Tesseract module "
+"encountered a problem: {}" : "The Tesseract module encountered a problem: {}",
+"Tesseract error : {}. "
+"Will be reinstallated" : "Tesseract error : {}. Will be reinstallated",
+"Document detected: {}\n" : "Document detected : {}\n",
+"Document detected again: {}\n" : "Document detected again : {}\n",
+"Character not accepted !\n" : "Character not accepted !\n",
+"Open a scan of document..." : "Open a scan of document...",
+"OpenCV error (image processing)" : "OpenCV error (image processing)",
+"A critical error has occurred in "
+"the OpenCV image processing "
+"manager used by CNIRevelator, the "
+"application will reset itself" : "A critical error has occurred in the OpenCV image processing manager used by CNIRevelator, the application will reset itself",
+
+"ABOUT" : 'Software Version: CNIRevelator' + globs.verstring_full + '\n\n'
+ "Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
+ "CNIRevelator is free software: you have the right to modify and / or distribute it"
+ "in the terms of the GNU General Public License as published by"
+ "Free Software Foundation, version 3 or"
+ "later." + "\n\n"
+ "CNIRevelator is distributed in the hope of being useful, without however"
+ "imply any guarantee of"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE Refer to the"
+ "GNU General Public License for more details about this."
+ "\n\n"
+ "You should have received a copy of the GNU General Public License"
+ "with CNIRevelator, if this is not the case, take a look at ."
+ "\n\n"
+ "The Tesseract 4.0 OCR module is subject to the 2004 Apache License."
+ "\n\n"
+ "Python libraries and the Anaconda 3 environment are subject to the BSD 2018-2019 license."
+ "\n\n"
+ "The source code for this program is available on Github at . \n"
+ "Its operation is in accordance with the standards and guidelines of ICAO document 9303 governing travel and identity documents." + '\n\n'
+ "In case of problems or special request, open an issue or send an email to neox@os-k.eu! \n\n",
+
+
+"KEYBHELP" : "Fast entry terminal (731): \n\n"
+ "Allowed characters: Alphanumeric uppercase and the character '<' No lowercase or special characters, otherwise the sum is set to zero \n\n"
+ "Calculate Result:\t\t\tControl Right\n"
+ "Copy:\t\t\t\tCtrl-C\n"
+ "Paste:\t\t\t\tCtrl-V\n"
+ "\n\n"
+ "MRZ input terminal complete: \n\n"
+ "Allowed characters: Alphanumeric uppercase and the character '<' No lowercase or special characters, otherwise the sum is set to zero \n\n"
+ "Calculate Result:\t\t\tControl Right\n"
+ "Complete field:\t\t\tTab button\n"
+ "Copy:\t\t\t\tCtrl-C\n"
+ "Paste:\t\t\t\tCtrl-V\n"
+ "Force a new document detection:\tEchap\n",
+
+"CHANGELOG" : "Version 3.1.1 \nMinor update with the following progressions: \n- Fixed a severe bug in the update system" + \
+"Version 3.1.0 \nMajor update with the following progressions: \n- Cosmetic modifications of the user interface \n- Stabilization of the changes made on the minor version 3.0 : user interface, OCR, VISA A and B, logging\n- Rationalization of the language system\n- Added update channels\n\n" + \
+"Version 3.0.8 final\nCorrection: bug in the update system'\n\n" + \
+"Version 3.0.6 \nMinor update with the following fixes:\n- Change in the appearance of the application launcher\n- Improvements to the interface, including stability\n- Added digital signature of the executable\n" + \
+"Version 3.0.7 final\nMajor update with the following corrections: \n- Redesign of the user interface\n- OCR function integrated into the application with TIFF and JPEG support\n- Corrections of errors on the processing of VISA type A and B, as well as residence permits\n\n" + \
+"Version 3.0.6 \nMinor update with the following fixes:\n- Change in the appearance of the application launcher\n- Improvements to the interface, including stability\n- Added digital signature of the executable\n" + \
+"Version 3.0.5 \n Minor update with the following corrections: \n- Change of executable icon to reflect the major version change accomplished in 3.0\n\n" + \
+"Version 3.0.4 \nMinor update with the following fixes:\n- Fixed a bug affecting the update system" + \
+"Version 3.0.3 \nMinor update with the following corrections: \n- Fixed a bug affecting the changelog\n- Fixed an error with the Delete Back key and Deleted causing a data loss" + \
+"Version 3.0.2 \nMinor update with the following corrections: \n- Change of executable icon\n- Fix of a bug affecting logging\n- Fix of a bug affecting document detection- And other minor modifications\n\n" + \
+"Version 3.0.1 \nMajor update with the following corrections: \n- Renewal of the executable's digital signature- Improvement of the log presentation in case of error\n- Total overhaul of the source code and disobfuscation\n- Reliable HTTPS downloads with checksum\n- New input terminals : a fast (731) and a complete one\n- Improved document detection, possibility of finer choice and the following regressions:\n- Temporary deletion of the OCR reading function. Planned return for a next version",
+
+"Document Review: {}\n\n" : "Document Review: {}\n\n",
+"Checksum position {}: Lu {} VS "
+"Calculated {} [facultative]\n" : "Checksum position {}: Read {} VS Calculated {} [facultative]\n",
+"Checksum position {}: Lu {} VS "
+"Calculated {}\n" : "Checksum position {}: Read {} VS Calculated {}\n",
+"COMPLIANT" : "COMPLIANT",
+"IMPROPER" : "IMPROPER",
+"Installing the updates" : "Installing the updates",
+"Verifying download..." : "Verifying download...",
+"Preparing installation..." : "Preparing installation...",
+"Success !" : "Success !",
+"Launching the new version..." : "Launching the new version...",
+"Credentials Error. No effective "
+"update !" : "Credentials Error. No effective update !",
+"Deleting old version" : "Deleting old version",
+'Software is up-to-date !' : "Software is up-to-date !",
+"An error occured. "
+"No effective update !" : "An error occured. No effective update !",
+"Shortcut creation" : "Shortcut creation",
+"Would you like to create/update "
+"the shortcut for CNIRevelator on "
+"your desktop ?" : "Would you like to create/update the shortcut for CNIRevelator on your desktop ?",
+"The file you provided is not "
+"found : {}" : "The file you provided is not found : {}",
+"Update options" : "Update options",
+"Language" : "Language",
+"Show Changelog" : "Show the changelog",
+"Please choose your language : " : "Please choose your language : ",
+"Please choose your update "
+"channel : " : "Please choose your update channel : ",
+"Passeport" : "Passport",
+"Carte-passeport" : "Passport card",
+"Titre d'identité/de voyage" : "Identity/travel document",
+"Certificat de membre d'équipage" : "Crew member certificate",
+"Visa de type A" : "Type A visa",
+"Visa de type B" : "Type B visa",
+"Carte de séjour" : "Residence permit",
+"Pièce d'identité/de voyage" : "Identity/travel document",
+"Pièce d'identité FR" : "French Identity card",
+"Permis de conduire" : "Driver License",
+
+"LANDCODE2" : {
+ "AW": "Aruba",
+ "AF": "Afghanistan",
+ "AO": "Angola",
+ "AI": "Anguilla",
+ "AL": "Albania",
+ "AD": "Andorra",
+ "AE": "United Arab Emirates",
+ "AR": "Argentina",
+ "AM": "Armenia",
+ "AS": "American Samoa",
+ "QA": "Antarctic",
+ "TF": 'French Southern and Antarctic Territories',
+ "AG": 'Antigua and Barbuda',
+ "TO": "Australia",
+ "AT": "Austria",
+ "AZ": "Azerbaidjan",
+ "BI": "Burundi",
+ "BE": "Belgium",
+ "BJ": "Benin",
+ "BQ": "Caribbean Netherlands",
+ "BF": "Burkina Faso",
+ "BD": "Bangladesh",
+ "BG": "Bulgaria",
+ "BH": "Bahrain",
+ "BS": "Bahamas",
+ "BA": "Bosnia and Herzegovina",
+ "BL": "Saint-Barthélemy",
+ "BY": "Belarus",
+ "BZ": "Belize",
+ "BM": "Bermuda",
+ "BO": "Bolivia",
+ "BR": 'Brazil',
+ "BB": "Barbados",
+ "BN": "Brunei",
+ "BT": "Bhutan",
+ "BW": "Botswana",
+ "CF": "Central African Republic",
+ "CA": "Canada",
+ "CC": "Cocos Islands",
+ "CH": "Switzerland",
+ "CL": "Chile",
+ "CN": "China",
+ "CI": "Côte d'Ivoire",
+ "CM": "Cameroon",
+ "CD": 'Congo (Democratic Republic)',
+ "CG": "Congo (Republic)",
+ "CK": "Cook Islands",
+ "CO": "Colombia",
+ "KM": "Comoros",
+ "CV": "Cape Verde",
+ "CR": "Costa Rica",
+ "CU": "Cuba",
+ "CW": "Curaçao",
+ "CX": "Christmas Island",
+ "KY": "Caimans",
+ "CY": "Cyprus",
+ "CZ": "Czech Republic",
+ "DE": "Germany",
+ "DJ": "Djibouti",
+ "DM": "Dominique",
+ "DK": "Denmark",
+ "DO": 'Dominican Republic',
+ "DZ": "Algeria",
+ "EC": "Ecuador",
+ "EG": "Egypt",
+ "ER": "Eritrea",
+ "EH": "Western Sahara",
+ "ES": "Spain",
+ "EE": "Estonia",
+ "AND": "Ethiopia",
+ "FI": "Finland",
+ "FJ": "Fiji",
+ "FK": "Falkland Islands",
+ "FR": "France",
+ "FO": "Faroese",
+ "FM": "Micronesia",
+ "GA": "Gabon",
+ "GB": "United Kingdom",
+ "GE": "Georgia",
+ "GG": "Guernsey",
+ "GH": "Ghana",
+ "GI": "Gibraltar",
+ "GN": "Guinea",
+ "GP": "Guadeloupe",
+ "GM": "Gambia",
+ "GW": "Guinea-Bissau",
+ "GQ": "Equatorial Guinea",
+ "GR": "Greece",
+ "GD": "Granada",
+ "GL": "Greenland",
+ "GT": "Guatemala",
+ "GF": "Guyana",
+ "GU": "Guam",
+ "GY": "Guyana",
+ "HK": "Hong Kong",
+ "HN": "Honduras",
+ "HR": "Croatia",
+ "HT": "Haiti",
+ "HU": "Hungary",
+ "ID": "Indonesia",
+ "IM": "Isle of Man",
+ "IN": "India",
+ "IO": 'British Indian Ocean Territory',
+ "IE": "Ireland",
+ "IR": "Iraq",
+ "IQ": "Iran",
+ "IS": "Iceland",
+ "IL": "Israel",
+ "IT": "Italy",
+ "JM": "Jamaica",
+ "I": "Jersey",
+ "JO": "Jordan",
+ "JP": "Japan",
+ "KZ": "Kazakhstan",
+ "KE": "Kenya",
+ "KG": "Kyrgyzstan",
+ "KH": "Cambodia",
+ "KI": "Kiribati",
+ "KN": "Saint Kitts and Nevis",
+ "KR": "South Korea",
+ "KW": "Kuwait",
+ "LA": "Laos",
+ "LB": "Lebanon",
+ "LR": "Liberia",
+ "LY": "Libya",
+ "LC": "Saint Lucia",
+ "LI": "Liechtenstein",
+ "LK": "Sri Lanka",
+ "LS": "Lesotho",
+ "LT": "Lithuania",
+ "LU": "Luxembourg",
+ "LV": "Latvia",
+ "MO": "Macao",
+ "MF": "Sint-Maarten",
+ "MA": "Morocco",
+ "MC": "Monaco",
+ "MD": 'Moldavia',
+ "MG": "Madagascar",
+ "MV": "Maldives",
+ "MX": "Mexico",
+ "MH": "Marshall",
+ "MK": "Macedonia",
+ "ML": "Mali",
+ "MT": "Malta",
+ "MM": "Burma",
+ "ME": "Montenegro",
+ "MN": "Mongolia",
+ "MP": "Northern Mariana Islands",
+ "MZ": "Mozambique",
+ "MR": "Mauritania",
+ "MS": "Montserrat",
+ "MQ": "Martinique",
+ "MU": "Mauritius",
+ "MW": "Malawi",
+ "MY": "Malaysia",
+ "YT": "Mayotte",
+ "NA": "Namibia",
+ "NC": "New Caledonia",
+ "NE": "Niger",
+ "NF": "Norfolk Island",
+ "NG": "Nigeria",
+ "NI": "Nicaragua",
+ "NU": "Niue",
+ "NL": 'Netherlands',
+ "NO": "Norway",
+ "NP": "Nepal",
+ "NR": "Nauru",
+ "NZ": "New Zealand",
+ "OM": "Oman",
+ "PK": "Pakistan",
+ "PA": "Panama",
+ "NP": "Pitcairn Islands",
+ "PE": "Peru",
+ "PH": "Philippines",
+ "PW": "Palau",
+ "PG": "Papua New Guinea",
+ "PL": "Poland",
+ "PR": "Puerto Rico",
+ "KP": "North Korea",
+ "PT": "Portugal",
+ "PY": "Paraguay",
+ "PS": "Palestine",
+ "FP": "French Polynesia",
+ "QA": "Qatar",
+ "RE": "Reunion",
+ "RO": "Romania",
+ "RU": "Russia",
+ "RW": "Rwanda",
+ "SA": "Saudi Arabia",
+ "SD": "Sudan",
+ "SN": "Senegal",
+ "SG": "Singapore",
+ "GS": "South Georgia and the South Sandwich Islands",
+ 'SH': 'St Helena, Ascension and Tristan da Cunha',
+ "SJ": "Svalbard and Jan Mayen Island",
+ "SB": "Solomon",
+ "SL": "Sierra Leone",
+ "SV": "El Salvador",
+ "SM": "San Marino",
+ "SO": "Somalia",
+ "PM": "Saint-Pierre-et-Miquelon",
+ "RS": "Serbia",
+ "SS": "South Sudan",
+ "ST": "Sao Tome and Principe",
+ "SR": "Suriname",
+ "SK": "Slovakia",
+ "SI": "Slovenia",
+ "SE": "Sweden",
+ "SZ": "eSwatani",
+ "SX": "Saint-Martin",
+ "SC": "Seychelles",
+ "SY": "Syria",
+ "TC": "Turks and Caicos Islands",
+ "TD": "Chad",
+ "TG": "Togo",
+ "TH": "Thailand",
+ "TJ": "Tajikistan",
+ "TK": "Tokelau",
+ "TM": "Turkmenistan",
+ "TL": "East Timor",
+ "TO": "Tonga",
+ "TT": "Trinidad and Tobago",
+ "TN": "Tunisia",
+ "TR": "Turkey",
+ "TV": "Tuvalu",
+ "TW": "Taiwan",
+ "TZ": "Tanzania",
+ "UG": "Uganda",
+ "UA": "Ukraine",
+ "UY": "Uruguay",
+ "US": "United States",
+ "UZ": "Uzbekistan",
+ 'VA': 'Holy See (Vatican City State)',
+ 'VC': 'Saint Vincent and the Grenadines',
+ "EV": "Venezuela",
+ "VG": "British Virgin Islands",
+ 'VI': 'Virgin Islands of the United States',
+ "VN": "Vietnam",
+ "VU": "Vanuatu",
+ "WF": "Wallis and Futuna",
+ 'WS': 'Samoa',
+ "XK": "Kosovo",
+ "YE": "Yemen",
+ "ZA": "South Africa",
+ "ZM": "Zambia",
+ "ZW": "Zimbabwe"
+ },
+
+"LANDCODE3" : {
+ "ABW": "Aruba",
+ "AFG": "Afghanistan",
+ "OGM": "Angola",
+ "AIA": "Anguilla",
+ 'ALB': 'Albania',
+ "AND": "Andorra",
+ "AER": "United Arab Emirates",
+ "ARG": "Argentina",
+ "ARM": "Armenia",
+ "ASM": "American Samoa",
+ "ATA": "Antarctica",
+ 'ATF': 'French Southern and Antarctic Lands',
+ "ATG": "Antigua and Barbuda",
+ "AUS": "Australia",
+ "AUT": "Austria",
+ "AZE": "Azerbaidjan",
+ "BDI": "Burundi",
+ "BEL": "Belgium",
+ "BEN": "Benin",
+ 'BES': 'Caribbean Netherlands',
+ "BFA": "Burkina Faso",
+ "BGD": "Bangladesh",
+ "BGR": "Bulgaria",
+ "BHR": "Bahrain",
+ "BHS": "Bahamas",
+ "BIH": "Bosnia and Herzegovina",
+ "BLM": "Saint-Barthélemy",
+ "BLR": "Belarus",
+ "BLZ": "Belize",
+ "BMU": "Bermuda",
+ "BOL": "Bolivia",
+ "BRA": "Brazil",
+ 'BRB': 'Barbados',
+ "BRN": "Brunei",
+ "BTN": "Bhutan",
+ "BWA": "Botswana",
+ 'CAF': 'Central African Republic',
+ 'CAN': 'Canada',
+ "CCK": "Cocos Islands",
+ "CHE": "Switzerland",
+ "CHL": "Chile",
+ "CHN": "China",
+ 'CIV': "Côte d'Ivoire",
+ "CMR": "Cameroon",
+ 'COD': 'Congo (Democratic Republic)',
+ "COG": "Congo (Republic)",
+ "COK": "Cook Islands",
+ "COL": "Colombia",
+ "COM": "Comoros",
+ 'CPV': 'Cape Verde',
+ "CRI": "Costa Rica",
+ "CUB": "Cuba",
+ "CUW": "Curaçao",
+ "CXR": "Christmas Island",
+ "CYM": "Caimans",
+ "CYP": "Cyprus",
+ "CZE": "Czech Republic",
+ "DEU": "Germany",
+ "DJI": "Djibouti",
+ "DMA": "Dominique",
+ "DNK": "Denmark",
+ "DOM": "Dominican Republic",
+ "DZA": "Algeria",
+ 'ECU': 'Ecuador',
+ "EGY": "Egypt",
+ "ERI": "Eritrea",
+ 'ESH': 'Western Sahara',
+ "ESP": "Spain",
+ "EST": "Estonia",
+ "ETH": "Ethiopia",
+ "FIN": "Finland",
+ "FJI": "Fiji",
+ "FLK": "Falkland Islands",
+ "FRA": "France",
+ "FRO": "Faroese",
+ "WSF": "Micronesia",
+ "ATM": "Gabon",
+ "GBR": "United Kingdom",
+ "GEO": "Georgia",
+ "GGY": "Guernsey",
+ "GHA": "Ghana",
+ "GIB": "Gibraltar",
+ "GIN": "Guinea",
+ "GLP": "Guadeloupe",
+ "GMB": "Gambia",
+ "GNB": "Guinea-Bissau",
+ "GNQ": "Equatorial Guinea",
+ "GRC": "Greece",
+ "DSO": "Granada",
+ "GRL": "Greenland",
+ "GTM": "Guatemala",
+ 'GUF': 'Guyana',
+ "GUM": "Guam",
+ "GUY": "Guyana",
+ "HKG": "Hong Kong",
+ "HND": "Honduras",
+ "HRV": "Croatia",
+ "HTI": "Haiti",
+ "HUN": "Hungary",
+ "IDN": "Indonesia",
+ "IMN": "Isle of Man",
+ "IND": "India",
+ 'IOT': 'British Indian Ocean Territory',
+ "IRL": "Ireland",
+ "IRN": "Iraq",
+ "IRQ": "Iran",
+ "ISL": "Iceland",
+ "SRI": "Israel",
+ "ITA": "Italy",
+ "JAM": "Jamaica",
+ "JEY": "Jersey",
+ "JOR": "Jordan",
+ 'JPN': 'Japan',
+ "KAZ": "Kazakhstan",
+ "KEN": "Kenya",
+ "KGZ": "Kyrgyzstan",
+ "KHM": "Cambodia",
+ "KIR": "Kiribati",
+ "KNA": "Saint Kitts and Nevis",
+ "KOR": "South Korea",
+ "KWT": "Kuwait",
+ "LAO": "Laos",
+ "LBN": "Lebanon",
+ "LBR": "Liberia",
+ "LBY": "Libya",
+ "LCA": "Saint Lucia",
+ "LEL": "Liechtenstein",
+ "LKA": "Sri Lanka",
+ "LSO": "Lesotho",
+ "LTU": "Lithuania",
+ "LUX": "Luxembourg",
+ "LVA": "Latvia",
+ "MAC": "Macao",
+ "MAF": "Sint-Maarten",
+ "MAR": "Morocco",
+ "MCO": "Monaco",
+ "MDA": "Moldavia",
+ "MDG": "Madagascar",
+ "MDV": "Maldives",
+ "MEX": "Mexico",
+ "MHL": "Marshall",
+ "MKD": "Macedonia",
+ "MLI": "Mali",
+ "MLT": "Malta",
+ "MMR": "Burma",
+ "MNE": "Montenegro",
+ "MNG": "Mongolia",
+ 'MNP': 'Northern Mariana Islands',
+ "MOZ": "Mozambique",
+ "MRT": "Mauritania",
+ "MSR": "Montserrat",
+ "MTQ": "Martinique",
+ "MUS": "Mauritius",
+ "MWI": "Malawi",
+ "MYS": "Malaysia",
+ "MYT": "Mayotte",
+ "NAM": "Namibia",
+ "NCL": "New Caledonia",
+ "NER": "Niger",
+ "NFK": "Norfolk Island",
+ "NGA": "Nigeria",
+ "NIC": "Nicaragua",
+ "NIU": "Niue",
+ 'NLD': 'Netherlands',
+ "NOR": "Norway",
+ "NPL": "Nepal",
+ "NRU": "Nauru",
+ "NZL": "New Zealand",
+ "OMN": "Oman",
+ "PAK": "Pakistan",
+ "PAN": "Panama",
+ "PCN": "Pitcairn Islands",
+ "PER": "Peru",
+ "PHL": "Philippines",
+ "PLW": "Palau",
+ "PNG": "Papua New Guinea",
+ "POL": "Poland",
+ "PRI": "Puerto Rico",
+ "PRK": "North Korea",
+ "PRT": "Portugal",
+ "PRY": "Paraguay",
+ "PES": "Palestine",
+ "PYF": "French Polynesia",
+ "QAT": "Qatar",
+ "REU": "Reunion",
+ "ROU": "Romania",
+ "RUS": "Russia",
+ "RWA": "Rwanda",
+ "UAA": "Saudi Arabia",
+ "SDN": "Sudan",
+ "SEN": "Senegal",
+ "SGP": "Singapore",
+ 'SGS': 'South Georgia and the South Sandwich Islands',
+ "SHN": "St Helena, Ascension and Tristan da Cunha",
+ "SJM": "Svalbard and Jan Mayen Island",
+ "SLB": "Solomon",
+ "SLE": "Sierra Leone",
+ "SLV": "El Salvador",
+ "SMR": "San Marino",
+ "SOM": "Somalia",
+ "SPM": "Saint-Pierre-et-Miquelon",
+ "SRB": "Serbia",
+ "SSD": "South Sudan",
+ "PTS": "Sao Tome and Principe",
+ "SUR": "Suriname",
+ "SVK": "Slovakia",
+ "SVN": "Slovenia",
+ "SWE": "Sweden",
+ "SWZ": "eSwatani",
+ "SXM": "Saint-Martin",
+ "SYC": "Seychelles",
+ "SYR": "Syria",
+ "TCA": "Turks and Caicos Islands",
+ "TCD": "Chad",
+ "TGO": "Togo",
+ "THA": "Thailand",
+ "TJK": "Tajikistan",
+ "TKL": "Tokelau",
+ "TKM": "Turkmenistan",
+ "TLS": "East Timor",
+ "TON": "Tonga",
+ 'TTO': 'Trinidad and Tobago',
+ "TUN": "Tunisia",
+ "TUR": "Turkey",
+ "TUV": "Tuvalu",
+ "TWN": "Taiwan",
+ "TZA": "Tanzania",
+ "UGA": "Uganda",
+ "UKR": "Ukraine",
+ "URY": "Uruguay",
+ "USA": "United States",
+ "UZB": "Uzbekistan",
+ 'VAT': 'Holy See (Vatican City State)',
+ 'VCT': 'Saint Vincent and the Grenadines',
+ "VEN": "Venezuela",
+ 'VGB': 'British Virgin Islands',
+ 'VIR': 'Virgin Islands of the United States',
+ "VNM": "Vietnam",
+ "STV": "Vanuatu",
+ "WLF": "Wallis and Futuna",
+ "WSM": "Samoa",
+ "XKX": "Kosovo",
+ "YEM": "Yemen",
+ "ZAF": "South Africa",
+ "ZMB": "Zambia",
+ "ZWE": "Zimbabwe",
+ 'NTZ': 'Neutral Zone',
+ 'UNO': 'United Nations official',
+ 'UNA': "Staff member of a United Nations-affiliated organization",
+ 'UNK': 'United Nations Representative in Kosovo',
+ 'XXA': 'Stateless Person 1954 Convention',
+ "XXB": "Refugee Convention 1954",
+ "XXC": "Other refugee",
+ 'XXX': 'Legal Resident of Unknown Nationality',
+ 'D' : 'Germany',
+ "EUE": "European Union",
+ "GBD": "British Overseas Citizen (BOTC)",
+ "GBN": "British National (Overseas)",
+ "GBO": "British Overseas Citizen",
+ 'GBP': 'British Protected Person',
+ "GBS": "British Subject",
+ 'XBA': 'African Development Bank',
+ 'XIM': "African Export Import Bank",
+ 'XCC':' Caribbean Community or one of its emissaries',
+ 'XCO': 'Common Market for Eastern and Southern Africa',
+ 'XEC': 'Economic Community of West African States',
+ 'XPO': 'International Criminal Police Organization',
+ 'XOM': 'Sovereign Military Order of Malta',
+ "RKS": "Kosovo",
+ "WSA": "World Service Authority World Passport"
+ }
+}
+
+## MAIN DICT
+all = \
+{
+"fr" : french,
+"en" : english
+}
+
+
+## Functions
+
+def readLang():
+
+ if os.path.isfile(globs.CNIRLangFile):
+ with open(globs.CNIRLangFile, 'r') as (configFile):
+ try:
+ # Reading it
+ globs.CNIRlang = configFile.read()
+ except Exception as e:
+ critical.crashCNIR()
+ raise IOError(str(e))
+ else:
+ # Recreating the url file
+ try:
+ os.mkdir(globs.CNIRFolder + '\\config')
+ except:
+ pass
+
+ with open(globs.CNIRLangFile, 'w') as (configFile):
+ try:
+ # Writing it
+ configFile.write(globs.CNIRlang)
+ except Exception as e:
+ critical.crashCNIR()
+ raise IOError(str(e))
+
+def updateLang(choice):
+
+ if os.path.isfile(globs.CNIRLangFile):
+ with open(globs.CNIRLangFile, 'w') as (configFile):
+ try:
+ # Writing it
+ globs.CNIRlang = choice
+ configFile.write(choice)
+ except Exception as e:
+ critical.crashCNIR()
+ raise IOError(str(e))
+ else:
+ # Recreating the url file
+ try:
+ os.mkdir(globs.CNIRFolder + '\\config')
+ except:
+ pass
+
+ with open(globs.CNIRLangFile, 'w') as (configFile):
+ try:
+ # Writing it
+ configFile.write(globs.CNIRlang)
+ except Exception as e:
+ critical.crashCNIR()
+ raise IOError(str(e))
\ No newline at end of file
diff --git a/src/launcher.py b/src/launcher.py
index 3edcfaa..116c642 100644
--- a/src/launcher.py
+++ b/src/launcher.py
@@ -26,12 +26,13 @@
import sys
import os
import threading
-import traceback
+import critical # critical.py
import updater # updater.py
import ihm # ihm.py
import globs # globs.py
import logger # logger.py
+import lang # lang.py
## Main function
def lmain(mainThread):
@@ -44,7 +45,7 @@ def lmain(mainThread):
# Hello user
launcherWindow.progressBar.configure(mode='indeterminate', value=0, maximum=20)
- launcherWindow.printmsg('Starting...')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Starting..."])
launcherWindow.progressBar.start()
# Starting the main update thread
diff --git a/src/logger.py b/src/logger.py
index 1e1d00f..9fea829 100644
--- a/src/logger.py
+++ b/src/logger.py
@@ -26,6 +26,7 @@
import logging
import os
+import critical # critical.py
import globs # globs.py
## The logging class
diff --git a/src/main.py b/src/main.py
index b921838..6e0f54f 100644
--- a/src/main.py
+++ b/src/main.py
@@ -31,29 +31,37 @@ from tkinter import filedialog
from tkinter import ttk
import threading
from datetime import datetime
+from importlib import reload
import re
-import traceback
import cv2
import PIL.Image, PIL.ImageTk
import os, shutil
import webbrowser
+import sys, os
+import critical # critical.py
import ihm # ihm.py
import logger # logger.py
import mrz # mrz.py
import globs # globs.py
import pytesseract # pytesseract.py
+import lang # lang.py
# Global handler
logfile = logger.logCur
class mainWindow(Tk):
+ ## App Pattern
+
def __init__(self):
Tk.__init__(self)
self.initialize()
def initialize(self):
+ """
+ Initializes the main window
+ """
self.mrzChar = ""
self.mrzDecided = False
self.Tags = []
@@ -61,6 +69,12 @@ class mainWindow(Tk):
self.corners = []
self.validatedtext = ""
+ # The icon
+ if getattr(sys, 'frozen', False):
+ self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
+ else:
+ self.iconbitmap('id-card.ico')
+
# Hide during construction
self.withdraw()
@@ -70,15 +84,16 @@ class mainWindow(Tk):
logfile.printdbg('Launching main window with resolution' + str(ws) + 'x' + str(hs))
# Configuring the size of each part of the window
- self.grid_columnconfigure(0, weight=1, minsize=(ws / 2 * 0.3333333333333333))
- self.grid_columnconfigure(1, weight=1, minsize=(ws / 2 * 0.3333333333333333))
+ self.grid_columnconfigure(0, minsize=(ws / 2 * 0.3333333333333333))
+ self.grid_columnconfigure(1, minsize=(ws / 2 * 0.3333333333333333))
self.grid_columnconfigure(2, weight=1, minsize=(ws / 2 * 0.3333333333333333))
- self.grid_rowconfigure(0, weight=1, minsize=(hs / 2 * 0.5))
- self.grid_rowconfigure(1, weight=1, minsize=(hs / 2 * 0.10))
- self.grid_rowconfigure(2, weight=1, minsize=(hs / 2 * 0.35))
+ self.grid_rowconfigure(0, minsize=(hs / 2 * 0.5))
+ self.grid_rowconfigure(1, minsize=(hs / 2 * 0.10))
+ self.grid_rowconfigure(2, minsize=(hs / 2 * 0.35))
+ self.grid_rowconfigure(3, minsize=10)
# Prepare the data sections
- self.lecteur_ci = ttk.Labelframe(self, text="Informations sur la pièce d'identité")
+ self.lecteur_ci = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Informations about the current document"])
self.lecteur_ci.grid_columnconfigure(0, weight=1)
self.lecteur_ci.grid_columnconfigure(1, weight=1)
self.lecteur_ci.grid_columnconfigure(2, weight=1)
@@ -90,52 +105,57 @@ class mainWindow(Tk):
self.lecteur_ci.grid_rowconfigure(3, weight=1)
self.lecteur_ci.grid_rowconfigure(4, weight=1)
self.lecteur_ci.grid_rowconfigure(5, weight=1)
+
+ # And what about the status bar ?
+ self.statusbar = ihm.StatusBar(self)
+ self.statusbar.grid(row=3, columnspan=3, sticky="NSEW")
# Fill the data sections
- ttk.Label((self.lecteur_ci), text='Statut : ').grid(column=0, row=0, padx=5, pady=5)
- self.STATUStxt = ttk.Label((self.lecteur_ci), text='EN ATTENTE', font=("TkDefaultFont", 13, "bold"), foreground="orange", anchor=CENTER)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Status"])).grid(column=0, row=0, padx=5, pady=5)
+ self.statusbar.set(lang.all[globs.CNIRlang]["IDLE"])
+ self.STATUStxt = ttk.Label((self.lecteur_ci), text=lang.all[globs.CNIRlang]["IDLE"], font=("TkDefaultFont", 13, "bold"), foreground="orange", anchor=CENTER)
self.STATUStxt.grid(column=1, row=0, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Nom : ').grid(column=0, row=1, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Name"])).grid(column=0, row=1, padx=5, pady=5)
self.nom = ttk.Label((self.lecteur_ci), text=' ')
self.nom.grid(column=1, row=1, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Nom (2) : ').grid(column=0, row=2, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} (2) : '.format(lang.all[globs.CNIRlang]["Name"])).grid(column=0, row=2, padx=5, pady=5)
self.prenom = ttk.Label((self.lecteur_ci), text=' ')
self.prenom.grid(column=1, row=2, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Date de naissance : ').grid(column=0, row=3, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Birth date"])).grid(column=0, row=3, padx=5, pady=5)
self.bdate = ttk.Label((self.lecteur_ci), text=' ')
self.bdate.grid(column=1, row=3, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Date de délivrance : ').grid(column=0, row=4, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Issue date"])).grid(column=0, row=4, padx=5, pady=5)
self.ddate = ttk.Label((self.lecteur_ci), text=' ')
self.ddate.grid(column=1, row=4, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text="Date d'expiration : ").grid(column=0, row=5, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text="{} : ".format(lang.all[globs.CNIRlang]["Expiration date"])).grid(column=0, row=5, padx=5, pady=5)
self.edate = ttk.Label((self.lecteur_ci), text=' ')
self.edate.grid(column=1, row=5, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Sexe du porteur : ').grid(column=4, row=1, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Sex"])).grid(column=4, row=1, padx=5, pady=5)
self.sex = ttk.Label((self.lecteur_ci), text=' ')
self.sex.grid(column=5, row=1, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Pays de délivrance : ').grid(column=4, row=2, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Issuing country"])).grid(column=4, row=2, padx=5, pady=5)
self.pays = ttk.Label((self.lecteur_ci), text=' ')
self.pays.grid(column=5, row=2, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Nationalité du porteur : ').grid(column=4, row=3, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Nationality"])).grid(column=4, row=3, padx=5, pady=5)
self.nat = ttk.Label((self.lecteur_ci), text=' ')
self.nat.grid(column=5, row=3, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Immatriculation : ').grid(column=4, row=4, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Registration"])).grid(column=4, row=4, padx=5, pady=5)
self.indic = ttk.Label((self.lecteur_ci), text=' ')
self.indic.grid(column=5, row=4, padx=5, pady=5)
- ttk.Label((self.lecteur_ci), text='Numéro de document : ').grid(column=4, row=5, padx=5, pady=5)
+ ttk.Label((self.lecteur_ci), text='{} : '.format(lang.all[globs.CNIRlang]["Document number"])).grid(column=4, row=5, padx=5, pady=5)
self.no = ttk.Label((self.lecteur_ci), text=' ')
self.no.grid(column=5, row=5, padx=5, pady=5)
- self.nom['text'] = 'Inconnu(e)'
- self.prenom['text'] = 'Inconnu(e)'
- self.bdate['text'] = 'Inconnu(e)'
- self.ddate['text'] = 'Inconnu(e)'
- self.edate['text'] = 'Inconnu(e)'
- self.no['text'] = 'Inconnu(e)'
- self.sex['text'] = 'Inconnu(e)'
- self.nat['text'] = 'Inconnu(e)'
- self.pays['text'] = 'Inconnu(e)'
- self.indic['text'] = 'Inconnu(e)'
+ self.nom['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.prenom['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.bdate['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.ddate['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.edate['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.no['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.sex['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.nat['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.pays['text'] = lang.all[globs.CNIRlang]["Unknown"]
+ self.indic['text'] = lang.all[globs.CNIRlang]["Unknown"]
self.infoList = \
@@ -153,7 +173,7 @@ class mainWindow(Tk):
}
# The the image viewer
- self.imageViewer = ttk.Labelframe(self, text='Affichage et traitement de documents')
+ self.imageViewer = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Display and processing of documents"])
self.imageViewer.grid_columnconfigure(0, weight=1)
self.imageViewer.grid_columnconfigure(1, weight=0)
self.imageViewer.grid_rowconfigure(0, weight=1)
@@ -258,7 +278,7 @@ class mainWindow(Tk):
# The terminal to enter the MRZ
- self.terminal = ttk.Labelframe(self, text='Terminal de saisie de MRZ complète')
+ self.terminal = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Complete MRZ capture terminal"])
self.terminal.grid_columnconfigure(0, weight=1)
self.terminal.grid_rowconfigure(0, weight=1)
self.termframe = Frame(self.terminal)
@@ -272,7 +292,7 @@ class mainWindow(Tk):
self.termtext.grid(column=0, row=0, sticky='SW', padx=5, pady=25)
# Speed Entry Zone for 731
- self.terminal2 = ttk.Labelframe(self, text='Terminal de saisie rapide (731)')
+ self.terminal2 = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Quick entry terminal (731)"])
self.terminal2.grid_columnconfigure(0, weight=1)
self.terminal2.grid_rowconfigure(0, weight=1)
self.speed731 = Frame(self.terminal2)
@@ -294,7 +314,7 @@ class mainWindow(Tk):
self.speedResult.grid(column=2, row=0, sticky='NEW', padx=5, pady=5)
# The monitor that indicates some useful infos
- self.monitor = ttk.Labelframe(self, text='Moniteur')
+ self.monitor = ttk.Labelframe(self, text=lang.all[globs.CNIRlang]["Monitor"])
self.monlog = Text((self.monitor), state='disabled', width=60, height=10, wrap='word')
self.monlog.grid(column=0, row=0, sticky='EWNS', padx=5, pady=5)
self.scrollb = ttk.Scrollbar((self.monitor), command=(self.monlog.yview))
@@ -313,41 +333,45 @@ class mainWindow(Tk):
# What is a window without a menu bar ?
menubar = Menu(self)
menu1 = Menu(menubar, tearoff=0)
- menu1.add_command(label='Nouveau', command=(self.newEntry))
- menu1.add_command(label='Ouvrir scan...', command=(self.openingScan))
+ menu1.add_command(label=lang.all[globs.CNIRlang]["New"], command=(self.newEntry))
+ menu1.add_command(label=lang.all[globs.CNIRlang]["Open scan..."], command=(self.openingScan))
menu1.add_separator()
- menu1.add_command(label='Quitter', command=(self.destroy))
- menubar.add_cascade(label='Fichier', menu=menu1)
+ menu1.add_command(label=lang.all[globs.CNIRlang]["Quit"], command=(self.destroy))
+ menubar.add_cascade(label=lang.all[globs.CNIRlang]["File"], menu=menu1)
+ menu2 = Menu(menubar, tearoff=0)
+ menu2.add_command(label=lang.all[globs.CNIRlang]["Update options"], command=(self.updateSet))
+ menu2.add_command(label=lang.all[globs.CNIRlang]["Show Changelog"], command=(self.showChangeLog))
+ menu2.add_separator()
+ menu2.add_command(label=lang.all[globs.CNIRlang]["Language"], command=(self.languageSet))
+ menubar.add_cascade(label=lang.all[globs.CNIRlang]["Settings"], menu=menu2)
menu3 = Menu(menubar, tearoff=0)
- menu3.add_command(label='Commandes au clavier', command=(self.helpbox))
- menu3.add_command(label='Signaler un problème', command=(self.openIssuePage))
+ menu3.add_command(label=lang.all[globs.CNIRlang]["Keyboard commands"], command=(self.helpbox))
+ menu3.add_command(label=lang.all[globs.CNIRlang]["Report a bug"], command=(self.openIssuePage))
menu3.add_separator()
- menu3.add_command(label='A propos de CNIRevelator', command=(self.infobox))
- menubar.add_cascade(label='Aide', menu=menu3)
+ menu3.add_command(label=lang.all[globs.CNIRlang]["About CNIRevelator"], command=(self.infobox))
+ menubar.add_cascade(label=lang.all[globs.CNIRlang]["Help"], menu=menu3)
+ menubar.add_command(label="<|>", command=(self.panelResize))
self.config(menu=menubar)
-
+
# The title
self.wm_title(globs.CNIRName)
- # The icon
- if getattr(sys, 'frozen', False):
- self.iconbitmap(sys._MEIPASS + '\\id-card.ico\\id-card.ico')
- else:
- self.iconbitmap('id-card.ico')
-
# Make this window resizable and set her size
- self.resizable(width=True, height=True)
+ self.resizable(0, 0)
self.update()
- w = int(self.winfo_reqwidth())
- h = int(self.winfo_reqheight())
- ws = self.winfo_screenwidth()
- hs = self.winfo_screenheight()
- x = (ws - w)/2
- y = (hs - h)/2
- self.geometry('%dx%d+%d+%d' % (w, h, x, y))
+ self.w = int(self.winfo_reqwidth())
+ self.h = int(self.winfo_reqheight())
+ self.ws = self.winfo_screenwidth()
+ self.hs = self.winfo_screenheight()
+ self.x = (self.ws - self.w)/2
+ self.y = (self.hs - self.h)/2
+ self.geometry('%dx%d+%d+%d' % (self.w, self.h, self.x, self.y))
self.update()
self.deiconify()
- self.minsize(self.winfo_width(), self.winfo_height())
+ self.attributes("-topmost", 1)
+ self.maxsize(self.w, self.h)
+ self.minsize(int(2.15 * (self.ws / 2 * 0.3333333333333333)), self.h)
+ self.currentw = self.w
# Set image
self.imageViewer.image = None
@@ -364,27 +388,33 @@ class mainWindow(Tk):
self.imageViewer.ZONE.bind("", self.rectangleSelectScan)
logfile.printdbg('Initialization successful')
-
- def statusUpdate(self, image=None, setplace=False):
- if image:
- self.imageViewer.image = image
- self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image))
- self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all"))
+ if globs.CNIROpenFile:
+ self.after_idle(lambda : self.openScanFile(sys.argv[1]))
+
+
+ ## OCR related functions
+
def rectangleSelectScan(self, event):
+ """
+ Realises the selection of the MRZ to make OCR possible
+ """
if self.imageViewer.image:
canvas = event.widget
- print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y))
+ #print("Get coordinates : [{}, {}], for [{}, {}]".format(canvas.canvasx(event.x), canvas.canvasy(event.y), event.x, event.y))
self.corners.append([canvas.canvasx(event.x), canvas.canvasy(event.y)])
if len(self.corners) == 2:
self.select = self.imageViewer.ZONE.create_rectangle(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1], outline ='cyan', width = 2)
- print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1]))
+ #print("Get rectangle : [{}, {}], for [{}, {}]".format(self.corners[0][0], self.corners[0][1], self.corners[1][0], self.corners[1][1]))
if len(self.corners) > 2:
self.corners = []
self.imageViewer.ZONE.delete(self.select)
def goOCRDetection(self):
+ """
+ Realises the OCR detection and get the text in self.mrzChar (and prints it)
+ """
if self.imageViewer.image:
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
@@ -434,7 +464,7 @@ class mainWindow(Tk):
invite.focus_force()
self.wait_window(invite)
- print("text : {}".format(self.validatedtext))
+ #print("text : {}".format(self.validatedtext))
self.mrzChar = ""
@@ -445,7 +475,7 @@ class mainWindow(Tk):
self.mrzChar = self.mrzChar + char
self.stringValidation("")
- print(self.mrzChar)
+ #print(self.mrzChar)
# Reinstall tesseract
except pytesseract.TesseractNotFoundError as e:
@@ -453,16 +483,20 @@ class mainWindow(Tk):
shutil.rmtree(globs.CNIRTesser)
except Exception:
pass
- showerror('Erreur de module OCR', ('Le module OCR localisé en ' + str(os.environ['PATH']) + 'est introuvable ou corrompu. Il sera réinstallé à la prochaine exécution'), parent=self)
- logfile.printerr("Tesseract error : {}. Will be reinstallated".format(e))
+ showerror(lang.all[globs.CNIRlang]["OCR module error"], (lang.all[globs.CNIRlang]["The OCR module located at {} can not be found or corrupted. It will be reinstalled at the next run"].format(os.environ['PATH'])), parent=self)
+ logfile.printerr(lang.all[globs.CNIRlang]["Tesseract error : {}. Will be reinstallated"].format(e))
# Tesseract error
except pytesseract.TesseractError as e:
logfile.printerr("Tesseract error : {}".format(e))
- showerror('Erreur de module OCR', ("Le module Tesseract a rencontré un problème : {}".format(e)), parent=self)
-
+ showerror(lang.all[globs.CNIRlang]["OCR module error"], (lang.all[globs.CNIRlang]["The Tesseract module encountered a problem: {}"].format(e)), parent=self)
+ ## Regex and document detection + control related functions
+
def stringValidation(self, keysym):
+ """
+ Analysis of the already typed document
+ """
# analysis
# If we must decide the type of the document
if not self.mrzDecided:
@@ -478,11 +512,13 @@ class mainWindow(Tk):
self.wait_window(invite)
- self.logOnTerm("Document detecté : {}\n".format(candidates[invite.choice][2]))
+ self.logOnTerm(lang.all[globs.CNIRlang]["Document detected: {}\n"].format(candidates[invite.choice][2]))
+ self.statusbar.set(candidates[invite.choice][2])
self.mrzDecided = candidates[invite.choice]
elif len(candidates) == 1:
- self.logOnTerm("Document detecté : {}\n".format(candidates[0][2]))
+ self.logOnTerm(lang.all[globs.CNIRlang]["Document detected: {}\n"].format(candidates[0][2]))
+ self.statusbar.set(candidates[0][2])
self.mrzDecided = candidates[0]
else:
# corrects some problems
@@ -569,11 +605,13 @@ class mainWindow(Tk):
self.wait_window(invite)
- self.logOnTerm("Document re-detecté : {}\n".format(candidates[invite.choice][2]))
+ self.logOnTerm(lang.all[globs.CNIRlang]["Document detected again: {}\n"].format(candidates[invite.choice][2]))
+ self.statusbar.set(candidates[invite.choice][2])
self.mrzDecided = candidates[invite.choice]
elif len(candidates) == 1:
- self.logOnTerm("Document re-detecté : {}\n".format(candidates[0][2]))
+ self.logOnTerm(lang.all[globs.CNIRlang]["Document detected again: {}\n"].format(candidates[0][2]))
+ self.statusbar.set(candidates[0][2])
self.mrzDecided = candidates[0]
return "break"
@@ -583,7 +621,7 @@ class mainWindow(Tk):
regex = re.compile("[A-Z]|<|[0-9]")
# match !
if not regex.fullmatch(event.char):
- self.logOnTerm("Caractère non accepté !\n")
+ self.logOnTerm(lang.all[globs.CNIRlang]["Character not accepted !\n"])
return "break"
# Adds the entry
tempChar = self.termtext.get("1.0", "end")[:-1]
@@ -625,35 +663,147 @@ class mainWindow(Tk):
char = self.speed731text.get()
self.speedResultPrint(str(mrz.computeControlSum(char)))
return "break"
+
+ def computeSigma(self):
+ """
+ Launch the checksum computation, infos validation and print/display the results
+ """
+ # the regex
+ regex = re.compile("[^A-Z0-9<]")
+ code = re.sub(regex, '', self.mrzChar)
+ self.compliance = True
+ allSums = mrz.computeAllControlSum(self.mrzDecided, code)["ctrlSumList"]
+ #print("Code : _{}_ | Sums : {}".format(code, allSums))
+
+ self.termtext.tag_remove("conforme", "1.0", "end")
+ self.termtext.tag_remove("nonconforme", "1.0", "end")
+
+ self.clearTerm()
+ self.logOnTerm(lang.all[globs.CNIRlang]["Document Review: {}\n\n"].format(self.mrzDecided[2]))
+
+ for sum in allSums:
+ x = sum[1] // len(self.mrzDecided[0][0]) +1
+ y = sum[1] % len(self.mrzDecided[0][0])
+ #print("index : {}.{}".format(x,y))
+ #print("{} == {}".format(code[sum[1]], sum[2]))
+
+ if sum[3]:
+ self.logOnTerm(lang.all[globs.CNIRlang]["Checksum position {}: Lu {} VS Calculated {} [facultative]\n"].format(sum[1], code[sum[1]], sum[2]))
+ else:
+ self.logOnTerm(lang.all[globs.CNIRlang]["Checksum position {}: Lu {} VS Calculated {}\n"].format(sum[1], code[sum[1]], sum[2]))
+
+ # if sum is facultative or if sum is ok
+ try:
+ if sum[3] or int(code[sum[1]]) == int(sum[2]):
+ self.termtext.tag_add("conforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
+ self.termtext.tag_configure("conforme", background="green", foreground="white")
+ else:
+ self.termtext.tag_add("nonconforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
+ self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white")
+ self.compliance = False
+ except ValueError:
+ self.termtext.tag_add("nonconforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
+ self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white")
+ self.compliance = False
+
+ # get the infos
+ docInfos = mrz.getDocInfos(self.mrzDecided, code)
+ #print(docInfos)
+ # display the infos
+ for key in [ e for e in docInfos ]:
+ #print(docInfos[key])
+ if key in ["CODE", "CTRL", "CTRLF"]:
+ continue
+ if not docInfos[key] == False:
+ self.infoList[key]['text'] = docInfos[key]
+ self.infoList[key]['background'] = self['background']
+ self.infoList[key]['foreground'] = "black"
+ else:
+ self.infoList[key]['background'] = "red"
+ self.infoList[key]['foreground'] = "white"
+ self.infoList[key]['text'] = "NC"
+ self.compliance = False
+
+ if self.compliance == True:
+ self.STATUStxt["text"] = lang.all[globs.CNIRlang]["COMPLIANT"]
+ self.STATUStxt["foreground"] = "green"
+ self.statusbar.set(lang.all[globs.CNIRlang]["COMPLIANT"])
+ else:
+ self.STATUStxt["text"] = lang.all[globs.CNIRlang]["IMPROPER"]
+ self.STATUStxt["foreground"] = "red"
+ self.statusbar.set(lang.all[globs.CNIRlang]["IMPROPER"])
+
+ ## Print functions
+
def logOnTerm(self, text):
+ """
+ Writes on the monitor
+ """
self.monlog['state'] = 'normal'
self.monlog.insert('end', text)
self.monlog['state'] = 'disabled'
self.monlog.yview(END)
def clearTerm(self):
+ """
+ Clears the monitor
+ """
self.monlog['state'] = 'normal'
self.monlog.delete('1.0', 'end')
self.monlog['state'] = 'disabled'
self.monlog.yview(END)
def speedResultPrint(self, text):
+ """
+ Prints a result in the quick entry terminal
+ """
self.speedResult['state'] = 'normal'
self.speedResult.delete("1.0", 'end')
self.speedResult.insert('end', text)
self.speedResult['state'] = 'disabled'
+ ## Document display related functions
+
+ def DisplayUpdate(self, image=None, setplace=False):
+ """
+ Reload the displayer to display the image or not
+ """
+ if image:
+ self.imageViewer.image = image
+ self.imageViewer.ZONE.itemconfigure(self.STATUSimg, image=(self.imageViewer.image))
+ self.imageViewer.ZONE.configure(scrollregion=self.imageViewer.ZONE.bbox("all"))
+
def goPageChoice(self, event):
+ """
+ Change the current viewed page of the multipage tiff if needed
+ """
self.imageViewer.pagenumber = int(self.toolbar.pageChooser.get()) - 1
self.resizeScan()
def openingScan(self):
+ """
+ Open the scan, ask its path and displays it
+ """
path = ''
- path = filedialog.askopenfilename(parent=self, title='Ouvrir un scan de CNI...', filetypes=(('TIF files', '*.tif'),
+ path = filedialog.askopenfilename(parent=self, title=lang.all[globs.CNIRlang]["Open a scan of document..."], filetypes=(('TIF files', '*.tif'),
('TIF files', '*.tiff'),
('JPEG files', '*.jpg'),
('JPEG files', '*.jpeg')))
+ self.openScanFile(path)
+
+ def openScanFile(self, path):
+ """
+ Open an image file at path to display it on the displayer
+ """
+ # Check if the file is valid
+ if ( path[-3:] != 'jpg'
+ and path[-3:] != 'tif'
+ and path[-4:] != 'jpeg'
+ and path[-4:] != 'tiff' ) or not os.path.isfile(path):
+ showerror(lang.all[globs.CNIRlang]["Open a scan of document..."], lang.all[globs.CNIRlang]["The file you provided is not valid : {}"].format(path))
+ return
+
# Load an image using OpenCV
self.imageViewer.imagePath = path
self.imageViewer.imgZoom = 1
@@ -685,7 +835,7 @@ class mainWindow(Tk):
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
- self.statusUpdate(photo)
+ self.DisplayUpdate(photo)
def zoomInScan50(self, quantity = 50):
if self.imageViewer.image:
@@ -746,6 +896,9 @@ class mainWindow(Tk):
self.resizeScan()
def negativeScan(self):
+ """
+ Invert the bits to make a negative of the scan (and highlight the contrasts)
+ """
if self.imageViewer.image:
# Load an image using OpenCV
cv_img = cv2.imreadmulti(self.imageViewer.imagePath)[1][self.imageViewer.pagenumber]
@@ -760,6 +913,9 @@ class mainWindow(Tk):
self.resizeScan(cv_img)
def resizeScan(self, cv_img = None):
+ """
+ Reloads the image according to settings
+ """
if self.imageViewer.image:
try:
if not hasattr(cv_img, 'shape'):
@@ -789,10 +945,10 @@ class mainWindow(Tk):
cv_img = cv2.resize(cv_img, dim, interpolation = cv2.INTER_AREA)
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
- self.statusUpdate( photo)
+ self.DisplayUpdate( photo)
except Exception as e:
logfile.printerr("Error with opencv : {}".format(e))
- traceback.print_exc(file=sys.stdout)
+ critical.crashCNIR()
try:
# Reload an image using OpenCV
path = self.imageViewer.imagePath
@@ -807,144 +963,97 @@ class mainWindow(Tk):
height, width, channels_no = cv_img.shape
# Use PIL (Pillow) to convert the NumPy ndarray to a PhotoImage
photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(cv_img))
- self.statusUpdate(photo)
+ self.DisplayUpdate(photo)
except Exception as e:
logfile.printerr("Critical error with opencv : ".format(e))
- traceback.print_exc(file=sys.stdout)
- showerror("Erreur OpenCV (traitement d'images)", "Une erreur critique s'est produite dans le gestionnaire de traitement d'images OpenCV utilisé par CNIRevelator. L'application va se réinitialiser")
+ critical.crashCNIR()
+ showerror(lang.all[globs.CNIRlang]["OpenCV error (image processing)"], lang.all[globs.CNIRlang]["A critical error has occurred in the OpenCV image processing manager used by CNIRevelator, the application will reset itself"])
self.initialize()
+ ## IHM and user interface related functions
+
def newEntry(self):
+ """
+ Reinits the IHM and invite
+ """
self.initialize()
- self.logOnTerm('\n\nEntrez la première ligne de MRZ svp \n')
+ self.logOnTerm('\n\n{}\n'.format(lang.all[globs.CNIRlang]["Please type a MRZ or open a scan"]))
def infobox(self):
+ """
+ Shows the About dialog
+ """
Tk().withdraw()
- showinfo('A propos de CNIRevelator',
- ( 'Version du logiciel : CNIRevelator ' + globs.verstring_full + '\n\n'
- "Copyright © 2018-2019 Adrien Bourmault (neox95)" + "\n\n"
- "CNIRevelator est un logiciel libre : vous avez le droit de le modifier et/ou le distribuer "
- "dans les termes de la GNU General Public License telle que publiée par "
- "la Free Software Foundation, dans sa version 3 ou "
- "ultérieure. " + "\n\n"
- "CNIRevelator est distribué dans l'espoir d'être utile, sans toutefois "
- "impliquer une quelconque garantie de "
- "QUALITÉ MARCHANDE ou APTITUDE À UN USAGE PARTICULIER. Référez vous à la "
- "GNU General Public License pour plus de détails à ce sujet. "
- "\n\n"
- "Vous devriez avoir reçu une copie de la GNU General Public License "
- "avec CNIRevelator. Si cela n'est pas le cas, jetez un oeil à . "
- "\n\n"
- "Le module d'OCR Tesseract 4.0 est soumis à l'Apache License 2004."
- "\n\n"
- "Les bibliothèques python et l'environnement Anaconda 3 sont soumis à la licence BSD 2018-2019."
- "\n\n"
- "Le code source de ce programme est disponible sur Github à l'adresse .\n"
- "Son fonctionnement est conforme aux normes et directives du document 9303 de l'OACI régissant les documents de voyages et d'identité." + '\n\n'
- " En cas de problèmes ou demande particulière, ouvrez-y une issue ou bien envoyez un mail à neox@os-k.eu !\n\n"
+ showinfo( lang.all[globs.CNIRlang]["About CNIRevelator"],
+ (
+ lang.all[globs.CNIRlang]["ABOUT"]
),
-
parent=self)
def helpbox(self):
+ """
+ Shows the keyboard help summary
+ """
Tk().withdraw()
- showinfo('Aide sur les contrôles au clavier',
- ( "Terminal de saisie rapide (731) : \n\n"
- " Caractères autorisés : Alphanumériques en majuscule et le caractère '<'. Pas de minuscules ni caractères spéciaux, autrement la somme est mise à zéro \n\n"
- " Calculer résultat :\t\t\tTouche Ctrl droite \n"
- " Copier :\t\t\t\tCtrl-C \n"
- " Coller :\t\t\t\tCtrl-V \n"
- "\n\n"
- "Terminal de saisie MRZ complète : \n\n"
- " Caractères autorisés : Alphanumériques en majuscule et le caractère '<'. Pas de minuscules ni caractères spéciaux, autrement la somme est mise à zéro \n\n"
- " Calculer résultat :\t\t\tTouche Ctrl droite \n"
- " Compléter champ :\t\t\tTouche Tab \n"
- " Copier :\t\t\t\tCtrl-C \n"
- " Coller :\t\t\t\tCtrl-V \n"
- " Forcer une nouvelle détection du document :\tEchap\n"
+ showinfo( lang.all[globs.CNIRlang]["Keyboard commands"],
+ (
+ lang.all[globs.CNIRlang]["KEYBHELP"]
),
parent=self)
def openIssuePage(self):
- self.openBrowser("https://github.com/neox95/CNIRevelator/issues")
+ """
+ Opens the Github Issue Repository page
+ """
+ webbrowser.open_new("https://github.com/neox95/CNIRevelator/issues")
- def openBrowser(self, url):
- webbrowser.open_new(url)
+ def showChangeLog(self):
+ changelogWin = ihm.ChangelogDialog(self, ('{} : CNIRevelator {}\n\n{}'.format(lang.all[globs.CNIRlang]["Program version"], globs.verstring_full, lang.all[globs.CNIRlang]["CHANGELOG"])))
+ changelogWin.transient(self)
+ changelogWin.grab_set()
+ changelogWin.focus_force()
+ self.wait_window(changelogWin)
- def computeSigma(self):
+ def updateSet(self):
"""
- Launch the checksum computation, infos validation and display the results
+ Update Settings
"""
- # the regex
- regex = re.compile("[^A-Z0-9<]")
- code = re.sub(regex, '', self.mrzChar)
- self.compliance = True
-
- allSums = mrz.computeAllControlSum(self.mrzDecided, code)["ctrlSumList"]
- #print("Code : _{}_ | Sums : {}".format(code, allSums))
-
- self.termtext.tag_remove("conforme", "1.0", "end")
- self.termtext.tag_remove("nonconforme", "1.0", "end")
-
- self.clearTerm()
- self.logOnTerm("Examen du document : {}\n\n".format(self.mrzDecided[2]))
-
- for sum in allSums:
- x = sum[1] // len(self.mrzDecided[0][0]) +1
- y = sum[1] % len(self.mrzDecided[0][0])
- #print("index : {}.{}".format(x,y))
- #print("{} == {}".format(code[sum[1]], sum[2]))
-
- self.logOnTerm("Somme de contrôle position {} : Lu {} VS Calculé {}\n".format(sum[1], code[sum[1]], sum[2]))
-
- # if sum is facultative or if sum is ok
- try:
- if sum[3] or int(code[sum[1]]) == int(sum[2]):
- self.termtext.tag_add("conforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
- self.termtext.tag_configure("conforme", background="green", foreground="white")
- else:
- self.termtext.tag_add("nonconforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
- self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white")
- self.compliance = False
- except ValueError:
- self.termtext.tag_add("nonconforme", "{}.{}".format(x,y), "{}.{}".format(x,y+1))
- self.termtext.tag_configure("nonconforme", background="red", relief='raised', foreground="white")
- self.compliance = False
-
- # get the infos
- docInfos = mrz.getDocInfos(self.mrzDecided, code)
- #print(docInfos)
- # display the infos
- for key in [ e for e in docInfos ]:
- #print(docInfos[key])
- if key in ["CODE", "CTRL"]:
- continue
- if not docInfos[key] == False:
- self.infoList[key]['text'] = docInfos[key]
- self.infoList[key]['background'] = self['background']
- self.infoList[key]['foreground'] = "black"
- else:
- self.infoList[key]['background'] = "red"
- self.infoList[key]['foreground'] = "white"
- self.infoList[key]['text'] = "NC"
- self.compliance = False
-
- if self.compliance == True:
- self.STATUStxt["text"] = "CONFORME"
- self.STATUStxt["foreground"] = "green"
+ changeupdateWin = ihm.updateSetDialog(self)
+ changeupdateWin.transient(self)
+ changeupdateWin.grab_set()
+ changeupdateWin.focus_force()
+ self.wait_window(changeupdateWin)
+
+ def languageSet(self):
+ """
+ Lang Settings
+ """
+ changelangWin = ihm.langDialog(self)
+ changelangWin.transient(self)
+ changelangWin.grab_set()
+ changelangWin.focus_force()
+ self.wait_window(changelangWin)
+
+ global mrz
+ mrz = reload(mrz)
+
+ self.initialize()
+
+ def panelResize(self):
+ """
+ Shows or hides the panel
+ """
+ if self.currentw > int(2.15 * (self.ws / 2 * 0.3333333333333333)):
+ self.currentw = int(2.15 * (self.ws / 2 * 0.3333333333333333))
+ self.geometry('%dx%d+%d+%d' % (self.currentw, self.h, self.x, self.y))
+ self.update()
else:
- self.STATUStxt["text"] = "NON CONFORME"
- self.STATUStxt["foreground"] = "red"
-
- return
-
-
-
-
-
+ self.currentw = self.w
+ self.geometry('%dx%d+%d+%d' % (self.currentw, self.h, self.x, self.y))
+ self.update()
diff --git a/src/mrz.py b/src/mrz.py
index e51fad6..ace7a69 100644
--- a/src/mrz.py
+++ b/src/mrz.py
@@ -24,537 +24,22 @@
********************************************************************************
"""
-import re
-import logger # logger.py
import re
import datetime
+import logger # logger.py
+import globs # globs.py
+import lang # lang.py
+import critical # critical.py
+
## SEX CODES
sexcode = {'M':'Homme', 'F':'Femme', 'X':'Non spécifié'}
## COUNTRY CODES
-landcode2 = {
- 'AW': 'Aruba',
- 'AF': 'Afghanistan',
- 'AO': 'Angola',
- 'AI': 'Anguilla',
- 'AL': 'Albanie',
- 'AD': 'Andorre',
- 'AE': 'Emirats arabes unis',
- 'AR': 'Argentine',
- 'AM': 'Arménie',
- 'AS': 'Samoa américaines',
- 'AQ': 'Antarctique',
- 'TF': 'Terres australes et antarctiques françaises',
- 'AG': 'Antigua-et-Barbuda',
- 'AU': 'Australie',
- 'AT': 'Autriche',
- 'AZ': 'Azerbaidjan',
- 'BI': 'Burundi',
- 'BE': 'Belgique',
- 'BJ': 'Benin',
- 'BQ': 'Pays-Bas caribéens',
- 'BF': 'Burkina Faso',
- 'BD': 'Bangladesh',
- 'BG': 'Bulgarie',
- 'BH': 'Bahrein',
- 'BS': 'Bahamas',
- 'BA': 'Bosnie-Herzegovine',
- 'BL': 'Saint-Barthélemy',
- 'BY': 'Bielorussie',
- 'BZ': 'Belize',
- 'BM': 'Bermudes',
- 'BO': 'Bolivie',
- 'BR': 'Brésil',
- 'BB': 'Barbade',
- 'BN': 'Brunei',
- 'BT': 'Bhoutan',
- 'BW': 'Botswana',
- 'CF': 'République Centrafricaine',
- 'CA': 'Canada',
- 'CC': 'Îles Cocos',
- 'CH': 'Suisse',
- 'CL': 'Chili',
- 'CN': 'Chine',
- 'CI': "Côte d'Ivoire",
- 'CM': 'Cameroun',
- 'CD': 'Congo (République démocratique)',
- 'CG': 'Congo (République)',
- 'CK': 'Îles Cook',
- 'CO': 'Colombie',
- 'KM': 'Comores',
- 'CV': 'Cap-Vert',
- 'CR': 'Costa Rica',
- 'CU': 'Cuba',
- 'CW': 'Curaçao',
- 'CX': 'Île Christmas',
- 'KY': 'Caimans',
- 'CY': 'Chypre',
- 'CZ': 'Tchéquie',
- 'DE': 'Allemagne',
- 'DJ': 'Djibouti',
- 'DM': 'Dominique',
- 'DK': 'Danemark',
- 'DO': 'République dominicaine',
- 'DZ': 'Algérie',
- 'EC': 'Equateur',
- 'EG': 'Egypte',
- 'ER': 'Erythrée',
- 'EH': 'Sahara occidental',
- 'ES': 'Espagne',
- 'EE': 'Estonie',
- 'ET': 'Ethiopie',
- 'FI': 'Finlande',
- 'FJ': 'Fidji',
- 'FK': 'Îles Malouines',
- 'FR': 'France',
- 'FO': 'Féroé',
- 'FM': 'Micronésie',
- 'GA': 'Gabon',
- 'GB': 'Royaume-Uni',
- 'GE': 'Géorgie',
- 'GG': 'Guernesey',
- 'GH': 'Ghana',
- 'GI': 'Gibraltar',
- 'GN': 'Guinée',
- 'GP': 'Guadeloupe',
- 'GM': 'Gambie',
- 'GW': 'Guinée-Bissau',
- 'GQ': 'Guinée équatoriale',
- 'GR': 'Grèce',
- 'GD': 'Grenade',
- 'GL': 'Groenland',
- 'GT': 'Guatemala',
- 'GF': 'Guyane',
- 'GU': 'Guam',
- 'GY': 'Guyana',
- 'HK': 'Hong Kong',
- 'HN': 'Honduras',
- 'HR': 'Croatie',
- 'HT': 'Haïti',
- 'HU': 'Hongrie',
- 'ID': 'Indonésie',
- 'IM': 'Île de Man',
- 'IN': 'Inde',
- 'IO': "Territoire britannique de l'océan Indien",
- 'IE': 'Irlande',
- 'IR': 'Irak',
- 'IQ': 'Iran',
- 'IS': 'Islande',
- 'IL': 'Israël',
- 'IT': 'Italie',
- 'JM': 'Jamaïque',
- 'JE': 'Jersey',
- 'JO': 'Jordanie',
- 'JP': 'Japon',
- 'KZ': 'Kazakhstan',
- 'KE': 'Kenya',
- 'KG': 'Kirghizistan',
- 'KH': 'Cambodge',
- 'KI': 'Kiribati',
- 'KN': 'Saint-Christophe-et-Niévès',
- 'KR': 'Corée du Sud',
- 'KW': 'Koweït',
- 'LA': 'Laos',
- 'LB': 'Liban',
- 'LR': 'Liberia',
- 'LY': 'Libye',
- 'LC': 'Sainte-Lucie',
- 'LI': 'Liechtenstein',
- 'LK': 'Sri Lanka',
- 'LS': 'Lesotho',
- 'LT': 'Lituanie',
- 'LU': 'Luxembourg',
- 'LV': 'Lettonie',
- 'MO': 'Macao',
- 'MF': 'Sint-Maarten',
- 'MA': 'Maroc',
- 'MC': 'Monaco',
- 'MD': 'Moldavie',
- 'MG': 'Madagascar',
- 'MV': 'Maldives',
- 'MX': 'Mexique',
- 'MH': 'Marshall',
- 'MK': 'Macedoine',
- 'ML': 'Mali',
- 'MT': 'Malte',
- 'MM': 'Birmanie',
- 'ME': 'Monténégro',
- 'MN': 'Mongolie',
- 'MP': 'Îles Mariannes du Nord',
- 'MZ': 'Mozambique',
- 'MR': 'Mauritanie',
- 'MS': 'Montserrat',
- 'MQ': 'Martinique',
- 'MU': 'Maurice',
- 'MW': 'Malawi',
- 'MY': 'Malaisie',
- 'YT': 'Mayotte',
- 'NA': 'Namibie',
- 'NC': 'Nouvelle-Calédonie',
- 'NE': 'Niger',
- 'NF': 'Île Norfolk',
- 'NG': 'Nigeria',
- 'NI': 'Nicaragua',
- 'NU': 'Niue',
- 'NL': 'Pays-Bas',
- 'NO': 'Norvège',
- 'NP': 'Nepal',
- 'NR': 'Nauru',
- 'NZ': 'Nouvelle-Zélande',
- 'OM': 'Oman',
- 'PK': 'Pakistan',
- 'PA': 'Panama',
- 'PN': 'Îles Pitcairn',
- 'PE': 'Pérou',
- 'PH': 'Philippines',
- 'PW': 'Palaos',
- 'PG': 'Papouasie-Nouvelle-Guinée',
- 'PL': 'Pologne',
- 'PR': 'Porto Rico',
- 'KP': 'Corée du Nord',
- 'PT': 'Portugal',
- 'PY': 'Paraguay',
- 'PS': 'Palestine',
- 'PF': 'Polynésie française',
- 'QA': 'Qatar',
- 'RE': 'Réunion',
- 'RO': 'Roumanie',
- 'RU': 'Russie',
- 'RW': 'Rwanda',
- 'SA': 'Arabie saoudite',
- 'SD': 'Soudan',
- 'SN': 'Sénégal',
- 'SG': 'Singapour',
- 'GS': 'Georgie du Sud-et-les iles Sandwich du Sud',
- 'SH': 'Sainte-Hélène, Ascension et Tristan da Cunha',
- 'SJ': 'Svalbard et île Jan Mayen',
- 'SB': 'Salomon',
- 'SL': 'Sierra Leone',
- 'SV': 'Salvador',
- 'SM': 'Saint-Marin',
- 'SO': 'Somalie',
- 'PM': 'Saint-Pierre-et-Miquelon',
- 'RS': 'Serbie',
- 'SS': 'Soudan du Sud',
- 'ST': 'Sao Tomé-et-Principe',
- 'SR': 'Suriname',
- 'SK': 'Slovaquie',
- 'SI': 'Slovénie',
- 'SE': 'Suède',
- 'SZ': 'eSwatani',
- 'SX': 'Saint-Martin ',
- 'SC': 'Seychelles',
- 'SY': 'Syrie',
- 'TC': 'Îles Turques-et-Caïques',
- 'TD': 'Tchad',
- 'TG': 'Togo',
- 'TH': 'Thaïlande',
- 'TJ': 'Tadjikistan',
- 'TK': 'Tokelau',
- 'TM': 'Turkmenistan',
- 'TL': 'Timor oriental',
- 'TO': 'Tonga',
- 'TT': 'Trinité-et-Tobago',
- 'TN': 'Tunisie',
- 'TR': 'Turquie',
- 'TV': 'Tuvalu',
- 'TW': 'Taiwan',
- 'TZ': 'Tanzanie',
- 'UG': 'Ouganda',
- 'UA': 'Ukraine',
- 'UY': 'Uruguay',
- 'US': 'Etats-Unis',
- 'UZ': 'Ouzbékistan',
- 'VA': 'Saint-Siège (État de la Cité du Vatican)',
- 'VC': 'Saint-Vincent-et-les-Grenadines',
- 'VE': 'Venezuela',
- 'VG': 'Îles Vierges britanniques',
- 'VI': 'Îles Vierges des États-Unis',
- 'VN': 'Viêt Nam',
- 'VU': 'Vanuatu',
- 'WF': 'Wallis-et-Futuna',
- 'WS': 'Samoa',
- 'XK': 'Kosovo',
- 'YE': 'Yémen',
- 'ZA': 'Afrique du Sud',
- 'ZM': 'Zambie',
- 'ZW': 'Zimbabwe'
- }
+landcode2 = lang.all[globs.CNIRlang]["LANDCODE2"]
-landcode3 = {
- 'ABW': 'Aruba',
- 'AFG': 'Afghanistan',
- 'AGO': 'Angola',
- 'AIA': 'Anguilla',
- 'ALB': 'Albanie',
- 'AND': 'Andorre',
- 'ARE': 'Emirats arabes unis',
- 'ARG': 'Argentine',
- 'ARM': 'Arménie',
- 'ASM': 'Samoa américaines',
- 'ATA': 'Antarctique',
- 'ATF': 'Terres australes et antarctiques françaises',
- 'ATG': 'Antigua-et-Barbuda',
- 'AUS': 'Australie',
- 'AUT': 'Autriche',
- 'AZE': 'Azerbaidjan',
- 'BDI': 'Burundi',
- 'BEL': 'Belgique',
- 'BEN': 'Benin',
- 'BES': 'Pays-Bas caribéens',
- 'BFA': 'Burkina Faso',
- 'BGD': 'Bangladesh',
- 'BGR': 'Bulgarie',
- 'BHR': 'Bahrein',
- 'BHS': 'Bahamas',
- 'BIH': 'Bosnie-Herzegovine',
- 'BLM': 'Saint-Barthélemy',
- 'BLR': 'Bielorussie',
- 'BLZ': 'Belize',
- 'BMU': 'Bermudes',
- 'BOL': 'Bolivie',
- 'BRA': 'Brésil',
- 'BRB': 'Barbade',
- 'BRN': 'Brunei',
- 'BTN': 'Bhoutan',
- 'BWA': 'Botswana',
- 'CAF': 'République Centrafricaine',
- 'CAN': 'Canada',
- 'CCK': 'Îles Cocos',
- 'CHE': 'Suisse',
- 'CHL': 'Chili',
- 'CHN': 'Chine',
- 'CIV': "Côte d'Ivoire",
- 'CMR': 'Cameroun',
- 'COD': 'Congo (République démocratique)',
- 'COG': 'Congo (République)',
- 'COK': 'Îles Cook',
- 'COL': 'Colombie',
- 'COM': 'Comores',
- 'CPV': 'Cap-Vert',
- 'CRI': 'Costa Rica',
- 'CUB': 'Cuba',
- 'CUW': 'Curaçao',
- 'CXR': 'Île Christmas',
- 'CYM': 'Caimans',
- 'CYP': 'Chypre',
- 'CZE': 'Tchéquie',
- 'DEU': 'Allemagne',
- 'DJI': 'Djibouti',
- 'DMA': 'Dominique',
- 'DNK': 'Danemark',
- 'DOM': 'République dominicaine',
- 'DZA': 'Algérie',
- 'ECU': 'Equateur',
- 'EGY': 'Egypte',
- 'ERI': 'Erythrée',
- 'ESH': 'Sahara occidental',
- 'ESP': 'Espagne',
- 'EST': 'Estonie',
- 'ETH': 'Ethiopie',
- 'FIN': 'Finlande',
- 'FJI': 'Fidji',
- 'FLK': 'Îles Malouines',
- 'FRA': 'France',
- 'FRO': 'Féroé',
- 'FSM': 'Micronésie',
- 'GAB': 'Gabon',
- 'GBR': 'Royaume-Uni',
- 'GEO': 'Géorgie',
- 'GGY': 'Guernesey',
- 'GHA': 'Ghana',
- 'GIB': 'Gibraltar',
- 'GIN': 'Guinée',
- 'GLP': 'Guadeloupe',
- 'GMB': 'Gambie',
- 'GNB': 'Guinée-Bissau',
- 'GNQ': 'Guinée équatoriale',
- 'GRC': 'Grèce',
- 'GRD': 'Grenade',
- 'GRL': 'Groenland',
- 'GTM': 'Guatemala',
- 'GUF': 'Guyane',
- 'GUM': 'Guam',
- 'GUY': 'Guyana',
- 'HKG': 'Hong Kong',
- 'HND': 'Honduras',
- 'HRV': 'Croatie',
- 'HTI': 'Haïti',
- 'HUN': 'Hongrie',
- 'IDN': 'Indonésie',
- 'IMN': 'Île de Man',
- 'IND': 'Inde',
- 'IOT': "Territoire britannique de l'océan Indien",
- 'IRL': 'Irlande',
- 'IRN': 'Irak',
- 'IRQ': 'Iran',
- 'ISL': 'Islande',
- 'ISR': 'Israël',
- 'ITA': 'Italie',
- 'JAM': 'Jamaïque',
- 'JEY': 'Jersey',
- 'JOR': 'Jordanie',
- 'JPN': 'Japon',
- 'KAZ': 'Kazakhstan',
- 'KEN': 'Kenya',
- 'KGZ': 'Kirghizistan',
- 'KHM': 'Cambodge',
- 'KIR': 'Kiribati',
- 'KNA': 'Saint-Christophe-et-Niévès',
- 'KOR': 'Corée du Sud',
- 'KWT': 'Koweït',
- 'LAO': 'Laos',
- 'LBN': 'Liban',
- 'LBR': 'Liberia',
- 'LBY': 'Libye',
- 'LCA': 'Sainte-Lucie',
- 'LIE': 'Liechtenstein',
- 'LKA': 'Sri Lanka',
- 'LSO': 'Lesotho',
- 'LTU': 'Lituanie',
- 'LUX': 'Luxembourg',
- 'LVA': 'Lettonie',
- 'MAC': 'Macao',
- 'MAF': 'Sint-Maarten',
- 'MAR': 'Maroc',
- 'MCO': 'Monaco',
- 'MDA': 'Moldavie',
- 'MDG': 'Madagascar',
- 'MDV': 'Maldives',
- 'MEX': 'Mexique',
- 'MHL': 'Marshall',
- 'MKD': 'Macedoine',
- 'MLI': 'Mali',
- 'MLT': 'Malte',
- 'MMR': 'Birmanie',
- 'MNE': 'Monténégro',
- 'MNG': 'Mongolie',
- 'MNP': 'Îles Mariannes du Nord',
- 'MOZ': 'Mozambique',
- 'MRT': 'Mauritanie',
- 'MSR': 'Montserrat',
- 'MTQ': 'Martinique',
- 'MUS': 'Maurice',
- 'MWI': 'Malawi',
- 'MYS': 'Malaisie',
- 'MYT': 'Mayotte',
- 'NAM': 'Namibie',
- 'NCL': 'Nouvelle-Calédonie',
- 'NER': 'Niger',
- 'NFK': 'Île Norfolk',
- 'NGA': 'Nigeria',
- 'NIC': 'Nicaragua',
- 'NIU': 'Niue',
- 'NLD': 'Pays-Bas',
- 'NOR': 'Norvège',
- 'NPL': 'Nepal',
- 'NRU': 'Nauru',
- 'NZL': 'Nouvelle-Zélande',
- 'OMN': 'Oman',
- 'PAK': 'Pakistan',
- 'PAN': 'Panama',
- 'PCN': 'Îles Pitcairn',
- 'PER': 'Pérou',
- 'PHL': 'Philippines',
- 'PLW': 'Palaos',
- 'PNG': 'Papouasie-Nouvelle-Guinée',
- 'POL': 'Pologne',
- 'PRI': 'Porto Rico',
- 'PRK': 'Corée du Nord',
- 'PRT': 'Portugal',
- 'PRY': 'Paraguay',
- 'PSE': 'Palestine',
- 'PYF': 'Polynésie française',
- 'QAT': 'Qatar',
- 'REU': 'Réunion',
- 'ROU': 'Roumanie',
- 'RUS': 'Russie',
- 'RWA': 'Rwanda',
- 'SAU': 'Arabie saoudite',
- 'SDN': 'Soudan',
- 'SEN': 'Sénégal',
- 'SGP': 'Singapour',
- 'SGS': 'Georgie du Sud-et-les iles Sandwich du Sud',
- 'SHN': 'Sainte-Hélène, Ascension et Tristan da Cunha',
- 'SJM': 'Svalbard et île Jan Mayen',
- 'SLB': 'Salomon',
- 'SLE': 'Sierra Leone',
- 'SLV': 'Salvador',
- 'SMR': 'Saint-Marin',
- 'SOM': 'Somalie',
- 'SPM': 'Saint-Pierre-et-Miquelon',
- 'SRB': 'Serbie',
- 'SSD': 'Soudan du Sud',
- 'STP': 'Sao Tomé-et-Principe',
- 'SUR': 'Suriname',
- 'SVK': 'Slovaquie',
- 'SVN': 'Slovénie',
- 'SWE': 'Suède',
- 'SWZ': 'eSwatani',
- 'SXM': 'Saint-Martin ',
- 'SYC': 'Seychelles',
- 'SYR': 'Syrie',
- 'TCA': 'Îles Turques-et-Caïques',
- 'TCD': 'Tchad',
- 'TGO': 'Togo',
- 'THA': 'Thaïlande',
- 'TJK': 'Tadjikistan',
- 'TKL': 'Tokelau',
- 'TKM': 'Turkmenistan',
- 'TLS': 'Timor oriental',
- 'TON': 'Tonga',
- 'TTO': 'Trinité-et-Tobago',
- 'TUN': 'Tunisie',
- 'TUR': 'Turquie',
- 'TUV': 'Tuvalu',
- 'TWN': 'Taiwan',
- 'TZA': 'Tanzanie',
- 'UGA': 'Ouganda',
- 'UKR': 'Ukraine',
- 'URY': 'Uruguay',
- 'USA': 'Etats-Unis',
- 'UZB': 'Ouzbékistan',
- 'VAT': 'Saint-Siège (État de la Cité du Vatican)',
- 'VCT': 'Saint-Vincent-et-les-Grenadines',
- 'VEN': 'Venezuela',
- 'VGB': 'Îles Vierges britanniques',
- 'VIR': 'Îles Vierges des États-Unis',
- 'VNM': 'Viêt Nam',
- 'VUT': 'Vanuatu',
- 'WLF': 'Wallis-et-Futuna',
- 'WSM': 'Samoa',
- 'XKX': 'Kosovo',
- 'YEM': 'Yémen',
- 'ZAF': 'Afrique du Sud',
- 'ZMB': 'Zambie',
- 'ZWE': 'Zimbabwe',
- 'NTZ': 'Zone neutre',
- 'UNO': 'Fonctionnaire des Nations Unies',
- 'UNA': "Fonctionnaire d'une organisation affiliée aux Nations Unies",
- 'UNK': 'Représentant des Nations Unies au Kosovo',
- 'XXA': 'Apatride Convention 1954',
- 'XXB': 'Réfugié Convention 1954',
- 'XXC': 'Réfugié autre',
- 'XXX': 'Résident Légal de Nationalité Inconnue',
- 'D': 'Allemagne',
- 'EUE': 'Union Européenne',
- 'GBD': "Citoyen Britannique d'Outre-mer (BOTC)",
- 'GBN': 'British National (Overseas)',
- 'GBO': 'British Overseas Citizen',
- 'GBP': 'British Protected Person',
- 'GBS': 'British Subject',
- 'XBA': 'Banque Africaine de Développement',
- 'XIM': "Banque Africaine d'Export–Import",
- 'XCC': 'Caribbean Community or one of its emissaries',
- 'XCO': 'Common Market for Eastern and Southern Africa',
- 'XEC': 'Economic Community of West African States',
- 'XPO': 'International Criminal Police Organization',
- 'XOM': 'Sovereign Military Order of Malta',
- 'RKS': 'Kosovo',
- 'WSA': 'World Service Authority World Passport'
-}
+landcode3 = lang.all[globs.CNIRlang]["LANDCODE3"]
## DOCUMENTS TYPES
@@ -576,7 +61,7 @@ P = [
"D": ["1", "CTRLF", "[0-9]", "C"],
"E": ["1", "CTRL", "[0-9]", "4578ABCD"]
},
- "Passeport"
+ lang.all[globs.CNIRlang]["Passeport"]
]
IP = [
@@ -596,7 +81,7 @@ IP = [
"C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "345679AC"]
},
- "Carte-passeport"
+ lang.all[globs.CNIRlang]["Carte-passeport"]
]
I_ = [
@@ -616,7 +101,7 @@ I_ = [
"C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "345679AC"]
},
- "Titre d'identité/de voyage"
+ lang.all[globs.CNIRlang]["Titre d'identité/de voyage"]
]
AC = [
@@ -637,7 +122,7 @@ AC = [
"C": ["11", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]","345679AC"]
},
- "Certificat de membre d'équipage"
+ lang.all[globs.CNIRlang]["Certificat de membre d'équipage"]
]
VA = [
@@ -656,7 +141,7 @@ VA = [
"B": ["1", "CTRL", "[0-9]", "A"],
"C": ["16", "FACULT", ".+"]
},
- "Visa de type A"
+ lang.all[globs.CNIRlang]["Visa de type A"]
]
VB = [
@@ -675,7 +160,7 @@ VB = [
"B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"]
},
- "Visa de type B"
+ lang.all[globs.CNIRlang]["Visa de type B"]
]
TSF = [
@@ -694,7 +179,7 @@ TSF = [
"B": ["1", "CTRL", "[0-9]", "A"],
"C": ["8", "FACULT", ".+"]
},
- "Carte de séjour"
+ lang.all[globs.CNIRlang]["Carte de séjour"]
]
I__ = [
@@ -714,7 +199,7 @@ I__ = [
"C": ["7", "FACULT", ".+"],
"D": ["1", "CTRL", "[0-9]", "4578ABC"]
},
- "Pièce d'identité/de voyage"
+ lang.all[globs.CNIRlang]["Pièce d'identité/de voyage"]
]
IDFR = [
@@ -734,7 +219,7 @@ IDFR = [
"C": ["1", "SEX", "[A-Z]"],
"D": ["1", "CTRL", "[0-9]", "123456789ABCE"]
},
- "Pièce d'identité FR"
+ lang.all[globs.CNIRlang]["Pièce d'identité FR"]
]
DL = [
@@ -748,7 +233,7 @@ DL = [
"6": ["8", "NOM", "([A-Z]|<)+"],
"7": ["1", "CTRL", "[0-9]", "123456"]
},
- "Permis de conduire"
+ lang.all[globs.CNIRlang]["Permis de conduire"]
]
TYPES = [IDFR, I__, VB, VA, AC, I_, IP, P, DL, TSF]
@@ -1010,6 +495,14 @@ def getDocInfos(doc, code):
res["INDIC"] += value
except KeyError:
res["INDIC"] = value
+
+ # Sex
+ elif field[0] == 'SEX':
+ if not value in "MF":
+ res[field[0]] = False
+ else:
+ res[field[0]] = value
+
# All other cases
else:
if value != "":
diff --git a/src/updater.py b/src/updater.py
index b41c16b..96445a7 100644
--- a/src/updater.py
+++ b/src/updater.py
@@ -24,7 +24,9 @@
"""
from win32com.client import Dispatch
-import traceback
+from tkinter.messagebox import *
+from tkinter import *
+import pythoncom
import sys
import time
import os
@@ -34,10 +36,12 @@ import hashlib
import subprocess
import psutil
+import critical # critical.py
import ihm # ihm.py
import logger # logger.py
import globs # globs.py
import downloader # downloader.py
+import lang # lang.py
UPDATE_IS_MADE = False
UPATH = ' '
@@ -80,52 +84,21 @@ def exitProcess(arg):
if process.pid == os.getpid():
process.terminate()
sys.exit(arg)
-
-def runPowershell(scriptblock, cwd=os.getcwd()):
- """
- Executes a powershell command
- """
- log.debug("Running PowerShell Block:\r\n%s", scriptblock)
- log.debug("Current Directory: %s\r\n" % cwd)
- psProc = subprocess.Popen([r'C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe',
- '-ExecutionPolicy', 'Bypass',
- '-noprofile',
- '-c', '-',],
- cwd=cwd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- stdoutdata, stderrdata = psProc.communicate(scriptblock)
-
- if stdoutdata:
- log.debug("Script Output:\r\n%s" % stdoutdata)
- elif not stderrdata:
- log.debug("Script completed succssfully (no stdout/stderr).")
- if stderrdata:
- log.error("Script Error:\r\n%s" % stderrdata)
-
- return stdoutdata, stderrdata
-
-
-def getCertificates(server_list, location="LocalMachine", store="My"):
- """
- Returns the json data of all installed certificates
- """
- cmd = '''
-$sb = { ls Cert:\%s\%s | Select Subject,ThumbPrint }
-$Servers = '%s' | ConvertFrom-Json
-
-Invoke-Command -ComputerName $Servers -ScriptBlock $sb -Authentication Negotiate | ConvertTo-Json -Depth 999
- ''' % (location, store, json.dumps(server_list))
- stdoutdata, stderrdata = runPowershell(cmd)
- return json.loads(stdoutdata)
-
-
+
+def updateChannel(choice):
+ if choice == "Beta":
+ with open(globs.CNIRUrlConfig, 'w') as (configFile):
+ configFile.write("{}\n0\n0".format(globs.CNIRBetaURL))
+ else:
+ with open(globs.CNIRUrlConfig, 'w') as (configFile):
+ configFile.write("{}\n0\n0".format(globs.CNIRDefaultURL))
def getLatestVersion(credentials):
"""
Returns the latest version of the software
"""
+
+ finalver, finalurl, finalchecksum = [None]*3
# Global Handlers
logfile = logger.logCur
@@ -155,7 +128,7 @@ def getLatestVersion(credentials):
except:
pass
with open(globs.CNIRUrlConfig, 'w') as (configFile):
- configFile.write("https://raw.githubusercontent.com/neox95/CNIRevelator/master/VERSIONS.LST\n0\n0")
+ configFile.write("{}\n0\n0".format(globs.CNIRDefaultURL))
# Getting the list of versions of the software
logfile.printdbg('Retrieving the software versions')
@@ -188,7 +161,7 @@ def getLatestVersion(credentials):
else:
finalurl = url
finalchecksum = None
-
+
return (finalver, finalurl, finalchecksum)
@@ -200,6 +173,11 @@ def tessInstall(PATH, credentials):
# Verifying that Tesseract is installed
if not os.path.exists(PATH + '\\Tesseract-OCR4\\'):
finalver, finalurl, finalchecksum = getLatestVersion(credentials)
+
+ if finalurl == None:
+ logfile.printerr('Unable to get the Tesseract url')
+ return False
+
tesseracturl = finalurl.replace("CNIRevelator.zip", "tesseract_4.zip")
# WE ASSUME THAT THE MAIN FILE IS CNIRevelator.zip AND THAT THE TESSERACT PACKAGE IS tesseract_4.zip
@@ -228,7 +206,7 @@ def tessInstall(PATH, credentials):
# Unzip Tesseract
logfile.printdbg("Unzipping the package")
- launcherWindow.printmsg('Installing the updates')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Installing the updates"])
zip_ref = zipfile.ZipFile(PATH + '\\downloads\\TsrtPackage.zip', 'r')
zip_ref.extractall(PATH)
zip_ref.close()
@@ -261,7 +239,7 @@ def batch(credentials):
getTheUpdate = downloader.newdownload(credentials, finalurl, globs.CNIRFolder + '\\downloads\\CNIPackage.zip', "CNIRevelator {}.{}.{}".format(finalver[0], finalver[1], finalver[2])).download()
- launcherWindow.printmsg('Verifying download...')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Verifying download..."])
# CHECKSUM
BUF_SIZE = 65536 # lets read stuff in 64kb chunks!
@@ -286,7 +264,7 @@ def batch(credentials):
global UPATH
UPATH = globs.CNIRFolder + '\\..\\CNIRevelator' + "{}.{}.{}".format(finalver[0], finalver[1], finalver[2])
logfile.printdbg("Make place")
- launcherWindow.printmsg('Preparing installation...')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Preparing installation..."])
# Cleanup
try:
shutil.rmtree(UPATH + 'temp')
@@ -298,7 +276,7 @@ def batch(credentials):
logfile.printdbg('Unable to cleanup : ' +str(e))
# Unzip
logfile.printdbg("Unzipping the package")
- launcherWindow.printmsg('Installing the updates')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Installing the updates"])
zip_ref = zipfile.ZipFile(globs.CNIRFolder + '\\downloads\\CNIPackage.zip', 'r')
zip_ref.extractall(UPATH + "temp")
zip_ref.close()
@@ -309,9 +287,16 @@ def batch(credentials):
logfile.printdbg('Extracted :' + UPATH + '\\CNIRevelator.exe')
# Make a shortcut
- createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH)
+ # hide main window
+ pythoncom.CoInitialize()
+ root = Tk()
+ root.withdraw()
+ res = askquestion(lang.all[globs.CNIRlang]["Shortcut creation"], lang.all[globs.CNIRlang]["Would you like to create/update the shortcut for CNIRevelator on your desktop ?"])
+ if res == "yes":
+ createShortcut("CNIRevelator.lnk", UPATH + '\\CNIRevelator.exe', UPATH)
+ root.destroy()
- launcherWindow.printmsg('Success !')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Success !"])
# Cleanup
try:
@@ -319,7 +304,7 @@ def batch(credentials):
except:
pass
# Time to quit
- launcherWindow.printmsg('Launched the new process.')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Launching the new version..."])
global UPDATE_IS_MADE
UPDATE_IS_MADE = True
return True
@@ -335,19 +320,19 @@ def umain():
if not credentials.valid:
logfile.printerr("Credentials Error. No effective update !")
- launcherWindow.printmsg('Credentials Error. No effective update !')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Credentials Error. No effective update !"])
time.sleep(2)
launcherWindow.exit()
return 0
# Cleaner for the old version if detected
- if len(sys.argv) > 2:
+ if len(sys.argv) > 2 and str(sys.argv[1]) == "DELETE":
globs.CNIRNewVersion = True
- launcherWindow.printmsg('Deleting old version !')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]["Deleting old version"])
logfile.printdbg("Old install detected : {}".format(sys.argv[1]))
while os.path.exists(str(sys.argv[2])):
try:
- os.remove(str(sys.argv[2]))
+ shutil.rmtree(str(sys.argv[2]))
except Exception as e:
logfile.printerr(str(e))
logfile.printdbg('Trying stop the process !')
@@ -361,45 +346,24 @@ def umain():
else:
logfile.printdbg('Terminating process !')
process.terminate()
- os.remove(str(sys.argv[2]))
+ shutil.rmtree(str(sys.argv[2]))
break
except Exception as e:
logfile.printerr(str(e))
launcherWindow.printmsg('Fail :{}'.format(e))
- launcherWindow.printmsg('Starting...')
- elif len(sys.argv) > 1:
- globs.CNIRNewVersion = True
- launcherWindow.printmsg('Deleting old version !')
- logfile.printdbg("Old install detected : {}".format(sys.argv[1]))
- while os.path.exists(str(sys.argv[1])):
- try:
- shutil.rmtree(str(sys.argv[1]))
- except Exception as e:
- logfile.printerr(str(e))
- logfile.printdbg('Trying stop the process !')
- launcherWindow.printmsg('Fail :{}'.format(e))
- try:
- for process in psutil.process_iter():
- if process.name() == 'CNIRevelator.exe':
- logfile.printdbg('Process found. Command line: {}'.format(process.cmdline()))
- if process.pid == os.getpid():
- logfile.printdbg("Don't touch us ! {} = {}".format(process.pid, os.getpid()))
- else:
- logfile.printdbg('Terminating process !')
- process.terminate()
- shutil.rmtree(str(sys.argv[1]))
- break
- except Exception as e:
- logfile.printerr(str(e))
- launcherWindow.printmsg('Fail :{}'.format(e))
- launcherWindow.printmsg('Starting...')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]['Starting...'])
+
+ # check we want open a file
+ elif len(sys.argv) > 1 and str(sys.argv[1]) != "DELETE":
+ globs.CNIROpenFile = True
+ print(sys.argv)
try:
try:
# EXECUTING THE UPDATE BATCH
success = batch(credentials)
except Exception as e:
- logfile.printerr("An error occured on the thread : " + str(traceback.format_exc()))
+ critical.crashCNIR()
launcherWindow.printmsg('ERROR : ' + str(e))
time.sleep(3)
launcherWindow.exit()
@@ -410,7 +374,7 @@ def umain():
launcherWindow.printmsg('Software is up-to-date !')
else:
logfile.printerr("An error occured. No effective update !")
- launcherWindow.printmsg('An error occured. No effective update !')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
time.sleep(2)
launcherWindow.exit()
return 0
@@ -419,7 +383,7 @@ def umain():
launcherWindow.exit()
return 0
except:
- logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc()))
+ critical.crashCNIR()
launcherWindow.exit()
sys.exit(2)
return 2
@@ -429,7 +393,7 @@ def umain():
# INSTALLING TESSERACT OCR
success = tessInstall(globs.CNIRFolder, credentials)
except Exception as e:
- logfile.printerr("An error occured on the thread : " + str(traceback.format_exc()))
+ critical.crashCNIR()
launcherWindow.printmsg('ERROR : ' + str(e))
time.sleep(3)
launcherWindow.exit()
@@ -437,16 +401,16 @@ def umain():
if success:
logfile.printdbg("Software is up-to-date !")
- launcherWindow.printmsg('Software is up-to-date !')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]['Software is up-to-date !'])
else:
logfile.printerr("An error occured. No effective update !")
- launcherWindow.printmsg('An error occured. No effective update !')
+ launcherWindow.printmsg(lang.all[globs.CNIRlang]['An error occured. No effective update !'])
time.sleep(2)
launcherWindow.exit()
return 0
except:
- logfile.printerr("A FATAL ERROR OCCURED : " + str(traceback.format_exc()))
+ critical.crashCNIR()
launcherWindow.exit()
sys.exit(2)
return 2