translator: better support for ambiguous translations

The translator picks "the first" translation by default, but the user can
choose among the generated translations from a popup menu.
This commit is contained in:
hallgren
2012-05-28 16:42:02 +00:00
parent b19ae37d9c
commit 9e34a7f7fa
3 changed files with 64 additions and 34 deletions

View File

@@ -20,7 +20,8 @@ of segments that are translated independently. The user can add segments
in the source language and obtain automatically translated segments in
the target language. If an unsatisfactory automatic translation is
obtained, the user can click on it and replace it with a manual translation.
If multiple translations are obtained, one of them is shown by default and
the other ones are available in a popup menu.
<p>
The GF web service is used for automatic translation. The user picks which
grammar to use from a menu of available grammars. Through menu options,
@@ -51,7 +52,7 @@ closed and reopened later.
<hr>
<div class=modtime><small>
<!-- hhmts start --> Last modified: Sun May 27 17:56:48 CEST 2012 <!-- hhmts end -->
<!-- hhmts start --> Last modified: Mon May 28 18:36:10 CEST 2012 <!-- hhmts end -->
</small></div>
<address>
<a href="http://www.cse.chalmers.se/~hallgren/">TH</a>

View File

@@ -7,7 +7,7 @@ div.pagehead { font-family: sans-serif;
background-color: #ccc;
}
table.menubar td { padding: 5px; }
table.menubar dl, td.options > div > dl {
table.menubar dl, td.options > div > dl, dl.popupmenu {
z-index: 1;
display: none; position: absolute;
background: white; color: black;
@@ -15,10 +15,12 @@ table.menubar dl, td.options > div > dl {
margin: 0;
box-shadow: 5px 5px 5px rgba(0,0,0,0.25);
}
table.menubar td:hover > dl { display: block; }
table.menubar dt { margin: 0; padding: 5px; }
table.menubar td:hover > dl, :hover > dl.popupmenu { display: block; }
table.menubar dt, dl.popupmenu > dt { margin: 0; padding: 5px; }
table.submenu dt { padding: 0; }
table.menubar td:hover, table.menubar dt:hover { background-color: #36f; color: white; }
table.menubar td:hover, table.menubar dt:hover, dl.popupmenu > dt:hover {
background-color: #36f; color: white;
}
table table dl { left: 6em; }
table.menubar dt { white-space: nowrap; }
div.document {
@@ -61,3 +63,4 @@ div.document form { width: 100%; }
span.arrow { color: blue; }
span.error { color: red; }
span.choices { color: blue; font-weight: bold; font-family: sans-serif; }

View File

@@ -80,16 +80,19 @@ Translator.prototype.update_translations=function() {
ts[i].appendChild(text(segment.target+" "))
}
}
function upd3(txt) {
segment.target=txt;
function upd3(txts) {
segment.target=txts[0];
segment.options={method:o.method,from:o.from,to:o.to} // no sharing!
if(txts.length>1) segment.choices=txts
else delete segment.choices
replace()
}
function upd2(ts) {
function unlex(txt,cont) { gfshell('ps -unlextext "'+txt+'"',cont) }
switch(ts.length) {
case 1: gfshell('ps -unlextext "'+ts[0]+'"',upd3); break;
case 0: upd3("[no translation]");break;
default: upd3("[ambiguous translation]")
case 0: upd3(["[no translation]"]);break;
default: mapc(unlex,ts,upd3); break;
}
}
function upd1(translate_output) {
@@ -310,35 +313,46 @@ Translator.prototype.remove=function(el) {
setTimeout(rm,100)
}
Translator.prototype.edit_translation=function(i) {
var t=this
var ds=t.drawing.segments
function replace_segment(sd) {
Translator.prototype.replace_segment=function(i,sd) {
var t=this;
var ds=t.drawing.segments;
if(ds) {
var old=ds[i]
ds[i]=sd
replaceNode(sd,old)
}
}
function edit_segment(s) {
function restore() { replace_segment(t.draw_segment(s,i)) }
function done() {
s.options.method="Manual"
s.options.from=t.document.options.from
s.options.to=t.document.options.to
s.target=inp.value // side effect, updating the document in-place
restore();
return false;
}
var inp=node("input",{name:"it",value:s.target})
var e=wrap("form",[inp, submit(), button("Cancel",restore)])
var target=wrap_class("td","target",e)
var edit=t.draw_segment_given_target(s,target)
replace_segment(edit)
e.onsubmit=done
inp.focus();
Translator.prototype.pick_translation=function(i,txt) {
var t=this
var s=t.document.segments[i]
s.options.method="Manual"
s.target=txt // side effect, updating the document in-place
t.replace_segment(i,t.draw_segment(s,i))
}
Translator.prototype.edit_translation=function(i) {
var t=this
var s=t.document.segments[i]
function restore() { t.replace_segment(i,t.draw_segment(s,i)) }
function done() {
s.options.method="Manual"
s.options.from=t.document.options.from
s.options.to=t.document.options.to
s.target=inp.value // side effect, updating the document in-place
restore();
return false;
}
edit_segment(t.document.segments[i])
var inp=node("input",{name:"it",value:s.target})
var e=wrap("form",[inp, submit(), button("Cancel",restore)])
var target=wrap_class("td","target",e)
var edit=t.draw_segment_given_target(s,target)
t.replace_segment(i,edit)
e.onsubmit=done
inp.focus();
}
function hide_menu(el) {
@@ -405,10 +419,22 @@ Translator.prototype.draw_segment=function(s,i) {
if(opt.from!=dopt.from || opt.to!=dopt.to) txt=span_class("error",txt)
var target=wrap_class("td","target",txt)
function edit() { t.edit_translation(i) }
function pick(txt) { t.pick_translation(i,txt) }
target.onclick=edit
if(s.choices) appendChildren(target,draw_choices(s.choices,pick))
return t.draw_segment_given_target(s,target)
}
function draw_choices(txts,onclick) {
function opt(txt) {
var o=dt(text(txt))
o.onclick=function(ev) { ev.stopPropagation(); onclick(txt) }
return o
}
return [span_class("choices",text("+")),
wrap_class("dl","popupmenu",map(opt,txts))]
}
Translator.prototype.draw_segment_given_target=function(s,target) {
var t=this