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 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 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, )