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 in the source language and obtain automatically translated segments in
the target language. If an unsatisfactory automatic translation is the target language. If an unsatisfactory automatic translation is
obtained, the user can click on it and replace it with a manual translation. 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> <p>
The GF web service is used for automatic translation. The user picks which 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, grammar to use from a menu of available grammars. Through menu options,
@@ -51,7 +52,7 @@ closed and reopened later.
<hr> <hr>
<div class=modtime><small> <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> </small></div>
<address> <address>
<a href="http://www.cse.chalmers.se/~hallgren/">TH</a> <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; background-color: #ccc;
} }
table.menubar td { padding: 5px; } table.menubar td { padding: 5px; }
table.menubar dl, td.options > div > dl { table.menubar dl, td.options > div > dl, dl.popupmenu {
z-index: 1; z-index: 1;
display: none; position: absolute; display: none; position: absolute;
background: white; color: black; background: white; color: black;
@@ -15,10 +15,12 @@ table.menubar dl, td.options > div > dl {
margin: 0; margin: 0;
box-shadow: 5px 5px 5px rgba(0,0,0,0.25); box-shadow: 5px 5px 5px rgba(0,0,0,0.25);
} }
table.menubar td:hover > dl { display: block; } table.menubar td:hover > dl, :hover > dl.popupmenu { display: block; }
table.menubar dt { margin: 0; padding: 5px; } table.menubar dt, dl.popupmenu > dt { margin: 0; padding: 5px; }
table.submenu dt { padding: 0; } 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 table dl { left: 6em; }
table.menubar dt { white-space: nowrap; } table.menubar dt { white-space: nowrap; }
div.document { div.document {
@@ -61,3 +63,4 @@ div.document form { width: 100%; }
span.arrow { color: blue; } span.arrow { color: blue; }
span.error { color: red; } 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+" ")) ts[i].appendChild(text(segment.target+" "))
} }
} }
function upd3(txt) { function upd3(txts) {
segment.target=txt; segment.target=txts[0];
segment.options={method:o.method,from:o.from,to:o.to} // no sharing! 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() replace()
} }
function upd2(ts) { function upd2(ts) {
function unlex(txt,cont) { gfshell('ps -unlextext "'+txt+'"',cont) }
switch(ts.length) { switch(ts.length) {
case 1: gfshell('ps -unlextext "'+ts[0]+'"',upd3); break; case 0: upd3(["[no translation]"]);break;
case 0: upd3("[no translation]");break; default: mapc(unlex,ts,upd3); break;
default: upd3("[ambiguous translation]")
} }
} }
function upd1(translate_output) { function upd1(translate_output) {
@@ -310,35 +313,46 @@ Translator.prototype.remove=function(el) {
setTimeout(rm,100) setTimeout(rm,100)
} }
Translator.prototype.edit_translation=function(i) { Translator.prototype.replace_segment=function(i,sd) {
var t=this var t=this;
var ds=t.drawing.segments var ds=t.drawing.segments;
function replace_segment(sd) { if(ds) {
var old=ds[i] var old=ds[i]
ds[i]=sd ds[i]=sd
replaceNode(sd,old) replaceNode(sd,old)
} }
}
function edit_segment(s) { Translator.prototype.pick_translation=function(i,txt) {
function restore() { replace_segment(t.draw_segment(s,i)) } var t=this
function done() { var s=t.document.segments[i]
s.options.method="Manual" s.options.method="Manual"
s.options.from=t.document.options.from s.target=txt // side effect, updating the document in-place
s.options.to=t.document.options.to t.replace_segment(i,t.draw_segment(s,i))
s.target=inp.value // side effect, updating the document in-place }
restore();
return false; Translator.prototype.edit_translation=function(i) {
} var t=this
var inp=node("input",{name:"it",value:s.target}) var s=t.document.segments[i]
var e=wrap("form",[inp, submit(), button("Cancel",restore)])
var target=wrap_class("td","target",e) function restore() { t.replace_segment(i,t.draw_segment(s,i)) }
var edit=t.draw_segment_given_target(s,target) function done() {
replace_segment(edit) s.options.method="Manual"
e.onsubmit=done s.options.from=t.document.options.from
inp.focus(); 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) { 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) if(opt.from!=dopt.from || opt.to!=dopt.to) txt=span_class("error",txt)
var target=wrap_class("td","target",txt) var target=wrap_class("td","target",txt)
function edit() { t.edit_translation(i) } function edit() { t.edit_translation(i) }
function pick(txt) { t.pick_translation(i,txt) }
target.onclick=edit target.onclick=edit
if(s.choices) appendChildren(target,draw_choices(s.choices,pick))
return t.draw_segment_given_target(s,target) 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) { Translator.prototype.draw_segment_given_target=function(s,target) {
var t=this var t=this