Jump to content

Tech

Add topic
From Meta, a Wikimedia project coordination wiki
Latest comment: 13 hours ago by Matrix in topic jQuery and dark mode styles

Geohack patch

[edit]

I have a patch for Geohack that I'd like to get reviewed and merged, but I am not getting any replies from Magnus Manske. Does anyone how I can progress on getting my patch merged? --ysangkok (talk) 22:46, 20 January 2025 (UTC)Reply

A map problem on Belarusian Wikipedia

[edit]

Hello!

There's a problem with the coordinates of the dot on the map on this page: https://be.wikipedia.org/wiki/%D0%90%D1%81%D1%96%D0%BF%D0%BE%D0%B2%D1%96%D1%87%D1%8B

The coordinates of the town in WikiData and in the main template are set right, but the point is located wrong. The red dot location is too much south.

The problem is connected with these module: https://be.wikipedia.org/wiki/Модуль:Location_map, https://be.wikipedia.org/wiki/Модуль:Location_map/styles.css

How can I fix it? Hapanovicz Anton (talk) 20:36, 22 January 2025 (UTC)Reply

Scoring tool for Wikidata

[edit]

Hello! I would like to request a scoring tool for Wikidata. I am part of a project that organizes editing contests on Wikipedia, Wikidata, and Wikimedia Commons, and we feel the need for a tool that simplifies the process of scoring contributions on Wikidata. In the Brazilian context, we have a similar initiative for Wikipedia called Wikiscore, but nothing comparable for Wikidata. Does anyone here know of a similar tool for Wikidata or would be interested in participating in its development? Vsdetoni (Projeto Mais+) (talk) 18:25, 28 January 2025 (UTC)Reply

Understanding Wikipedia titles batching API

[edit]

With the MediaWiki API we can query the Wikipedia API. One of the fields is `titles` where one *or more* titles can be queried at the same time. Batching them together is recommended in high load scenarios to avoid multiple consecutive requests. Multiple titles should be separated by a pipe `|` character.

I am using the Wikipedia API to find "translations" of categories. Let's say I have an English category "Antiquity", I want to find the corresponding category in a different language. That is possible by querying the API for the prop `langlinks`.

I find that, indeed, I can find such one-on-one mappings of an English category if I do not use batching, but if I *do* use batching, I do not always get all of the results back. To illustrate, I have a list of English categories, and at each iteration I process one item more than before (starting with only one). With batching, it becomes clear that with larger lists (still well within the max. limit of 50 imposed by the API), the earlier categories are lost and not included anymore. When not using batching (batch size=1), this issue does not occur.


import requests

def get_translated_category(category_titles: str | list[str], target_lang: str, batch_size: int = 50) -> list[str]:
    """Fetch the translated equivalent of a Wikipedia category."""
   
    endpoint = "https://en.wikipedia.org/w/api.php"
    if isinstance(category_titles, str):
        category_titles = [category_titles]

    category_titles = [f"Category:{title}" for title in category_titles]

    translated_categories = {}
    # API is limited to 50 titles per request
    for start_idx in range(0, len(category_titles), batch_size):
        end_idx = start_idx + batch_size
        batch_titles = category_titles[start_idx:end_idx]
        params = {
            "action": "query",
            "format": "json",
            "prop": "langlinks",
            "titles": "|".join(batch_titles),
            "lllimit": "max"
        }

        response = requests.get(endpoint, params=params)
        data = response.json()

        pages = data.get("query", {}).get("pages", {})
        for page_data in pages.values():
            title = page_data["title"].split(":")[-1]
            if title in translated_categories:
                print("We already found this category title!")
            langlinks = page_data.get("langlinks", [])
            for link in langlinks:
                if link["lang"] == target_lang:
                    translated_categories[title] = link["*"].split(":")[-1]

    return translated_categories




if __name__ == "__main__":
    english_categories: list[str] = [
        "Classical antiquity",
        "Late antiquity",
        "Latin-language literature",
        "Roman Kingdom",
        "Roman Republic",
        "Roman Empire",
        "Byzantine Empire",
        "Latin language",
        "Ancient Greek",
        "Ancient Greece",
        "Ancient Greek literature",
        "Medieval history of Greece",
    ]

    print("Batch size 50 (default)")
    for idx in range(len(english_categories)):
        categories = english_categories[:idx+1]
        latin_categories = get_translated_category(categories, "la")
        print(latin_categories)
   
    print()
    print("Batch size 1 (no batching)")
    for idx in range(len(english_categories)):
        categories = english_categories[:idx+1]
        latin_categories = get_translated_category(categories, "la", batch_size=1)
        print(latin_categories)

The output of the code above is:

