Translate plugin
-
Thank you, but I don’t understand any of this.
What is “databird”?
There is no DLL file on Github for npptranslate64,
There are only CS files.github .com/databird/npptranslate64
-
@Olek-Ksasi said in Translate plugin:
Thank you, but I don’t understand any of this.
What is “databird”?
There is no DLL file on Github for npptranslate64,
There are only CS files.github .com/databird/npptranslate64
There is a DLL file on GitHub for npptranslate64, if you follow my instructions.
- You searched “GitHub” for “npptranslate64” and found github.com/databird/npptranslate64 . which is the one with “databird” in its name, so good job so far, you found the right URL, even though you didn’t see “databird” even when you pasted that URL.
- I then said “follow the ‘releases’ link”:
so click on that link. - That page, in the most recent release (at the top) has a DLL link.
-
@PeterJones A ok.
Thank you again for your help.
Unfortunately, you need to connect a debit card to use this plugin. Additionally, there is a significant limitation in the number of characters that can be translated per month. Be it in Azure, My Memory or DEEPL. It’s a pity that the author of the plugin doesn’t write about it. It would save a lot of time for people who think it’s free.
I have to look for another program like Notepad, which has Google Translate. I have no intention of linking my card anywhere. -
@Olek-Ksasi said in Translate plugin:
@databird said in :
A 64 bits version is available as a fork on github :
Search “npptranslate64” on GitHub
Enjoy !
How install this?
Is there a plugin option that works with Google Translate API?
-
I don’t know of any other translation plugins for Notepad++.
And despite what @Olek-Ksasi thought, “Google” doesn’t solve all your woes.
At least at some resources I have found, Google charges you for every successful translation when using the API, similar to the service that the Translate plugin uses. Maybe they have a free plan that I just haven’t been able to find, but …
In general, I’ve only ever seen “free translation” for the manual web-based translation services, with charges for their API version (though I’ve never really looked, because automated translation isn’t something I need). (And such services are pretty good at blocking access to bots trying to pretend to use the web-based version even though they are automatic: such tactics violate T.O.S. for most websites)
If you were able to find a translation API that was free-to-use, if it had a REST-style API, you could probably use the RestApiToText plugin in Notepad++ to try it out, and then either write a PythonScript-based wrapper, or just implement or instantiate a REST client in PythonScript. (I’m sure Python would have a library for such an interface; how to do that implementation/instantiation is off-topic for this Forum, since we’re focused on the Notepad++ end of things, and that implementation/instantiation is generic Python programming)
-
@A-Notepad-User
@PeterJones said in Translate plugin:If you were able to find a translation API that was free-to-use, if it had a REST-style API, you could probably use the RestApiToText plugin in Notepad++ to try it out, and then either write a PythonScript-based wrapper, or
… or, just use “mine”:
https://community.notepad-plus-plus.org/topic/24389/little-dialog-wrapper-for-pythonscript/31
Cheers.
-
Ooh, nice, I had forgotten you had shared that.
A word to anyone wanting to use it: in case you don’t see it higher in the conversation:
- You need to have at least PythonScript 3.0.16 installed (the Plugins Admin doesn’t install the PS 3.x versions, so you will have to manually install the beta version).
- You need to install the “Little Dialog Wrapper” that @Ekopalypse shared in the first post in that Topic.
-
Moving the
translate.py
specific question to this Topic, rather than the Little Dialog Wrapper conversation…Like happened with the
dictionary
script in the other Topic, thetranslate
script relies on therequests
library, which I don’t have. I tried to follow @rdipardo’s changes for thedictionary
in the analogous locations int hetranslate
, but I’m having difficulty.#import requests #### per @rdipardo's updates on Michael's other script import json import urllib.request as requests import urllib.parse ... def on_translate(self): ... ###r = requests.get(f"http://mymemory.translated.net/api/get?q={text_encoded}&langpair={langpair}") r = requests.urlopen(requests.Request(f"http://mymemory.translated.net/api/get?q={text_encoded}&langpair={langpair}")) ###response = r.json()['responseData']['translatedText'] console.writeError(f"r.status: {r.status}\nr.read: {r.read().decode('utf8')}"); return; ###### exit here, because the next line gives an error response = json.loads(r.read().decode('utf8'))['responseData']['translatedText'] # Set return translation if response is not None: self.ret.trans = response else: self.ret.trans = "(no translation found)" self.trans.setText(self.ret.trans) # Set return text self.ret.text = self.text.getText()
When I run that with the console.writeError, I get:
r.status: 200 r.read: can't open file
Any ideas what I’m doing wrong? Or has the translation API changed?
----
update: printing the URL it is trying to access usingconsole.writeError(f"\n\nhttp://mymemory.translated.net/api/get?q={text_encoded}&langpair={langpair}\n");
shows
http://mymemory.translated.net/api/get?q=Hello&langpair=en|de
If I paste that URL into my browser, I get valid JSON for the translation:
{"responseData":{"translatedText":"Hallo","match":1},"quotaFinished":false,"mtLangSupported":null,"responseDetails":"","responseStatus":200,"responderId":"45","exception_code":null,"matches":[{"id":"758976106","segment":"Hello","translation":"Hallo","source":"en-GB","target":"de-DE","quality":"74","reference":null,"usage-count":93,"subject":"All","created-by":"MateCat","last-updated-by":"MateCat","create-date":"2022-10-06 13:45:27","last-update-date":"2022-10-06 13:45:27","match":1},{"id":"757809118","segment":"Hello","translation":"Hello","source":"en-GB","target":"de-DE","quality":"74","reference":null,"usage-count":2,"subject":"All","created-by":"MateCat","last-updated-by":"MateCat","create-date":"2022-09-16 12:45:34","last-update-date":"2022-09-16 12:45:34","match":0.98999999999999999}]}
So why is that URL working for browser but not for API?
-
@PeterJones said in Translate plugin:
Any ideas what I’m doing wrong? Or has the translation API changed?
Not off hand. Pressed for time now, can look at it later. In the meantime, here is my updated full script. It may have other dependencies I’m overlooking, but at least you can see my non-
requests
version:import json import urllib.request as requests import urllib.parse from enum import Enum from Npp import editor from WinDialog import Button, ComboBox, DefaultButton, Dialog, Label, TextBox from WinDialog.win_helper import WindowStyle as WS TITLE = "Translate" DEFAULTLANG = "English" class Languages(Enum): """Translated language options.""" Chinese = "zh" English = "en" French = "fr" German = "de" Italian = "it" Japanese = "ja" Portuguese = "pt" Russian = "ru" Spanish = "es" class Returns(object): """The input / output for the Translator service.""" def __init__(self, text="", srclang=DEFAULTLANG, dstlang=DEFAULTLANG): self.text = text self.trans = "" self.srclang = srclang self.dstlang = dstlang class Translator(Dialog): """A Translator dialog interface.""" def __init__(self, ret=Returns()): super().__init__( title=TITLE , center = True , size=(290, 165) ) self.translate = DefaultButton( title='&Translate' , position=(120, 145), size=(50, 11) ) self.label1 = Label( title='Text:' , position=(10, 12) , size=(35, 11) ) self.text = TextBox( position=(45, 10) , size=(235, 55) ) self.swapt = Button( title='^&v' , position=(45, 67) , size=(20, 14) ) self.srclang = ComboBox( position=(75, 68) , size=(80, 14) ) self.swapl = Button( title='<&=>' , position=(165, 67) , size=(20, 14) ) self.dstlang = ComboBox( position=(200, 68) , size=(80, 14) ) self.label2 = Label( title='Translated:' , position=(10, 84) , size=(35, 11) ) self.trans = TextBox( position=(45, 82) , size=(235, 55) ) self.replace = Button( title='&Replace' , position=(175, 145), size=(50, 11) ) self.close = Button( title='&Close' , position=(230, 145), size=(50, 11) ) self.ret = ret self.onIdOk = self._on_translate self.translate.onClick = self._on_translate self.swapt.onClick = self._on_swapt self.swapl.onClick = self._on_swapl self.srclang.onSelEndOk = self._on_translate self.dstlang.onSelEndOk = self._on_translate self.replace.onClick = self._on_replace self.close.onClick = self._on_close self.srclang.style = self.srclang.style | WS.TABSTOP self.dstlang.style = self.dstlang.style | WS.TABSTOP self.text.style = self.text.style | WS.VSCROLL # | WS.HSCROLL self.trans.style = self.trans.style | WS.VSCROLL # | WS.HSCROLL self.show() def initialize(self): """Initialize the dialog.""" self.text.setText(self.ret.text) self._init_langs() if self.ret.srclang != self.ret.dstlang and self.ret.text != "": self._on_translate() def _init_langs(self): srclang = list(n.name for n in Languages) if self.ret.srclang in srclang: srclang.insert(0, self.ret.srclang) self.srclang.set(srclang) dstlang = list(n.name for n in Languages) if self.ret.dstlang in dstlang: dstlang.insert(0, self.ret.dstlang) self.dstlang.set(dstlang) def _on_translate(self): """Translate the text.""" if self.text.getText() == "": return text_encoded = urllib.parse.quote(self.text.getText()) srclang = Languages[self.srclang.getSelectedItemText()] dstlang = Languages[self.dstlang.getSelectedItemText()] if srclang == dstlang: return # Set return languages self.ret.srclang = srclang.name self.ret.dstlang = dstlang.name srccode = srclang.value dstcode = dstlang.value # EXAMPLE: LANGPAIR=EN|IT USING 2 LETTER ISO OR RFC3066 LIKE ZH-CN langpair = f"{srccode}|{dstcode}" headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"} r = requests.urlopen(requests.Request(url=f"http://mymemory.translated.net/api/get?q={text_encoded}&langpair={langpair}", headers=headers)) if r.status != 200: return ret = r.read() response = json.loads(ret.decode('utf8'))['responseData']['translatedText'] # Set return translation if response is not None: self.ret.trans = response else: self.ret.trans = "(no translation found)" self.trans.setText(self.ret.trans) # Set return text self.ret.text = self.text.getText() def _on_swapl(self): """Swap languages.""" self.ret.dstlang = self.srclang.getSelectedItemText() self.ret.srclang = self.dstlang.getSelectedItemText() self._init_langs() self._on_translate() def _on_swapt(self): """Swap texts.""" self.ret.trans = self.text.getText() self.ret.text = self.trans.getText() self.text.setText(self.ret.text) self.trans.setText(self.ret.trans) self._on_swapl() def _on_replace(self): """Replace text with translation in document.""" if self.ret.trans != "": editor.replaceSel(self.ret.trans) self.terminate() def _on_close(self): self.terminate() class Translate(): """A translator service.""" def __init__(self): self.srclang = DEFAULTLANG self.dstlang = DEFAULTLANG def _editor_getWordAtCaretOrSelection(self): retval = '' (sel_start, sel_end) = (editor.getSelectionStart(), editor.getSelectionEnd()) if editor.getSelections() == 1 and sel_start != sel_end: retval = editor.getTextRange(sel_start, sel_end) else: start_of_word_pos = editor.wordStartPosition(editor.getCurrentPos(), True) end_of_word_pos = editor.wordEndPosition(start_of_word_pos, True) if start_of_word_pos != end_of_word_pos: retval = editor.getTextRange(start_of_word_pos, end_of_word_pos) editor.setSelection(end_of_word_pos, start_of_word_pos) return retval def translate(self): text = "" if editor.getSelectionEmpty(): sel = self._editor_getWordAtCaretOrSelection() if len(sel) > 0: text = sel else: text = editor.getSelText() ret = Returns(text, self.srclang, self.dstlang) Translator(ret) self.srclang = ret.srclang self.dstlang = ret.dstlang Translate().translate()
Cheers.
-
@Michael-Vincent said in Translate plugin:
In the meantime, here is my updated full script.
That one works for me. My guess is that it’s your User-Agent headers allowing it to work.
update: yes, adding the headers to my edits makes mine work
Thank you.