34
submitted 3 days ago* (last edited 3 days ago) by Erika3sis@hexbear.net to c/languagelearning@hexbear.net

How to use:

Step 1: Install a script manager if you don't have one already. I use TamperMonkey, the most popular script manager on Firefox. I will be assuming you're using that script manager, too. You may want to give it permission to run in private windows.

Step 2: Click on TamperMonkey in your list of browser extensions, make sure it's enabled, then click "create a new script".

Step 3: Copy-paste the following script.

script

// ==UserScript==
// @name         Wikipedia Language Redirector
// @version      v3
// @match        https://en.wikipedia.org/*
// @description  Redirects wikipedia pages to alternate language pages in order of predefined preference
// @author       Enjoyer_of_Games
// @author       Edie
// @run-at       document-idle
// @license      AGPL 3+
// ==/UserScript==

const langBtn = document.querySelector('#p-lang-btn');

if (langBtn) {
    let LanguageList = ['nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh'];
    for (const langCode of LanguageList) {
        let linktarget = document.querySelector(`a.interlanguage-link-target[lang="${langCode}"]`);
        if(linktarget){
            let langLink = linktarget.href;
            if (langLink){
              console.log(window.location);
              console.log(`Navigating to language: ${langCode}`);
              window.location.href = langLink;
              break;
            }
            else {
               console.warn(`Could not find language link for "${langCode}"`);
            }
        }
    }
}
else {
    console.log('Could not find the #p-lang-btn element');
}

Step 4: Modify the script at the following points:

Point 1:

// @match        https://en.wikipedia.org/*

Replace the "en" in https://en.wikipedia.org/* with the Wikipedia language code of whatever your first language is.

Point 2:

    let LanguageList = ['nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh'];

Replace 'nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh' with the Wikipedia language codes of your target languages in order of priority, using the same syntax. Note that you need to use "nb" as the language code for Norwegian Bokmål, not "no". Edie says to use ISO 639 codes instead of Wikipedia language codes, because of the nb/no issue, but I'm not sure if this is accurate.

Step 5: Click "file" → "save", then under TamperMonkey's "installed userscripts" tab make sure that the Wikipedia Language Redirector script is enabled.

Step 6: Test it out and see if it works!

top 12 comments
sorted by: hot top new old
[-] wheresmysurplusvalue@hexbear.net 6 points 3 days ago* (last edited 3 days ago)

Kudos to the authors for making it!

I was considering an alternate approach by calling Wikipedia's REST API Get languages GET /page/{title}/links/language to get all the available languages for a page. Then search the response for the first language in the list which is available, and redirect to that. It's an extra network request, but maybe more resilient to differences in how the HTML is rendered in the future.

See for example the languages list for the article on the Soviet Union: https://en.wikipedia.org/w/rest.php/v1/page/Soviet_Union/links/language

[-] wheresmysurplusvalue@hexbear.net 5 points 3 days ago* (last edited 2 days ago)

Alright I had nothing to do this evening so here's my API version. It was noticeably slower when using @run-at document-idle, but since this version doesn't need to reference anything on the page, I moved it up to document-start.

version 3 (code cleanup and using language code 'no' instead of 'nb')

// ==UserScript==
// @name         Wikipedia Language Redirector (Using Mediawiki API)
// @version      v3
// @match        https://en.wikipedia.org/wiki/*
// @description  Redirects wikipedia pages to alternate language pages in order of predefined preference
// @author       wheresmysurplusvalue
// @run-at       document-start
// @license      AGPL 3+
// ==/UserScript==