# Batch size 50 (default)
{'Classical antiquity': 'Res classicae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum'}
{'Byzantine Empire': 'Imperium Byzantinum', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum'}
{'Byzantine Empire': 'Imperium Byzantinum', 'Late antiquity': 'Antiquitas Posterior', 'Latin language': 'Lingua Latina', 'Roman Empire': 'Imperium Romanum'}
{'Byzantine Empire': 'Imperium Byzantinum', 'Late antiquity': 'Antiquitas Posterior', 'Latin language': 'Lingua Latina', 'Roman Empire': 'Imperium Romanum'}
{'Ancient Greece': 'Graecia antiqua', 'Byzantine Empire': 'Imperium Byzantinum', 'Late antiquity': 'Antiquitas Posterior', 'Roman Empire': 'Imperium Romanum'}
{'Ancient Greece': 'Graecia antiqua', 'Byzantine Empire': 'Imperium Byzantinum', 'Late antiquity': 'Antiquitas Posterior', 'Roman Empire': 'Imperium Romanum'}
{'Ancient Greece': 'Graecia antiqua', 'Byzantine Empire': 'Imperium Byzantinum', 'Late antiquity': 'Antiquitas Posterior', 'Roman Empire': 'Imperium Romanum'}

# Batch size 1 (no batching)
{'Classical antiquity': 'Res classicae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum', 'Byzantine Empire': 'Imperium Byzantinum'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum', 'Byzantine Empire': 'Imperium Byzantinum', 'Latin language': 'Lingua Latina'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum', 'Byzantine Empire': 'Imperium Byzantinum', 'Latin language': 'Lingua Latina', 'Ancient Greek': 'Lingua Graeca antiqua'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum', 'Byzantine Empire': 'Imperium Byzantinum', 'Latin language': 'Lingua Latina', 'Ancient Greek': 'Lingua Graeca antiqua', 'Ancient Greece': 'Graecia antiqua'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum', 'Byzantine Empire': 'Imperium Byzantinum', 'Latin language': 'Lingua Latina', 'Ancient Greek': 'Lingua Graeca antiqua', 'Ancient Greece': 'Graecia antiqua', 'Ancient Greek literature': 'Litterae Graecae antiquae'}
{'Classical antiquity': 'Res classicae', 'Late antiquity': 'Antiquitas Posterior', 'Latin-language literature': 'Litterae Latinae', 'Roman Empire': 'Imperium Romanum', 'Byzantine Empire': 'Imperium Byzantinum', 'Latin language': 'Lingua Latina', 'Ancient Greek': 'Lingua Graeca antiqua', 'Ancient Greece': 'Graecia antiqua', 'Ancient Greek literature': 'Litterae Graecae antiquae'}

It should be immediately clear that there is a difference between batching and not using batching and, more worrisome, that using batching leads to some items being discarded. I thought that perhaps this would be the case if categories are merged in Latin and have the same name, so the API resolves to only returning one of them, but as far as I can tell that is not the case.

How can I ensure that batching my requests (titles) together, I get the same results as firing individual requests with the Wikipedia API?

EDIT: after further investigation it would seem that the API does return results for all categories (the `pages ` variable) but for some reason the corresponding languages (`langlinks`) are not the same. BramVanroy (talk) 13:21, 12 February 2025 (UTC)Reply

You need to follow API continuation, e.g. using continuation=True when using mwapi. Lucas Werkmeister (talk) 14:00, 12 February 2025 (UTC)Reply

User group without rights

[edit]

At Wikidata:Project_chat#Should_we_certify_Wikidata_trainers?, we are currently discussing how best to ensure that those embarking on the task of introducing new users to the project are appropriately experienced. A proposal is to create a new user group, say "trainer", that is not necessarily associated with any user rights. This is related to the existing Event Organizer group, but differs in a significant way: The criteria for event organizer say that the user should either have experience of organizing an event or be a grant recipient. We want to turn this around and say that editors should have qualifying experience of normal editing before either organizing an event or being eligible to receive a grant. I see that there is some precedent for having specific user groups only used on one project, but there seems to be little precedent for user groups not associated with user rights. We want it to be easy to check that someone is qualified, for example by using the global accounts page. I anticipate that other projects may want to adopt a similar process, so this would allow users to be checked on multiple projects at once.

My question is, is this a reasonable approach, or would there be resistance to the idea of a user group not (necessarily) associated with any user rights? Bovlb (talk) 21:21, 12 February 2025 (UTC)Reply

Technically it is impossible to create a group without rights, but this is often worked around by giving some dummy right like read. For example the VRTS member global group and Founder local group on enwiki work in the same way. Personally this idea seems a bit odd to me, but if you get local consensus to do it the sysadmins will be wiling to oblige. * Pppery * it has begun 00:31, 13 February 2025 (UTC)Reply
Thanks. Just out of curiosity, what about this idea seems odd? Bovlb (talk) 23:36, 13 February 2025 (UTC)Reply

jQuery and dark mode styles

[edit]

Hi, is there a pre-defined list of dark mode styles I can apply to jQuery? I'm trying to convert c:MediaWiki:Gadget-VisualFileChange.js to use dark mode styles, but I need to change styles for elements like .ui-widget. I know the correct thing would be to convert this to ooUI, but is there a short term fix I can apply? —Matrix (user page (@ commons) - talk?) 12:35, 15 February 2025 (UTC)Reply