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
chrox 10 years ago
parent 56fa8a45b7
commit 7b10d66e1b

@ -12,6 +12,7 @@ local ReaderDictionary = EventListener:new{}
function ReaderDictionary:onLookupWord(word, box, highlight)
self.highlight = highlight
self:stardictLookup(word, box)
return true
end
function ReaderDictionary:stardictLookup(word, box)
@ -47,24 +48,7 @@ end
function ReaderDictionary:showDict(results, box)
if results and results[1] then
DEBUG("showing quick lookup dictionary window")
local align = "center"
local region = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
if box then
if box.y + box.h/2 < Screen:getHeight()/2 then
region.y = box.y + box.h
region.h = Screen:getHeight() - box.y - box.h
align = "top"
else
region.y = 0
region.h = box.y
align = "bottom"
end
end
DEBUG("showing quick lookup window")
UIManager:show(DictQuickLookup:new{
ui = self.ui,
highlight = self.highlight,
@ -72,9 +56,9 @@ function ReaderDictionary:showDict(results, box)
results = results,
dictionary = self.default_dictionary,
width = Screen:getWidth() - Screen:scaleByDPI(80),
height = math.min(region.h*0.7, Screen:getHeight()*0.5),
region = region,
align = align,
word_box = box,
-- differentiate between dict and wiki
wiki = self.wiki,
})
end
end
@ -82,6 +66,7 @@ end
function ReaderDictionary:onUpdateDefaultDict(dict)
DEBUG("make default dictionary:", dict)
self.default_dictionary = dict
return true
end
function ReaderDictionary:onReadSettings(config)

@ -294,8 +294,7 @@ function ReaderHighlight:onHoldRelease()
text = _("Highlight"),
callback = function()
self:saveHighlight()
UIManager:close(self.highlight_dialog)
self:handleEvent(Event:new("Tap"))
self:onClose()
end,
},
{
@ -303,39 +302,44 @@ function ReaderHighlight:onHoldRelease()
enabled = false,
callback = function()
self:addNote()
UIManager:close(self.highlight_dialog)
self:handleEvent(Event:new("Tap"))
self:onClose()
end,
},
},
{
{
text = _("Wikipedia"),
callback = function()
UIManager:scheduleIn(0.1, function()
self:lookupWikipedia()
self:onClose()
end)
end,
},
{
text = _("Translate"),
enabled = false,
callback = function()
self:translate(self.selected_text)
UIManager:close(self.highlight_dialog)
self:handleEvent(Event:new("Tap"))
self:onClose()
end,
},
},
{
{
text = _("Share"),
enabled = false,
callback = function()
self:shareHighlight()
UIManager:close(self.highlight_dialog)
self:handleEvent(Event:new("Tap"))
self:onClose()
end,
},
},
{
{
text = _("More"),
enabled = false,
callback = function()
self:moreAction()
UIManager:close(self.highlight_dialog)
self:handleEvent(Event:new("Tap"))
self:onClose()
end,
},
},
@ -411,6 +415,12 @@ function ReaderHighlight:addNote()
DEBUG("add Note")
end
function ReaderHighlight:lookupWikipedia()
if self.selected_text then
self.ui:handleEvent(Event:new("LookupWikipedia", self.selected_text.text))
end
end
function ReaderHighlight:shareHighlight()
DEBUG("share highlight")
end
@ -436,4 +446,10 @@ function ReaderHighlight:onSaveSettings()
self.ui.doc_settings:saveSetting("highlight_drawer", self.view.highlight.saved_drawer)
end
function ReaderHighlight:onClose()
UIManager:close(self.highlight_dialog)
-- clear highlighted text
self:handleEvent(Event:new("Tap"))
end
return ReaderHighlight

@ -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

@ -29,6 +29,7 @@ local ReaderHighlight = require("apps/reader/modules/readerhighlight")
local ReaderScreenshot = require("apps/reader/modules/readerscreenshot")
local ReaderFrontLight = require("apps/reader/modules/readerfrontlight")
local ReaderDictionary = require("apps/reader/modules/readerdictionary")
local ReaderWikipedia = require("apps/reader/modules/readerwikipedia")
local ReaderHyphenation = require("apps/reader/modules/readerhyphenation")
local ReaderActivityIndicator = require("apps/reader/modules/readeractivityindicator")
local ReaderLink = require("apps/reader/modules/readerlink")
@ -142,6 +143,13 @@ function ReaderUI:init()
ui = self,
document = self.document,
})
-- wikipedia
table.insert(self, ReaderWikipedia:new{
dialog = self.dialog,
view = self[1],
ui = self,
document = self.document,
})
-- screenshot controller
table.insert(self.active_widgets, ReaderScreenshot:new{
dialog = self.dialog,

@ -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

@ -37,6 +37,8 @@ local DictQuickLookup = InputContainer:new{
content_face = Font:getFace("cfont", DDICT_FONT_SIZE),
width = nil,
height = nil,
-- box of highlighted word, quick lookup window tries to not hide the word
word_box = nil,
title_padding = Screen:scaleByDPI(5),
title_margin = Screen:scaleByDPI(2),
@ -85,6 +87,26 @@ function DictQuickLookup:init()
end
function DictQuickLookup:update()
-- calculate window dimension and try to not hide highlighted word
self.align = "center"
self.region = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
if self.word_box then
local box = self.word_box
if box.y + box.h/2 < Screen:getHeight()/2 then
self.region.y = box.y + box.h
self.region.h = Screen:getHeight() - box.y - box.h
self.align = "top"
else
self.region.y = 0
self.region.h = box.y
self.align = "bottom"
end
end
self.height = math.min(self.region.h*0.7, Screen:getHeight()*0.5)
-- dictionary title
self.dict_title = FrameContainer:new{
padding = self.title_padding,
@ -150,9 +172,11 @@ function DictQuickLookup:update()
{
{
text = _("Wikipedia"),
enabled = false,
callback = function()
self.ui:handleEvent(Event:new("HighlightWiki"))
UIManager:scheduleIn(0.1, function()
self:lookupWikipedia()
self:onClose()
end)
end,
},
{
@ -225,7 +249,7 @@ function DictQuickLookup:update()
}
self[1] = WidgetContainer:new{
align = self.align,
dimen = self.region:copy(),
dimen = self.region,
FrameContainer:new{
bordersize = 0,
padding = Screen:scaleByDPI(5),
@ -336,6 +360,7 @@ function DictQuickLookup:lookupInputWord(hint)
self:onClose()
self.input_dialog = InputDialog:new{
title = _("Input lookup word"),
input = hint,
input_hint = hint or "",
input_type = "text",
buttons = {
@ -369,7 +394,8 @@ end
function DictQuickLookup:inputLookup()
local word = self.input_dialog:getInputText()
if word and word ~= "" then
self.ui:handleEvent(Event:new("LookupWord", word))
local event = self.wiki and "LookupWikipedia" or "LookupWord"
self.ui:handleEvent(Event:new(event, word))
end
end
@ -378,4 +404,8 @@ function DictQuickLookup:closeInputDialog()
UIManager:close(self.input_dialog)
end
function DictQuickLookup:lookupWikipedia()
self.ui:handleEvent(Event:new("LookupWikipedia", self.lookupword, self.word_box))
end
return DictQuickLookup

@ -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…
Cancel
Save