summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali <kali@leap.se>2012-12-20 08:20:56 +0900
committerkali <kali@leap.se>2012-12-20 08:20:56 +0900
commita7b091a0553e6120f3e0eb6d4e73a89732c589b2 (patch)
tree55036b34f7d8e92b46472218553984870c036730
parente98c3cc5fad75bea038dc67238e5ce85d701b1e1 (diff)
parent06bccc52c84a93407ab4699a2749b24f55fe3061 (diff)
Merge branch 'feature/translations-setup' into develop
-rw-r--r--.tx/config7
-rw-r--r--Makefile18
-rw-r--r--data/leap_client.pro20
-rwxr-xr-xdata/mkpyqt.py271
-rw-r--r--data/resources/locale.qrc5
-rw-r--r--data/translations/README.rst8
-rw-r--r--data/translations/es.qmbin0 -> 6194 bytes
-rw-r--r--data/translations/es.ts218
-rw-r--r--data/ts/README.rst14
-rw-r--r--data/ts/en_US.ts219
-rw-r--r--docs/dev/internationalization.rst68
-rw-r--r--docs/testers/howto.rst10
-rw-r--r--docs/user/install.rst2
-rw-r--r--docs/user/intro.rst2
-rw-r--r--src/leap/app.py16
-rw-r--r--src/leap/gui/firstrun/intro.py10
-rw-r--r--src/leap/gui/locale_rc.py132
17 files changed, 998 insertions, 22 deletions
diff --git a/.tx/config b/.tx/config
index f1603f25..db998b21 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,3 +1,10 @@
[main]
host = https://www.transifex.com
+[leap-client.leap-client]
+
+file_filter = data/translations/<lang>.ts
+source_file = data/ts/en_US.ts
+source_lang = en
+type = QT
+#minimum_perc = 90 # minimum percentage completed before pulling
diff --git a/Makefile b/Makefile
index 59343dfc..5bdf9c36 100644
--- a/Makefile
+++ b/Makefile
@@ -4,23 +4,33 @@
# TODO move to setup scripts
# and implement it in python
# http://die-offenbachs.homelinux.org:48888/hg/eric5/file/5072605ad4dd/compileUiFiles.py
-###### EDIT ######################
+###### EDIT ######################
+
#Directory with ui and resource files
RESOURCE_DIR = data/resources
#Directory for compiled resources
COMPILED_DIR = src/leap/gui
+
+#Directory for (finished) translations
+TRANSLAT_DIR = data/translations
+
+#Project file, used for translations
+PROJFILE = data/leap_client.pro
#UI files to compile
# UI_FILES = foo.ui
UI_FILES =
#Qt resource files to compile
#images.qrc
-RESOURCES = mainwindow.qrc
+RESOURCES = mainwindow.qrc locale.qrc
#pyuic4 and pyrcc4 binaries
PYUIC = pyuic4
PYRCC = pyrcc4
+PYLUP = pylupdate4
+LRELE = lrelease
+
#################################
# DO NOT EDIT FOLLOWING
@@ -37,6 +47,10 @@ all : resources ui
resources : $(COMPILED_RESOURCES)
ui : $(COMPILED_UI)
+
+translations:
+ $(PYLUP) $(PROJFILE)
+ $(LRELE) $(TRANSLAT_DIR)/*.ts
$(COMPILED_DIR)/ui_%.py : $(RESOURCE_DIR)/%.ui
$(PYUIC) $< -o $@
diff --git a/data/leap_client.pro b/data/leap_client.pro
new file mode 100644
index 00000000..4c559029
--- /dev/null
+++ b/data/leap_client.pro
@@ -0,0 +1,20 @@
+# qmake file
+
+# is not there a f*** way of expanding this? other to template with python I mean...
+
+SOURCES += ../src/leap/gui/firstrun/intro.py
+SOURCES += ../src/leap/gui/firstrun/last.py
+SOURCES += ../src/leap/gui/firstrun/login.py
+SOURCES += ../src/leap/gui/firstrun/providerinfo.py
+SOURCES += ../src/leap/gui/firstrun/providerselect.py
+SOURCES += ../src/leap/gui/firstrun/providersetup.py
+SOURCES += ../src/leap/gui/firstrun/register.py
+SOURCES += ../src/leap/gui/firstrun/regvalidation.py
+SOURCES += ../src/leap/gui/firstrun/wizard.py
+
+# where to generate ts files -- tx will pick from here
+
+# original file, english
+
+TRANSLATIONS += ts/en_US.ts
+
diff --git a/data/mkpyqt.py b/data/mkpyqt.py
new file mode 100755
index 00000000..1ce2cd28
--- /dev/null
+++ b/data/mkpyqt.py
@@ -0,0 +1,271 @@
+#!/usr/bin/env python
+# Copyright (c) 2007-10 Qtrac Ltd. All rights reserved.
+# This program or module 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 2 of the License, or
+# version 3 of the License, or (at your option) any later version. It is
+# provided for educational purposes and 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.
+
+import os
+import platform
+import stat
+import subprocess
+import sys
+import PyQt4.QtCore
+
+__version__ = "1.0.4"
+
+Windows = sys.platform.lower().startswith(("win", "microsoft"))
+if Windows:
+ PATH = os.path.join(os.path.dirname(sys.executable),
+ "Lib/site-packages/PyQt4")
+ if os.access(os.path.join(PATH, "bin"), os.R_OK):
+ PATH = os.path.join(PATH, "bin")
+else:
+ app = PyQt4.QtCore.QCoreApplication([])
+ PATH = unicode(app.applicationDirPath())
+ del app
+if sys.platform.startswith("darwin"):
+ i = PATH.find("Resources")
+ if i > -1:
+ PATH = PATH[:i] + "bin"
+PYUIC4 = os.path.join(PATH, "pyuic4") # e.g. PYUIC4 = "/usr/bin/pyuic4"
+if sys.platform.startswith("darwin"):
+ PYUIC4 = os.path.dirname(sys.executable)
+ i = PYUIC4.find("Resources")
+ if i > -1:
+ PYUIC4 = PYUIC4[:i] + "Lib/python2.5/site-packages/PyQt4/uic/pyuic.py"
+PYRCC4 = os.path.join(PATH, "pyrcc4")
+PYLUPDATE4 = os.path.join(PATH, "pylupdate4")
+LRELEASE = "lrelease"
+if Windows:
+ PYUIC4 = PYUIC4.replace("/", "\\") + ".bat"
+ PYRCC4 = PYRCC4.replace("/", "\\") + ".exe"
+ PYLUPDATE4 = PYLUPDATE4.replace("/", "\\") + ".exe"
+
+msg = []
+shell = lambda command: subprocess.Popen(['which', command],
+ stdout=subprocess.PIPE).communicate()
+
+if not os.access(PYUIC4, os.F_OK):
+ PYUIC4 = shell('pyuic4')[0].strip('\n')
+ if not os.access(PYUIC4, os.F_OK):
+ msg.append("failed to find pyuic4; tried %s" % PYUIC4)
+
+if not os.access(PYRCC4, os.F_OK):
+ PYRCC4 = shell('pyrcc4')[0].strip('\n')
+ if not os.access(PYRCC4, os.F_OK):
+ msg.append("failed to find pyrcc4; tried %s" % PYRCC4)
+
+if not os.access(PYLUPDATE4, os.F_OK):
+ PYLUPDATE4 = shell('pylupdate4')[0].strip('\n')
+ if not os.access(PYLUPDATE4, os.F_OK):
+ msg.append("failed to find pylupdate4; tried %s" % PYLUPDATE4)
+
+if msg:
+ print "\n".join(msg)
+ print "try manually editing this program to put the correct " + \
+ "paths in place"
+ sys.exit()
+
+Debug = False
+Verbose = False
+
+def usage():
+ print """usage: mkpyqt.py [options] [path]
+
+Options (which can be given in any of the forms shown):
+-b --build build [default]
+-c --clean clean
+-f --force force
+-t --translate translate
+-r --recurse recurse
+-v --verbose verbose
+-D --debug debug
+path defaults to .
+
+If executed with no arguments (or with a build argument) it does a
+build, i.e., it looks for all *.ui and *.qrc files and makes sure that
+the corresponding ui_*.py and qrc_*.py files exist and are up-to-date.
+
+If executed with clean, deletes all ui_*.py and qrc_*.py files that have
+corresponding *.ui and *.qrc files, and all *.pyc and *.pyo files.
+
+If executed with force, it does a clean followed by a build.
+
+If building and the translate option is given, after building, it runs
+pylupdate4 on all .py and .pyw files it encounters, and then runs lrelease
+on all .ts files it encounters. It does not use a .pro file so the .ts
+files must be created in the first place, e.g., using pylupdate4 on one
+of the source files and using its -ts option.
+
+WARNING: Do not give any hand-coded files names that match ui_*.py or
+qrc_*.py since these will be deleted by mkpyqt.py clean!
+
+NOTE: If any tool fails to run, e.g., pyuic4, then edit this program and
+hard-code the path; the variables with the tool paths are near the top
+of the file.
+
+mkpyqt.py v %s. Copyright (c) 2007-9 Qtrac Ltd. All rights reserved.
+""" % __version__
+ sys.exit()
+
+
+def report_failure(command, args, process):
+ msg = ""
+ ba = process.readAllStandardError()
+ if not ba.isEmpty():
+ msg = ": " + str(QString(ba))
+ print "failed", command, " ".join(args), msg
+
+
+def build(path):
+ for name in os.listdir(path):
+ source = os.path.join(path, name)
+ target = None
+ if source.endswith(".ui"):
+ target = os.path.join(path,
+ "ui_" + name.replace(".ui", ".py"))
+ command = PYUIC4
+ elif source.endswith(".qrc"):
+ target = os.path.join(path,
+ "qrc_" + name.replace(".qrc", ".py"))
+ command = PYRCC4
+ process = PyQt4.QtCore.QProcess()
+ if target is not None:
+ if not os.access(target, os.F_OK) or (
+ os.stat(source)[stat.ST_MTIME] > \
+ os.stat(target)[stat.ST_MTIME]):
+ args = ["-o", target, source]
+ if sys.platform.startswith("darwin") and command == PYUIC4:
+ command = sys.executable
+ args = [PYUIC4] + args
+ if Debug:
+ print "# %s %s" % (command, " ".join(args))
+ else:
+ process.start(command, args)
+ if not process.waitForFinished(2 * 60 * 1000):
+ report_failure(command, args, process)
+ else:
+ print source, "->", target
+ elif Verbose:
+ print source, "is up-to-date"
+
+
+def clean(path):
+ deletelist = []
+ for name in os.listdir(path):
+ target = os.path.join(path, name)
+ source = None
+ if target.endswith(".py") or target.endswith(".pyc") or \
+ target.endswith(".pyo"):
+ if name.startswith("ui_") and not name[-1] in "oc":
+ source = os.path.join(path, name[3:-3] + ".ui")
+ elif name.startswith("qrc_"):
+ if target[-1] in "oc":
+ source = os.path.join(path, name[4:-4] + ".qrc")
+ else:
+ source = os.path.join(path, name[4:-3] + ".qrc")
+ elif target[-1] in "oc":
+ source = target[:-1]
+ if source is not None:
+ if os.access(source, os.F_OK):
+ if Debug:
+ print "# delete ", target
+ else:
+ deletelist.append(target)
+ else:
+ print "will not remove '%s' since `%s' not found" % (
+ target, source)
+ if not Debug:
+ for target in deletelist:
+ if Verbose:
+ print "deleted", target
+ os.remove(target)
+
+
+def translate(path):
+ files = []
+ tsfiles = []
+ for name in os.listdir(path):
+ if name.endswith((".py", ".pyw")):
+ files.append(os.path.join(path, name))
+ elif name.endswith(".ts"):
+ tsfiles.append(os.path.join(path, name))
+ if not tsfiles:
+ return
+ verbose = "-verbose" if Verbose else ""
+ silent = "-silent" if not Verbose else ""
+ process = PyQt4.QtCore.QProcess()
+ for ts in tsfiles:
+ qm = ts[:-3] + ".qm"
+ command1 = PYLUPDATE4
+ args1 = [verbose] + files + ["-ts", ts]
+ command2 = LRELEASE
+ args2 = [silent, ts, "-qm", qm]
+ if Debug:
+ print "updated", ts
+ print "generated", qm
+ else:
+ process.start(command1, args1)
+ if not process.waitForFinished(2 * 60 * 1000):
+ report_failure(command1, args1, process)
+ process.start(command2, args2)
+ if not process.waitForFinished(2 * 60 * 1000):
+ report_failure(command2, args2, process)
+
+
+def apply(recurse, function, path):
+ if not recurse:
+ function(path)
+ else:
+ for root, dirs, files in os.walk(path):
+ for dir in dirs:
+ function(os.path.join(root, dir))
+
+
+def main():
+ global Debug, Verbose
+ function = build
+ recurse = False
+ trans = False
+ force = False
+ path = "."
+ args = sys.argv[1:]
+ while args:
+ arg = args.pop(0)
+ if arg in ("-D", "--debug", "debug"):
+ Debug = True
+ elif arg in ("-b", "--build", "build"):
+ pass # This is the default
+ elif arg in ("-c", "--clean", "clean"):
+ function = clean
+ elif arg in ("-f", "--force", "force"):
+ force = True
+ elif arg in ("-t", "--translate", "translate"):
+ trans = True
+ elif arg in ("-r", "--recurse", "recurse"):
+ recurse = True
+ elif arg in ("-v", "--verbose", "verbose"):
+ Verbose = True
+ elif arg in ("-h", "--help", "help"):
+ usage()
+ else:
+ path = arg
+ if not force:
+ apply(recurse, function, path)
+ else:
+ apply(recurse, clean, path)
+ apply(recurse, build, path)
+ if trans and (function == build or force):
+ apply(recurse, translate, path)
+
+main()
+
+# 1.0.1 Fixed bug reported by Brian Downing where paths that contained
+# spaces were not handled correctly.
+# 1.0.2 Changed default path on Windows to match PyQt 4.4
+# 1.0.3 Tried to make the paths work on Mac OS X
diff --git a/data/resources/locale.qrc b/data/resources/locale.qrc
new file mode 100644
index 00000000..53576b49
--- /dev/null
+++ b/data/resources/locale.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+<file>../translations/leap_client_es.qm</file>
+</qresource>
+</RCC>
diff --git a/data/translations/README.rst b/data/translations/README.rst
new file mode 100644
index 00000000..1f3dd0b3
--- /dev/null
+++ b/data/translations/README.rst
@@ -0,0 +1,8 @@
+data/translations
+=================
+
+We expect finished translations (i.e., those downloaded from ``transifex``) to live here.
+
+Translator object will pick them from here.
+
+(Actually, from the embedded locale_rc)
diff --git a/data/translations/es.qm b/data/translations/es.qm
new file mode 100644
index 00000000..8daa2037
--- /dev/null
+++ b/data/translations/es.qm
Binary files differ
diff --git a/data/translations/es.ts b/data/translations/es.ts
new file mode 100644
index 00000000..84aa6f0a
--- /dev/null
+++ b/data/translations/es.ts
@@ -0,0 +1,218 @@
+<?xml version="1.0" ?><!DOCTYPE TS><TS language="es" version="2.0">
+<context>
+ <name>IntroPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="14"/>
+ <source>First run wizard.</source>
+ <translation>Primera Conexion.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="24"/>
+ <source>Now we will guide you through some configuration that is needed before you can connect for the first time.&lt;br&gt;&lt;br&gt;If you ever need to modify these options again, you can find the wizard in the &apos;&lt;i&gt;Settings&lt;/i&gt;&apos; menu from the main window.&lt;br&gt;&lt;br&gt;Do you want to &lt;b&gt;sign up&lt;/b&gt; for a new account, or &lt;b&gt;log in&lt;/b&gt; with an already existing username?&lt;br&gt;</source>
+ <translation>Vamos a configurar algunas cosas antes de que te puedas conectar por primera vez.&lt;br&gt;&lt;br&gt;Si necesitas modificar estas opciones de nuevo, puedes encontrar este asistente en el menu de &apos;&lt;i&gt;Opciones&lt;/i&gt;&apos; en la ventana principal.&lt;br&gt;&lt;br&gt;Quieres &lt;b&gt;registrar&lt;/b&gt; una nueva cuenta, o &lt;b&gt;loguearte&lt;/b&gt; con tu usuario?&lt;br&gt; </translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="37"/>
+ <source>Sign up for a new account.</source>
+ <translation>Registrar una cuenta nueva.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="40"/>
+ <source>Log In with my credentials.</source>
+ <translation>Loguearme con un usuario que ya tengo.</translation>
+ </message>
+</context>
+<context>
+ <name>LogInPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="96"/>
+ <source>Username must be in the username@provider form.</source>
+ <translation>El usuario tiene que ser usuario@tu.proveedor</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="140"/>
+ <source>Resolving domain name</source>
+ <translation>Resolviendo nombre de dominio</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="163"/>
+ <source>Authentication error: %s</source>
+ <translation>Error de autenticacion: %s</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="179"/>
+ <source>Credentials validated.</source>
+ <translation>Credenciales validadas.</translation>
+ </message>
+</context>
+<context>
+ <name>ProviderInfoPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerinfo.py" line="18"/>
+ <source>Provider Info</source>
+ <translation>Info del Proveedor</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerinfo.py" line="19"/>
+ <source>This is what provider says.</source>
+ <translation>Esto es lo que dice el proveedor.</translation>
+ </message>
+</context>
+<context>
+ <name>ProviderSetupValidationPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="26"/>
+ <source>Provider setup</source>
+ <translation>Configuracion del Proveedor</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="27"/>
+ <source>Doing autoconfig.</source>
+ <translation>Autoconfigurando.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="83"/>
+ <source>Fetching CA certificate</source>
+ <translation>Obteniendo certificado de la CA</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="105"/>
+ <source>Checking CA fingerprint</source>
+ <translation>Comprobando el fingerprint de la CA</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="134"/>
+ <source>Validating api certificate</source>
+ <translation>Validando certificado de la api</translation>
+ </message>
+</context>
+<context>
+ <name>RegisterUserPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="31"/>
+ <source>Sign Up</source>
+ <translation>Nueva Cuenta</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="208"/>
+ <source>Registration succeeded!</source>
+ <translation>Cuenta creada con exito!</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="238"/>
+ <source>Password does not match..</source>
+ <translation>Las contrasenas no son iguales..</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="242"/>
+ <source>Password too short.</source>
+ <translation>Contrasena demasiado corta.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="247"/>
+ <source>Password too obvious.</source>
+ <translation>Contrasena demasiado obvia.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="279"/>
+ <source>Error connecting to provider (timeout)</source>
+ <translation>Error conectandose al proveedor (timeout)</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="284"/>
+ <source>Error Connecting to provider (connerr).</source>
+ <translation>Error conectandose al proveedor (connerr).</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="292"/>
+ <source>Error during registration (%s)</source>
+ <translation>Error durante el registro (%s)</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="302"/>
+ <source>Could not register (bad response)</source>
+ <translation>No se pudo registrar (bad response)</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="309"/>
+ <source>Username not available.</source>
+ <translation>Usuario no disponible.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="375"/>
+ <source>Register a new user with provider %s.</source>
+ <translation>Registrar un nuevo usuario con el proveedor %s.</translation>
+ </message>
+</context>
+<context>
+ <name>RegisterUserValidationPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/regvalidation.py" line="95"/>
+ <source>Fetching provider config...</source>
+ <translation>Obteniendo configuracion del proveedor...</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/regvalidation.py" line="112"/>
+ <source>Authentication error: %s</source>
+ <translation>Error de autenticacion: %s</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/regvalidation.py" line="117"/>
+ <source>Fetching eip certificate</source>
+ <translation>Obteniendo certificado eip</translation>
+ </message>
+</context>
+<context>
+ <name>SelectProviderPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="32"/>
+ <source>Enter Provider</source>
+ <translation>Entra tu Proveedor</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="33"/>
+ <source>Please enter the domain of the provider you want to use for your connection.</source>
+ <translation>Por favor, rellena el dominio del proveedor que quieras usar para tu conexion.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="87"/>
+ <source>chec&amp;k!</source>
+ <translation>compro&amp;bar!</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="97"/>
+ <source>Server certificate could not be verified.</source>
+ <translation>No se pudo verificar el certificado del servidor.</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="136"/>
+ <source>Certificate validation</source>
+ <translation>Validacion del certificado</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="222"/>
+ <source>checking domain name</source>
+ <translation>comprobando nombre de dominio</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="276"/>
+ <source>checking https connection</source>
+ <translation>comprobando conexion https</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="292"/>
+ <source>Could not get info from provider.</source>
+ <translation>no se pudo obtener info del proveedor</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="295"/>
+ <source>Could not download provider info (refused conn.).</source>
+ <translation>no se pudo obtener info del proveedor (refused conn.).</translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="305"/>
+ <source>fetching provider info</source>
+ <translation>obteniendo info del preveedor</translation>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/data/ts/README.rst b/data/ts/README.rst
new file mode 100644
index 00000000..3db2d104
--- /dev/null
+++ b/data/ts/README.rst
@@ -0,0 +1,14 @@
+data/ts
+=======
+
+Here we expect the .ts files generated by typing::
+
+ $ make translations
+
+Which will generate the sources (en_US)
+
+For uploading a source::
+
+ $ tx push -s
+
+Translator should pick finished ``.qm`` files from ``data/translations`` instead of this folder.
diff --git a/data/ts/en_US.ts b/data/ts/en_US.ts
new file mode 100644
index 00000000..f6aadc5c
--- /dev/null
+++ b/data/ts/en_US.ts
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS><TS version="2.0">
+<context>
+ <name>IntroPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="14"/>
+ <source>First run wizard.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="24"/>
+ <source>Now we will guide you through some configuration that is needed before you can connect for the first time.&lt;br&gt;&lt;br&gt;If you ever need to modify these options again, you can find the wizard in the &apos;&lt;i&gt;Settings&lt;/i&gt;&apos; menu from the main window.&lt;br&gt;&lt;br&gt;Do you want to &lt;b&gt;sign up&lt;/b&gt; for a new account, or &lt;b&gt;log in&lt;/b&gt; with an already existing username?&lt;br&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="37"/>
+ <source>Sign up for a new account.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/intro.py" line="40"/>
+ <source>Log In with my credentials.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>LogInPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="96"/>
+ <source>Username must be in the username@provider form.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="140"/>
+ <source>Resolving domain name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="163"/>
+ <source>Authentication error: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/login.py" line="179"/>
+ <source>Credentials validated.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ProviderInfoPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerinfo.py" line="18"/>
+ <source>Provider Info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerinfo.py" line="19"/>
+ <source>This is what provider says.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ProviderSetupValidationPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="26"/>
+ <source>Provider setup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="27"/>
+ <source>Doing autoconfig.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="83"/>
+ <source>Fetching CA certificate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="105"/>
+ <source>Checking CA fingerprint</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providersetup.py" line="134"/>
+ <source>Validating api certificate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>RegisterUserPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="31"/>
+ <source>Sign Up</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="208"/>
+ <source>Registration succeeded!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="238"/>
+ <source>Password does not match..</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="242"/>
+ <source>Password too short.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="247"/>
+ <source>Password too obvious.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="279"/>
+ <source>Error connecting to provider (timeout)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="284"/>
+ <source>Error Connecting to provider (connerr).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="292"/>
+ <source>Error during registration (%s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="302"/>
+ <source>Could not register (bad response)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="309"/>
+ <source>Username not available.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/register.py" line="375"/>
+ <source>Register a new user with provider %s.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>RegisterUserValidationPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/regvalidation.py" line="95"/>
+ <source>Fetching provider config...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/regvalidation.py" line="112"/>
+ <source>Authentication error: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/regvalidation.py" line="117"/>
+ <source>Fetching eip certificate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SelectProviderPage</name>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="32"/>
+ <source>Enter Provider</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="33"/>
+ <source>Please enter the domain of the provider you want to use for your connection.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="87"/>
+ <source>chec&amp;k!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="97"/>
+ <source>Server certificate could not be verified.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="136"/>
+ <source>Certificate validation</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="222"/>
+ <source>checking domain name</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="276"/>
+ <source>checking https connection</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="292"/>
+ <source>Could not get info from provider.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="295"/>
+ <source>Could not download provider info (refused conn.).</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/leap/gui/firstrun/providerselect.py" line="305"/>
+ <source>fetching provider info</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/docs/dev/internationalization.rst b/docs/dev/internationalization.rst
index 6cbc6f72..e6b89dea 100644
--- a/docs/dev/internationalization.rst
+++ b/docs/dev/internationalization.rst
@@ -6,24 +6,22 @@ Internationalization
This part of the documentation covers the localization and translation of LEAP Client.
Because we want to *bring fire to the people*, in as many countries and languages as possible.
-.. note::
- We should probably move the translators info to a top level section of the docs, and leave this
- as internal/tech-savvy notes.
-
Translating the LEAP Client PyQt Application
--------------------------------------------
.. raw:: html
- <div> <a target="_blank" style="text-decoration:none; color:black; font-size:66%" href="https://www.transifex.com/projects/p/leap-client/resource/leap_client_es/" title="See more information on Transifex.com">Top translations: leap-client » leap_client_es</a><br/> <img border="0" src="https://www.transifex.com/projects/p/leap-client/resource/leap_client_es/chart/image_png"/><br/><a target="_blank" href="https://www.transifex.com/"><img border="0" src="https://ds0k0en9abmn1.cloudfront.net/static/charts/images/tx-logo-micro.646b0065fce6.png"/></a></div>
+ <div><a target="_blank" style="text-decoration:none; color:black; font-size:66%" href="https://www.transifex.com/projects/p/leap-client/resource/leap-client/" title="See more information on Transifex.com">Top translations: leap-client » leap-client</a><br/><img border="0" src="https://www.transifex.com/projects/p/leap-client/resource/leap-client/chart/image_png"/><br/><a target="_blank" href="https://www.transifex.com/"><img border="0" src="https://ds0k0en9abmn1.cloudfront.net/static/charts/images/tx-logo-micro.646b0065fce6.png"/></a></div>
For translators
^^^^^^^^^^^^^^^
.. note::
- ... unfinished
+ We should probably move the translators info to a top level section of the docs, and leave this
+ as internal notes.
-We are using `transifex <http://transifex.com/projects/p/leap-client>`_ site to coordinate translation efforts. If you want to contribute, just sign up there and ...
+
+We are using `transifex <http://transifex.com/projects/p/leap-client>`_ to coordinate translation efforts. If you want to contribute, just sign up there and ...
.. note::
... and what??
@@ -32,8 +30,9 @@ For devs: i18n conventions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. note::
- should link to PyQt docs on i18n
- also our special cases (labels and exceptions)
+ should say something about our special cases (provider labels and exceptions) when we get decision about it.
+
+Refer to `pyqt documentation <http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/i18n.html>`_.
tl;dr;::
@@ -41,17 +40,64 @@ tl;dr;::
for any string that you want to be translated.
+.. Note about this: there seems to be some problems with the .tr method
+ on QObjects. Investigate this.
+ I still believe we can use a generic _ method which is smart enough to
+ fallback to QObject.tr methods or lookup our own tr implementation (for our
+ multilungual objects, like in exceptions or provider labels that came from json objects).
+ --kali
+
For i18n maintainers
^^^^^^^^^^^^^^^^^^^^
-.. note::
+You need ``pylupdate4`` for these steps. To get it, in debian::
- how do we use the transifex client; automation.
+ $ apt-get install python-qt4-utils
If you do not already have it, install the ``transifex-client`` from the cheese shop::
pip install transifex-client
+You can learn more about the transifex-client `here <http://help.transifex.com/features/client/index.html>`_.
+
+**1.** Add any new source files to the project file, ``data/leap_client.pro``. *We should automate this with some templating, it's tedious.*
+
+**2.** Update the source .ts file ``data/ts/en_US.ts``.::
+
+ $ make translations
+
+**3.** Push source .ts file to transifex::
+
+ $ tx push -s
+
+**4.** Let the translation fairies do their work...
+
+**5.** *Et voila!* Get updated .ts files for each language from ``Transifex``. For instance, to pull updated spanish translations::
+
+ $ tx pull -l es
+ Pulling new translations for resource leap-client.leap-client (source: data/ts/en_US.ts)
+ -> es: data/translations/es.ts
+ Done.
+
+
+Note that there is a configuration option in ``.tx/config`` for setting the minimum completion percentage needed to be able to actually pull a resource.
+
+**6.** Generate .qm files from the updated .ts files::
+
+ $ make translations
+
+and yes, it's the same command than in step 2. One less thing to remember :)
+
+**7.** Check that the .qm for the language you're working with is listed in ``data/resources/locale.qrc`` file. That should take the translated files from ``data/translations``
+
+**8.** Re-generate ``src/leap/gui/locale_qrc``. This is the embedded resource file that we load in the main app entry point; and from where we load the data for the qt translator object::
+
+ $ make resources
+
+If you want to try it, just set your LANG environment variable::
+
+ $ LANG=es_ES leap-client
+
Translating the Documentation
------------------------------
diff --git a/docs/testers/howto.rst b/docs/testers/howto.rst
index 8de4a1eb..e5bf1fa8 100644
--- a/docs/testers/howto.rst
+++ b/docs/testers/howto.rst
@@ -141,6 +141,16 @@ Testing the packages
^^^^^^^^^^^^^^^^^^^^
When we have a release candidate for the supported platforms (Debian stable, Ubuntu 12.04 by now), we will announce also the URI where you can download the rc for testing in your system. Stay tuned!
+Testing the status of translations
+----------------------------------
+
+We need translators! You can go to `transifex <https://www.transifex.com/projects/p/leap-client/>`_, get an account and start contributing.
+
+If you want to check the current status of the client localization in a language other than the one set in your machine, you can do it with a simple trick (under linux). For instance, do::
+
+ $ lang=es_ES leap-client
+
+for running LEAP Client with the spanish locales.
Reporting bugs
--------------
diff --git a/docs/user/install.rst b/docs/user/install.rst
index 22f88b12..1f0fd831 100644
--- a/docs/user/install.rst
+++ b/docs/user/install.rst
@@ -32,7 +32,7 @@ Get the code
.. warning::
- This... won't work either, as-is. This should be the third optional way to install stable releases from master branch. Right now that does not work because there is *nothing* updated in the master branch. Leaving this here since this is what we will be doing, but if you really intend to have a working tree, refer to the sections :ref:`setting up a working environment <environment>` or :ref:`fetching latest code <fetchinglatest>`.
+ This... won't work either, as-is. This should be the third optional way to install stable releases from master branch. Right now that does not work because there is *nothing* updated in the master branch. Leaving this here since this is what we will be doing, but if you really intend to have a working tree, refer to the sections :ref:`setting up a working environment <environment>` or :ref:`fetching latest code for testing <fetchinglatest>`.
You can get the code from LEAP public git repository ::
diff --git a/docs/user/intro.rst b/docs/user/intro.rst
index fe983b63..abb6d487 100644
--- a/docs/user/intro.rst
+++ b/docs/user/intro.rst
@@ -74,7 +74,7 @@ All contributions should have these three points in mind.
.. _`gpl3`:
GPLv3 License
-------------
+--------------
.. image:: gpl.*
diff --git a/src/leap/app.py b/src/leap/app.py
index d594c7cd..334b58c8 100644
--- a/src/leap/app.py
+++ b/src/leap/app.py
@@ -8,10 +8,11 @@ import sip
sip.setapi('QVariant', 2)
sip.setapi('QString', 2)
from PyQt4.QtGui import (QApplication, QSystemTrayIcon, QMessageBox)
-from PyQt4.QtCore import QTimer
+from PyQt4 import QtCore
from leap import __version__ as VERSION
from leap.baseapp.mainwindow import LeapWindow
+from leap.gui import locale_rc
def sigint_handler(*args, **kwargs):
@@ -62,6 +63,17 @@ def main():
logger.info('Starting app')
app = QApplication(sys.argv)
+ # To test:
+ # $ LANG=es ./app.py
+ locale = QtCore.QLocale.system().name()
+ print locale
+ qtTranslator = QtCore.QTranslator()
+ if qtTranslator.load("qt_%s" % locale, ":/translations"):
+ app.installTranslator(qtTranslator)
+ appTranslator = QtCore.QTranslator()
+ if appTranslator.load("leap_client_%s" % locale, ":/translations"):
+ app.installTranslator(appTranslator)
+
# needed for initializing qsettings
# it will write .config/leap/leap.conf
# top level app settings
@@ -83,7 +95,7 @@ def main():
# this dummy timer ensures that
# control is given to the outside loop, so we
# can hook our sigint handler.
- timer = QTimer()
+ timer = QtCore.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
diff --git a/src/leap/gui/firstrun/intro.py b/src/leap/gui/firstrun/intro.py
index 4bb008c7..0a7484e2 100644
--- a/src/leap/gui/firstrun/intro.py
+++ b/src/leap/gui/firstrun/intro.py
@@ -11,7 +11,7 @@ class IntroPage(QtGui.QWizardPage):
def __init__(self, parent=None):
super(IntroPage, self).__init__(parent)
- self.setTitle("First run wizard.")
+ self.setTitle(self.tr("First run wizard."))
#self.setPixmap(
#QtGui.QWizard.WatermarkPixmap,
@@ -21,7 +21,7 @@ class IntroPage(QtGui.QWizardPage):
QtGui.QWizard.LogoPixmap,
QtGui.QPixmap(APP_LOGO))
- label = QtGui.QLabel(
+ label = QtGui.QLabel(self.tr(
"Now we will guide you through "
"some configuration that is needed before you "
"can connect for the first time.<br><br>"
@@ -29,16 +29,16 @@ class IntroPage(QtGui.QWizardPage):
"you can find the wizard in the '<i>Settings</i>' menu from the "
"main window.<br><br>"
"Do you want to <b>sign up</b> for a new account, or <b>log "
- "in</b> with an already existing username?<br>")
+ "in</b> with an already existing username?<br>"))
label.setWordWrap(True)
radiobuttonGroup = QtGui.QGroupBox()
self.sign_up = QtGui.QRadioButton(
- "Sign up for a new account.")
+ self.tr("Sign up for a new account."))
self.sign_up.setChecked(True)
self.log_in = QtGui.QRadioButton(
- "Log In with my credentials.")
+ self.tr("Log In with my credentials."))
radiobLayout = QtGui.QVBoxLayout()
radiobLayout.addWidget(self.sign_up)
diff --git a/src/leap/gui/locale_rc.py b/src/leap/gui/locale_rc.py
new file mode 100644
index 00000000..f165ff8e
--- /dev/null
+++ b/src/leap/gui/locale_rc.py
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created: vie nov 16 22:33:33 2012
+# by: The Resource Compiler for PyQt (Qt v4.8.2)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore
+
+qt_resource_data = "\
+\x00\x00\x05\xaa\
+\x3c\
+\xb8\x64\x18\xca\xef\x9c\x95\xcd\x21\x1c\xbf\x60\xa1\xbd\xdd\x42\
+\x00\x00\x00\x20\x09\xfc\x2c\x8e\x00\x00\x04\xfb\x0a\x74\xb8\x1e\
+\x00\x00\x00\xd6\x0a\xfd\x99\xfe\x00\x00\x00\x51\x0c\x44\x41\xbe\
+\x00\x00\x00\x00\x69\x00\x00\x05\x69\x03\x00\x00\x00\x22\x00\x50\
+\x00\x72\x00\x69\x00\x6d\x00\x65\x00\x72\x00\x61\x00\x20\x00\x63\
+\x00\x6f\x00\x6e\x00\x65\x00\x78\x00\x69\x00\x6f\x00\x6e\x00\x2e\
+\x08\x00\x00\x00\x00\x06\x00\x00\x00\x11\x46\x69\x72\x73\x74\x20\
+\x72\x75\x6e\x20\x77\x69\x7a\x61\x72\x64\x2e\x07\x00\x00\x00\x09\
+\x49\x6e\x74\x72\x6f\x50\x61\x67\x65\x01\x03\x00\x00\x00\x4c\x00\
+\x4c\x00\x6f\x00\x67\x00\x75\x00\x65\x00\x61\x00\x72\x00\x6d\x00\
+\x65\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x20\x00\x6d\x00\x69\x00\
+\x20\x00\x75\x00\x73\x00\x75\x00\x61\x00\x72\x00\x69\x00\x6f\x00\
+\x20\x00\x79\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x74\x00\x72\x00\
+\x61\x00\x73\x00\x65\x00\x6e\x00\x61\x00\x2e\x08\x00\x00\x00\x00\
+\x06\x00\x00\x00\x1b\x4c\x6f\x67\x20\x49\x6e\x20\x77\x69\x74\x68\
+\x20\x6d\x79\x20\x63\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x73\x2e\
+\x07\x00\x00\x00\x09\x49\x6e\x74\x72\x6f\x50\x61\x67\x65\x01\x03\
+\x00\x00\x02\xaa\x00\x56\x00\x61\x00\x6d\x00\x6f\x00\x73\x00\x20\
+\x00\x61\x00\x20\x00\x72\x00\x65\x00\x75\x00\x6e\x00\x69\x00\x72\
+\x00\x20\x00\x6c\x00\x61\x00\x20\x00\x69\x00\x6e\x00\x66\x00\x6f\
+\x00\x72\x00\x6d\x00\x61\x00\x63\x00\x69\x00\x6f\x00\x6e\x00\x20\
+\x00\x71\x00\x75\x00\x65\x00\x20\x00\x6e\x00\x65\x00\x63\x00\x65\
+\x00\x73\x00\x69\x00\x74\x00\x61\x00\x73\x00\x20\x00\x61\x00\x6e\
+\x00\x74\x00\x65\x00\x73\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6c\
+\x00\x61\x00\x20\x00\x70\x00\x72\x00\x69\x00\x6d\x00\x65\x00\x72\
+\x00\x61\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x65\x00\x78\x00\x69\
+\x00\x6f\x00\x6e\x00\x2e\x00\x3c\x00\x62\x00\x72\x00\x3e\x00\x3c\
+\x00\x62\x00\x72\x00\x3e\x00\x53\x00\x69\x00\x20\x00\x61\x00\x6c\
+\x00\x67\x00\x75\x00\x6e\x00\x61\x00\x20\x00\x76\x00\x65\x00\x7a\
+\x00\x20\x00\x6e\x00\x65\x00\x63\x00\x65\x00\x73\x00\x69\x00\x74\
+\x00\x61\x00\x73\x00\x20\x00\x6d\x00\x6f\x00\x64\x00\x69\x00\x66\
+\x00\x69\x00\x63\x00\x61\x00\x72\x00\x20\x00\x65\x00\x73\x00\x74\
+\x00\x61\x00\x73\x00\x20\x00\x6f\x00\x70\x00\x63\x00\x69\x00\x6f\
+\x00\x6e\x00\x65\x00\x73\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6e\
+\x00\x75\x00\x65\x00\x76\x00\x6f\x00\x2c\x00\x20\x00\x70\x00\x75\
+\x00\x65\x00\x64\x00\x65\x00\x73\x00\x20\x00\x65\x00\x6e\x00\x63\
+\x00\x6f\x00\x6e\x00\x74\x00\x72\x00\x61\x00\x72\x00\x20\x00\x65\
+\x00\x73\x00\x74\x00\x65\x00\x20\x00\x61\x00\x73\x00\x69\x00\x73\
+\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x20\x00\x65\x00\x6e\
+\x00\x20\x00\x65\x00\x6c\x00\x20\x00\x6d\x00\x65\x00\x6e\x00\x75\
+\x00\x20\x00\x3c\x00\x69\x00\x3e\x00\x4f\x00\x70\x00\x63\x00\x69\
+\x00\x6f\x00\x6e\x00\x65\x00\x73\x00\x3c\x00\x2f\x00\x69\x00\x3e\
+\x00\x20\x00\x65\x00\x6e\x00\x20\x00\x6c\x00\x61\x00\x20\x00\x76\
+\x00\x65\x00\x6e\x00\x74\x00\x61\x00\x6e\x00\x61\x00\x20\x00\x70\
+\x00\x72\x00\x69\x00\x6e\x00\x63\x00\x69\x00\x70\x00\x61\x00\x6c\
+\x00\x2e\x00\x3c\x00\x62\x00\x72\x00\x3e\x00\x3c\x00\x62\x00\x72\
+\x00\x3e\x00\x51\x00\x75\x00\x65\x00\x20\x00\x64\x00\x65\x00\x73\
+\x00\x65\x00\x61\x00\x73\x00\x20\x00\x68\x00\x61\x00\x63\x00\x65\
+\x00\x72\x00\x20\x00\x61\x00\x68\x00\x6f\x00\x72\x00\x61\x00\x3f\
+\x00\x20\x00\x50\x00\x75\x00\x65\x00\x64\x00\x65\x00\x73\x00\x20\
+\x00\x3c\x00\x62\x00\x3e\x00\x72\x00\x65\x00\x67\x00\x69\x00\x73\
+\x00\x74\x00\x72\x00\x61\x00\x72\x00\x3c\x00\x2f\x00\x62\x00\x3e\
+\x00\x20\x00\x75\x00\x6e\x00\x61\x00\x20\x00\x6e\x00\x75\x00\x65\
+\x00\x76\x00\x61\x00\x20\x00\x63\x00\x75\x00\x65\x00\x6e\x00\x74\
+\x00\x61\x00\x20\x00\x6f\x00\x20\x00\x3c\x00\x62\x00\x3e\x00\x6c\
+\x00\x6f\x00\x67\x00\x75\x00\x65\x00\x61\x00\x72\x00\x74\x00\x65\
+\x00\x3c\x00\x2f\x00\x62\x00\x3e\x00\x20\x00\x63\x00\x6f\x00\x6e\
+\x00\x20\x00\x75\x00\x6e\x00\x61\x00\x20\x00\x71\x00\x75\x00\x65\
+\x00\x20\x00\x79\x00\x61\x00\x20\x00\x74\x00\x69\x00\x65\x00\x6e\
+\x00\x65\x00\x73\x00\x3f\x00\x3c\x00\x62\x00\x72\x00\x3e\x08\x00\
+\x00\x00\x00\x06\x00\x00\x01\x5d\x4e\x6f\x77\x20\x77\x65\x20\x77\
+\x69\x6c\x6c\x20\x67\x75\x69\x64\x65\x20\x79\x6f\x75\x20\x74\x68\
+\x72\x6f\x75\x67\x68\x20\x73\x6f\x6d\x65\x20\x63\x6f\x6e\x66\x69\
+\x67\x75\x72\x61\x74\x69\x6f\x6e\x20\x74\x68\x61\x74\x20\x69\x73\
+\x20\x6e\x65\x65\x64\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x79\
+\x6f\x75\x20\x63\x61\x6e\x20\x63\x6f\x6e\x6e\x65\x63\x74\x20\x66\
+\x6f\x72\x20\x74\x68\x65\x20\x66\x69\x72\x73\x74\x20\x74\x69\x6d\
+\x65\x2e\x3c\x62\x72\x3e\x3c\x62\x72\x3e\x49\x66\x20\x79\x6f\x75\
+\x20\x65\x76\x65\x72\x20\x6e\x65\x65\x64\x20\x74\x6f\x20\x6d\x6f\
+\x64\x69\x66\x79\x20\x74\x68\x65\x73\x65\x20\x6f\x70\x74\x69\x6f\
+\x6e\x73\x20\x61\x67\x61\x69\x6e\x2c\x20\x79\x6f\x75\x20\x63\x61\
+\x6e\x20\x66\x69\x6e\x64\x20\x74\x68\x65\x20\x77\x69\x7a\x61\x72\
+\x64\x20\x69\x6e\x20\x74\x68\x65\x20\x27\x3c\x69\x3e\x53\x65\x74\
+\x74\x69\x6e\x67\x73\x3c\x2f\x69\x3e\x27\x20\x6d\x65\x6e\x75\x20\
+\x66\x72\x6f\x6d\x20\x74\x68\x65\x20\x6d\x61\x69\x6e\x20\x77\x69\
+\x6e\x64\x6f\x77\x2e\x3c\x62\x72\x3e\x3c\x62\x72\x3e\x44\x6f\x20\
+\x79\x6f\x75\x20\x77\x61\x6e\x74\x20\x74\x6f\x20\x3c\x62\x3e\x73\
+\x69\x67\x6e\x20\x75\x70\x3c\x2f\x62\x3e\x20\x66\x6f\x72\x20\x61\
+\x20\x6e\x65\x77\x20\x61\x63\x63\x6f\x75\x6e\x74\x2c\x20\x6f\x72\
+\x20\x3c\x62\x3e\x6c\x6f\x67\x20\x69\x6e\x3c\x2f\x62\x3e\x20\x77\
+\x69\x74\x68\x20\x61\x6e\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x65\
+\x78\x69\x73\x74\x69\x6e\x67\x20\x75\x73\x65\x72\x6e\x61\x6d\x65\
+\x3f\x3c\x62\x72\x3e\x07\x00\x00\x00\x09\x49\x6e\x74\x72\x6f\x50\
+\x61\x67\x65\x01\x03\x00\x00\x00\x36\x00\x52\x00\x65\x00\x67\x00\
+\x69\x00\x73\x00\x74\x00\x72\x00\x61\x00\x72\x00\x20\x00\x75\x00\
+\x6e\x00\x61\x00\x20\x00\x63\x00\x75\x00\x65\x00\x6e\x00\x74\x00\
+\x61\x00\x20\x00\x6e\x00\x75\x00\x65\x00\x76\x00\x61\x00\x2e\x08\
+\x00\x00\x00\x00\x06\x00\x00\x00\x1a\x53\x69\x67\x6e\x20\x75\x70\
+\x20\x66\x6f\x72\x20\x61\x20\x6e\x65\x77\x20\x61\x63\x63\x6f\x75\
+\x6e\x74\x2e\x07\x00\x00\x00\x09\x49\x6e\x74\x72\x6f\x50\x61\x67\
+\x65\x01\x88\x00\x00\x00\x02\x01\x01\
+"
+
+qt_resource_name = "\
+\x00\x0c\
+\x0d\xfc\x11\x13\
+\x00\x74\
+\x00\x72\x00\x61\x00\x6e\x00\x73\x00\x6c\x00\x61\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x73\
+\x00\x14\
+\x08\xa9\x0f\x1d\
+\x00\x6c\
+\x00\x65\x00\x61\x00\x70\x00\x5f\x00\x63\x00\x6c\x00\x69\x00\x65\x00\x6e\x00\x74\x00\x5f\x00\x65\x00\x73\x00\x5f\x00\x45\x00\x53\
+\x00\x2e\x00\x71\x00\x6d\
+"
+
+qt_resource_struct = "\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()