mirror of https://github.com/koreader/koreader
enable Wikipedia support
Since wikipedia server is language specific we should first detect language of the text by querying Google Translate. Make sure you have access to both Google Translate and Wikipedia service to use this function.pull/818/head
parent
56fa8a45b7
commit
7b10d66e1b
@ -0,0 +1,51 @@
|
||||
local ReaderDictionary = require("apps/reader/modules/readerdictionary")
|
||||
local EventListener = require("ui/widget/eventlistener")
|
||||
local Translator = require("ui/translator")
|
||||
local Wikipedia = require("ui/wikipedia")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local Geom = require("ui/geometry")
|
||||
local Screen = require("ui/screen")
|
||||
local JSON = require("JSON")
|
||||
local DEBUG = require("dbg")
|
||||
local _ = require("gettext")
|
||||
|
||||
-- Wikipedia as a special dictionary
|
||||
local ReaderWikipedia = ReaderDictionary:new{
|
||||
-- identify itself
|
||||
wiki = true,
|
||||
no_page = _("No wiki page found."),
|
||||
}
|
||||
|
||||
function ReaderWikipedia:onLookupWikipedia(word, box)
|
||||
local lang = Translator:detect(word) or "en"
|
||||
-- convert "zh-CN" and "zh-TW" to "zh"
|
||||
lang = lang:match("(.*)-") or lang
|
||||
local results = {}
|
||||
local ok, pages = pcall(Wikipedia.wikintro, Wikipedia, word, lang)
|
||||
if ok and pages then
|
||||
for pageid, page in pairs(pages) do
|
||||
local result = {
|
||||
dict = _("Wikipedia"),
|
||||
word = page.title,
|
||||
definition = page.extract or self.no_page,
|
||||
}
|
||||
table.insert(results, result)
|
||||
end
|
||||
DEBUG("lookup result:", word, results)
|
||||
self:showDict(results, box)
|
||||
else
|
||||
DEBUG("error:", pages)
|
||||
-- dummy results
|
||||
results = {
|
||||
{
|
||||
dict = _("Wikipedia"),
|
||||
word = word,
|
||||
definition = self.no_page,
|
||||
}
|
||||
}
|
||||
DEBUG("dummy result table:", word, results)
|
||||
self:showDict(results, box)
|
||||
end
|
||||
end
|
||||
|
||||
return ReaderWikipedia
|
@ -0,0 +1,85 @@
|
||||
local socket = require('socket')
|
||||
local url = require('socket.url')
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local ltn12 = require('ltn12')
|
||||
local JSON = require("JSON")
|
||||
local DEBUG = require("dbg")
|
||||
|
||||
--[[
|
||||
-- Translate text using Google Translate.
|
||||
-- http://translate.google.com/translate_a/t?client=z&ie=UTF-8&oe=UTF-8&hl=en&tl=en&text=hello
|
||||
--]]
|
||||
|
||||
local Translator = {
|
||||
trans_servers = {
|
||||
"http://translate.google.cn",
|
||||
"http://translate.google.com",
|
||||
},
|
||||
trans_path = "/translate_a/t",
|
||||
trans_params = {
|
||||
client = "z", -- client z returns normal JSON result
|
||||
ie = "UTF-8",
|
||||
oe = "UTF-8",
|
||||
hl = "en",
|
||||
tl = "en",
|
||||
sl = nil, -- we don't specify source languagae to detect language
|
||||
},
|
||||
default_lang = "en",
|
||||
}
|
||||
|
||||
function Translator:getTransServer()
|
||||
return G_reader_settings:readSetting("trans_server") or self.trans_servers[1]
|
||||
end
|
||||
|
||||
--[[
|
||||
-- return decoded JSON table from translate server
|
||||
--]]
|
||||
function Translator:loadPage(target_lang, source_lang, text)
|
||||
local request, sink = {}, {}
|
||||
local query = ""
|
||||
self.trans_params.tl = target_lang
|
||||
self.trans_params.sl = source_lang
|
||||
for k,v in pairs(self.trans_params) do
|
||||
query = query .. k .. '=' .. v .. '&'
|
||||
end
|
||||
local parsed = url.parse(self:getTransServer())
|
||||
parsed.path = self.trans_path
|
||||
parsed.query = query .. "text=" .. url.escape(text)
|
||||
|
||||
-- HTTP request
|
||||
request['url'] = url.build(parsed)
|
||||
request['method'] = 'GET'
|
||||
request['sink'] = ltn12.sink.table(sink)
|
||||
DEBUG("request", request)
|
||||
http.TIMEOUT, https.TIMEOUT = 10, 10
|
||||
local httpRequest = parsed.scheme == 'http' and http.request or https.request
|
||||
local code, headers, status = socket.skip(1, httpRequest(request))
|
||||
|
||||
-- raise error message when network is unavailable
|
||||
if headers == nil then
|
||||
error("Network is unreachable")
|
||||
end
|
||||
|
||||
local content = table.concat(sink)
|
||||
if content ~= "" then
|
||||
local ok, result = pcall(JSON.decode, JSON, content)
|
||||
if ok and result then
|
||||
--DEBUG("translate result", result)
|
||||
return result
|
||||
else
|
||||
DEBUG("error:", result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Translator:detect(text)
|
||||
local result = self:loadPage("en", nil, text)
|
||||
if result then
|
||||
local src_lang = result.src
|
||||
DEBUG("detected language:", src_lang)
|
||||
return src_lang
|
||||
end
|
||||
end
|
||||
|
||||
return Translator
|
@ -0,0 +1,84 @@
|
||||
local socket = require('socket')
|
||||
local url = require('socket.url')
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local ltn12 = require('ltn12')
|
||||
local JSON = require("JSON")
|
||||
local DEBUG = require("dbg")
|
||||
|
||||
--[[
|
||||
-- Query wikipedia using Wikimedia Web API.
|
||||
-- http://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&exintro=&explaintext=&redirects=&titles=hello
|
||||
--]]
|
||||
|
||||
local Wikipedia = {
|
||||
wiki_server = "http://%s.wikipedia.org",
|
||||
wiki_path = "/w/api.php",
|
||||
wiki_params = {
|
||||
action = "query",
|
||||
prop = "extracts",
|
||||
format = "json",
|
||||
exintro = "",
|
||||
explaintext = "",
|
||||
redirects = "",
|
||||
},
|
||||
default_lang = "en",
|
||||
}
|
||||
|
||||
function Wikipedia:getWikiServer(lang)
|
||||
return string.format(self.wiki_server, lang or self.default_lang)
|
||||
end
|
||||
|
||||
--[[
|
||||
-- return decoded JSON table from Wikipedia
|
||||
--]]
|
||||
function Wikipedia:loadPage(text, lang, intro, plain)
|
||||
local request, sink = {}, {}
|
||||
local query = ""
|
||||
self.wiki_params.exintro = intro and "" or nil
|
||||
self.wiki_params.explaintext = plain and "" or nil
|
||||
for k,v in pairs(self.wiki_params) do
|
||||
query = query .. k .. '=' .. v .. '&'
|
||||
end
|
||||
local parsed = url.parse(self:getWikiServer(lang))
|
||||
parsed.path = self.wiki_path
|
||||
parsed.query = query .. "titles=" .. url.escape(text)
|
||||
|
||||
-- HTTP request
|
||||
request['url'] = url.build(parsed)
|
||||
request['method'] = 'GET'
|
||||
request['sink'] = ltn12.sink.table(sink)
|
||||
DEBUG("request", request)
|
||||
http.TIMEOUT, https.TIMEOUT = 10, 10
|
||||
local httpRequest = parsed.scheme == 'http' and http.request or https.request
|
||||
local code, headers, status = socket.skip(1, httpRequest(request))
|
||||
|
||||
-- raise error message when network is unavailable
|
||||
if headers == nil then
|
||||
error("Network is unreachable")
|
||||
end
|
||||
|
||||
local content = table.concat(sink)
|
||||
if content ~= "" then
|
||||
local ok, result = pcall(JSON.decode, JSON, content)
|
||||
if ok and result then
|
||||
DEBUG("wiki result", result)
|
||||
return result
|
||||
else
|
||||
DEBUG("error:", result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- extract intro passage in wiki page
|
||||
function Wikipedia:wikintro(text, lang)
|
||||
local result = self:loadPage(text, lang, true, true)
|
||||
if result then
|
||||
local query = result.query
|
||||
if query then
|
||||
return query.pages
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Wikipedia
|
Loading…
Reference in New Issue