2025-01-15 22:48:25 +05:00
|
|
|
-- Options
|
|
|
|
local o = {
|
|
|
|
source_lang = 'en', -- Translate from, e.g. 'ru', 'en', 'de', etc. Change to 'auto' to detect the source language
|
|
|
|
destination_lang = 'ru', -- Translate to
|
|
|
|
duration = 10, -- how long will the translation be shown on the OSD screen (in secs.)
|
2025-01-16 21:09:27 +05:00
|
|
|
key_binding = "t" -- Keybind for translating the current sub
|
2025-01-15 22:48:25 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
local mp = require 'mp'
|
|
|
|
local utils = require 'mp.utils'
|
|
|
|
|
|
|
|
-- Custom URL-encode function (Lua 5.1+)
|
|
|
|
local function url_encode(str)
|
|
|
|
if not str then return "" end
|
|
|
|
-- Convert line breaks to spaces, trim leading/trailing whitespace
|
|
|
|
str = str:gsub("\n", " "):gsub("^%s*(.-)%s*$", "%1")
|
|
|
|
-- Percent-encode special characters
|
|
|
|
str = str:gsub("([^%w _%%%-%.~])", function(char)
|
|
|
|
return string.format("%%%02X", string.byte(char))
|
|
|
|
end)
|
|
|
|
-- Replace spaces with %20
|
|
|
|
str = str:gsub(" ", "%%20")
|
|
|
|
return str
|
|
|
|
end
|
|
|
|
|
|
|
|
local function translate_subtitle()
|
|
|
|
-- Get the current subtitle text
|
|
|
|
local text = mp.get_property("sub-text")
|
|
|
|
if not text or text == "" then
|
|
|
|
mp.osd_message("No subtitles to translate.")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Encode text for URL
|
|
|
|
local encodedText = url_encode(text)
|
|
|
|
|
|
|
|
-- Google Translate API endpoint
|
|
|
|
local url = string.format(
|
|
|
|
"https://translate.googleapis.com/translate_a/single?client=gtx&sl=" .. o.source_lang .. "&tl=" .. o.destination_lang .. "&dt=t&q=%s",
|
|
|
|
encodedText
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Use curl to fetch the translation result
|
|
|
|
local res = utils.subprocess({
|
|
|
|
args = {"curl", "-s", url},
|
|
|
|
cancellable = false
|
|
|
|
})
|
|
|
|
|
|
|
|
if res.status ~= 0 or not res.stdout or res.stdout == "" then
|
|
|
|
mp.osd_message("Translation request failed.")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Parse the JSON returned by Google Translate
|
|
|
|
local data = utils.parse_json(res.stdout)
|
2025-01-16 17:51:40 +05:00
|
|
|
if not data or not data[1] then
|
2025-01-15 22:48:25 +05:00
|
|
|
mp.osd_message("Failed to parse translation.")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2025-01-16 17:51:40 +05:00
|
|
|
-- Concatenate translation chunks
|
|
|
|
-- Google may split the translation into multiple segments for punctuation, etc.
|
|
|
|
local translation_parts = {}
|
|
|
|
for _, segment in ipairs(data[1]) do
|
|
|
|
if segment and segment[1] then
|
|
|
|
table.insert(translation_parts, segment[1])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local translation = table.concat(translation_parts, "")
|
2025-01-15 22:48:25 +05:00
|
|
|
|
2025-01-16 17:51:40 +05:00
|
|
|
mp.osd_message(translation, o.duration)
|
2025-01-15 22:48:25 +05:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Bind the function to a hotkey, e.g. Ctrl+T
|
|
|
|
mp.add_key_binding(o.key_binding, "translate_subtitle", translate_subtitle)
|