Dodgy MUD translation script

Share your scripts and packages with other Mudlet users.
User avatar
Vadi
Posts: 5035
Joined: Sat Mar 14, 2009 3:13 pm

Dodgy MUD translation script

Post by Vadi »

A quick thing I threw together to translate MUD output from another language into English. Uses the Yandex translation service for the job.
Selection_024.png
Selection_024.png (33.34 KiB) Viewed 10651 times
Selection_025.png
Install by copy/pasting this into Mudlet:
Code: [show] | [select all] lua
lua function downloaded_package(a,b)if not b:find("translator",1,true)then return end installPackage(b)os.remove(b)end registerAnonymousEventHandler("sysDownloadDone","downloaded_package")downloadFile(getMudletHomeDir().."/translator.mpackage","http://forums.mudlet.org/download/file.php?id=1470")
Doesn't look that great when there's a lot of text, it doesn't do a great job of aligning the translation with the output - that's something that could be improved.
Attachments
translator.mpackage
(1.35 KiB) Downloaded 559 times

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Dodgy MUD translation script

Post by Jor'Mox »

So, I'm looking at the code involved, and I see generally how it is working, but I'm unsure how to adjust how it is picking languages (though I can see the "en" specifying that it is getting translated into English). Is there any way to specify which language it is being translated from (in case there might be confusion)? Also, having a way to specify the target language in the script would be handy. And while I obviously know what needs to be changed, I don't know what it would need to be changed TO in order to select a different language.