const LanguageList = ['no', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh'];

function main() {
    if (LanguageList.length == 0) {
        return;
    }

    const path = window.location.pathname;
    const title = parseTitle(path);

    if (title) {
        resolveTitle(title)
        .then(getLanguages)
        .then(chooseLanguage)
        .then(redirectLanguage)
        .catch(err => console.error(err));
    } else {
        console.log("Article title could not be parsed:", path);
    }
}

function redirectLanguage(pageLanguage) {
    window.location.href = `https://${pageLanguage.code}.wikipedia.org/wiki/${pageLanguage.key}`;
}

function chooseLanguage(availableLanguages) {
    const pageLanguage = filterLanguages(availableLanguages).next().value;
    if (!pageLanguage) {
        throw new Error(`Article not available in preferred languages: ${LanguageList}`);
    }
    return pageLanguage;
}

function* filterLanguages(availableLanguages) {
   for (const langCode of LanguageList) {
      for (const pageLanguage of availableLanguages) {
         if (pageLanguage.code == langCode) {
             yield pageLanguage;
         }
      }
   }
}

function parseTitle(path) {
    const regex = /^\/wiki\/(.*)/;
    const match = path.match(regex);

    if (!match) {
        console.error(`Could not parse title from path: ${path}`);
        return null;
    }

    const title = match[1];
    console.log("Extracted article title:", title);
    return title;
}

async function request(url) {
    const response = await fetch(url);
    if (!response.ok) {
        throw new Error(`HTTP error! url: ${url}, status: ${response.status}`);
    }
    return await response.json();
}

async function resolveTitle(title) {
    return getPage(title).then(data => data.key);
}

async function getPage(title) {
    const url = `/w/rest.php/v1/page/${title}/bare`;
    return requestPage(url, true);
}

async function requestPage(url, followRedirect) {
    return request(url).then(data => {
        console.log("data:", data);
        if (followRedirect && data.redirect_target) {
            return requestPage(data.redirect_target, followRedirect);
        }
        return data;
    });
}

async function getLanguages(title) {
    const url = `/w/rest.php/v1/page/${title}/links/language`;
    return request(url);
}

main();

version 2 (added a call to the page API to follow redirects)

// ==UserScript==
// @name         Wikipedia Language Redirector (Using Mediawiki API)
// @version      v2
// @match        https://en.wikipedia.org/wiki/*
// @description  Redirects wikipedia pages to alternate language pages in order of predefined preference
// @author       wheresmysurplusvalue
// @run-at       document-start
// @license      AGPL 3+
// ==/UserScript==

const LanguageList = ['nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh'];

function main() {
    const path = window.location.pathname;
    const title = getTitle(path);

    if (title) {
        getRealTitle(title)
        .then(title => getLanguages(title))
        .then(data => chooseLanguage(data));
    } else {
        console.log("Article title could not be parsed: ", path);
    }
}

function chooseLanguage(availableLanguages) {
   for (const langCode of LanguageList) {
      for (const pageLanguage of availableLanguages) {
         if (pageLanguage.code == langCode) {
             console.log("Found match: ", langCode);
             window.location.href = `https://${pageLanguage.code}.wikipedia.org/wiki/${pageLanguage.key}`;
             return;
         }
      }
   }
   console.log("Article not available in preferred languages.");
}

function getTitle(path) {
    const regex = /^\/wiki\/(.*)/;

    const match = path.match(regex);

    if (match) {
        const title = match[1];
        console.log("Extracted article title: ", title);

        return title;
    }

    return null;
}

async function request(url) {
    try {
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error fetching data:', error);
    }
}

async function getLanguages(title) {
    const url = `/w/rest.php/v1/page/${title}/links/language`;
    return request(url);
}

async function getRealTitle(title) {
    const url = `/w/rest.php/v1/page/${title}/bare`;
    return getPage(url).then(data => {
        console.log("Resolved title: ", data.key);
        return data.key;
    });
}

async function getPage(url) {
    return request(url).then(data => {
        console.log("data: ", data);
        if (data.redirect_target) {
            return getPage(data.redirect_target);
        }
        return data;
    });

}

main();

version 1 (does not work if the page is redirected)

// ==UserScript==
// @name         Wikipedia Language Redirector (Using Mediawiki API)
// @version      v1
// @match        https://en.wikipedia.org/wiki/*
// @description  Redirects wikipedia pages to alternate language pages in order of predefined preference
// @author       wheresmysurplusvalue
// @run-at       document-start
// @license      AGPL 3+
// ==/UserScript==

const LanguageList = ['nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh'];

function handleResponse(json) {
   for (const langCode of LanguageList) {
      for (const pageLanguage of json) {
         if (pageLanguage.code == langCode) {
             console.log("Found match: ", langCode);
             window.location.href = `https://${pageLanguage.code}.wikipedia.org/wiki/${pageLanguage.key}`;
             return;
         }
      }
   }
   console.log("Article not available in preferred languages.");
}

const path = window.location.pathname;
const title = getTitle(path);

if (title) {
    getLanguages(title, handleResponse);
} else {
    console.log("Article title could not be parsed: ", path);
}

function getTitle(path) {
    const regex = /^\/wiki\/(.*)/;

    const match = path.match(regex);

    if (match) {
        const title = match[1];
        console.log("Extracted article title: ", title);

        return title;
    }

    return null;
}

function getLanguages(title, callback) {
    const request_url = `/w/rest.php/v1/page/${title}/links/language`;
    console.log("Request url: ", request_url);

    fetch(request_url)
        .then(response => {
            if (!response.ok) {
                throw new Error("HTTP status code in error: " + response.statusText);
            }
            return response.json();
        })
        .then(data => callback(data))
        .catch(error => {
            console.error("Error: ", error);
        });
}

[-] Erika3sis@hexbear.net 4 points 3 days ago

Curiously, in this script you apparently need to use 'no' instead of 'nb' to get to Norwegian Bokmål, rather than the reverse.

Oh interesting, dunno why they use a slightly different list of languages codes:

Language matrix

[-] edie@lemmy.encryptionin.space 4 points 3 days ago* (last edited 3 days ago)

Replace [LanguageList] with the Wikipedia language codes

Actually the ISO 639. Enjoyer_of_Games made the mistake of using no for bokmål because that is what wikipedia uses, no.wikipedia.org, the correct code is nb from ISO 639. But usually this isn't a problem, and the wikipedia code corresponds to the 639 one.


This user is suspected of being a cat. Please report any suspicious behavior.

[-] edie@lemmy.encryptionin.space 3 points 3 days ago* (last edited 3 days ago)

hang on... wait a minute, why are we doing a while loop? What need is there to do it again after we have looped through it once? If we don't find a link from one of the languages, we shouldn't try again.

Here's v3, with the loop removed

// ==UserScript==
// @name         Wikipedia Language Redirector
// @version      v3
// @match        https://en.wikipedia.org/*
// @description  Redirects wikipedia pages to alternate language pages in order of predefined preference
// @author       Enjoyer_of_Games
// @author       Edie
// @run-at       document-idle
// @license      AGPL 3+
// ==/UserScript==

const langBtn = document.querySelector('#p-lang-btn');

if (langBtn) {
    let LanguageList = ['nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh'];
    for (const langCode of LanguageList) {
        let linktarget = document.querySelector(`a.interlanguage-link-target[lang="${langCode}"]`);
        if(linktarget){
            let langLink = linktarget.href;
            if (langLink){
              console.log(window.location);
              console.log(`Navigating to language: ${langCode}`);
              window.location.href = langLink;
              break;
            }
            else {
               console.warn(`Could not find language link for "${langCode}"`);
            }
        }
    }
}
else {
    console.log('Could not find the #p-lang-btn element');
}


This user is suspected of being a cat. Please report any suspicious behavior.

[-] Erika3sis@hexbear.net 3 points 3 days ago

I'm glad I've apparently given you a fun challenge. I've updated the post.

Regarding the language codes, let LanguageList = ['be-tarask', 'nb', 'nn', 'da', 'sv', 'eo', 'tok', 'ru', 'ja', 'zh']; makes the script redirect me to Belarusian Taraškievica Wikipedia. So it seems to be a bit of a mix of Wikipedia and ISO 639 codes. In the cases where the codes differ, I think it's best to try one code and see if it works, and if the first code you tried doesn't work, to try the other code.

[-] edie@lemmy.encryptionin.space 3 points 3 days ago

So it's actually a BCP 47 language tag, per this MDN article: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/lang


This user is suspected of being a cat. Please report any suspicious behavior.

[-] edie@lemmy.encryptionin.space 3 points 3 days ago* (last edited 3 days ago)

You seem to have highlighted my code while clicking edit on the post, as it has quoted it at the end of the post.


This user is suspected of being a cat. Please report any suspicious behavior.

[-] Erika3sis@hexbear.net 3 points 3 days ago
[-] Erika3sis@hexbear.net 5 points 3 days ago

@Edie@hexbear.net @Enjoyer_of_Games@hexbear.net I hope you don't mind that I changed // @name Erika3sis to // @name Wikipedia Language Redirector

[-] edie@lemmy.encryptionin.space 4 points 3 days ago* (last edited 3 days ago)

Idc, that was simply what comrade had called it.


This user is suspected of being a cat. Please report any suspicious behavior.

this post was submitted on 13 Feb 2026
34 points (100.0% liked)

languagelearning

14460 readers
1 users here now

Building Solidarity - One Word at a Time

Rules:

  1. No horny posting
  2. No pooh posting
  3. Don't be an ass

founded 5 years ago
MODERATORS