2 # -*- coding: utf-8 -*-
4 # Copyright 2006 Zuza Software Foundation
6 # This file is part of translate.
8 # translate is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 """Server program to serve messages over XML-RPC
25 As this is implemented using the base classes (see storage.base), the
26 work is minimal to use this with any storage format that is implemented
27 using the base classes. Strictly speaking, only an init... function needs
30 from translate
.convert
import convert
31 from translate
.storage
import tbx
32 from translate
.storage
import tmx
33 from translate
.storage
import po
34 from translate
.storage
import csvl10n
35 from translate
.search
import match
36 from translate
.misc
.multistring
import multistring
38 from SimpleXMLRPCServer
import SimpleXMLRPCServer
39 from SimpleXMLRPCServer
import SimpleXMLRPCRequestHandler
41 class lookupRequestHandler(SimpleXMLRPCRequestHandler
):
42 """Sets up the requested file for parsing"""
43 #TODO: Parse request to see if tbx/tmx is requested,
44 # or perhaps the url can specify the file to be queried
46 class lookupServer(SimpleXMLRPCServer
):
47 def __init__(self
, addr
, storage
):
48 """Loads the initial tbx file from the given filename"""
49 SimpleXMLRPCServer
.__init
__(self
, addr
, requestHandler
=lookupRequestHandler
, logRequests
=1)
50 self
.storage
= storage
51 self
.storage
.makeindex()
52 self
.matcher
= match
.matcher(storage
)
53 print "Performing lookup from %d units" % len(storage
.units
)
54 print "Translation memory using %d units" % len(self
.matcher
.candidates
.units
)
56 def _dispatch(self
, method
, params
):
58 # All public methods must be prefixed with 'public_' so no
59 # internal methods are callable.
60 func
= getattr(self
, 'public_' + method
)
61 except AttributeError:
62 raise Exception('no method called "%s"' % method
)
70 def internal_lookup(self
, message
):
71 """Could perhaps include some intelligence in future, like case trying with different casing, etc."""
72 message
= message
.strip()
75 if not isinstance(message
, unicode):
76 message
= unicode(message
)
78 unit
= self
.storage
.findunit(message
)
83 def public_lookup(self
, message
):
84 """Returns the source string of whatever was found. Keep in mind that this might not be what you want."""
85 unit
= self
.internal_lookup(message
)
91 def public_translate(self
, message
):
92 """Translates the message from the storage and returns a plain string"""
93 unit
= self
.internal_lookup(message
)
94 if unit
and unit
.target
:
99 def public_matches(self
, message
, max_candidates
=15, min_similarity
=50):
100 """Returns matches from the storage with the associated similarity"""
101 self
.matcher
.setparameters(max_candidates
=max_candidates
, min_similarity
=min_similarity
)
102 if not isinstance(message
, unicode):
103 message
= unicode(message
)
104 candidates
= self
.matcher
.matches(message
)
105 clean_candidates
= []
106 for unit
in candidates
:
107 score
= unit
.getnotes()
108 original
= unit
.source
109 translation
= unit
.target
111 # We might have gotten multistrings, so just convert them for now
112 if isinstance(original
, multistring
):
113 original
= unicode(original
)
114 if isinstance(translation
, multistring
):
115 translation
= unicode(translation
)
116 clean_candidates
+= [(score
, original
, translation
)]
117 return clean_candidates
119 class lookupOptionParser(convert
.ConvertOptionParser
):
120 """Parser that calls instantiates the lookupServer"""
122 """parses arguments and instantiates the server"""
123 (options
, args
) = self
.parse_args()
124 options
.inputformats
= self
.inputformats
125 self
.usepsyco(options
)
126 inputbase
, inputext
= self
.splitinputext(options
.input)
127 asdf
, storagebuilder
= self
.outputoptions
[inputext
, None]
128 storage
= storagebuilder(open(options
.input))
129 server
= lookupServer((options
.address
, int(options
.port
)), storage
)
131 server
.serve_forever()
133 server
.server_close()
135 def inittbx(inputfile
, columnorder
=None):
136 return tbx
.tbxfile(inputfile
)
138 def inittmx(inputfile
, columnorder
=None):
139 return tmx
.tmxfile(inputfile
)
141 def initpo(inputfile
, columnorder
=None):
142 return po
.pofile(inputfile
)
144 def initcsv(inputfile
, columnorder
=None):
145 return csvl10n
.csvfile(inputfile
, columnorder
)
148 formats
= {"tbx": (None, inittbx
), "tmx": (None, inittmx
), "po": (None, initpo
), "csv": (None, initcsv
)}
149 parser
= lookupOptionParser(formats
, usepots
=False, description
=__doc__
)
150 parser
.add_option("-a", "--address", dest
="address", default
="localhost",
151 help="the host to bind to")
152 parser
.add_option("-p", "--port", dest
="port", default
=1234,
153 help="the port to listen on")
154 parser
.add_option("-l", "--language", dest
="targetlanguage", default
=None,
155 help="set target language code", metavar
="LANG")
156 parser
.add_option("", "--source-language", dest
="sourcelanguage", default
='en',
157 help="set source language code", metavar
="LANG")
158 parser
.remove_option("--output")
159 parser
.remove_option("--exclude")
160 parser
.passthrough
.append("sourcelanguage")
161 parser
.passthrough
.append("targetlanguage")
162 parser
.add_option("", "--columnorder", dest
="columnorder", default
=None,
163 help="specify the order and position of columns for CSV (comment,source,target)")
164 parser
.passthrough
.append("columnorder")
167 if __name__
== '__main__':