Side note, I found that when I used this script (admittedly translating english to english, because I'm not playing any non-english MUDs), it put all of the translations on the last line displayed, rather than lined up with whatever line it should have gone on (yes, I know that is what the closure was supposed to be taking care of, and it probably would have if there were something in there figuring out what line matched up with what download). So... I tweaked the code until I got it working how I wanted it to.

Here is the resulting code:
Code: [show] | [select all] lua
function downloadedTranslation(_, filename)
  if not filename:find("translation", 1, true) then return end
 
  local f, text = io.open(filename)
  if f then text = f:read("*a"); io.close(f) end

  text = yajl.to_value(text).text[1]
  local ln,txt = string.match(text,"(%d+): (.*)")
  moveCursor(0,ln)
  cinsertText(string.format("<dark_slate_gray>(%s)<reset> ",txt))
end
 
registerAnonymousEventHandler("sysDownloadDone", "downloadedTranslation")

function translate(text)
  local apikey = "trnsl.1.1.20170412T072751Z.75e604ad6edc1b26.805ffe27a7253c7b241b3e27204ab61e20e7fc79"
  local translationid = ""
  if text == "" then return end
  text = getLineNumber() .. ": " .. text
  local url = string.format([[https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=en&format=plain&callback=%s]],
                apikey, text, translationid)

  downloadFile(getMudletHomeDir().."/translation", url)
end
Note that for this version, the trigger calling for the translation just needs to have this code: translate(line)

User avatar
Vadi
Posts: 5035
Joined: Sat Mar 14, 2009 3:13 pm

Re: Dodgy MUD translation script

Post by Vadi »

Yandex API autodetects the language - seemed to work for me with two languages so I was happy. See https://tech.yandex.com/translate/doc/d ... te-docpage on how to specify it explicitly - you do ru-en in lang to say from Russian to English.

Yeah the dodgy part is that it doesn't do a very good job of aligning the translation with the output. Depends on how the MUD displays it, it'll be off. It really should remember what it sent for translation and match up the text accordingly. I'll check your version out!

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Dodgy MUD translation script

Post by Jor'Mox »

So, I threw in the ability to specify languages to translate from and to (so no one needs to look up the right language code, they just need to see if the language they want is on the list). Otherwise, everything is the same as before.
Code: [show] | [select all] lua
-- Automatic Translation Script
-- Pick from the languages below, using the full language name as listed in the languages table below
-- If the original language is unknown, leave the translate_from variable nil
local translate_to = "latin"
local translate_from = "english"

local languages = {
    azerbaijan = "az",		maltese = "mt",
    albanian = "sq",		macedonian = "mk",
    amharic = "am",		    maori = "mi",
    english = "en",		    marathi = "mr",
    arabic = "ar",		    mari = "mhr",
    armenian = "hy",		mongolian = "mn",
    afrikaans = "af",		german = "de",
    basque = "eu",		    nepali = "ne",
    bashkir = "ba",		    norwegian = "no",
    belarusian = "be",		punjabi = "pa",
    bengali = "bn",		    papiamento = "pap",
    bulgarian = "bg",		persian = "fa",
    bosnian = "bs",		    polish = "pl",
    welsh = "cy",		    portuguese = "pt",
    hungarian = "hu",		romanian = "ro",
    vietnamese = "vi",		russian = "ru",
    haitian = "ht",         cebuano = "ceb",
    galician = "gl",        serbian = "sr",
    dutch = "nl",           sinhala = "si",
    ["hill mari"] = "mrj",	slovakian = "sk",
    greek = "el",		    slovenian = "sl",
    georgian = "ka",		swahili = "sw",
    gujarati = "gu",		sundanese = "su",
    danish = "da",		    tajik = "tg",
    hebrew = "he",		    thai = "th",
    yiddish = "yi",		    tagalog = "tl",
    indonesian = "id",		tamil = "ta",
    irish = "ga",		    tatar = "tt",
    italian = "it",		    telugu = "te",
    icelandic = "is",		turkish = "tr",
    spanish = "es",		    udmurt = "udm",
    kazakh = "kk",		    uzbek = "uz",
    kannada = "kn",		    ukrainian = "uk",
    catalan = "ca",		    urdu = "ur",
    kyrgyz = "ky",		    finnish = "fi",
    chinese = "zh",		    french = "fr",
    korean = "ko",		    hindi = "hi",
    xhosa = "xh",		    croatian = "hr",
    latin = "la",		    czech = "cs",
    latvian = "lv",		    swedish = "sv",
    lithuanian = "lt",		scottish = "gd",
    luxembourgish = "lb",	estonian = "et",
    malagasy = "mg",		esperanto = "eo",
    malay = "ms",		    javanese = "jv",
    malayalam = "ml",		japanese = "ja",
}

function downloadedTranslation(_, filename)
    if not filename:find("translation", 1, true) then return end

    local f, text = io.open(filename)
    if f then text = f:read("*a"); io.close(f) end

    text = yajl.to_value(text).text[1]
    local ln,txt = string.match(text,"(%d+): (.*)")
    moveCursor(0,ln)
    cinsertText(string.format("<dark_slate_gray>(%s)<reset> ",txt))
end

registerAnonymousEventHandler("sysDownloadDone", "downloadedTranslation")

function translate(text)
    local apikey = "trnsl.1.1.20170412T072751Z.75e604ad6edc1b26.805ffe27a7253c7b241b3e27204ab61e20e7fc79"
    local translationid = ""
    local target_language = languages[translate_to]
    if languages[translate_from] then
        target_language = languages[translate_from] .. "-" .. target_language
    end
    if text == "" then return end
    text = getLineNumber() .. ": " .. text
    local url = string.format([[https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s&format=plain&callback=%s]],
        apikey, text, target_language, translationid)

    downloadFile(getMudletHomeDir().."/translation", url)
end
Edit: There are two main reasons that the original script had issues lining up translation with original text. The first is that translations are not always downloaded in the order they are requested, and the script was assuming that they would be. The second is that it was checking the last callback value stored (should have been checking the first), but it never cleared that value, so if you got a block of lines all more or less at once, then all of them would use the same callback value (the last one), and therefore they would write everything on the last line. To avoid creating a ton of distinct files that could be used to identify which file went with which callback, I just jammed the line number into the translation text and then pulled it back out again on the other side. Seemed to work pretty well.

User avatar
Vadi
Posts: 5035
Joined: Sat Mar 14, 2009 3:13 pm

Re: Dodgy MUD translation script

Post by Vadi »

Ah you can use the callback URL to get your custom string back from the translation, try that out - would be a bit neater.

I see you're on your way onto making it not so dodgy

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Dodgy MUD translation script

Post by Jor'Mox »

Unfortunately, the callback bit takes the text being returned and wraps it as a function call to whatever text is given in the callback field, which produces an error when you try to have yajl.to_value parse it. While obviously I can still pull the number out that way, I'm not sure I would call it "cleaner". But, I suppose since it won't be translated, and there is the chance that the number will be if it is part of the translation string, it is potentially less problematic.

But, if you just use a single string.match call, you can avoid the issues with the new string and yajl.to_value, and simplify things a bit. So, here is the ever so slightly more optimized version.
Code: [show] | [select all] lua
-- Automatic Translation Script
-- Pick from the languages below, using the full language name as listed in the languages table
-- If the original language is unknown, leave the translate_from variable nil
local translate_to = "english"
local translate_from = nil

local languages = {
    azerbaijan = "az",      maltese = "mt",
    albanian = "sq",        macedonian = "mk",
    amharic = "am",         maori = "mi",
    english = "en",         marathi = "mr",
    arabic = "ar",          mari = "mhr",
    armenian = "hy",        mongolian = "mn",
    afrikaans = "af",       german = "de",
    basque = "eu",          nepali = "ne",
    bashkir = "ba",         norwegian = "no",
    belarusian = "be",      punjabi = "pa",
    bengali = "bn",         papiamento = "pap",
    bulgarian = "bg",       persian = "fa",
    bosnian = "bs",         polish = "pl",
    welsh = "cy",           portuguese = "pt",
    hungarian = "hu",       romanian = "ro",
    vietnamese = "vi",      russian = "ru",
    haitian = "ht",         cebuano = "ceb",
    galician = "gl",        serbian = "sr",
    dutch = "nl",           sinhala = "si",
    ["hill mari"] = "mrj",  slovakian = "sk",
    greek = "el",           slovenian = "sl",
    georgian = "ka",        swahili = "sw",
    gujarati = "gu",        sundanese = "su",
    danish = "da",          tajik = "tg",
    hebrew = "he",          thai = "th",
    yiddish = "yi",         tagalog = "tl",
    indonesian = "id",      tamil = "ta",
    irish = "ga",           tatar = "tt",
    italian = "it",         telugu = "te",
    icelandic = "is",       turkish = "tr",
    spanish = "es",         udmurt = "udm",
    kazakh = "kk",          uzbek = "uz",
    kannada = "kn",         ukrainian = "uk",
    catalan = "ca",         urdu = "ur",
    kyrgyz = "ky",          finnish = "fi",
    chinese = "zh",         french = "fr",
    korean = "ko",          hindi = "hi",
    xhosa = "xh",           croatian = "hr",
    latin = "la",           czech = "cs",
    latvian = "lv",         swedish = "sv",
    lithuanian = "lt",      scottish = "gd",
    luxembourgish = "lb",   estonian = "et",
    malagasy = "mg",        esperanto = "eo",
    malay = "ms",           javanese = "jv",
    malayalam = "ml",       japanese = "ja",
}

function downloadedTranslation(_, filename)
    if not filename:find("translation", 1, true) then return end
    
    local f, text, ln = io.open(filename)
    if f then text = f:read("*a"); io.close(f) end
    
    ln, text = string.match(text,[[(%w+)%({"code":%w+,"lang":"[%w-]+","text":%["(.*)"%]}%)]])
    if ln ~= "print" then
        moveCursor(0,ln)
        cinsertText(string.format("<dark_slate_gray>(%s)<reset> ",text))
    else
        print(text)
    end
end

registerAnonymousEventHandler("sysDownloadDone", "downloadedTranslation")

function translate(text,reverse)
    local apikey = "trnsl.1.1.20170412T072751Z.75e604ad6edc1b26.805ffe27a7253c7b241b3e27204ab61e20e7fc79"
    local translationid = (reverse and "print") or getLineNumber()
    local target_language
    if reverse then
        target_language = languages[translate_to] .. "-" .. (languages[reverse] or languages[translate_from])
    else
        target_language = languages[translate_to]
        if languages[translate_from] then
            target_language = languages[translate_from] .. "-" .. target_language
        end
    end
    if text == "" then return end
    local url = string.format([[https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s&format=plain&callback=%s]],
        apikey, text, target_language, translationid)

    downloadFile(getMudletHomeDir().."/translation", url)
end
Edit: Added a little something so you could prompt it to give a reverse translation printed out for you, in case you wanted something from your native language translated into the target language, perhaps to send back to the game you are playing). To do that, pass the translate function the name of your desired language to translate to, or true (the boolean value) if you have a "translate_from" language set.

