[gnome-maps] wikipedia: Find articles in the user's language
- From: Marcus Lundblad <mlundblad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-maps] wikipedia: Find articles in the user's language
- Date: Sun, 15 Nov 2020 21:43:12 +0000 (UTC)
commit ec20d9c28582c5a47fe932fec8b9d333feb993c4
Author: James Westman <james flyingpimonster net>
Date: Mon Aug 10 14:58:25 2020 -0500
wikipedia: Find articles in the user's language
Using Wikipedia's Language Links feature, we can try to find an article in the
user's language, even if the place's wikipedia tag is a different language.
This involved refactoring a bit of wikipedia.js.
src/placeBubble.js | 6 ++--
src/wikipedia.js | 92 +++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 72 insertions(+), 26 deletions(-)
---
diff --git a/src/placeBubble.js b/src/placeBubble.js
index 8d2a3bbc..2e59fc8f 100644
--- a/src/placeBubble.js
+++ b/src/placeBubble.js
@@ -376,8 +376,6 @@ var PlaceBubble = GObject.registerClass({
}
_requestWikipedia(wiki) {
- this._wiki = wiki;
-
Wikipedia.fetchArticleInfo(wiki,
THUMBNAIL_FETCH_SIZE,
this._onWikiMetadataComplete.bind(this),
@@ -388,10 +386,10 @@ var PlaceBubble = GObject.registerClass({
this.thumbnail = thumbnail;
}
- _onWikiMetadataComplete(metadata) {
+ _onWikiMetadataComplete(wiki, metadata) {
if (metadata.extract) {
let text = GLib.markup_escape_text(metadata.extract, -1);
- let link = this._formatWikiLink(this._wiki);
+ let link = this._formatWikiLink(wiki);
/* If the text goes past some number of characters (see
* wikipedia.js), it is ellipsized with '...'
diff --git a/src/wikipedia.js b/src/wikipedia.js
index cca2ab36..ebe3fa20 100644
--- a/src/wikipedia.js
+++ b/src/wikipedia.js
@@ -58,9 +58,9 @@ function getHtmlEntityEncodedArticle(wiki) {
*
* @size is the maximum width of the thumbnail.
*
- * Calls @metadataCb with an object containing information about the article.
- * For the keys/values of this object, see the relevant MediaWiki API
- * documentation.
+ * Calls @metadataCb with the lang:title pair for the article and an object
+ * containing information about the article. For the keys/values of this
+ * object, see the relevant MediaWiki API documentation.
*
* Calls @thumbnailCb with the Gdk.Pixbuf of the icon when successful, otherwise
* null.
@@ -71,13 +71,16 @@ function fetchArticleInfo(wiki, size, metadataCb, thumbnailCb) {
let uri = Format.vprintf('https://%s.wikipedia.org/w/api.php', [ lang ]);
let msg = Soup.form_request_new_from_hash('GET', uri, { action: 'query',
titles: title,
- prop: 'extracts|pageimages',
+ prop: 'extracts|pageimages|langlinks',
format: 'json',
/* Allow redirects, for example if an
article is renamed. */
redirects: '1',
+ /* Make sure we get all lang links */
+ lllimit: 'max',
+
/* don't go past first section header */
exintro: 'yes',
/* limit the length */
@@ -88,19 +91,19 @@ function fetchArticleInfo(wiki, size, metadataCb, thumbnailCb) {
pithumbsize: size + ''});
let session = _getSoupSession();
let cachedMetadata = _metadataCache[wiki];
- let cachedThumbnail = _thumbnailCache[wiki + '/' + size];
- if (cachedMetadata && cachedThumbnail) {
- metadataCb(cachedMetadata);
- thumbnailCb(cachedThumbnail);
+ if (cachedMetadata) {
+ _onMetadataFetched(wiki, cachedMetadata, size, metadataCb, thumbnailCb);
return;
}
session.queue_message(msg, (session, msg) => {
if (msg.status_code !== Soup.KnownStatusCode.OK) {
log("Failed to request Wikipedia metadata: " + msg.reason_phrase);
- metadataCb({});
- thumbnailCb(null);
+ metadataCb(null, {});
+ if (thumbnailCb) {
+ thumbnailCb(null);
+ }
return;
}
@@ -116,30 +119,52 @@ function fetchArticleInfo(wiki, size, metadataCb, thumbnailCb) {
let page = pages[pageId];
_metadataCache[wiki] = page;
- metadataCb(page);
-
- let thumbnail = page.thumbnail;
- if (thumbnail) {
- let source = page.thumbnail.source;
-
- _fetchThumbnailImage(wiki, size, source, thumbnailCb);
- } else {
- thumbnailCb(null);
- }
+ _onMetadataFetched(wiki, page, size, metadataCb, thumbnailCb);
return;
}
} else {
- metadataCb({});
- thumbnailCb(null);
+ metadataCb(null, {});
+ if (thumbnailCb) {
+ thumbnailCb(null);
+ }
}
});
}
+function _onMetadataFetched(wiki, page, size, metadataCb, thumbnailCb) {
+ /* Try to get a thumbnail *before* following language links--the primary
+ article probably has the best thumbnail image */
+ if (thumbnailCb && page.thumbnail) {
+ let source = page.thumbnail.source;
+
+ _fetchThumbnailImage(wiki, size, source, thumbnailCb);
+ thumbnailCb = null;
+ }
+
+ /* Follow language links if necessary */
+ let langlink = _findLanguageLink(wiki, page);
+ if (langlink) {
+ fetchArticleInfo(langlink, size, metadataCb, thumbnailCb);
+ } else {
+ metadataCb(wiki, page);
+
+ if (thumbnailCb) {
+ thumbnailCb(null);
+ }
+ }
+}
+
function _fetchThumbnailImage(wiki, size, source, callback) {
let uri = new Soup.URI(source);
let msg = new Soup.Message({ method: 'GET', uri: uri });
let session = _getSoupSession();
+ let cachedThumbnail = _thumbnailCache[wiki + '/' + size];
+ if (cachedThumbnail) {
+ callback(cachedThumbnail);
+ return;
+ }
+
session.queue_message(msg, (session, msg) => {
if (msg.status_code !== Soup.KnownStatusCode.OK) {
log("Failed to download thumbnail: " + msg.reason_phrase);
@@ -163,3 +188,26 @@ function _fetchThumbnailImage(wiki, size, source, callback) {
stream.close(null);
});
}
+
+/* Finds the best language to use, based on the language of the original
+ article and the langlinks data from the Wikipedia API.
+
+ Returns a lang:title string if that article should be used, or undefined if
+ the original article should be used. */
+function _findLanguageLink(wiki, page) {
+ let originalLang = getLanguage(wiki);
+ let languages = GLib.get_language_names().map((lang) => lang.split(/[\._\-]/)[0]);
+
+ if (!languages.includes(originalLang)) {
+ let langlinks = {};
+ for (let langlink of (page.langlinks || [])) {
+ langlinks[langlink.lang] = langlink["*"];
+ }
+
+ for (let language of languages) {
+ if (language in langlinks) {
+ return language + ":" + langlinks[language];
+ }
+ }
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]