[openstreetmap/openstreetmap-website] Integrate human-readable wikidata browser plugin (PR #6127)
Minh Nguyễn
notifications at github.com
Thu Jul 3 18:50:07 UTC 2025
@1ec5 commented on this pull request.
> + $("<a>")
+ .attr("href", OSM.WIKIMEDIA_COMMONS_URL + "File:" + data.icon)
+ .append($("<img>").attr({ src: OSM.WIKIMEDIA_COMMONS_URL + "Special:FilePath/" + data.icon, height: "32" }))
+ .addClass("float-end mb-1 ms-2")
+ .appendTo(cell);
+ }
+ if (data.label) {
+ $btn
+ .siblings(`a[href*="wikidata.org/entity/${data.qid}"]`)
+ .clone()
+ .text(data.label)
+ .addClass("me-1")
+ .appendTo(cell);
+ }
+ if (data.article) {
+ $(`<${data.label ? "sup" : "div"}>`)
The <sup>superscript</sup> suffix style probably comes from Wikidata’s former practice of glossing any fallback label with its fallback language, for example, “openstreetmap-website <sup>English</sup>” when you view [Q115259353](https://www.wikidata.org/wiki/Q115259353) in a language other than English. Otherwise, a user might not easily intuit that a suffix like “enwiki” means the title came from the English Wikipedia.
> + .append($("<img>").attr({ src: OSM.WIKIMEDIA_COMMONS_URL + "Special:FilePath/" + data.icon, height: "32" }))
+ .addClass("float-end mb-1 ms-2")
+ .appendTo(cell);
+ }
+ if (data.label) {
+ $btn
+ .siblings(`a[href*="wikidata.org/entity/${data.qid}"]`)
+ .clone()
+ .text(data.label)
+ .addClass("me-1")
+ .appendTo(cell);
+ }
+ if (data.article) {
+ $(`<${data.label ? "sup" : "div"}>`)
+ .append($("<a>")
+ .attr("href", `https://${data.article.site.slice(0, -4)}.wikipedia.org/wiki/` + encodeURIComponent(data.article.title))
The Wikidata API can return the item’s label in the relevant language. I think the label would be more relevant to OSM than the Wikipedia article, which often contains disambiguators and substitute characters for technical reasons. The label is designed to pair well with the description, which we’re using below. (Ideally, we’d fall back to the `mul` code to improve language coverage: ZeLonewolf/osm-wikidata-greasemonkey#9.)
If the idea is that the Wikidata item is already linked above, maybe we could link the label to the Wikidata item redundantly, then have a separate Wikipedia link right after it, reusing app/assets/images/social_link_icons/wikipedia.svg.
> + items
+ .filter(qid => entities[qid])
+ .map(qid => getLocalizedResponse(entities[qid]))
+ .filter(data => data.label || data.icon || data.description || data.article)
+ .map(data => renderWikidataResponse(data, $btn))
+ );
+ })
+ .catch(() => $btn.removeClass("disabled").addClass("wdt-preview"));
+ }
+
+ function getLocalizedResponse(entity) {
+ const localizedProperty = (property, langs) => langs.reduce((out, lang) => out ?? entity[property][lang], null);
+ const data = {
+ qid: entity.id,
+ label: localizedProperty("labels", langs)?.value,
+ icon: ["P8972", "P154", "P14"].reduce((out, prop) => out ?? entity.claims[prop]?.[0]?.mainsnak?.datavalue?.value, null),
For reference:
* [small logo or icon <small>(P8972)</small>](https://www.wikidata.org/wiki/Property:P8972)
* [logo image <small>(P154)</small>](https://www.wikidata.org/wiki/Property:P154)
* [traffic sign <small>(P14)</small>](https://www.wikidata.org/wiki/Property:P14)
P14 surprised me at first, but then I remembered that this would probably result in displaying a route marker alongside a `wikidata=*` tag when viewing a route relation. That does make some sense to me.
> + items
+ .filter(qid => entities[qid])
+ .map(qid => getLocalizedResponse(entities[qid]))
+ .filter(data => data.label || data.icon || data.description || data.article)
+ .map(data => renderWikidataResponse(data, $btn))
+ );
+ })
+ .catch(() => $btn.removeClass("disabled").addClass("wdt-preview"));
+ }
+
+ function getLocalizedResponse(entity) {
+ const localizedProperty = (property, langs) => langs.reduce((out, lang) => out ?? entity[property][lang], null);
+ const data = {
+ qid: entity.id,
+ label: localizedProperty("labels", langs)?.value,
+ icon: ["P8972", "P154", "P14"].reduce((out, prop) => out ?? entity.claims[prop]?.[0]?.mainsnak?.datavalue?.value, null),
In case the item has multiple statements associated with one of these properties, the `claims[prop]` array will contain multiple items, but the first one isn’t guaranteed to be the best. For example, [Deutsche Post <small>(Q157645)</small>](https://www.wikidata.org/wiki/Q157645#P154) has four different P154 statements. The last is the most current, so the `mainsnak` has a `rank` of `preferred` rather than `normal`.
> + label: localizedProperty("labels", langs)?.value,
+ icon: ["P8972", "P154", "P14"].reduce((out, prop) => out ?? entity.claims[prop]?.[0]?.mainsnak?.datavalue?.value, null),
+ description: localizedProperty("descriptions", langs)?.value,
+ article: localizedProperty("sitelinks", wikis)
+ };
+ return data;
+ }
+
+ function renderWikidataResponse(data, $btn) {
+ const cell = $("<td>")
+ .attr("colspan", 2)
+ .addClass("bg-body-tertiary");
+
+ if (data.icon && OSM.WIKIMEDIA_COMMONS_URL) {
+ $("<a>")
+ .attr("href", OSM.WIKIMEDIA_COMMONS_URL + "File:" + data.icon)
Do we need to escape the `icon` in any way?
> + icon: ["P8972", "P154", "P14"].reduce((out, prop) => out ?? entity.claims[prop]?.[0]?.mainsnak?.datavalue?.value, null),
+ description: localizedProperty("descriptions", langs)?.value,
+ article: localizedProperty("sitelinks", wikis)
+ };
+ return data;
+ }
+
+ function renderWikidataResponse(data, $btn) {
+ const cell = $("<td>")
+ .attr("colspan", 2)
+ .addClass("bg-body-tertiary");
+
+ if (data.icon && OSM.WIKIMEDIA_COMMONS_URL) {
+ $("<a>")
+ .attr("href", OSM.WIKIMEDIA_COMMONS_URL + "File:" + data.icon)
+ .append($("<img>").attr({ src: OSM.WIKIMEDIA_COMMONS_URL + "Special:FilePath/" + data.icon, height: "32" }))
Special:FilePath is now an alias for Special:Redirect:
```suggestion
.append($("<img>").attr({ src: OSM.WIKIMEDIA_COMMONS_URL + "Special:Redirect/file/" + data.icon, height: "32" }))
```
> + icon: ["P8972", "P154", "P14"].reduce((out, prop) => out ?? entity.claims[prop]?.[0]?.mainsnak?.datavalue?.value, null),
+ description: localizedProperty("descriptions", langs)?.value,
+ article: localizedProperty("sitelinks", wikis)
+ };
+ return data;
+ }
+
+ function renderWikidataResponse(data, $btn) {
+ const cell = $("<td>")
+ .attr("colspan", 2)
+ .addClass("bg-body-tertiary");
+
+ if (data.icon && OSM.WIKIMEDIA_COMMONS_URL) {
+ $("<a>")
+ .attr("href", OSM.WIKIMEDIA_COMMONS_URL + "File:" + data.icon)
+ .append($("<img>").attr({ src: OSM.WIKIMEDIA_COMMONS_URL + "Special:FilePath/" + data.icon, height: "32" }))
> I'm not sure if it's allowed according to [their policy](https://commons.wikimedia.org/w/index.php?title=Commons:HOTLINK), but we're already doing it in iD.
As far as I know, Wikimedia would prefer that we use the Wikimedia Commons API to get the image thumbnail. For example, [this API call](https://commons.wikimedia.org/wiki/Special:ApiSandbox#action=query&format=json&prop=imageinfo&titles=File%3ADHL%20Group%2006.2023.svg&formatversion=2&iiprop=url%7Csize&iiurlwidth=32) gets a thumbnail of [this image](https://commons.wikimedia.org/wiki/File:DHL_Group_06.2023.svg) scaled to 32 pixels wide, along with responsive images at 1.5× and 2×. The API allows batching up to 50 images at a time.
--
Reply to this email directly or view it on GitHub:
https://github.com/openstreetmap/openstreetmap-website/pull/6127#pullrequestreview-2984219344
You are receiving this because you are subscribed to this thread.
Message ID: <openstreetmap/openstreetmap-website/pull/6127/review/2984219344 at github.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstreetmap.org/pipermail/rails-dev/attachments/20250703/dbd8d399/attachment-0001.htm>
More information about the rails-dev
mailing list