Ex: translate("This is a test.","czech")
or
translate("This is a test.", true)

User avatar
SlySven
Posts: 1019
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Dodgy MUD translation script

Post by SlySven »

I'd expect there would be an issue in getting non-ASCII text from any of the Mudlet provided commands to get text received from the MUD - AFAIR there is no guarantee that you will get anything other than Latin1 text from them at present - and I am really uncertain that UTF-8 will get through the Mudlet internals for the Lua sub-system to pass to the user/scripts anyhow - at least in the Release 3.0.1 and prior versions.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Dodgy MUD translation script

Post by Jor'Mox »

This script worked with most languages I tested it with, such as Hindi, Chinese, Korean, Arabic, etc. whether or not any of that is useable for anything other than display purposes, I have no idea.

User avatar
Vadi
Posts: 5035
Joined: Sat Mar 14, 2009 3:13 pm

Re: Dodgy MUD translation script

Post by Vadi »

Yeah I was using MudletRL to display Russian and Spanish correctly there.

Lua subsystem does not care what it is, the issue comes when you want to manipulate that text - that's where we need https://github.com/Mudlet/Mudlet/issues/854.

User avatar
SlySven
Posts: 1019
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: Dodgy MUD translation script

Post by SlySven »

I have attempted to contact the person/people responsible for that fork to see if they would be willing to come on board to hep to get the features upstream. I have, I think identified the features they modified but as they forked from somewhere before the 3.0.0 beta preview there are some other things that they currently behind on.

Post Reply