LibreOffice plugin to pipe whole Writer documents through Google Translate, that ought to keep most of the page formatting.

⌈⌋ ⎇ branch:  PageTranslate


Check-in [d4530cf627]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Reenable cursor/selection mode (Tradutor trigger). Prepare binding to Draw documents.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d4530cf627811d47a234fe88771dc33f8fb1483f
User & Date: mario 2020-05-03 14:53:53
Context
2020-05-03
19:02
More langauge options in Extra> menu, explicit support for paragraph/system language targets; to unify option handling for textselection method. check-in: 4e60f20156 user: mario tags: trunk
14:53
Reenable cursor/selection mode (Tradutor trigger). Prepare binding to Draw documents. check-in: d4530cf627 user: mario tags: trunk
00:09
Crude table translation via Cell-wise .getText.getString/setString (which obviously strips all formatting/linebreaks) check-in: 4dba4de60d user: mario tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to description.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version='1.0' encoding='UTF-8'?>
<description
 xmlns="http://openoffice.org/extensions/description/2006"
 xmlns:dep="http://openoffice.org/extensions/description/2006"
 xmlns:xlink="http://www.w3.org/1999/xlink">
	<identifier value="vnd.include-once.pagetranslate"/>
	<version value="0.5"/>
	  <display-name>
        <name lang="en">PageTranslate</name>
    </display-name>
	
	<dependencies>
		<OpenOffice.org-minimal-version value="3.0" dep:name="OpenOffice.org 3.0"/>
	</dependencies>
	<registration>
	<simple-license  accept-by="admin" default-license-id="en" suppress-on-update="true" >
			<license-text xlink:href="registration/lgpl-en.txt" lang="en" license-id="en" />
	</simple-license>
	</registration>
	<publisher>                                                          
		<name xlink:href="mailto:milky@users.sf.net" lang="en">Mario</name>
	</publisher>
</description>






|








|
|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version='1.0' encoding='UTF-8'?>
<description
 xmlns="http://openoffice.org/extensions/description/2006"
 xmlns:dep="http://openoffice.org/extensions/description/2006"
 xmlns:xlink="http://www.w3.org/1999/xlink">
	<identifier value="vnd.include-once.pagetranslate"/>
	<version value="0.7"/>
	  <display-name>
        <name lang="en">PageTranslate</name>
    </display-name>
	
	<dependencies>
		<OpenOffice.org-minimal-version value="3.0" dep:name="OpenOffice.org 3.0"/>
	</dependencies>
	<registration>
	<simple-license  accept-by="admin" default-license-id="en" suppress-on-update="true" suppress-if-required="true" >
		<license-text xlink:href="registration/lgpl-en.txt" lang="en" license-id="en" />
	</simple-license>
	</registration>
	<publisher>                                                          
		<name xlink:href="mailto:milky@users.sf.net" lang="en">Mario</name>
	</publisher>
</description>

Added off/contentxmltrans.py.













































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/python
# encoding: utf-8
# api: cli
# type: main
# category: transform
# title: PageTranslate
# description: rewrite content.xml from Draw document
# version: 0.6
# state: experimental
# author: mario
# license: GNU LGPL 2.1
# config: -
# 
# Rewrite text nodes from Draw content.xml document
#


# OpenOffice UNO bridge
None
# sys modules
import string
import json
import sys
from traceback import format_exc
# http preparations
import urllib
from urllib2 import urlopen, Request
from six.moves.urllib.parse import urlencode, quote, quote_plus
ssl_args = dict()
if sys.platform != 'win32':
    import ssl
    myssl = ssl.create_default_context();
    myssl.check_hostname = False
    myssl.verify_mode = ssl.CERT_NONE
    ssl_args["context"] = myssl
http_headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux; LibreOffice/6.3; TradutorLibreText/1.3+PageTranslate/0.5)"
}
# log file
import logging
logging.basicConfig(filename='/tmp/pagetranslate-libreoffice.log', level=logging.DEBUG)
# regex
import re
rx_xmltrans = re.compile('(<text:span[^>]+>)([\w\s,.]+)(?=</text)', re.S|re.UNICODE)
rx_gtrans = re.compile('class="t0">(.+?)</div>', re.S)
rx_splitpara = re.compile("(.{1,1895\.}|.{1,1900}\s|.*$)", re.S)
rx_empty = re.compile("^[\s\d,.:;§():-]+$")
rx_letters = re.compile("\w\w+", re.UNICODE)





# cli tool
class pagetranslate:


    def __init__(self, ctx):
        try:
            xml = open("content.xml", "r").read().decode("utf-8")
            xml = re.sub(rx_xmltrans, self.repl, xml)
            open("content.en.xml", "w").write(xml.encode("utf-8"))
        except Exception as e:
            print(format_exc(e))

    # re.sub callback
    def repl(self, parts):
        parts = [parts.group(1), parts.group(2)]
        parts[1] = self.translate(parts[1])
        print(repr(parts))
        return "".join(parts)

    # request text translation from google
    def askgoogle(self, text, dst_lang="en", src_lang='auto'):
        # fetch translation page
        url = "http://translate.google.com/m?hl=%s&sl=%s&q=%s" % (
            dst_lang, src_lang, quote_plus(text.encode("utf-8"))
        )
        html = urlopen(
            Request(url, headers=http_headers), **ssl_args
        ).read().decode('utf-8')
        # extract content from text <div>
        m = rx_gtrans.search(html)
        if m:
            text = m.group(1)
            text = text.replace("&#39;", "'").replace("&amp;", "&").replace("&lt;", "<").replace("&gt;", ">").replace("&quot;", '"')
            #@todo: https://stackoverflow.com/questions/2087370/decode-html-entities-in-python-string
        else:
            logging.warning("NO TRANSLATION RESULT EXTRACTED: " + html)
            logging.debug("ORIG TEXT: " + repr(text))
        return text

    # iterate over text segments (1900 char limit)        
    def translate(self, text, lang="auto"):
        #logging.debug("translate %d chars" % len(text))
        if len(text) < 2:
            logging.debug("skipping/len<2")
            return text
        elif rx_empty.match(text):
            logging.debug("skipping/empty")
            return text
        elif not rx_letters.search(text):
            logging.debug("skipping/noletters")
            return text
        elif len(text) >= 1900:
            logging.debug("spliterate/1900+")
            return " ".join(self.askgoogle(segment) for segment in rx_splitpara.findall(text))
        else:
            return self.askgoogle(text)
            
    # translate w/ preserving paragraph breaks (meant for table cell content)
    def linebreakwise(self, text, lang="auto"):
        return "\n\n".join(self.translate(text) for text in text.split("\n\n"))
        # alternatively, use a temp placeholder '/#/'


# register with LibreOffice
pagetranslate(None)

Changes to pagetranslate.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python
# encoding: utf-8
# api: uno
# type: callback
# category: transform
# title: PageTranslate
# description: Action button to get whole Writer document translated
# version: 0.5
# state: experimental
# author: mario
# forked-from: TradutorLibreText (Claudemir de Almeida Rosa)
# license: GNU LGPL 2.1
# config: -
# 
# LibreOffice plugin for translating documents that's supposed to retain formatting.







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python
# encoding: utf-8
# api: uno
# type: callback
# category: transform
# title: PageTranslate
# description: Action button to get whole Writer document translated
# version: 0.7
# state: experimental
# author: mario
# forked-from: TradutorLibreText (Claudemir de Almeida Rosa)
# license: GNU LGPL 2.1
# config: -
# 
# LibreOffice plugin for translating documents that's supposed to retain formatting.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
if sys.platform != 'win32':
    import ssl
    myssl = ssl.create_default_context();
    myssl.check_hostname = False
    myssl.verify_mode = ssl.CERT_NONE
    ssl_args["context"] = myssl
http_headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux; LibreOffice/6.3; TradutorLibreText/1.3.7)"
}
# log file
import logging
logging.basicConfig(filename='/tmp/pagetranslate-libreoffice.log', level=logging.DEBUG)
# regex
import re
rx_gtrans = re.compile('class="t0">(.+?)</div>', re.S)







|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
if sys.platform != 'win32':
    import ssl
    myssl = ssl.create_default_context();
    myssl.check_hostname = False
    myssl.verify_mode = ssl.CERT_NONE
    ssl_args["context"] = myssl
http_headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux; LibreOffice/6.3; TradutorLibreText/1.3+PageTranslate/0.5)"
}
# log file
import logging
logging.basicConfig(filename='/tmp/pagetranslate-libreoffice.log', level=logging.DEBUG)
# regex
import re
rx_gtrans = re.compile('class="t0">(.+?)</div>', re.S)
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124





125
126
127
128
129




130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158


159
160
161
162

163
164
165
166



167
168
169
170
171
172
173


    def __init__(self, ctx):
        logging.info("init")
        self.ctx = ctx
        desktop = self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", self.ctx )
        self.document = desktop.getCurrentComponent()
        #self.dispatcher=self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.DispatchHelper", self.ctx )
        #self.language=self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.i18n.LocaleData", self.ctx )
        #self.lang=self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.configuration.ConfigurationProvider", self.ctx )


    # request text translation from google
    def askgoogle(self, text, dst_lang="en", src_lang='auto'):
        # fetch translation page
        url = "http://translate.google.com/m?hl=%s&sl=%s&q=%s" % (
            dst_lang, src_lang, urllib.parse.quote_plus(text)
        )
        html = urlopen(
            Request(url, headers=http_headers), **ssl_args
        ).read().decode('utf-8')
        # extract content from text <div>
        m = rx_gtrans.search(html)
        if m:
            text = m.group(1)
            text = text.replace("&#39;", "'").replace("&lt;", "<").replace("&gt;", ">").replace("&quot;", '"')

        else:
            logging.warning("NO TRANSLATION RESULT EXTRACTED: "+ html)

        return text

    # iterate over text segments (1900 char limit)        
    def translate(self, text):
        logging.debug("translate %d chars" % len(text))
        if len(text) < 2:
            logging.debug("skipping/len<2")
            return text
        elif rx_empty.match(text):
            logging.debug("skipping/empty")
            return text
        elif not rx_letters.search(text):
            logging.debug("skipping/noletters")
            return text
        elif len(text) >= 1900:
            logging.debug("spliterate/1900+")
            return " ".join(self.askgoogle(segment) for segment in rx_splitpara.findall(text))
        else:
            return self.askgoogle(text)







    # invoked from toolbar button
    def trigger(self, args):
        logging.debug("start")




        tree = self.document.getText().createEnumeration()
        logging.info("enum")
        try:
            self.traverse(tree)
        except Exception as exc:
            logging.error(format_exc())
            self.MessageBox(formet_exc())
        logging.info("----")


    # iterate over TextContent/TextTable nodes
    def traverse(self, tree):
        while tree.hasMoreElements():
            para = tree.nextElement()
            logging.info(para)
            # table/cells
            if para.supportsService("com.sun.star.text.TextTable"):
                for cellname in para.getCellNames():
                    logging.debug(cellname)
                    cell = para.getCellByName(cellname)
                    text = cell.getText()
                    text.setString(self.translate(text.getString()))
                #self.traverse(para)

                pass
            # normal flow text
            elif para.supportsService("com.sun.star.text.TextContent"):
                text = para.getString()
                text = self.translate(text)
                para.setString(text)


            else:
                logging.warning("unsupported document element:")
                logging.info(para)
#           logging.info(para.getSelection().getByIndex(0).getString())



    # TradutorLibreText (selection rewrite)
    def trigger_selection(self, args):




        # Obtem  um texto selecionado
        controller = self.document.getCurrentController()
        selection = controller.getSelection()
        xTextRange = selection.getByIndex(0)
        string = xTextRange.getString()








<
<
<















|
>

|
>



|
|














>
>
>
>
>




|
>
>
>
>

|

















|
<
<
|
>






>
>

|
<
|
>




>
>
>







78
79
80
81
82
83
84



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157


158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185


    def __init__(self, ctx):
        logging.info("init")
        self.ctx = ctx
        desktop = self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", self.ctx )
        self.document = desktop.getCurrentComponent()





    # request text translation from google
    def askgoogle(self, text, dst_lang="en", src_lang='auto'):
        # fetch translation page
        url = "http://translate.google.com/m?hl=%s&sl=%s&q=%s" % (
            dst_lang, src_lang, urllib.parse.quote_plus(text)
        )
        html = urlopen(
            Request(url, headers=http_headers), **ssl_args
        ).read().decode('utf-8')
        # extract content from text <div>
        m = rx_gtrans.search(html)
        if m:
            text = m.group(1)
            text = text.replace("&#39;", "'").replace("&amp;", "&").replace("&lt;", "<").replace("&gt;", ">").replace("&quot;", '"')
            #@todo: https://stackoverflow.com/questions/2087370/decode-html-entities-in-python-string
        else:
            logging.warning("NO TRANSLATION RESULT EXTRACTED: " + html)
            logging.debug("ORIG TEXT: " + repr(text))
        return text

    # iterate over text segments (1900 char limit)        
    def translate(self, text, lang="auto"):
        #logging.debug("translate %d chars" % len(text))
        if len(text) < 2:
            logging.debug("skipping/len<2")
            return text
        elif rx_empty.match(text):
            logging.debug("skipping/empty")
            return text
        elif not rx_letters.search(text):
            logging.debug("skipping/noletters")
            return text
        elif len(text) >= 1900:
            logging.debug("spliterate/1900+")
            return " ".join(self.askgoogle(segment) for segment in rx_splitpara.findall(text))
        else:
            return self.askgoogle(text)
            
    # translate w/ preserving paragraph breaks (meant for table cell content)
    def linebreakwise(self, text, lang="auto"):
        return "\n\n".join(self.translate(text) for text in text.split("\n\n"))
        # alternatively, use a temp placeholder '/#/'


    # invoked from toolbar button
    def trigger(self, args):
        logging.debug(".trigger(args=%s) invoked" % repr(args))
        if len(self.document.getCurrentController().getSelection().getByIndex(0).getString()):
            logging.info("SELECTION ACTIVE")
            return self.trigger_selection(args)
        # else iterate over text snippets
        tree = self.document.getText().createEnumeration()
        logging.info("TextDocument.Enumeration…")
        try:
            self.traverse(tree)
        except Exception as exc:
            logging.error(format_exc())
            self.MessageBox(formet_exc())
        logging.info("----")


    # iterate over TextContent/TextTable nodes
    def traverse(self, tree):
        while tree.hasMoreElements():
            para = tree.nextElement()
            logging.info(para)
            # table/cells
            if para.supportsService("com.sun.star.text.TextTable"):
                for cellname in para.getCellNames():
                    logging.debug(cellname)
                    text = para.getCellByName(cellname).getText()


                    #self.traverse(text.createEnumeration())
                    text.setString(self.linebreakwise(text.getString())) # or .translate #linebreakwise
                pass
            # normal flow text
            elif para.supportsService("com.sun.star.text.TextContent"):
                text = para.getString()
                text = self.translate(text)
                para.setString(text)
                # the paragraph itself can be enumerated for text portions,
                # but for now it's really slow enough
            else:
                logging.warning("Unsupported document element.")

        #logging.info(para.getSelection().getByIndex(0).getString())
        pass


    # TradutorLibreText (selection rewrite)
    def trigger_selection(self, args):
        self.dispatcher=self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.DispatchHelper", self.ctx )
        self.language=self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.i18n.LocaleData", self.ctx )
        self.lang=self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.configuration.ConfigurationProvider", self.ctx )

        # Obtem  um texto selecionado
        controller = self.document.getCurrentController()
        selection = controller.getSelection()
        xTextRange = selection.getByIndex(0)
        string = xTextRange.getString()

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
            elif len(text) == 0 : raise selectsize(str(len(text)),code)
            try:
                lang2=xTextRange.CharLocale.Language
                if  Langinfo.CountryDefaultName != "United States":
                    msglang = Langinfo.LanguageDefaultName + " " + Langinfo.CountryDefaultName
                else:
                    msglang = " "
                trans=self.translate(text,lang2)
                xTextRange.setString(trans.replace('\\n',"\n").replace('\\r',"\n"))
            except Exception as e:
                try:
                    self.MessageBox(e)
                except Exception as e:
                    logging.info(e)








|







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
            elif len(text) == 0 : raise selectsize(str(len(text)),code)
            try:
                lang2=xTextRange.CharLocale.Language
                if  Langinfo.CountryDefaultName != "United States":
                    msglang = Langinfo.LanguageDefaultName + " " + Langinfo.CountryDefaultName
                else:
                    msglang = " "
                trans=self.linebreakwise(text,lang2)
                xTextRange.setString(trans.replace('\\n',"\n").replace('\\r',"\n"))
            except Exception as e:
                try:
                    self.MessageBox(e)
                except Exception as e:
                    logging.info(e)

Changes to registry/data/org/openoffice/Office/Addons.xcu.

19
20
21
22
23
24
25

26

27
28
29
30
31
32
33
34
35
36
                            <prop oor:name="Title">
                                <value xml:lang="en">PageTranslate</value>
                                <!--value xml:lang="pt-BR">TradutorLibreText</value-->
                            </prop>
                            <node oor:name="Submenu">
                                <node oor:name="M2" oor:op="replace">
				 <prop oor:name="Context" oor:type="xs:string">

                                        <value>com.sun.star.text.TextDocument</value>

                                    </prop>
                                    <prop oor:name="URL" oor:type="xs:string">
                                        <value>service:org.openoffice.comp.pyuno.pagetranslate?execute</value>
                                    </prop>
                                    <prop oor:name="Title" oor:type="xs:string">
                                        <value />
                                       	<value xml:lang="pt-BR">Traduzir</value>
					<value xml:lang="en-US">→English</value>
                                    </prop>                                   
                                    <prop oor:name="Target" oor:type="xs:string">







>
|
>


|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
                            <prop oor:name="Title">
                                <value xml:lang="en">PageTranslate</value>
                                <!--value xml:lang="pt-BR">TradutorLibreText</value-->
                            </prop>
                            <node oor:name="Submenu">
                                <node oor:name="M2" oor:op="replace">
				 <prop oor:name="Context" oor:type="xs:string">
                                        <value/>
                                        <!--value>com.sun.star.text.TextDocument</value>
                                        <value>com.sun.star.drawing.DrawingDocument</value-->
                                    </prop>
                                    <prop oor:name="URL" oor:type="xs:string">
                                        <value>service:org.openoffice.comp.pyuno.pagetranslate?trigger&amp;lang=en</value>
                                    </prop>
                                    <prop oor:name="Title" oor:type="xs:string">
                                        <value />
                                       	<value xml:lang="pt-BR">Traduzir</value>
					<value xml:lang="en-US">→English</value>
                                    </prop>                                   
                                    <prop oor:name="Target" oor:type="xs:string">
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81

82
83
84
85
86
87
88
                        <node oor:name="m1" oor:op="replace">
                            <prop oor:name="URL" oor:type="xs:string">
                                <value>private:separator</value>
                            </prop>
                        </node>
                        <node oor:name="m2" oor:op="replace">
                            <prop oor:name="URL" oor:type="xs:string">
                                <value>service:org.openoffice.comp.pyuno.pagetranslate?execute</value>
                            </prop>
                            <prop oor:name="ImageIdentifier" oor:type="xs:string">
                                <value/>
                            </prop>
                            <prop oor:name="Target" oor:type="xs:string">
                                <value>_self</value>
                            </prop>
                            <prop oor:name="Context" oor:type="xs:string">

                                <value>com.sun.star.text.TextDocument</value>

                            </prop>
                            <prop oor:name="ControlType" oor:type="xs:string">
                                <value>Checkbutton</value>
                            </prop>
                            <prop oor:name="Title" oor:type="xs:string">
                               <value/>
				<value xml:lang="pt-BR">Traduzir</value>







|








>

>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
                        <node oor:name="m1" oor:op="replace">
                            <prop oor:name="URL" oor:type="xs:string">
                                <value>private:separator</value>
                            </prop>
                        </node>
                        <node oor:name="m2" oor:op="replace">
                            <prop oor:name="URL" oor:type="xs:string">
                                <value>service:org.openoffice.comp.pyuno.pagetranslate?trigger&amp;lang=en</value>
                            </prop>
                            <prop oor:name="ImageIdentifier" oor:type="xs:string">
                                <value/>
                            </prop>
                            <prop oor:name="Target" oor:type="xs:string">
                                <value>_self</value>
                            </prop>
                            <prop oor:name="Context" oor:type="xs:string">
                                <!--value/-->
                                <value>com.sun.star.text.TextDocument</value>
                                <!--value>com.sun.star.drawing.DrawingDocument</value-->
                            </prop>
                            <prop oor:name="ControlType" oor:type="xs:string">
                                <value>Checkbutton</value>
                            </prop>
                            <prop oor:name="Title" oor:type="xs:string">
                               <value/>
				<value xml:lang="pt-BR">Traduzir</value>