From 9ac4d0d3494c5a2550b6cec3d51edee314be8211 Mon Sep 17 00:00:00 2001 From: bemanuel Date: Tue, 16 Jan 2018 12:38:14 -0300 Subject: [PATCH 01/28] Babel Package to translation --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 46ab6bacf..0283ef13b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ Flask>=0.10 +Flask-Babel==0.11.2 Flask-WTF>=0.11 Flask-Login>=0.2.11 configobj==5.0.5 From 340b8fe779f263cba8be01f7c796a337a966e7ec Mon Sep 17 00:00:00 2001 From: Bruno Emanuel Date: Tue, 16 Jan 2018 21:08:20 +0000 Subject: [PATCH 02/28] Ajustes iniciais para traducao --- babel.cfg | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 babel.cfg diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 000000000..f0234b326 --- /dev/null +++ b/babel.cfg @@ -0,0 +1,3 @@ +[python: **.py] +[jinja2: **/templates/**.html] +extensions=jinja2.ext.autoescape,jinja2.ext.with_ From ba4b4f287f3e35f8652f2c217bfff93aa8d954f0 Mon Sep 17 00:00:00 2001 From: Bruno Emanuel Date: Tue, 16 Jan 2018 21:10:09 +0000 Subject: [PATCH 03/28] Ignore translations files .mo --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index d54802417..c3a6d38f3 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ db_repository/* upload/avatar/* tmp/* .ropeproject + +# translate +*.mo From 52143e3f8a0ad08240be20340dca2f50e6368327 Mon Sep 17 00:00:00 2001 From: Bruno Emanuel Date: Tue, 16 Jan 2018 21:11:52 +0000 Subject: [PATCH 04/28] Files for babel and Requirements --- app/translations/en/LC_MESSAGES/messages.mo | Bin 0 -> 717 bytes app/translations/en/LC_MESSAGES/messages.po | 55 ++++++++++++++++++ .../pt_BR/LC_MESSAGES/messages.mo | Bin 0 -> 732 bytes .../pt_BR/LC_MESSAGES/messages.po | 52 +++++++++++++++++ babel.cfg | 4 ++ babel/messages.pot | 48 +++++++++++++++ 6 files changed, 159 insertions(+) create mode 100644 app/translations/en/LC_MESSAGES/messages.mo create mode 100644 app/translations/en/LC_MESSAGES/messages.po create mode 100644 app/translations/pt_BR/LC_MESSAGES/messages.mo create mode 100644 app/translations/pt_BR/LC_MESSAGES/messages.po create mode 100644 babel/messages.pot diff --git a/app/translations/en/LC_MESSAGES/messages.mo b/app/translations/en/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..7c6ca7a0247b37296588eb177a14e03f2b78f5c2 GIT binary patch literal 717 zcmb`Ev2N5r5QYtk0GSFzNih^iiO?SQLD1pkqFnAAyGBIH zD?pcybo5XmD!M!XB@K_jGccR82#A)EKK=WTW;~*5^OMx}pIlw`zazDEr>#FDwf!I3{3lY||Ao{U zD&z)%3*dP!8)2N0ta&L~(M~K2h=h}3jr9x_Bt0ffmQinj-&Q5sIC?qr;? zi{km8%Dr70XF72d$>-?v|V}Dr}b8T3rxX=|hQU$R4 zJdR<1kc6=L*XS)b=AvkLK_gN8HY`J4+YD^R@pe^qq$;-DN!2J`v0bTZ9e`L|Sl#b# z!1CE&6>zT){+gRaNqBh@zvH<>DGUl)>Ucq;48AcB7Zu%p1M(xTG@5>64q5NA&Mtq5 niiIMV^HLN6^k$`TpP@iS7ouAp2e89uSV6b5-g)Hy|KIxy|E|7s literal 0 HcmV?d00001 diff --git a/app/translations/en/LC_MESSAGES/messages.po b/app/translations/en/LC_MESSAGES/messages.po new file mode 100644 index 000000000..4d2c95cc7 --- /dev/null +++ b/app/translations/en/LC_MESSAGES/messages.po @@ -0,0 +1,55 @@ +# English translations for PROJECT. +# Copyright (C) 2018 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2018-01-16 21:05+0000\n" +"PO-Revision-Date: 2018-01-16 19:41+0000\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.5.3\n" + +#: app/templates/dashboard.html:35 +msgid "Domains" +msgstr "" + +#: app/templates/dashboard.html:35 +msgid "Domain" +msgstr "" + +#: app/templates/login.html:6 +msgid "Log In" +msgstr "" + +#: app/templates/login.html:31 +#, python-format +msgid "Sign In %(log_ttle)s" +msgstr "" + +#: app/templates/login.html:92 +msgid "Remember Me" +msgstr "" + +#: app/templates/login.html:98 +msgid "Sign In" +msgstr "" + +#: app/templates/login.html:108 +msgid "Create an account" +msgstr "" + +#~ msgid "*Remember Me" +#~ msgstr "" + +#~ msgid "Sign In %(login_title)" +#~ msgstr "" + diff --git a/app/translations/pt_BR/LC_MESSAGES/messages.mo b/app/translations/pt_BR/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..ccb176bfdf0be14ee63e66217e3976b5469990d7 GIT binary patch literal 732 zcmZvZ&1w`u5XV~)l@S!hqldaE3DWD#N+ir?m+Z$xR%Wux?3$AhdS@$R%S`vu-6Q7c z19%a<#WxVVh(|q%XOCWd1fRj0WJruy@Z;ZAT|HG(_3PH9cZ}>Raff(TJAc^`oo^EF ziOa-C;tKJ(@xPE>Bfb%J{0DKH_({CIz}Ron`u_Dr#;%jTA-zF*L|W&6AoWN;HU3x9 z`u%rOHZ&+4f>0o`OjpXWkuHT)jaU}z9L9>JSYo+A0|~O3%vBw06z;ASI^TD$z;(-} zM!&$!@$r)Hp|Mh{5T@zmNi>|pUX;$plU*;xl{StiHkV62sB+8aI)o_ckK^tBXp}~? znKzxx`Ehgf1wNu4LumWKCiep#Jc4!*`WyFsGD_qrzLa&P|K$0hADraH!a6=TLfJw% zZ9>?28pp8PPa@blSGwoLLgkgnspQJ-57JYg&ry_35VqoYyO1qy@}4&>DkBQMqfKc; zP^)9tcH12|Id<0+^dMOGl5rB9%_V60-cT!tiaI-7Q9XyR+=Ep?3+O=hTo{Y4Te$, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2018-01-16 21:05+0000\n" +"PO-Revision-Date: 2018-01-16 20:01+0000\n" +"Last-Translator: FULL NAME \n" +"Language: pt_BR\n" +"Language-Team: pt_BR \n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.5.3\n" + +#: app/templates/dashboard.html:35 +msgid "Domains" +msgstr "Domínios" + +#: app/templates/dashboard.html:35 +msgid "Domain" +msgstr "Domínio" + +#: app/templates/login.html:6 +msgid "Log In" +msgstr "Acessar" + +#: app/templates/login.html:31 +#, python-format +msgid "Sign In %(log_ttle)s" +msgstr "Acessar %(log_ttle)s" + +#: app/templates/login.html:92 +msgid "Remember Me" +msgstr "Lembrar-me" + +#: app/templates/login.html:98 +msgid "Sign In" +msgstr "Acessar" + +#: app/templates/login.html:108 +msgid "Create an account" +msgstr "Criar conta" + +#~ msgid "Sign In %(login_title)" +#~ msgstr "Acessar %(login_title)" + diff --git a/babel.cfg b/babel.cfg index f0234b326..47b0e699b 100644 --- a/babel.cfg +++ b/babel.cfg @@ -1,3 +1,7 @@ [python: **.py] [jinja2: **/templates/**.html] +encoding = utf-8 extensions=jinja2.ext.autoescape,jinja2.ext.with_ +silent=False +[extractors] +jinja2 = jinja2.ext:babel_extract diff --git a/babel/messages.pot b/babel/messages.pot new file mode 100644 index 000000000..8b4458502 --- /dev/null +++ b/babel/messages.pot @@ -0,0 +1,48 @@ +# Translations template for PROJECT. +# Copyright (C) 2018 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2018-01-16 21:05+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.5.3\n" + +#: app/templates/dashboard.html:35 +msgid "Domains" +msgstr "" + +#: app/templates/dashboard.html:35 +msgid "Domain" +msgstr "" + +#: app/templates/login.html:6 +msgid "Log In" +msgstr "" + +#: app/templates/login.html:31 +#, python-format +msgid "Sign In %(log_ttle)s" +msgstr "" + +#: app/templates/login.html:92 +msgid "Remember Me" +msgstr "" + +#: app/templates/login.html:98 +msgid "Sign In" +msgstr "" + +#: app/templates/login.html:108 +msgid "Create an account" +msgstr "" + From 5d12f40034f914c3de6829c04494eca820807319 Mon Sep 17 00:00:00 2001 From: Bruno Emanuel Date: Tue, 16 Jan 2018 21:12:11 +0000 Subject: [PATCH 05/28] Files for babel and Requirements --- app/__init__.py | 2 ++ app/templates/dashboard.html | 4 ++- app/templates/login.html | 12 ++++---- app/views.py | 10 ++++++- requirements.txt | 54 ++++++++++++++++++++++++++++-------- 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index bcb352566..f5478fe47 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -2,10 +2,12 @@ from flask import Flask, request, session, redirect, url_for from flask_login import LoginManager from flask_sqlalchemy import SQLAlchemy +from flask_babel import Babel, gettext app = Flask(__name__) app.config.from_object('config') app.wsgi_app = ProxyFix(app.wsgi_app) +babel = Babel(app) login_manager = LoginManager() login_manager.init_app(app) diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index dee30fc17..cb8095069 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -32,7 +32,7 @@

Statistics

{{ domain_count }}

-

{% if domain_count > 1 %}Domains{% else %}Domain{% endif %}

+

{% if domain_count > 1 %}{{_('Domains')}}{% else %}{{_('Domain')}}{% endif %}

@@ -71,7 +71,9 @@

{{ history_number }}

+{% autoescape false %}

{{ uptime|display_second_to_time }}

+{% endautoescape %}

Uptime

diff --git a/app/templates/login.html b/app/templates/login.html index 9527f22fa..36a3b78e4 100644 --- a/app/templates/login.html +++ b/app/templates/login.html @@ -3,7 +3,7 @@ - DNS Control Panel - Log In + DNS Control Panel - {{ _('Log In') }} @@ -27,7 +27,9 @@ diff --git a/app/views.py b/app/views.py index 8cc876100..099f58e64 100644 --- a/app/views.py +++ b/app/views.py @@ -17,14 +17,18 @@ from werkzeug.security import gen_salt from .models import User, Domain, Record, Server, History, Anonymous, Setting, DomainSetting -from app import app, login_manager, github +from app import app, login_manager, github, babel from lib import utils +from config import LANGUAGES jinja2.filters.FILTERS['display_record_name'] = utils.display_record_name jinja2.filters.FILTERS['display_master_name'] = utils.display_master_name jinja2.filters.FILTERS['display_second_to_time'] = utils.display_time jinja2.filters.FILTERS['email_to_gravatar_url'] = utils.email_to_gravatar_url +app.jinja_env.filters['display_second_to_time'] = utils.display_time +app.jinja_env.filters['display_master_name'] = utils.display_master_name +app.jinja_env.filters['email_to_gravatar_url'] = utils.email_to_gravatar_url # Flag for pdns v4.x.x # TODO: Find another way to do this @@ -34,6 +38,10 @@ else: NEW_SCHEMA = False +@babel.localeselector +def get_locale(): + return request.accept_languages.best_match(LANGUAGES.keys()) + @app.context_processor def inject_fullscreen_layout_setting(): fullscreen_layout_setting = Setting.query.filter(Setting.name == 'fullscreen_layout').first() diff --git a/requirements.txt b/requirements.txt index 0283ef13b..76a109fe2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,47 @@ -Flask>=0.10 -Flask-Babel==0.11.2 -Flask-WTF>=0.11 -Flask-Login>=0.2.11 -configobj==5.0.5 +asn1crypto==0.24.0 +Babel==2.5.3 bcrypt==3.1.0 -requests==2.7.0 -python-ldap==2.4.21 +cffi==1.11.4 +click==6.7 +configobj==5.0.5 +cryptography==2.1.4 +decorator==4.2.1 +dnspython==1.15.0 +enum34==1.1.6 +Flask==0.12.2 +Flask-Assets==0.12 +Flask-Babel==0.11.2 +Flask-BabelEx==0.9.3 +Flask-Login==0.4.1 +Flask-OAuthlib==0.9.3 Flask-SQLAlchemy==2.1 -SQLAlchemy==1.0.9 -sqlalchemy-migrate==0.10.0 +Flask-WTF==0.14.2 +idna==2.6 +ipaddress==1.0.19 +itsdangerous==0.24 +Jinja2==2.10 +MarkupSafe==1.0 +MySQL-python==1.2.5 +ndg-httpsclient==0.4.3 +oauthlib==2.0.6 +pbr==1.10.0 +pkg-resources==0.0.0 +pyasn1==0.4.2 +pycparser==2.18 +pyOpenSSL==17.5.0 pyotp==2.2.1 +python-ldap==2.4.21 +pytz==2017.3 qrcode==5.3 -Flask-OAuthlib==0.9.3 -dnspython>=1.12.0 +requests==2.7.0 +requests-oauthlib==0.8.0 +six==1.11.0 +speaklater==1.3 +SQLAlchemy==1.0.9 +sqlalchemy-migrate==0.10.0 +sqlparse==0.2.4 +Tempita==0.5.2 +virtualenv==15.0.1 +webassets==0.12.1 +Werkzeug==0.14.1 +WTForms==2.1 From 8fbc7b72d2da0b0fb959c4c7c83042d0dce9f2f5 Mon Sep 17 00:00:00 2001 From: Bruno Emanuel Date: Tue, 16 Jan 2018 21:45:39 +0000 Subject: [PATCH 06/28] Adjusting some parts of source code --- app/static/js/gettext.js | 1265 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1265 insertions(+) create mode 100644 app/static/js/gettext.js diff --git a/app/static/js/gettext.js b/app/static/js/gettext.js new file mode 100644 index 000000000..8a905e6a1 --- /dev/null +++ b/app/static/js/gettext.js @@ -0,0 +1,1265 @@ +/* +Pure Javascript implementation of Uniforum message translation. +Copyright (C) 2008 Joshua I. Miller , all rights reserved + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU Library General Public License as published +by the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +USA. + +=head1 NAME + +Javascript Gettext - Javascript implemenation of GNU Gettext API. + +=head1 SYNOPSIS + + // ////////////////////////////////////////////////////////// + // Optimum caching way + + + + var gt = new Gettext({ "domain" : "myDomain" }); + // rest is the same + + + // ////////////////////////////////////////////////////////// + // The reson the shortcuts aren't exported by default is because they'd be + // glued to the single domain you created. So, if you're adding i18n support + // to some js library, you should use it as so: + + if (typeof(MyNamespace) == 'undefined') MyNamespace = {}; + MyNamespace.MyClass = function () { + var gtParms = { "domain" : 'MyNamespace_MyClass' }; + this.gt = new Gettext(gtParams); + return this; + }; + MyNamespace.MyClass.prototype._ = function (msgid) { + return this.gt.gettext(msgid); + }; + MyNamespace.MyClass.prototype.something = function () { + var myString = this._("this will get translated"); + }; + + // ////////////////////////////////////////////////////////// + // Adding the shortcuts to a global scope is easier. If that's + // ok in your app, this is certainly easier. + var myGettext = new Gettext({ 'domain' : 'myDomain' }); + function _ (msgid) { + return myGettext.gettext(msgid); + } + alert( _("text") ); + + // ////////////////////////////////////////////////////////// + // Data structure of the json data + // NOTE: if you're loading via the + + // in domain.json + json_locale_data = { + "mydomain" : { + // po header fields + "" : { + "plural-forms" : "...", + "lang" : "en", + }, + // all the msgid strings and translations + "msgid" : [ "msgid_plural", "translation", "plural_translation" ], + }, + }; + // please see the included bin/po2json script for the details on this format + +This method also allows you to use unsupported file formats, so long as you can parse them into the above format. + +=item 2. Use AJAX to load language file. + +Use XMLHttpRequest (actually, SJAX - syncronous) to load an external resource. + +Supported external formats are: + +=over + +=item * Javascript Object Notation (.json) + +(see bin/po2json) + + type=application/json + +=item * Uniforum Portable Object (.po) + +(see GNU Gettext's xgettext) + + type=application/x-po + +=item * Machine Object (compiled .po) (.mo) + +NOTE: .mo format isn't actually supported just yet, but support is planned. + +(see GNU Gettext's msgfmt) + + type=application/x-mo + +=back + +=back + +=head1 METHODS + +The following methods are implemented: + + new Gettext(args) + textdomain (domain) + gettext (msgid) + dgettext (domainname, msgid) + dcgettext (domainname, msgid, LC_MESSAGES) + ngettext (msgid, msgid_plural, count) + dngettext (domainname, msgid, msgid_plural, count) + dcngettext (domainname, msgid, msgid_plural, count, LC_MESSAGES) + pgettext (msgctxt, msgid) + dpgettext (domainname, msgctxt, msgid) + dcpgettext (domainname, msgctxt, msgid, LC_MESSAGES) + npgettext (msgctxt, msgid, msgid_plural, count) + dnpgettext (domainname, msgctxt, msgid, msgid_plural, count) + dcnpgettext (domainname, msgctxt, msgid, msgid_plural, count, LC_MESSAGES) + strargs (string, args_array) + + +=head2 new Gettext (args) + +Several methods of loading locale data are included. You may specify a plugin or alternative method of loading data by passing the data in as the "locale_data" option. For example: + + var get_locale_data = function () { + // plugin does whatever to populate locale_data + return locale_data; + }; + var gt = new Gettext( 'domain' : 'messages', + 'locale_data' : get_locale_data() ); + +The above can also be used if locale data is specified in a statically included