def review_translation(translation_id): ''' Formulario de revisión de traducción ''' page = request.args.get("page", 0, int) mode = request.args.get("show", "old", str) size = request.args.get("size", 15, int) # Optimización: si envío en un campo la lista de strids, no la pido a BBDD data = None if request.form.get("field_keys", None): data_fields = {i:"" for i in request.form.get("fields").replace("‚",",").replace("&","&").split(",")} else: data = pagesdb.get_translation(translation_id) data_fields = data["texts"] # Lenguaje base base_lang = pomanager.get_lang("en") # Campos de traducción fields = {"field_%s" % key: TextAreaField(key, default=unfix_lang_values(value, base_lang[key]) or value) if len(value) > 40 else TextField(key, default=unfix_lang_values(value, base_lang[key]) or value) for key, value in data_fields.iteritems() if key in base_lang} # Checkboxes fields.update( ("check_%s" % key, BooleanField(default=False)) for key in data_fields.iterkeys()) form = expanded_instance(ValidateTranslationForm, fields, request.form, prefix="translation_") # Guardo en el Hiddenfield la lista de strids form.field_keys = "&".join(i.replace("&","&").replace(",","‚") for i in data_fields.iterkeys()) if request.method=='POST' and form.validate(): if form.submit.data: # Actualizamos el lenguaje de destino con los valores con checkbox marcado pomanager.update_lang(data["dest_lang"], {key: form["field_%s" % key].data for key in data_fields.iterkeys() if form["check_%s" % key].data}) pagesdb.update_translation({"_id":translation_id,"processed":True}) flash("admin_saved") return redirect(url_for('admin.translations', page=page, mode=mode, size=size)) elif data is None: # Si no he pedido a base de datos la traducción por optimizar, pero no queda otra data = pagesdb.get_translation(translation_id) pomanager.preload((g.lang, data["dest_lang"], data["user_lang"])) cur_lang = pomanager.get_lang(g.lang) user_lang = pomanager.get_lang(data["user_lang"]) dest_lang = pomanager.get_lang(data["dest_lang"]) translation = { key:( cur_lang[key] if key in cur_lang else None, user_lang[key] if key in user_lang else None, dest_lang[key] if key in dest_lang else None) for key, value in data.pop("texts").iteritems() if key in base_lang } return render_template('admin/translation_review.html', page_title=_('admin_translation_review'), title=admin_title('admin_translation_review'), form=form, langs=(g.lang, data["user_lang"], data["dest_lang"]), data=data, page=page, list_mode=mode, field_keys=",".join(translation.iterkeys()), fields=translation)
def db_edit(collection, document_id=None): ''' Edición de base de datos ''' page = request.args.get("page", 0, int) grps = request.args.get("mode", "all", str) mode = request.args.get("show", "current", str) size = request.args.get("size", 15, int) page_title = "admin_edit" form_title = "admin_edit" data = None form_force_fields = ("_id",) if document_id is None else () form_readonly_fields = ("_id",) if document_id else () form_ignored_fields = () form_fieldtypes = {} form_fieldkwargs = {} form_fieldparams = {} document = {} deleteable = bool(document_id) # Mostrar o no el botón de borrar # Especificidades de las colecciones if collection == "user": # Nota: El campo "password" es un hash, de modo que lo establezco de # sólo lectura y creo un nuevo campo "new password" para # cambiarla (ver endpoint "db_confirm"). page_title = 'admin_users' form_title = 'admin_users_info' form_force_fields += ("karma", "token", "username", "email", "new password", "lang", "location", "karma", "active", "type", "oauthid") form_readonly_fields += ("created","password") data = usersdb.find_userid(document_id) if document_id else {} elif collection == "origin": deleteable = current_app.debug page_title = 'admin_origins_info' form_title = 'admin_origins_info' form_force_fields += ("tb", "crbl", "d", "g", "ig") #form_readonly_fields += () data = filesdb.get_source_by_id(float(document_id)) if document_id else {} elif collection == "alternatives": url_id = "admin.alternatives" available_methods = configdb.list_alternatives_methods() available_endpoints = configdb.list_alternatives_endpoints(document_id) if document_id else [] available_param_types = configdb.list_alternatives_param_types() form_force_fields += ("default", "methods", "param_name", "param_type", "remember_id", "probability") form_fieldtypes["probability"] = TextAreaField form_fieldtypes["param_type"] = SelectField if document_id: form_fieldtypes["default"] = SelectField form_fieldkwargs["default"] = {"choices": ((repr(i), repr(i)) for i in available_endpoints)} data = {"default":available_endpoints[0] if available_endpoints else None} data.update(configdb.get_alternative_config(document_id)) if not "_id" in data: data["_id"] = document_id if not "remember_id" in data: data["remember_id"] = document_id if not "param_name" in data: data["param_name"] = "alt" else: data = {} data["available_methods"] = ", ".join(available_methods) form_fieldkwargs["param_type"] = {"choices": ((i, i) for i in available_param_types)} form_fieldparams["available_methods"] = form_fieldparams["available_endpoints"] = {"readonly":"readonly"} form_fieldparams["probability"] = {"rows": len(available_endpoints), "class":"monospaced"} else: abort(404) document.update((i, db_ftd(collection, i, "")) for i in form_force_fields) if data: document.update(data) document_defaults = document document_writeable = sorted(k for k in document.iterkeys() if not (k in form_readonly_fields or k in form_ignored_fields)) edict = {} edit_form = expanded_instance(EditForm, { db_fnm(k): form_fieldtypes.get(k, TextField)(k, default=db_dtf(collection, k, document[k]), **form_fieldkwargs.get(k, edict)) for k in document_writeable }, request.form) edit_form.defaults.data = db_serialize(collection, document_defaults) edit_form.editable.data = json.dumps(document_writeable) return render_template('admin/edit.html', deleteable = deleteable, collection=collection, document_id=document_id, title = admin_title(page_title), page_title = _(page_title), edit_form = edit_form, form_title = _(form_title), fieldname = db_fnm, fieldparams = form_fieldparams, document_writeable = [(k, document[k]) for k in document_writeable], document_readonly = [(k, document[k]) for k in document if not (k in document_writeable or k in form_ignored_fields)], list_mode = grps, mode = mode, page = page)
def db_confirm(collection, document_id=None): ''' Confirmación de edición de base de datos ''' page = request.args.get("page", 0, int) grps = request.args.get("mode", "all", str) mode = request.args.get("show", "current", str) size = request.args.get("size", 15, int) document = db_unserialize(collection, request.form.get("defaults")) document_writeable = json.loads(request.form.get("editable")) request_form_dict = MultiDict(request.form) # Valores por defecto page_title = "admin_edit" form_title = "admin_edit" success_msgid = "admin_saved" unchanged_msgid = "admin_nochanges" form_fieldtypes = {} form_fieldkwargs = {} url_id = "admin.index" goback = lambda : redirect(url_for(url_id, page = page, mode = grps, show = mode, size = size)) # Especificaciones de las colecciones if collection == "user": page_title = 'admin_users' form_title = 'admin_users_info' success_msgid = "admin_users_updated" url_id = "admin.users" save_fnc = lambda data: ( usersdb.create_user(data) if document_id is None else usersdb.update_user(data) ) # La contraseña se mueve del campo "new password" a "password" new_password = request_form_dict.pop(db_fnm("new password"), None) if new_password: document_writeable.append("password") request_form_dict[db_fnm("password")] = new_password elif collection == "origin": page_title = 'admin_origins_info' form_title = 'admin_origins_info' url_id = "admin.origins" save_fnc = lambda data: ( filesdb.create_source(data) if document_id is None else filesdb.update_source(data) ) elif collection == "alternatives": url_id = "admin.alternatives" save_fnc = lambda data: configdb.update_alternative_config(document_id or data["_id"], data) else: abort(404) if db_confirm_debug: # debug mode def dummy_save(x): logging.debug(("Update:" if document_id else "Create: ") + repr(x)) save_fnc = dummy_save # Procesamiento de formulario if request.form.get("confirmed", "False") == "True": # La petición ya ha sido confirmada, procesamos check_form = expanded_instance(EditForm, {db_fnm(k): BooleanField(k) for k in document_writeable}, request_form_dict) data = {k: document[k] for k in document_writeable if check_form[db_fnm(k)].data} if data: # Hay datos que modificar, se ejecuta save_fnc y redirigimos if not document_id is None: data["_id"] = db_ftd(collection, "_id", document_id) try: save_fnc(data) flash(success_msgid, "success") return goback() except BaseException as e: flash(traceback.format_exc(e), "error") return goback() else: # No hay datos que modificar, redirigimos flash(unchanged_msgid, "error") return goback() else: # No se trata de la petición confirmada, procesamos el formulario como # viene de db_edit, generamos el formulario de confirmación. edict = {} edit_form = expanded_instance(EditForm, { db_fnm(k): form_fieldtypes.get(k, TextField)( k, default=db_dtf(collection, k, document[k]) if k in document else None, **form_fieldkwargs.get(k, edict)) for k in document_writeable }, request_form_dict) document_changes = [ (k, document.get(k, None), db_ftd(collection, k, edit_form[db_fnm(k)].data)) for k in document_writeable if document.get(k, None) != db_ftd(collection, k, edit_form[db_fnm(k)].data) ] if document_changes: # Si hay cambios, generamos el formulario de confirmación check_form = expanded_instance(EditForm, {db_fnm(k): BooleanField(k, default=False) for k, w, w in document_changes}) check_form.defaults.data = db_serialize(collection, {k: w for k, v, w in document_changes}) check_form.editable.data = json.dumps([k for k, w, v in document_changes]) check_form.confirmed.data = True else: # Si no hay cambios, redirigimos flash(unchanged_msgid, "error") return goback() return render_template('admin/confirm.html', collection=collection, document_id=document_id, title = admin_title(page_title), page_title = _(page_title), check_form = check_form, form_title = _(form_title), fieldname = db_fnm, repr=repr, document_changes = document_changes, list_mode = grps, mode = mode, page = page)
def translate(): ''' Edita la traducción a un idioma ''' def fix_values(entry,sample=False): ''' Si la traduccion contiene campos de valores los sustituimos por ______[X] y ponemos un ejemplo de uso, además se eliminan los saltos de linea ''' result=re.finditer(r'(%\(([^\)]+)\)([s|d]))', entry.msgstr) subs=dict() # se cargan los ejemplos si es necesario if entry.msgid in samples: subs=samples[entry.msgid] # para cada valor encontrado se sustituye por _____[X] for i,item in enumerate(result): entry.msgstr=entry.msgstr.replace(item.group(1),"_____["+str(i+1)+"]") # para los ejemplos numericos se utiliza uno aleatorio if item.group(3)=="d": subs[item.group(2)]=random.randint(2,10) if sample: if subs!={}: return (entry.msgid,(entry.msgstr,_(entry.msgid,**subs))) else: return (entry.msgid,(entry.msgstr,False)) # se sustituyen los saltos de linea html y se devuelve todo return (entry.msgid,entry.msgstr.replace("<br>","\n").replace("<br />","\n").replace("<br/>","\n") if "<br" in entry.msgstr else entry.msgstr) languages = localedata.load(g.lang)["languages"] keystrcoll = cmp_to_key(locale.strcoll) form = None forml = SelectLanguageForm(request.form) forml.lang.choices = [("", "-- "+_("choose_language")+" --")] + sorted( ((code, localedata.load(code)["languages"][code].capitalize()+" ("+languages[code].capitalize()+")") for code, language in languages.items() if code in current_app.config["TRANSLATE_LANGS"] and not code in current_app.config["LANGS"] and localedata.exists(code) and code in localedata.load(code)["languages"]), key=lambda x: keystrcoll(x[1])) total=99999 no_translation=0 msgids=[] lang_edit = request.args.get("lang") if not lang_edit in languages: lang_edit = None formfields = {} # mostrar el idioma a traducir if lang_edit is not None: forml.lang.default=lang_edit # cargar idioma actual current_lang = dict(fix_values(entry,True) for entry in polib.pofile(lang_path(g.lang))) # si existe el idioma se carga, sino vacio lpath = lang_path(lang_edit) new_lang = dict(fix_values(entry) for entry in polib.pofile(lpath)) if lpath else {} # recorre los ids en ingles y los coge el mensaje del idioma actual y el valor del nuevo for i, (msgid, msgstr) in enumerate(fix_values(entry,True) for entry in polib.pofile(lang_path("en"))): # se excluyen los textos legales que concluyen con safe_ if not msgid.startswith(("safe_","admin_")): # si no esta traducida la cadena en el idioma actual se deja vacio if not msgid in new_lang: no_translation+=1 new_lang[msgid]="" # si el mensaje esta traducido al idioma actual se usa, sino se usa el ingles if msgid in current_lang: msg=current_lang[msgid][0] description=current_lang[msgid][1] else: msg=msgstr[0] description=msgstr[1] # si la traduccion es mayor de 80 caracteres se utiliza un textarea en vez de un input text length=len(new_lang[msgid] or msg) if length>80: formfields[msgid]=TextAreaField(msg,default=new_lang[msgid],description=description) # se le establecen las filas al text area dependiendo del tamaño de la traduccion formfields["_args_%s" % msgid]={"rows":length/50} else: formfields[msgid]=TextField(msg,default=new_lang[msgid],description=description) formfields["_args_%s" % msgid]={} #se añade a la lista que se le envia al formulario msgids.append(msgid) total=float(len(msgids)) form=expanded_instance(TranslateForm, formfields, request.form, prefix="translate_") # si es el envio de la traducción if request.method == 'POST' and form.validate(): pagesdb.create_translation({"ip":request.remote_addr,"user_lang":g.lang,"dest_lang":lang_edit,"texts":{field.short_name: field.data for field in form if not field.short_name in ("captcha", "submit_form") and field.data!=new_lang[field.short_name]}}) flash("translation_sent") return redirect(url_for('index.home')) if lang_edit: forml.lang.data = lang_edit # sino se muestra la seleccion de idioma a traducir g.title+=_("translate_to_your_language") return render_template('pages/translate.html', page_title=_("translate_to_your_language"), lang=lang_edit, forml=forml, form=form, msgids=msgids, complete=round(((total-no_translation)/total)*100,2))
def translate(): ''' Edita la traducción a un idioma ''' languages = localedata.load(g.lang)["languages"] keystrcoll = cmp_to_key(locale.strcoll) form = None forml = SelectLanguageForm(request.form) forml.lang.choices = [("", "-- "+_("choose_language")+" --")] + sorted( ((code, localedata.load(code)["languages"][code].capitalize()+" ("+languages[code].capitalize()+")") for code, language in languages.items() if code in current_app.config["TRANSLATE_LANGS"] and not code in current_app.config["LANGS"] and localedata.exists(code) and code in localedata.load(code)["languages"]), key=lambda x: keystrcoll(x[1])) total=99999 no_translation=0 msgids=[] lang_edit = request.args.get("lang") if not lang_edit in languages: lang_edit = None formfields = {} # mostrar el idioma a traducir if lang_edit is not None: forml.lang.default=lang_edit # cargar idioma actual current_lang = dict(fix_lang_values(entry,True) for entry in polib.pofile(lang_path(g.lang))) # si existe el idioma se carga, sino vacio lpath = lang_path(lang_edit) new_lang = dict(fix_lang_values(entry) for entry in polib.pofile(lpath)) if lpath else {} # recorre los ids en ingles y los coge el mensaje del idioma actual y el valor del nuevo for i, (msgid, msgstr) in enumerate(fix_lang_values(entry,True) for entry in polib.pofile(lang_path("en"))): # se excluyen los textos legales que concluyen con safe_ if not msgid.startswith(current_app.config["PRIVATE_MSGID_PREFIXES"]): # si no esta traducida la cadena en el idioma actual se deja vacio if not msgid in new_lang: no_translation+=1 new_lang[msgid]="" # si el mensaje esta traducido al idioma actual se usa, sino se usa el ingles if msgid in current_lang: msg=current_lang[msgid][0] description=current_lang[msgid][1] else: msg=msgstr[0] description=msgstr[1] # si la traduccion es mayor de 80 caracteres se utiliza un textarea en vez de un input text length=len(new_lang[msgid] or msg) if length>50: formfields[msgid]=TextAreaField(msg,default=new_lang[msgid],description=description) # se le establecen las filas al text area dependiendo del tamaño de la traduccion formfields["_args_%s" % msgid]={"rows":length/15} else: formfields[msgid]=TextField(msg,default=new_lang[msgid],description=description) formfields["_args_%s" % msgid]={} #se añade a la lista que se le envia al formulario msgids.append(msgid) total=float(len(msgids)) form=expanded_instance(TranslateForm, formfields, request.form, prefix="translate_") # si es el envio de la traducción if request.method == 'POST' and form.validate(): pagesdb.create_translation({"ip":request.remote_addr,"user_lang":g.lang,"dest_lang":lang_edit,"texts":{field.short_name: field.data for field in form if not field.short_name in ("captcha", "submit_form") and field.data!=new_lang[field.short_name]}}) flash("translation_sent") return redirect(url_for('index.home')) if lang_edit: forml.lang.data = lang_edit # sino se muestra la seleccion de idioma a traducir g.title+=_("translate_to_your_language") return render_template('pages/translate.html', page_title=_("translate_to_your_language"), pagination=["submitlink","submitlink",2,2], lang=lang_edit, forml=forml, form=form, pname="translate", msgids=msgids, complete=round(((total-no_translation)/total)*100,2))
def db_confirm(collection, document_id=None): """ Confirmación de edición de base de datos """ page = request.args.get("page", 0, int) grps = request.args.get("mode", "all", str) mode = request.args.get("show", "current", str) size = request.args.get("size", 15, int) goback = lambda: redirect(url_for(url_id, page=page, mode=grps, show=mode, size=size)) document = json.loads(request.form.get("defaults")) document_writeable = json.loads(request.form.get("editable")) request_form_dict = MultiDict(request.form) success_msgid = "admin_saved" unchanged_msgid = "admin_nochanges" if collection == "user": page_title = "admin_users" form_title = "admin_users_info" success_msgid = "admin_users_updated" url_id = "admin.users" save_fnc = lambda data: usersdb.update_user(data) new_password = request_form_dict.pop(db_fnm("new password"), None) if new_password: document_writeable.append("password") request_form_dict[db_fnm("password")] = new_password elif collection == "origin": page_title = "admin_origins_info" form_title = "admin_origins_info" url_id = "admin.origins" save_fnc = lambda data: filesdb.update_source(data) if request.form.get("confirmed", "False") == "True": # La petición ha sido realizada por el formulario de confirmación, # lo procesamos. check_form = expanded_instance( EditForm, {db_fnm(k): BooleanField(k) for k in document_writeable}, request_form_dict ) data = {k: document[k] for k in document_writeable if check_form[db_fnm(k)].data} if data: data["_id"] = hex2mid(document_id) save_fnc(data) flash(success_msgid, "success") return goback() else: flash(unchanged_msgid, "error") return goback() else: # No se trata del petición confirmada, procesamos el formulario como # viene de db_edit, generamos el formulario de confirmación. edit_form = expanded_instance( EditForm, {db_fnm(k): TextField(k, default=db_dtf(collection, k, document[k])) for k in document_writeable}, request_form_dict, ) document_changes = [ (k, document[k], db_ftd(collection, k, edit_form[db_fnm(k)].data)) for k in document_writeable if edit_form[db_fnm(k)].data != db_dtf(collection, k, document[k]) ] if document_changes: check_form = expanded_instance( EditForm, {db_fnm(k): BooleanField(k, default=False) for k, w, w in document_changes} ) check_form.defaults.data = json.dumps({k: v for k, w, v in document_changes}) check_form.editable.data = json.dumps([k for k, w, v in document_changes]) check_form.confirmed.data = True else: flash(unchanged_msgid, "error") return goback() return render_template( "admin/confirm.html", collection=collection, document_id=document_id, title=admin_title(page_title), page_title=_(page_title), check_form=check_form, form_title=_(form_title), fieldname=db_fnm, repr=repr, document_changes=document_changes, list_mode=grps, mode=mode, page_size=size, page=page, )
def db_edit(collection, document_id=None): """ Edición de base de datos """ page = request.args.get("page", 0, int) grps = request.args.get("mode", "all", str) mode = request.args.get("show", "current", str) size = request.args.get("size", 15, int) page_title = "admin_edit" form_title = "admin_edit" data = None form_force_fields = () form_readonly_fields = ("_id",) document = {} if collection == "user": page_title = "admin_users" form_title = "admin_users_info" form_force_fields += ( "karma", "token", "username", "email", "new password", "lang", "location", "karma", "active", "type", "oauthid", ) form_readonly_fields += ("created", "password") data = usersdb.find_userid(document_id) if document_id else {} elif collection == "origin": page_title = "admin_origins_info" form_title = "admin_origins_info" form_force_fields += ("tb", "crbl", "d", "g") # form_readonly_fields += () data = filesdb.get_source_by_id(float(document_id)) if document_id else {} else: abort(500) document.update((i, db_ftd(collection, i, "")) for i in form_force_fields) document.update(data) document_defaults = {fjson(i): fjson(j) for i, j in document.iteritems()} document_writeable = [k for k in document.iterkeys() if k not in form_readonly_fields] edit_form = expanded_instance( EditForm, {db_fnm(k): TextField(k, default=db_dtf(collection, k, document[k])) for k in document_writeable}, request.form, ) edit_form.defaults.data = json.dumps(document_defaults) edit_form.editable.data = json.dumps(document_writeable) return render_template( "admin/edit.html", collection=collection, document_id=document_id, title=admin_title(page_title), page_title=_(page_title), edit_form=edit_form, form_title=_(form_title), fieldname=db_fnm, document_writeable=[(k, document[k]) for k in document_writeable], document_readonly=[(k, document[k]) for k in document if not k in document_writeable], list_mode=grps, mode=mode, page_size=size, page=page, )
def review_translation(translation_id): """ Formulario de revisión de traducción """ page = request.args.get("page", 0, int) mode = request.args.get("show", "old", str) size = request.args.get("size", 15, int) select = request.args.get("select", "default", str) # Optimización: si envío en un campo la lista de strids, no la pido a BBDD data = None if request.form.get("field_keys", None): data_fields = { i: "" for i in request.form.get("fields").replace("‚", ",").replace("&", "&").split(",") } else: data = pagesdb.get_translation(translation_id) data_fields = data["texts"] def denuke(o): """Evita nukeos de msgstrs malformados""" try: return _(o) # TODO: Investigar porqué esto hace falta except: return o # Campos de traducción fields = { "field_%s" % key: TextAreaField(key, default=value, description=denuke(key)) if len(value) > 40 else TextField(key, default=value, description=denuke(key)) for key, value in data_fields.iteritems() } # Checkboxes fields.update(("check_%s" % key, BooleanField(default=(select == all))) for key in data_fields.iterkeys()) form = expanded_instance(ValidateTranslationForm, fields, request.form, prefix="translation_") # Guardo en el Hiddenfield la lista de strids form.field_keys = "&".join(i.replace("&", "&").replace(",", "‚") for i in data_fields.iterkeys()) if request.method == "POST" and form.validate(): if form.submit.data: pomanager.update_lang( data["dest_lang"], {key: form["field_%s" % key].data for key in data_fields.iterkeys() if form["check_%s" % key].data}, ) pagesdb.update_translation({"_id": translation_id, "processed": True}) return redirect(url_for("admin.translations", page=page, mode=mode, size=size)) elif data is None: # Si no he pedido a base de datos la traducción por optimizar data = pagesdb.get_translation(translation_id) dest_lang = {key: value for key, value in pomanager.get_lang(data["dest_lang"]).iteritems() if key in data["texts"]} user_lang_path = lang_path(data["user_lang"]) user_lang = ( {i.msgid: i.msgstr for i in polib.pofile(user_lang_path) if i.msgid in data["texts"]} if user_lang_path else {} ) def try_current(o): try: return _(o) except: return None translation = { key: ( user_lang[key] if key in user_lang else None, dest_lang[key] if key in dest_lang else None, try_current(key), ) for key, value in data.pop("texts").iteritems() } return render_template( "admin/translation_review.html", page_title=_("admin_translation_review"), title=admin_title("admin_translation_review"), form=form, select=select, data=data, page=page, list_mode=mode, page_size=size, field_keys=",".join(translation.iterkeys()), fields=translation, )