diff --git a/.gitignore b/.gitignore index af2f537..7a31788 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,7 @@ coverage.xml .hypothesis/ # Translations -*.mo +#*.mo *.pot # Django stuff: diff --git a/paramecio2/libraries/db/usermodel.py b/paramecio2/libraries/db/usermodel.py index 1708951..f172f8b 100644 --- a/paramecio2/libraries/db/usermodel.py +++ b/paramecio2/libraries/db/usermodel.py @@ -3,7 +3,7 @@ from paramecio2.libraries.db.webmodel import WebModel from paramecio2.libraries.db.coreforms import PasswordForm from paramecio2.libraries.i18n import I18n -from flask import request +from flask import request, session class UserModel(WebModel): """Model used with basic things for users login and signup @@ -46,7 +46,7 @@ class UserModel(WebModel): repeat_password.required=1 - repeat_password.label=I18n.lang('common', 'repeat_password', 'Repeat Password') + repeat_password.label=_('Repeat Password') repeat_password.field=self.fields[self.password_field] @@ -99,7 +99,7 @@ class UserModel(WebModel): if dict_values['repeat_password']!=dict_values[self.password_field]: self.fields[self.password_field].error=True - self.fields[self.password_field].txt_error=I18n.lang('common', 'error_passwords_no_match', 'Error: passwords doesn\'t match') + self.fields[self.password_field].txt_error=_('Error: passwords doesn\'t match') error+=1 diff --git a/paramecio2/libraries/formsutils.py b/paramecio2/libraries/formsutils.py index b479586..0f87a20 100644 --- a/paramecio2/libraries/formsutils.py +++ b/paramecio2/libraries/formsutils.py @@ -5,6 +5,8 @@ from paramecio2.libraries.db.coreforms import PasswordForm from paramecio2.libraries.i18n import I18n from flask import session, request, abort from paramecio2.libraries.keyutils import create_key_encrypt +from paramecio2.libraries.i18n import I18n, PGetText + # Need unittest """Functions and classes for process forms""" @@ -178,7 +180,7 @@ def set_extra_forms_user(user_admin): user_admin.forms['repeat_password'].required=True - user_admin.forms['repeat_password'].label=I18n.lang('common', 'repeat_password', 'Repeat Password') + user_admin.forms['repeat_password'].label=_('Repeat Password') def csrf_token(token_id='csrf_token'): diff --git a/paramecio2/libraries/generate_admin_class.py b/paramecio2/libraries/generate_admin_class.py index 718dc19..114458a 100644 --- a/paramecio2/libraries/generate_admin_class.py +++ b/paramecio2/libraries/generate_admin_class.py @@ -3,14 +3,22 @@ from flask import request, redirect, flash from paramecio2.libraries.urls import add_get_parameters #from paramecio.citoplasma.mtemplates import set_flash_message from paramecio2.libraries.formsutils import show_form -from paramecio2.libraries.i18n import I18n +from paramecio2.libraries.mtemplates import env_theme, PTemplate +from paramecio2.libraries.i18n import I18n, PGetText from collections import OrderedDict +pgettext=PGetText(__file__) +_=pgettext.gettext + +#env=env_theme(__file__) + +#t=PTemplate(env) + class GenerateAdminClass: """Class for insert, update and list items of a model """ - def __init__(self, model, url, t): + def __init__(self, model, url, t=None): """A class for generate forms, insert and update items from a database model For an easy and fast access to database data, you can use this class for get a simple database model of paramecio and get list of items, add forms, edit forms and more. @@ -38,9 +46,20 @@ class GenerateAdminClass: self.model=model - self.t=t + if t: + + self.t=t + else: + + env=env_theme(__file__) - self.list=SimpleList(model, url, t) + self.t=PTemplate(env) + + #self.t.l=pgettext + + #self.t.add_filter(self.t._) + + self.list=SimpleList(model, url, self.t) self.arr_fields_edit=list(model.fields.keys()) @@ -76,7 +95,7 @@ class GenerateAdminClass: self.post_update=None - self.text_home=I18n.lang('common', 'home', 'Home') + self.text_home=_('Home') def show(self): """ Method for show the admin model @@ -106,13 +125,13 @@ class GenerateAdminClass: post=None - title_edit=I18n.lang('common', 'add_new_item', 'Add new item') + title_edit=_('Add new item') pass_value=False if item_id!='0': post=self.model.select_a_row(item_id, [], True) - title_edit=I18n.lang('common', 'edit_new_item', 'Edit item') + title_edit=_('Edit item') pass_value=True if post==None or post==False: @@ -149,12 +168,12 @@ class GenerateAdminClass: item_id='0' - title_edit=I18n.lang('common', 'add_new_item', 'Add new item') + title_edit=_('Add new item') if item_id!='0': insert_row=self.model.update - title_edit=I18n.lang('common', 'edit_new_item', 'Edit item') + title_edit=_('Edit item') self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]] post=dict(request.form) @@ -162,7 +181,7 @@ class GenerateAdminClass: if pre_update_ret: if insert_row(post): - flash(I18n.lang('common', 'task_successful', 'Task successful')) + flash(_('Task successful')) if self.post_update: if item_id=='0': @@ -203,7 +222,7 @@ class GenerateAdminClass: if item_id!='0': self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]] self.model.delete() - flash(I18n.lang('common', 'task_successful', 'Task successful')) + flash(_('Task successful')) return redirect(self.url_redirect) else: @@ -282,7 +301,7 @@ class GenerateConfigClass: self.post_update=None - self.text_home=I18n.lang('common', 'home', 'Home') + self.text_home=_('Home') def show(self): @@ -298,7 +317,7 @@ class GenerateConfigClass: self.model.create_forms() - title_edit=I18n.lang('common', 'edit', 'Edit')+' '+self.title_name + title_edit=_('Edit')+' '+self.title_name edit_forms=OrderedDict() @@ -323,7 +342,7 @@ class GenerateConfigClass: post=dict(request.form) if insert_model(post): - set_flash_message(I18n.lang('common', 'task_successful', 'Task successful')) + set_flash_message(_('Task successful')) self.model.yes_reset_conditions=True if self.post_update: diff --git a/paramecio2/libraries/i18n.py b/paramecio2/libraries/i18n.py index 8045232..752bc08 100644 --- a/paramecio2/libraries/i18n.py +++ b/paramecio2/libraries/i18n.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 from importlib import import_module +import gettext #from paramecio.citoplasma.sessions import get_session import json from flask import session, has_request_context +import os yes_session=False @@ -27,7 +29,45 @@ def load_lang(*args): pass # here load the language + +class PGetText: + + # Dict where all gettext domain are saved -> domain=name, example, admin, libraries, pastafari2, etc... + + l={} + + def __init__(self, module_file): + module_dir=os.path.dirname(os.path.realpath(module_file)) + + module_name=os.path.basename(module_dir) + + if module_name not in PGetText.l: + + PGetText.l[module_name]={} + + for i in I18n.dict_i18n: + + if i not in PGetText.l[module_name]: + + PGetText.l[module_name][i]=gettext.translation(module_name, module_dir+'/languages/', languages=[i], fallback=True) + PGetText.l[module_name][i].install() + + self.module=module_name + + def gettext(self, text): + + return PGetText.l[self.module][I18n.get_default_lang()].gettext(text) + +def pgettext(module_file): + + module=os.path.dirname(os.path.realpath(module_file)) + + base_name=os.path.dirname(os.path.realpath(module)) + + l=gettext.translation(os.path.basename(base_name), module+'/languages/', languages=I18n.get_default_lang(), fallback=True) + + return l.gettext class I18n: """Class for i18n tasks @@ -130,3 +170,4 @@ class I18n: return json.dumps(arr_final) +common_pgettext=PGetText(__file__) diff --git a/paramecio2/libraries/lists.py b/paramecio2/libraries/lists.py index 4305fb3..0ff00f0 100644 --- a/paramecio2/libraries/lists.py +++ b/paramecio2/libraries/lists.py @@ -2,12 +2,15 @@ from paramecio2.libraries.pages import Pages from paramecio2.libraries.urls import add_get_parameters -from paramecio2.libraries.i18n import I18n +from paramecio2.libraries.i18n import I18n, PGetText #from flask import request, session from paramecio2.libraries.get_data import get_query_args import sys import re +pgettext=PGetText(__file__) +_=pgettext.gettext + class SimpleList: """Class for create item list from a model table """ @@ -107,7 +110,7 @@ class SimpleList: #self.yes_options=True - self.arr_extra_fields=[I18n.lang('common', 'options', 'Options')] + self.arr_extra_fields=[_('Options')] self.arr_extra_options=[SimpleList.standard_options] @@ -216,8 +219,8 @@ class SimpleList: options (list): Return a list of basic options for items row """ options=[] - options.append(''+I18n.lang('common', 'edit', 'Edit')+'') - options.append(''+I18n.lang('common', 'delete', 'Delete')+'') + options.append(''+_('Edit')+'') + options.append(''+_('Delete')+'') return options def show(self): @@ -286,7 +289,7 @@ class AjaxList(SimpleList): """Class for make a list from a table based in Ajax """ - # Fields example: [[I18n.lang('cuchulu', 'hostname', 'Hostname'), True], ['IP', True], [I18n.lang('cuchulu', 'options', 'Options'), False]] + # Fields example: [['Hostname', True], ['IP', True], ['Options', False]] # arr_order_fields=['server.hostname', 'server.ip'] @@ -389,7 +392,7 @@ class AjaxList(SimpleList): pages=Pages() - html_pages=I18n.lang('cuchulu', 'pages', 'Pages')+': '+pages.show( begin_page, total_elements, limit, '#' ,initial_num_pages=self.initial_num_pages, variable='begin_page', label='', func_jscript='') + html_pages=_('Pages')+': '+pages.show( begin_page, total_elements, limit, '#' ,initial_num_pages=self.initial_num_pages, variable='begin_page', label='', func_jscript='') with self.db.query(str_query, params) as cursor: for row in cursor: diff --git a/paramecio2/libraries/mtemplates.py b/paramecio2/libraries/mtemplates.py index 6b24ef6..1cb8371 100644 --- a/paramecio2/libraries/mtemplates.py +++ b/paramecio2/libraries/mtemplates.py @@ -1,6 +1,6 @@ # Template frontend from mako. -import gettext +#import gettext from mako.template import Template from flask import session, url_for from mako.lookup import TemplateLookup @@ -12,15 +12,17 @@ except: theme='default' reloader=False -import gettext +#import gettext import sys -from paramecio2.libraries.i18n import I18n +from paramecio2.libraries.i18n import I18n, PGetText from paramecio2.libraries.urls import make_url, make_media_url, add_get_parameters from paramecio2.libraries.formsutils import csrf_token +""" def _(text): return gettext.gettext(text) +""" def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_directory="./tmp/modules"): """Function for create an environment for mako templates @@ -46,6 +48,8 @@ def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_d module=path.dirname(module) standard_templates=path.dirname(__file__)+'/templates' + + standard_languages=path.dirname(__file__)+'/languages' module_directory+='/'+module @@ -94,8 +98,6 @@ class PTemplate: self.add_filter(I18n.lang) - self.add_filter(_) - #self.add_filter(make_url) self.add_filter(make_media_url) @@ -109,6 +111,22 @@ class PTemplate: self.add_filter(self.add_js) self.add_filter(self.load_js) + + # Loading language domain for gettext in templates + + base_name=path.dirname(path.realpath(__file__)) + + module_env=self.env.directories[1].replace('/templates', '') + + #print(path.basename(module_env)+' '+base_name+'/languages/') + + self.l=PGetText(module_env+'/app.py') + + self.add_filter(self._) + + def _(self, text): + + return self.l.gettext(text) def add_js(self, js, module=''): """Function for add js to self.js attribute diff --git a/paramecio2/libraries/templates/utils/admin.phtml b/paramecio2/libraries/templates/utils/admin.phtml index 7fb9756..b11299b 100644 --- a/paramecio2/libraries/templates/utils/admin.phtml +++ b/paramecio2/libraries/templates/utils/admin.phtml @@ -1,3 +1,3 @@ -
${lang('common', 'add_item', 'Add new item')}
+ ${admin.list.show()|n} diff --git a/paramecio2/libraries/templates/utils/list.phtml b/paramecio2/libraries/templates/utils/list.phtml index b843cbc..72b7eee 100644 --- a/paramecio2/libraries/templates/utils/list.phtml +++ b/paramecio2/libraries/templates/utils/list.phtml @@ -11,13 +11,13 @@ % if simplelist.yes_search:% if pages!='': -${lang('common', 'pages', 'Pages')}: ${pages|n} +${_('Pages')}: ${pages|n} % endif
diff --git a/paramecio2/libraries/templates/utils/verify_delete.phtml b/paramecio2/libraries/templates/utils/verify_delete.phtml index 0f08117..f7cd4b0 100644 --- a/paramecio2/libraries/templates/utils/verify_delete.phtml +++ b/paramecio2/libraries/templates/utils/verify_delete.phtml @@ -3,6 +3,6 @@ - + diff --git a/paramecio2/modules/admin/__init__.py b/paramecio2/modules/admin/__init__.py index 0341fa8..bf4f1e8 100644 --- a/paramecio2/modules/admin/__init__.py +++ b/paramecio2/modules/admin/__init__.py @@ -4,7 +4,6 @@ try: admin_app=Blueprint('admin_app', __name__, static_folder='static') - env=env_theme(__file__) t=PTemplate(env) diff --git a/paramecio2/modules/admin/admin/ausers.py b/paramecio2/modules/admin/admin/ausers.py index 212e5ea..cca37df 100644 --- a/paramecio2/modules/admin/admin/ausers.py +++ b/paramecio2/modules/admin/admin/ausers.py @@ -1,13 +1,17 @@ from settings import config -from flask import g, url_for +from flask import g, url_for, session from paramecio2.modules.admin.models.admin import UserAdmin from paramecio2.libraries.generate_admin_class import GenerateAdminClass -from paramecio2.libraries.i18n import I18n +from paramecio2.libraries.i18n import I18n, PGetText from paramecio2.libraries.db.coreforms import SelectForm from paramecio2.libraries.db.coreforms import HiddenForm import copy from paramecio2.modules.admin import admin_app, t as admin_t +pgettext=PGetText(__file__+'/../') + +_=pgettext.gettext + t=copy.copy(admin_t) @admin_app.route('/admin/ausers/', methods=['GET', 'POST']) @@ -29,22 +33,22 @@ def ausers(): user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'dark_theme', 'disabled', 'double_auth', 'last_login']) - user_admin.forms['privileges'].arr_select={0: I18n.lang('admin', 'without_privileges', 'Without privileges'), 1: I18n.lang('admin', 'selected_privileges', 'Selected privileges'), 2: I18n.lang('admin', 'administrator', 'Administrator')} + user_admin.forms['privileges'].arr_select={0: _('Without privileges'), 1: _('Selected privileges'), 2: _('Administrator')} - user_admin.forms['disabled'].arr_select={0: I18n.lang('admin', 'user_enabled', 'User enabled'), 1: I18n.lang('admin', 'user_disabled', 'User disabled')} + user_admin.forms['disabled'].arr_select={0: _('User enabled'), 1: _('User disabled')} - user_admin.forms['double_auth'].arr_select={0: I18n.lang('admin', 'no', 'No'), 1: I18n.lang('admin', 'yes', 'Yes')} + user_admin.forms['double_auth'].arr_select={0: _('No'), 1: _('Yes')} user_admin.fields['password'].protected=False - user_admin.forms['dark_theme'].arr_select={0: I18n.lang('admin', 'light_theme', 'Light theme'), 1: I18n.lang('admin', 'dark_theme', 'Dark theme')} + user_admin.forms['dark_theme'].arr_select={0: _('Light theme'), 1: _('Dark theme')} user_admin.check_user=False user_admin.check_email=False url=url_for('admin_app.ausers') - admin=GenerateAdminClass(user_admin, url, t) + admin=GenerateAdminClass(user_admin, url) admin.list.fields_showed=['username'] @@ -52,12 +56,22 @@ def ausers(): admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'lang', 'dark_theme', 'double_auth', 'disabled', 'last_login'] + admin.post_update=update_lang + form_admin=admin.show() if type(form_admin).__name__=='str': - return t.load_template('content.phtml', title=I18n.lang('admin', 'users_edit', 'Users edit'), contents=form_admin, path_module='admin_app.ausers') + return t.load_template('content.phtml', title=_('Users edit'), contents=form_admin, path_module='admin_app.ausers') else: return form_admin + +def update_lang(admin, item_id): + + arr_row=admin.model.select_a_row(item_id) + + session['lang']=arr_row.get('lang', I18n.get_default_lang()) + + return True diff --git a/paramecio2/modules/admin/app.py b/paramecio2/modules/admin/app.py index ff030aa..9772755 100644 --- a/paramecio2/modules/admin/app.py +++ b/paramecio2/modules/admin/app.py @@ -1,6 +1,6 @@ from flask import Blueprint, redirect, session, url_for, request, g, make_response, abort from settings import config -from paramecio2.libraries.i18n import I18n +from paramecio2.libraries.i18n import I18n, PGetText from paramecio2.libraries.datetime import now, format_local_strtime, timestamp_to_datetime, obtain_timestamp from paramecio2.libraries.formsutils import show_form, generate_csrf, set_extra_forms_user, pass_values_to_form from paramecio2.libraries.db.webmodel import WebModel @@ -15,6 +15,13 @@ from os import path from paramecio2.modules.admin import admin_app, t from paramecio2.libraries.sendmail import SendMail from paramecio2.libraries.formsutils import check_csrf +#import gettext + +#_=pgettext(__file__) + +gtext=PGetText(__file__) + +_=gtext.gettext yes_recovery_login=False email_address='localhost' @@ -116,7 +123,7 @@ for app_load in config_admin: @admin_app.route('/admin/') def admin(): - return t.load_template('home.phtml', title=I18n.lang('admin', 'admin', 'Admin')) + return t.load_template('home.phtml', title=_('Admin')) """ @admin_app.route('/admin/') @@ -250,7 +257,7 @@ def login(): # def send(self, from_address, to_address: list, subject, message, content_type='plain', attachments=[]): - sendmail.send(config.portal_email, [arr_user['email']], I18n.lang('admin', 'code_for_complete_login', 'Code for complete login'), I18n.lang('admin', 'code_for_complete_login_explain', 'We send to you a code for activate your account using double authentication:')+"\n"+token_auth, content_type='plain', attachments=[]) + sendmail.send(config.portal_email, [arr_user['email']], _('Code for complete login'), _('We send to you a code for activate your account using double authentication:')+"\n"+token_auth, content_type='plain', attachments=[]) if arr_user['dark_theme']: session['theme']='1' @@ -259,6 +266,8 @@ def login(): arr_update['last_login']=now() + session['lang']=arr_user.get('lang', I18n.default_lang) + if len(arr_update)>0: user_admin.set_conditions('WHERE id=%s', [arr_user['id']]).update(arr_update) diff --git a/paramecio2/modules/admin/languages/es-ES/LC_MESSAGES/admin.mo b/paramecio2/modules/admin/languages/es-ES/LC_MESSAGES/admin.mo new file mode 100644 index 0000000..f5bf787 Binary files /dev/null and b/paramecio2/modules/admin/languages/es-ES/LC_MESSAGES/admin.mo differ diff --git a/paramecio2/modules/admin/languages/es-ES/LC_MESSAGES/admin.po b/paramecio2/modules/admin/languages/es-ES/LC_MESSAGES/admin.po new file mode 100644 index 0000000..ba10a09 --- /dev/null +++ b/paramecio2/modules/admin/languages/es-ES/LC_MESSAGES/admin.po @@ -0,0 +1,132 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR