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

⌈⌋ ⎇ branch:  PageTranslate


Check-in [4620700b36]

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

Overview
Comment:Add PONS Text Translation backend.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4620700b36108b027646ca0e1aaf4c6b0386699e
User & Date: mario 2021-05-15 05:42:51
Context
2021-05-15
16:21
Transform OptionsPageURL= into code; switching to our dialog still non-functional. check-in: 93f1a54882 user: mario tags: trunk
05:42
Add PONS Text Translation backend. check-in: 4620700b36 user: mario tags: trunk
05:37
Minor documentation updates, yield errors for DeepL failures. check-in: ead6fe2706 user: mario tags: trunk, 1.8
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to OptionsDialog.xdl.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  <dlg:fixedline dlg:id="Label1" dlg:tab-index="10" dlg:left="140" dlg:top="30" dlg:width="23" dlg:height="8" dlg:value="API key "/>
  <dlg:fixedline dlg:id="Label2" dlg:tab-index="11" dlg:left="140" dlg:top="52" dlg:width="28" dlg:height="8" dlg:printable="false" dlg:value="Email adr "/>
  <dlg:fixedline dlg:id="Label3" dlg:tab-index="12" dlg:left="140" dlg:top="74" dlg:width="30" dlg:height="8" dlg:value="Command "/>
  <dlg:menulist dlg:id="backend" dlg:tab-index="13" dlg:left="20" dlg:top="30" dlg:width="105" dlg:height="14" dlg:help-text="Which translation service to use. (Some might require an API key, or email address.)" dlg:spin="true" dlg:linecount="16">
   <dlg:menupopup>
    <dlg:menuitem dlg:value="Google Translate" dlg:help-text="default"/>
    <dlg:menuitem dlg:value="MyMemory"/>
    <!--dlg:menuitem dlg:value="PONS Text Translation"/-->
    <dlg:menuitem dlg:value="command line tool"/>
    <dlg:menuitem dlg:value="DeepL API"/>
    <dlg:menuitem dlg:value="DeepL Free API"/>
    <dlg:menuitem dlg:value="DeepL web interface"/>
    <dlg:menuitem dlg:value="Microsoft Translator (T-P)"/>
    <dlg:menuitem dlg:value="QCRI Machine Translation (D-T)"/>
    <dlg:menuitem dlg:value="Yandex Translation (D-T)"/>







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  <dlg:fixedline dlg:id="Label1" dlg:tab-index="10" dlg:left="140" dlg:top="30" dlg:width="23" dlg:height="8" dlg:value="API key "/>
  <dlg:fixedline dlg:id="Label2" dlg:tab-index="11" dlg:left="140" dlg:top="52" dlg:width="28" dlg:height="8" dlg:printable="false" dlg:value="Email adr "/>
  <dlg:fixedline dlg:id="Label3" dlg:tab-index="12" dlg:left="140" dlg:top="74" dlg:width="30" dlg:height="8" dlg:value="Command "/>
  <dlg:menulist dlg:id="backend" dlg:tab-index="13" dlg:left="20" dlg:top="30" dlg:width="105" dlg:height="14" dlg:help-text="Which translation service to use. (Some might require an API key, or email address.)" dlg:spin="true" dlg:linecount="16">
   <dlg:menupopup>
    <dlg:menuitem dlg:value="Google Translate" dlg:help-text="default"/>
    <dlg:menuitem dlg:value="MyMemory"/>
    <dlg:menuitem dlg:value="PONS Text Translation"/>
    <dlg:menuitem dlg:value="command line tool"/>
    <dlg:menuitem dlg:value="DeepL API"/>
    <dlg:menuitem dlg:value="DeepL Free API"/>
    <dlg:menuitem dlg:value="DeepL web interface"/>
    <dlg:menuitem dlg:value="Microsoft Translator (T-P)"/>
    <dlg:menuitem dlg:value="QCRI Machine Translation (D-T)"/>
    <dlg:menuitem dlg:value="Yandex Translation (D-T)"/>

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: language
# title: PageTranslate
# description: Action button to get whole Writer document translated
# version: 1.8
# state: beta
# author: mario
# url: https://fossil.include-once.org/pagetranslate/
# depends: python:requests (>= 2.5), python:uno
# pack: *.py, pythonpath/*.py, META-INF/*, pkg-desc, *.x*, icons/*
# license: GNU LGPL 2.1
# forked-from: TradutorLibreText (Claudemir de Almeida Rosa)







