#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2004-2009 Zuza Software Foundation
#
# This file is part of Pootle.
#
# This file is somewhat based on the older Pootle/translatepage.py
#
# This program 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
# (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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
import re
import difflib
import os
import sys
import gettextpo
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.html import urlize
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from translate.storage import po
from translate.misc.multistring import multistring
from pootle.i18n.gettext import tr_lang, language_dir
from pootle_store.models import Store
from pootle_app.views import pagelayout
from pootle_app.models import TranslationProject, Directory
from pootle_app.models.profile import get_profile
from pootle_app import unit_update
from pootle_app.models.permissions import check_permission
from pootle_app.views.language import dispatch, navbar_dict, search_forms
xml_re = re.compile("<.*?>")
def oddoreven(polarity):
if polarity % 2 == 0:
return "even"
elif polarity % 2 == 1:
return "odd"
def get_alt_projects(request):
# do we have enabled alternative source language?
if settings.ENABLE_ALT_SRC:
# try to get the project if the user has chosen an alternate source language
return TranslationProject.objects.filter(language__in=get_profile(request.user).alt_src_langs.all(),
project=request.translation_project.project_id)
else:
return TranslationProject.objects.none()
def add_file_links(request, store):
"""adds a section on the current file, including any checks happening"""
state = dispatch.TranslatePageState(request.GET)
template_vars = {}
if store is not None:
if len(state.match_names) > 0:
checknames = \
["%(checkname)s" % \
{"checkname": matchname.replace("check-", "", 1)} for matchname in state.match_names]
# TODO: put the following parameter in quotes, since it will be foreign in all target languages
# l10n: the parameter is the name of one of the quality checks, like "fuzzy"
template_vars["checking_text"] = _("checking %s", ", ".join(checknames))
return template_vars
def get_rows_and_icon(request, profile):
state = dispatch.TranslatePageState(request.GET)
if state.view_mode == 'view':
return get_display_rows(profile), "file"
else:
return get_display_rows(profile), "edit"
def get_page_links(request, store, pagesize, translations, item, first_item):
"""gets links to other pages of items, based on the given baselink"""
pagelinks = []
pofilelen = store.file.getitemslen()
if pofilelen <= pagesize or item is None:
return pagelinks
lastitem = min(pofilelen - 1, first_item + pagesize - 1)
if pofilelen > pagesize and not item == 0:
pagelinks.append({"href": dispatch.translate(request, request.path_info, item=0),
# l10n: navigation link
"text": _("Start")})
if item > 0:
linkitem = max(item - pagesize, 0)
pagelinks.append({"href": dispatch.translate(request, request.path_info, item=linkitem),
# l10n: the parameter refers to the number of messages
"text": _("Previous %d", (item - linkitem))})
# l10n: the third parameter refers to the total number of messages in the file
pagelinks.append({"text": _("Items %(first)d to %(last)d of %(total)d",
{"first": first_item + 1, "last": lastitem + 1, "total": pofilelen})
})
if item + len(translations) < pofilelen:
linkitem = item + pagesize
itemcount = min(pofilelen - linkitem, pagesize)
pagelinks.append({"href": dispatch.translate(request, request.path_info, item=linkitem),
# l10n: the parameter refers to the number of messages
"text": _("Next %d", itemcount)})
if pofilelen > pagesize and (item + pagesize) < pofilelen:
pagelinks.append({"href": dispatch.translate(request, request.path_info,
item=max(pofilelen - 1, 0)),
# l10n: navigation link
"text": _("End")})
for n, pagelink in enumerate(pagelinks):
if n < len(pagelinks)-1:
pagelink["sep"] = " | "
else:
pagelink["sep"] = ""
return pagelinks
def get_display_rows(profile):
"""get the number of rows to display"""
rowsdesired = profile.unit_rows
maximum = 30
return min(rowsdesired, maximum)
def get_units(store, item_start, item_stop):
return [store.file.store.units[index] for index in store.file.total[max(item_start, 0):item_stop]]
def get_translations(request, profile, store, item):
"""gets the list of translations desired for the view, and sets editable and firstitem parameters"""
state = dispatch.TranslatePageState(request.GET)
if store is None:
# editable, first item, items
return -1, item, []
elif state.view_mode == 'view':
rows = get_display_rows(profile)
return -1, item, get_units(store, item, item + rows)
else:
rows = get_display_rows(profile)
before = (rows / 2) - 1
first_item = max(item - before, 0)
last_item = first_item + rows
pofilelen = store.file.getitemslen()
if last_item > pofilelen:
last_item = pofilelen
first_item = max(last_item - rows, 0)
items = get_units(store, first_item, last_item)
return item, first_item, items
def get_header_plural(request, store):
# get plural information from Language model
nplurals = request.translation_project.language.nplurals
plurals = request.translation_project.language.pluralequation
try:
# get plural information from Store
snplurals, splurals = store.file.store.getheaderplural()
if snplurals and snplurals.isdigit():
# file has plural information
#FIXME: should we check if file has correct language headers
nplurals = int(snplurals)
plurals = splurals
except:
# not a POHeader store
pass
return nplurals, plurals
def ensure_trans_plurals(request, store, orig, trans):
nplurals, plurals = get_header_plural(request, store)
if len(orig) > 1:
if len(trans) != nplurals:
# Chop if in case it is too long
trans = trans[:nplurals]
trans.extend([u""] * (nplurals-len(trans)))
return trans
def get_string_array(string):
if isinstance(string, multistring):
return string.strings
else:
return [string or u""]
def fancy_spaces(string):
"""Returns the fancy spaces that are easily visible."""
spaces = string.group()
while spaces[0] in "\t\n\r":
spaces = spaces[1:]
return ' \n' * len(spaces)
def add_fancy_spaces(text):
"""Insert fancy spaces"""
if not text:
return u""
#More than two consecutive:
text = re.sub("[ ]{2,}", fancy_spaces, text)
#At start of string
text = re.sub("^[ ]+", fancy_spaces, text)
#After newline
text = re.sub("\\n([ ]+)", fancy_spaces, text)
#At end of string
text = re.sub("[ ]+$", fancy_spaces, text)
return text
def replace_in_seq(text, *replacements):
if not text:
return u""
for original, replacement in replacements:
text = text.replace(original, replacement)
return text
def escape_text(text, fancyspaces=True, stripescapes=False):
"""Replace special characters &, <, >, add and handle escapes if asked."""
text = replace_in_seq(text,
("&", "&"), # Must be done first!
("<", "<"),
(">", ">"))
if stripescapes:
text = replace_in_seq(text,
("\n", '
'),
("\r", '
'))
else:
fancyescape = lambda escape: \
'%s' % escape
fancy_xml = lambda escape: \
'%s' % escape.group()
text = xml_re.sub(fancy_xml, text)
text = replace_in_seq(text,
("\r\n", fancyescape('\\r\\n') + '
'),
("\n", fancyescape('\\n') + '
'),
("\r", fancyescape('\\r') + '
'),
("\t", fancyescape('\\t')))
text = replace_in_seq(text, ("
", '
\n'))
# we don't need it at the end of the string
if text.endswith("
\n"):
text = text[:-len("
\n")]
if fancyspaces:
text = add_fancy_spaces(text)
return text
def getorigdict(item, orig, editable):
if editable:
focus_class = "translate-original-focus"
else:
focus_class = ""
purefields = []
for pluralid, pluraltext in enumerate(orig):
pureid = "orig-pure%d-%d" % (item, pluralid)
purefields.append({"pureid": pureid, "name": pureid, "value": pluraltext})
origdict = {
"focus_class": focus_class,
"itemid": "orig%d" % item,
"pure": purefields,
"isplural": len(orig) > 1 or None,
"singular_title": _("Singular"),
"plural_title": _("Plural"),
}
if len(orig) > 1:
origdict["singular_text"] = escape_text(orig[0])
origdict["plural_text"] = escape_text(orig[1])
else:
origdict["text"] = escape_text(orig[0])
return origdict
def get_terminology(request, store, item):
try:
term_matcher = request.translation_project.gettermmatcher()
if term_matcher is not None:
return term_matcher.matches(store.file.getitem(item).source)
else:
return []
except:
import logging
import traceback
logging.log(logging.ERROR, traceback.format_exc())
return []
def remove_button_if_no_permission(label, buttons, request):
if label in buttons and not check_permission(label, request):
buttons.remove(label)
def get_trans_buttons(request, translation_project, item, desiredbuttons):
"""gets buttons for actions on translation"""
remove_button_if_no_permission("suggest", desiredbuttons, request)
remove_button_if_no_permission("translate", desiredbuttons, request)
specialchars = translation_project.language.specialchars
return {
"desired": desiredbuttons,
"item": item,
"specialchars": specialchars,
}
def escape_for_textarea(text):
return replace_in_seq(text,
("&", "&"), # Must be done first!
("<", "<"),
(">", ">"),
("\r\n", '\\r\\n'),
("\n", '\\n'),
("\\n", '\\n\n'),
("\t", '\\t'))
def unescape_submition(text):
return replace_in_seq(text,
("\t", ""),
("\n", ""),
("\r", ""),
("\\t", "\t"),
("\\n", "\n"),
("\\r", "\r"))
def get_edit_link(request, store, item):
"""gets a link to edit the given item, if the user has permission"""
if check_permission("translate", request) or check_permission("suggest", request):
return {"href": dispatch.translate(request, store.pootle_path, view_mode='translate',
item=item, match_names=[]),
"linkid": "editlink%d" % item }
else:
return {}
def get_trans_view(request, store, item, trans, textarea=False):
"""returns a widget for viewing the given item's translation"""
if textarea:
escapefunction = escape_for_textarea
else:
escapefunction = escape_text
editlink = get_edit_link(request, store, item)
transdict = {"editlink": editlink}
if len(trans) > 1:
forms = []
for pluralitem, pluraltext in enumerate(trans):
form = {"title": _("Plural Form %d", pluralitem), "n": pluralitem, "text": escapefunction(pluraltext)}
forms.append(form)
transdict["forms"] = forms
elif trans:
transdict["text"] = escapefunction(trans[0])
else:
# Error, problem with plurals perhaps?
transdict["text"] = escapefunction(_("Translation not possible because plural information for your language is not available. Please contact the site administrator."))
transdict["error"] = True
return transdict
def get_trans_edit(request, store, item, trans):
"""returns a widget for editing the given item and translation"""
transdict = { "rows": 5 }
if check_permission("translate", request) or check_permission("suggest", request):
profile = get_profile(request.user)
transdict = { "rows": profile.input_height }
focusbox = ""
if len(trans) > 1:
buttons = get_trans_buttons(request, request.translation_project, item, ["translate", "suggest", "copy", "skip", "back"])
forms = []
for pluralitem, pluraltext in enumerate(trans):
pluralform = _("Plural Form %d", pluralitem)
pluraltext = escape_for_textarea(pluraltext)
textid = "trans%d-%d" % (item, pluralitem)
forms.append({"title": pluralform, "name": textid, "text": pluraltext, "n": pluralitem})
if not focusbox:
focusbox = textid
transdict["forms"] = forms
elif trans:
buttons = get_trans_buttons(request, request.translation_project, item, ["translate", "suggest", "copy", "skip", "back"])
transdict["text"] = escape_for_textarea(trans[0])
textid = "trans%d" % item
focusbox = textid
else:
# Perhaps there is no plural information available
buttons = get_trans_buttons(request, request.translation_project, item, ["skip", "back"])
# l10n: This is an error message that will display if the relevant problem occurs
transdict["text"] = escape_for_textarea(_("Translation not possible because plural information for your language is not available. Please contact the site administrator."))
textid = "trans%d" % item
transdict["error"] = True
focusbox = textid
transdict["focusbox"] = focusbox
else:
# TODO: work out how to handle this (move it up?)
transdict.update(get_trans_view(request, store, item, trans, textarea=True))
buttons = get_trans_buttons(request, request.translation_project, item, ["skip", "back"])
transdict["buttons"] = buttons
return transdict
def highlight_diffs(text, diffs, issrc=True):
"""highlights the differences in diffs in the text.
diffs should be list of diff opcodes
issrc specifies whether to use the src or destination positions in reconstructing the text
this escapes the text on the fly to prevent confusion in escaping the highlighting"""
if issrc:
diffstart = [(i1, 'start', tag) for (tag, i1, i2, j1, j2) in diffs if tag != 'equal']
diffstop = [(i2, 'stop', tag) for (tag, i1, i2, j1, j2) in diffs if tag != 'equal']
else:
diffstart = [(j1, 'start', tag) for (tag, i1, i2, j1, j2) in diffs if tag != 'equal']
diffstop = [(j2, 'stop', tag) for (tag, i1, i2, j1, j2) in diffs if tag != 'equal']
diffswitches = diffstart + diffstop
diffswitches.sort()
textdiff = ""
textnest = 0
textpos = 0
spanempty = False
for i, switch, tag in diffswitches:
textsection = escape_text(text[textpos:i], fancyspaces=False)
textdiff += textsection
if textsection:
spanempty = False
if switch == 'start':
textnest += 1
elif switch == 'stop':
textnest -= 1
if switch == 'start' and textnest == 1:
# start of a textition
textdiff += "" % tag
spanempty = True
elif switch == 'stop' and textnest == 0:
# start of an equals block
if spanempty:
# FIXME: work out why kid swallows empty spans, and browsers display them horribly, then remove this
textdiff += "()"
textdiff += ""
textpos = i
textdiff += escape_text(text[textpos:], fancyspaces=False)
return textdiff
def get_diff_codes(cmp1, cmp2):
"""compares the two strings and returns opcodes"""
return difflib.SequenceMatcher(None, cmp1, cmp2).get_opcodes()
def get_trans_review(request, store, item, trans, suggestions):
"""returns a widget for reviewing the given item's suggestions"""
hasplurals = len(trans) > 1
diffcodes = {}
for pluralitem, pluraltrans in enumerate(trans):
if isinstance(pluraltrans, str):
trans[pluralitem] = pluraltrans.decode("utf-8")
for suggestion in suggestions:
for pluralitem, pluralsugg in enumerate(suggestion):
if isinstance(pluralsugg, str):
suggestion[pluralitem] = pluralsugg.decode("utf-8")
forms = []
for pluralitem, pluraltrans in enumerate(trans):
pluraldiffcodes = [get_diff_codes(pluraltrans, suggestion[pluralitem]) for suggestion in suggestions]
diffcodes[pluralitem] = pluraldiffcodes
combineddiffs = reduce(list.__add__, pluraldiffcodes, [])
transdiff = highlight_diffs(pluraltrans, combineddiffs, issrc=True)
form = {"n": pluralitem, "diff": transdiff, "title": None}
if hasplurals:
pluralform = _("Plural Form %d", pluralitem)
form["title"] = pluralform
forms.append(form)
transdict = {
"current_title": _("Current Translation:"),
"editlink": get_edit_link(request, store, item),
"forms": forms,
"isplural": hasplurals or None,
"itemid": "trans%d" % item,
}
suggitems = []
for suggid, msgstr in enumerate(suggestions):
suggestedby = store.getsuggester(item, suggid)
if len(suggestions) > 1:
if suggestedby:
# l10n: First parameter: number
# l10n: Second parameter: name of translator
suggtitle = _("Suggestion %(suggid)d by %(user)s:", {"suggid": (suggid+1), "user": suggestedby})
else:
suggtitle = _("Suggestion %d:", (suggid+1))
else:
if suggestedby:
# l10n: parameter: name of translator
suggtitle = _("Suggestion by %s:", suggestedby)
else:
suggtitle = _("Suggestion:")
forms = []
for pluralitem, pluraltrans in enumerate(trans):
pluralsuggestion = msgstr[pluralitem]
suggdiffcodes = diffcodes[pluralitem][suggid]
suggdiff = highlight_diffs(pluralsuggestion, suggdiffcodes, issrc=False)
if isinstance(pluralsuggestion, str):
pluralsuggestion = pluralsuggestion.decode("utf8")
form = {"diff": suggdiff}
form["suggid"] = "suggest%d-%d-%d" % (item, suggid, pluralitem)
form["value"] = pluralsuggestion
if hasplurals:
form["title"] = _("Plural Form %d", pluralitem)
forms.append(form)
suggdict = {
"title": suggtitle,
"author": suggestedby,
"forms": forms,
"suggid": "%d-%d" % (item, suggid),
"back": None,
"skip": None,
}
suggitems.append(suggdict)
# l10n: Button that takes the user to the previous unit or page
backbutton = {"item": item, "text": _("Back")}
skipbutton = {"item": item, "text": _("Skip")}
if suggitems:
suggitems[-1]["back"] = backbutton
suggitems[-1]["skip"] = skipbutton
transdict["suggtext"] = ungettext("%d suggestion",
"%d suggestions",
len(suggitems), len(suggitems))
else:
transdict["back"] = backbutton
transdict["skip"] = skipbutton
transdict["suggestions"] = suggitems
return transdict
def get_translated_directory(target_language_code, root_directory, directory):
if directory.parent != root_directory:
translated_directory = get_translated_directory(target_language_code,
root_directory,
directory.parent)
return translated_directory.child_dirs.get(name=directory.name)
else:
return root_directory.child_dirs.get(name=target_language_code)
def get_translated_store(alt_project, store):
"""returns the file corresponding to store in the alternative TranslationProject"""
try:
translation_directory = get_translated_directory(alt_project.language.code,
Directory.objects.root,
store.parent)
if alt_project.project.get_treestyle() == 'gnu':
name = alt_project.language.code + os.extsep + alt_project.project.localfiletype
else:
name = store.name
try:
return translation_directory.child_stores.get(name=name)
except Store.DoesNotExist:
return None
except Directory.DoesNotExist:
return None
def get_alt_src_dict(request, store, unit, alt_project):
alt_src_dict = {"available": False}
# TODO: handle plurals !!
if alt_project is not None:
#FIXME: we should bail out if alternative language == target language
language = alt_project.language
alt_src_dict.update({
"languagename": language.fullname,
"languagecode": language.code,
"dir": language_dir(language.code),
"title": tr_lang(language.fullname),
"available": True })
translated_store = get_translated_store(alt_project, store)
if translated_store is not None:
translated_store.file.store.require_index()
translated_unit = translated_store.file.store.findunit(unit.source)
if translated_unit is not None and translated_unit.istranslated():
if unit.hasplural():
unit_dict = {
"forms": [{"title": _("Plural Form %d", i),
"n": i,
"text": escape_text(text)}
for i, text in enumerate(translated_unit.target.strings)],
"isplural": True }
else:
unit_dict = {
"text": escape_text(translated_unit.target),
"isplural": False }
alt_src_dict.update(unit_dict)
else:
alt_src_dict["available"] = False
else:
alt_src_dict["available"] = False
return alt_src_dict
def get_alt_src_list(request, store, unit):
return [get_alt_src_dict(request, store, unit, alt_project)
for alt_project in get_alt_projects(request)]
def make_table(request, profile, store, item):
editable, first_item, translations = get_translations(request, profile, store, item)
state = dispatch.TranslatePageState(request.GET)
items = []
suggestions = {}
if (state.view_mode in ('review', 'translate')):
suggestions = {item: store.getsuggestions(item)}
for row, unit in enumerate(translations):
tmsuggestions = []
orig = get_string_array(unit.source)
trans = ensure_trans_plurals(request, store, orig, get_string_array(unit.target))
item = first_item + row
origdict = getorigdict(item, orig, item == editable)
transmerge = {}
suggestions[item] = store.getsuggestions(item)
message_context = ""
if item == editable:
translator_comments = unit.getnotes(origin="translator")
developer_comments = urlize(escape_text(unit.getnotes(origin="developer"), stripescapes=True))
locations = " ".join(unit.getlocations())
if isinstance(unit, po.pounit):
message_context = "".join(unit.getcontext())
tmsuggestions = store.gettmsuggestions(item)
tmsuggestions.extend(get_terminology(request, store, item))
transmerge = get_trans_edit(request, store, item, trans)
else:
translator_comments = unit.getnotes(origin="translator")
developer_comments = unit.getnotes(origin="developer")
locations = ""
transmerge = get_trans_view(request, store, item, trans)
itemsuggestions = []
for suggestion in suggestions[item]:
if suggestion.hasplural():
itemsuggestions.append(suggestion.target.strings)
else:
itemsuggestions.append([suggestion.target])
transreview = get_trans_review(request, store, item, trans, itemsuggestions)
if 'forms' in transmerge.keys():
for fnum in range(len(transmerge['forms'])):
transreview['forms'][fnum].update(transmerge['forms'][fnum])
elif 'text' in transmerge and not transmerge.get('error', False):
transreview['forms'][0]['text'] = transmerge['text']
transmerge.update(transreview)
transdict = {
"itemid": "trans%d" % item,
"focus_class": origdict["focus_class"],
"isplural": len(trans) > 1,
}
transdict.update(transmerge)
polarity = oddoreven(item)
if item == editable:
focus_class = "translate-focus"
else:
focus_class = ""
state_class = ""
fuzzy = None
if unit.isfuzzy():
state_class += "translate-translation-fuzzy"
fuzzy = "checked"
hassuggestion = len(transdict.get("suggestions", {})) > 0
itemdict = {
"itemid": item,
"orig": origdict,
"trans": transdict,
"polarity": polarity,
"focus_class": focus_class,
"editable": item == editable,
"state_class": state_class,
"fuzzy": fuzzy,
"translator_comments": translator_comments,
"developer_comments": developer_comments,
"locations": locations,
"message_context": message_context,
"tm": tmsuggestions,
"hassuggestion": hassuggestion
}
itemdict["altsrcs"] = []
# do we have enabled alternative source language?
if settings.ENABLE_ALT_SRC:
# get alternate source project information in a dictionary
if item == editable:
itemdict["altsrcs"] = get_alt_src_list(request, store, unit)
items.append(itemdict)
return items, translations, first_item
keymatcher = re.compile("(\D+)([0-9\-]+)")
def parsekey(key):
match = keymatcher.match(key)
if match:
keytype, itemcode = match.groups()
return keytype, itemcode
return None, None
def dashsplit(item):
dashcount = item.count("-")
if dashcount == 2:
item, dashitem, subdashitem = item.split("-", 2)
return int(item), int(dashitem), int(subdashitem)
elif dashcount == 1:
item, dashitem = item.split("-", 1)
return int(item), int(dashitem), None
else:
return int(item), None, None
def handle_skips(last_item, skips):
for item in skips:
last_item = item
return last_item
def handle_backs(last_item, backs):
for item in backs:
last_item = item
return last_item
def handle_suggestions(last_item, request, store, submitsuggests, skips, translations):
for item in submitsuggests:
if item in skips or item not in translations:
continue
value = translations[item]
unit_update.suggest_translation(store, item, value, request)
last_item = item
return last_item
def handle_submits(last_item, request, store, submits, skips, translations, comments, fuzzies):
validation_error = {}
for item in submits:
if item in skips or item not in translations:
continue
newvalues = {}
newvalues["target"] = translations[item]
if isinstance(newvalues["target"], dict) and len(newvalues["target"]) == 1 and 0 in newvalues["target"]:
newvalues["target"] = newvalues["target"][0]
newvalues["fuzzy"] = False
if (fuzzies.get(item) == u'on'):
newvalues["fuzzy"] = True
translator_comments = comments.get(item)
if translator_comments:
newvalues["translator_comments"] = translator_comments
try:
unit_update.update_translation(store, item, newvalues, request)
except gettextpo.error:
validation_error = _("Gettext validation error: %s") % (sys.exc_info()[1])
last_item = item
return last_item, validation_error
def process_post(request, store):
"""receive any translations submitted by the user"""
post_dict = request.POST.copy()
backs = []
skips = []
submitsuggests = []
submits = []
translations = {}
suggestions = {}
comments = {}
fuzzies = {}
delkeys = []
for key, value in post_dict.iteritems():
keytype, item = parsekey(key)
if keytype is None:
continue
try:
item, dashitem, subdashitem = dashsplit(item)
except:
continue
if keytype == "skip":
skips.append(item)
elif keytype == "back":
backs.append(item)
elif keytype == "submitsuggest":
submitsuggests.append(item)
elif keytype == "submit":
submits.append(item)
elif keytype == "translator_comments":
# We need to remove carriage returns from the input.
value = value.replace("\r", "")
comments[item] = value
elif keytype == "fuzzy":
fuzzies[item] = value
elif keytype == "trans":
value = unescape_submition(value)
if dashitem is not None:
translations.setdefault(item, {})[dashitem] = value
else:
translations[item] = value
elif keytype == "suggest":
suggestions.setdefault((item, dashitem), {})[subdashitem] = value
elif keytype == "orig-pure":
# this is just to remove the hidden fields from the argdict
pass
else:
continue
delkeys.append(key)
for key in delkeys:
del post_dict[key]
prev_last_item = handle_backs(-1, backs)
last_item = handle_skips(-1, skips)
last_item = handle_suggestions(last_item, request, store, submitsuggests, skips, translations)
last_item, validation_error = handle_submits(last_item, request, store, submits, skips, translations, comments, fuzzies)
return prev_last_item, last_item, validation_error
def process_post_main(store_name, item, request, next_store_item, prev_store_item):
store = Store.objects.get(pootle_path=store_name)
request.translation_project.indexer # Force initialization of the indexer
prev_item, next_item, validation_error = process_post(request, store)
if len(validation_error) > 0:
if prev_item > -1:
prev_item = prev_item - 1
if next_item > -1:
next_item = next_item - 1
search = search_forms.search_from_request(request)
if next_item > -1:
ret = next_store_item(search, store_name, next_item + 1)
return ret[0], ret[1], validation_error
elif prev_item > -1:
ret = prev_store_item(search, store_name, prev_item - 1)
return ret[0], ret[1], validation_error
else:
return store, item, validation_error
def get_position(request, next_store_item, prev_store_item):
state = dispatch.TranslatePageState(request.GET)
store_name = dispatch.get_store(request)
item = state.item
validation_error = {}
if request.method == 'POST':
if 'new_search' in request.POST:
ret = next_store_item(search_forms.search_from_request(request), store_name, item)
return ret[0], ret[1], validation_error
else:
return process_post_main(store_name, item, request, next_store_item, prev_store_item)
else:
ret = next_store_item(search_forms.search_from_request(request), store_name, item)
return ret[0], ret[1], validation_error
def get_failure_message(request):
# We are reviewing a check
if 'match_names' in request.GET:
if request.GET['match_names'] == u'check-isfuzzy,untranslated':
return _("End of Quick Translate.")
else:
return _("End of Quality Check Review.")
# This is a search
if 'new_search' in request.POST and 'store' not in request.POST:
return _("No file matched your query.")
return _("End of results.")
def find_and_display(request, directory, next_store_item, prev_store_item):
try:
store, item, validation_error = get_position(request, next_store_item, prev_store_item)
return view(request, directory, store, item, validation_error = validation_error)
except StopIteration:
return view(request, directory, None, 0, get_failure_message(request))
def view(request, directory, store, item, stopped_by=None, validation_error={}):
"""the page which lets people edit translations"""
state = dispatch.TranslatePageState(request.GET)
if not check_permission("view", request):
raise PermissionDenied(_('You do not have rights to access view mode.'))
if store is not None:
formaction = dispatch.translate(request, request.path_info, store=store.pootle_path, item=0)
store_path = store.pootle_path
else:
formaction = ''
store_path = ''
if stopped_by is not None:
notice = stopped_by
else:
notice = {}
profile = get_profile(request.user)
translation_project = request.translation_project
language = translation_project.language
project = translation_project.project
if store is not None:
items, translations, first_item = make_table(request, profile, store, item)
navbar = navbar_dict.make_store_navbar_dict(request, store)
else:
items, translations, first_item = [], [], -1
navbar = navbar_dict.make_directory_navbar_dict(request, directory, links_required='translate')
pagelinks = None
rows, icon = get_rows_and_icon(request, profile)
navbar["icon"] = icon
if store is not None:
postats = store.getquickstats()
untranslated, fuzzy = postats["total"] - postats["translated"], postats["fuzzy"]
translated, total = postats["translated"], postats["total"]
pagelinks = get_page_links(request, store, rows, translations, item, first_item)
# templatising
instancetitle = _(settings.TITLE)
language_data = {"code": pagelayout.weblanguage(language.code),
"name": language.fullname,
"dir": language_dir(language.code)}
templatevars = {
"title_path": store_path,
"project": {"code": project.code,
"name": project.fullname},
"language": language_data,
"store": store_path,
# navigation bar
"navitems": [navbar],
"pagelinks": pagelinks,
# translation form
"actionurl": formaction,
"notice": notice,
"validationerror": validation_error,
# l10n: Heading above the table column with the source language
"original_title": _("Original"),
# l10n: Heading above the table column with the target language
"translation_title": _("Translation"),
"items": items,
"reviewmode": state.view_mode == 'review',
"accept_title": _("Accept suggestion"),
"reject_title": _("Reject suggestion"),
"fuzzytext": _("Fuzzy"),
# l10n: Heading above the textarea for translator comments.
"translator_comments_title": _("Translator Comments"),
# l10n: Heading above the comments extracted from the programing source code
"developer_comments_title": _("Developer Comments"),
# l10n: This heading refers to related translations and terminology
"related_title": _("Related"),
'search': search_forms.get_search_form(request),
# general vars
"instancetitle": instancetitle,
"permissions": request.permissions,
"canedit": check_permission("translate", request) or check_permission("suggest", request),
"cantranslate": check_permission("translate", request),
"cansuggest": check_permission("suggest", request),
"canreview": check_permission("review", request),
# l10n: Button label
"accept_button": _("Accept"),
# l10n: Button label
"reject_button": _("Reject")
}
templatevars.update(add_file_links(request, store))
return render_to_response("language/translatepage.html", templatevars, RequestContext(request))