|







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: language
# title: PageTranslate
# description: Action button to get whole Writer document translated
# version: 1.8.1
# state: beta
# author: mario
# url: https://fossil.include-once.org/pagetranslate/
# depends: python:requests (>= 2.5), python:uno
# pack: *.py, pythonpath/*.py, META-INF/*, pkg-desc, *.x*, icons/*
# license: GNU LGPL 2.1
# forked-from: TradutorLibreText (Claudemir de Almeida Rosa)

Changes to pythonpath/translationbackends.py.

490
491
492
493
494
495
496














































497
498
499
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
515
516
517
518
        }
        for k,v in repl.items():
            if re.match("""^["']?[\{%$]" + k + "[\}%$]?["']?$""", arg):
                return v
        return arg

















































# maps a pagetranslate.t.* object (in main module),
# according to configured backend (now a string)
def assign_service(params):
    w = params.get("backend", "Google")
    map = {
        "^google": google,
        "^deepl [\s_] web": deepl_web,
        "^deepl [\s_] (api|pro)": deepl_api,
        "^deepl \s free": deepl_free_api,
        "^mymemory | translated\.net": mymemory,

        "^command | ^CLI | tool | program": cli,
        "^microsoft | translate[_-]py | ^T-?P: | \(T-?P\)": translate_python,
        "linguee | pons | QCRI | yandex | ^D-?T: | \(D-?T\)": deep_translator,
    }
    for rx, cls in map.items():
        if re.search(rx, w, re.I|re.X):
            break
    else:
        cls = google
    return cls(params)








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>


|








490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
        }
        for k,v in repl.items():
            if re.match("""^["']?[\{%$]" + k + "[\}%$]?["']?$""", arg):
                return v
        return arg


# PONS text translation
#
# This is a mix of web scraping and API usage. It's not an official API,
# so unlikely to last. Unlike the PonsTranslator in D-L, this one uses
# the full text translation interface, not the dictionary.
#
class pons():
    init_url = "https://en.pons.com/text-translation"
    api_url = "https://api.pons.com/text-translation-web/v4/translate?locale=en"

    def __init__(self, params):
        self.params = params
        self.session = self.impressionId()

    # fetch from v4 api    
    def fetch(self, text, dst_lang="de", src_lang='en'):
        r = http.post(
            self.api_url,
            json = {
                "impressionId": self.session,
                "sourceLanguage": src_lang,
                "targetLanguage": dst_lang,
                "text": text
            }
        ).json()
        if r.get("serviceMessage"):
            raise Exception(r)
        elif r.get("text"):
            return r["text"]
        else:
            return text
    
    # detect language, and avoid non-text snippets
    def translate(self, text):
        r = self.fetch(text, "de", "en")
        if r:
            return r
        else:
            return text

    # invoked once to get session identifier        
    def impressionId(self):
        html = http.get(self.init_url).text
        return re.findall(""" ["']?impressionId["']? \s*[:=]\s* ["'](\w+-[\w-]+-\w+)["'] """, html, re.X)[0]



# maps a pagetranslate.t.* object (in main module),
# according to configured backend (now a string)
def assign_service(params):
    w = params.get("backend", "Google")
    map = {
        "^google": google,
        "^deepl [\s_] web": deepl_web,
        "^deepl [\s_] (api|pro)": deepl_api,
        "^deepl \s free": deepl_free_api,
        "^mymemory | translated\.net": mymemory,
        "^pons \s text": pons,
        "^command | ^CLI | tool | program": cli,
        "^microsoft | translate[_-]py | ^T-?P: | \(T-?P\)": translate_python,
        "linguee | pons\sdict | QCRI | yandex | ^D-?T: | \(D-?T\)": deep_translator,
    }
    for rx, cls in map.items():
        if re.search(rx, w, re.I|re.X):
            break
    else:
        cls = google
    return cls(params)