Page MenuHomePhabricator

Add missing $namespaceNames to MessagesXX.php files for language Wikipedias
Open, MediumPublic

Description

If you are interested in working on this task, you can create a subtask for the language wiki (see the checklist in the task description below) that you plan to work on and assign the task to yourself.

Description

Namespaces are a core feature of all Wikimedia projects. They separate different types of content, for example, main articles, user pages, and discussions and are essential for the organization and functionality of a wiki. MediaWiki comes with built-in core namespaces (e.g., Talk, User, File), but these need to be localized per language in files like MessagesXX.php. Without this, contributors may see fallback or English namespace names, which leads to a bad user experience.

🛠️ What needs to be done

For the languages listed below, a Wikipedia does exist, but the corresponding MessagesXX.php file in MediaWiki is missing the $namespaceNames array.

This task is to:

  • Collaborate with active community members, preferably administrators, to gather correct localized namespace names for each language.
  • Submit a patch to the MediaWiki core repository by adding $namespaceNames to the corresponding file, based on gathered input.
🧭 How to proceed
✅ Checklist

(9 languages for which Wikipedia exists, but $namespaceNames are missing in MediaWiki Core even in fallback language message files)

Filename in MediaWiki coreStatus
MessagesFf.phpRequest for namespace translations ongoing on ff wiki See T394870.
MessagesIk.php
MessagesDz.php
MessagesSt.php
MessagesNy.php
MessagesBo.php
MessagesIu.php
MessagesEe.php
MessagesTum.php
📚 Resources

Event Timeline

srishakatux triaged this task as Unbreak Now! priority.Apr 11 2025, 8:01 PM
srishakatux lowered the priority of this task from Unbreak Now! to Needs Triage.

Below is a script to check which MessagesXX.php files in MediaWiki core are missing $namespaceNames. Then it looks to see if those languages have a Wikipedia. This script was used to generate the checklist in the task description.

<?php
// Directory containing the MessagesXX.php files
$directory = __DIR__ . '/languages/messages'; 

// Function to check if a file contains the $namespaceNames array
function hasNamespaceNames($filePath) {
    $fileContents = file_get_contents($filePath);
    return strpos($fileContents, '$namespaceNames') !== false;
}

// Function to check if a Wikipedia exists for a given language code
function hasWikipedia($langCode) {
    $url = "https://" . $langCode . ".wikipedia.org/wiki/Main_Page";
    $headers = @get_headers($url);
    return $headers && strpos($headers[0], '200') !== false;
}

// Open the directory and iterate over the files
$dir = opendir($directory);

$count = 0;

while (($file = readdir($dir)) !== false) {
    if (preg_match('/^Messages([a-zA-Z_-]+)\.php$/', $file, $matches)) {
        $rawLangCode = strtolower($matches[1]);
        $langCode = str_replace('_', '-', $rawLangCode);
        $filePath = $directory . '/' . $file;

        if (!hasNamespaceNames($filePath) && hasWikipedia($langCode)) {
            echo "Missing \$namespaceNames in $file — Wikipedia exists for $langCode\n";
            $count++;
        }
    }
}

closedir($dir);
echo "Total: $count\n";
?>

for scn wiki we can follow https://scn.wikipedia.org/wiki/Utenti:GiovanniPen/msgs.php that is based on the old version on gerrit. the scn community developed that.

Some of these, like Sr and Skr do have namespaces in practice, but they are in the file for the fallback language.

Based on suggestion from @Aaharoni-WMF, updating the script and task description to only count languages with Wikipedia and no fallback support.

<?php
$directory = __DIR__ . '/languages/messages'; 

function hasNamespaceNames($filePath) {
    if (!file_exists($filePath)) return false;
    $contents = file_get_contents($filePath);
    return strpos($contents, '$namespaceNames') !== false;
}

function getFallbackLanguages($filePath) {
    $contents = file_get_contents($filePath);
    if (preg_match("/\\\$fallback\s*=\s*['\"]([^'\"]+)['\"]\s*;/", $contents, $matches)) {
        return array_map('trim', explode(',', $matches[1]));
    }
    return [];
}

function hasWikipedia($langCode) {
    $url = "https://$langCode.wikipedia.org/wiki/Main_Page";
    $headers = @get_headers($url);
    return $headers && strpos($headers[0], '200') !== false;
}

$dir = opendir($directory);
$count = 0;

echo "Starting check...\n\n";

while (($file = readdir($dir)) !== false) {
    if (preg_match('/^Messages([a-zA-Z_-]+)\.php$/', $file, $matches)) {
        $rawLangCode = $matches[1];
        $langCode = strtolower(str_replace('_', '-', $rawLangCode));
        $filePath = "$directory/$file";

        echo "🔍 Checking: $file (langCode: $langCode)\n";

        $hasWiki = hasWikipedia($langCode);
        echo "    🌐 Wikipedia exists? " . ($hasWiki ? "Yes" : "No") . "\n";

        if (hasNamespaceNames($filePath)) {
            echo "    ✅ Contains \$namespaceNames — skipping\n\n";
            continue;
        } else {
            echo "    ⚠️ No \$namespaceNames in $file\n";
        }

        $fallbacks = getFallbackLanguages($filePath);
        echo "    🔁 Fallbacks found: " . (empty($fallbacks) ? "None" : implode(', ', $fallbacks)) . "\n";

        $namespaceInFallback = false;

        foreach ($fallbacks as $fallbackCode) {
            $parts = explode('-', $fallbackCode);
            $main = ucfirst($parts[0]);
            $variant = isset($parts[1]) ? '_' . strtolower($parts[1]) : '';
            $fallbackFile = "$directory/Messages{$main}{$variant}.php";

            echo "        ↳ Checking fallback file: Messages{$main}{$variant}.php... ";

            if (file_exists($fallbackFile)) {
                if (hasNamespaceNames($fallbackFile)) {
                    echo "✅ has \$namespaceNames\n";
                    $namespaceInFallback = true;
                    break;
                } else {
                    echo "❌ does NOT have \$namespaceNames\n";
                }
            } else {
                echo "❓ file does not exist\n";
            }
        }

        if ($namespaceInFallback) {
            echo "    🔄 Found namespace names in fallback — skipping\n\n";
            continue;
        }

        if ($hasWiki) {
            echo "    🚨 Counted: Missing \$namespaceNames + Wikipedia exists + no fallback with namespaces\n\n";
            $count++;
        } else {
            echo "    ✅ Skipped: No Wikipedia exists\n\n";
        }
    }
}

closedir($dir);
echo "✅ Total missing \$namespaceNames (with Wikipedia, no fallback support): $count\n";
?>

Sample outputs

🔍 Checking: MessagesHif.php (langCode: hif)
    🌐 Wikipedia exists? Yes
    ⚠️ No $namespaceNames in MessagesHif.php
    🔁 Fallbacks found: hif-latn
        ↳ Checking fallback file: MessagesHif_latn.php... ✅ has $namespaceNames
    🔄 Found namespace names in fallback — skipping
🔍 Checking: MessagesEe.php (langCode: ee)
    🌐 Wikipedia exists? Yes
    ⚠️ No $namespaceNames in MessagesEe.php
    🔁 Fallbacks found: None
    🚨 Counted: Missing $namespaceNames + Wikipedia exists + no fallback with namespaces

@Aaharoni-WMF @ToluAyo Could you take a look at the updated task description? Now we have 9 languages for which Wikipedia exists, but $namespaceNames are missing in MediaWiki Core - even in fallback language message files.

Thank you for tagging this task with good first task for Wikimedia newcomers!

Newcomers often may not be aware of things that may seem obvious to seasoned contributors, so please take a moment to reflect on how this task might look to somebody who has never contributed to Wikimedia projects.

A good first task is a self-contained, non-controversial task with a clear approach. It should be well-described with pointers to help a completely new contributor, for example it should clearly pointed to the codebase URL and provide clear steps to help a contributor get setup for success. We've included some guidelines at https://phabricator.wikimedia.org/tag/good_first_task/ !

Thank you for helping us drive new contributions to our projects <3

Ankita2005 subscribed.

Hi! I’m working on this task as part of Outreachy. I’d like to claim it and start the implementation

@Ankita2005 Thanks for your interest in working on this task! This task can have multiple assignees, so I will go ahead and remove you for now. You can pick a language from the checklist and refer to the guidance in the task description to get started. If you have any questions, let us know!

@srishakatux, your code makes three assumptions that may not hold:

  • It assumes that <langcode>.wikipedia.org redirects to the Wikipedia in that language. There are some legacy discrepancies between wiki codes and language codes, e.g. the language file for Alemannic German is called LanguageGsw.php, but the wiki is https://als.wikipedia.org/.
  • It assumes that if <langcode>.wikipedia.org resolves, a Wikipedia exists in that language. The domain name may redirect to Incubator (if the language has no own Wikipedia yet), which uses English namespace names in all languages.
  • It assumes that the page Main_Page exists on all wikis. This is just a regular wiki page, which by convention redirects to the main page, but there’s no guarantee for that, so it may happen that $headers[0] contains 404, not 200.

Here is an improved version, using the sitematrix API to get all languages used on WMF wikis. This also means that a single HTTP request is made, rather than one per wiki, making it more efficient. Another improvement is that all problematic languages are listed at the end, as I found it difficult to find those nine languages in the long output. (By the way, those nine languages are exactly the same as in the task description, so my improvement didn’t uncover newer languages, but it still gives more confidence.)

<?php
$directory = __DIR__ . '/languages/messages'; 

function hasNamespaceNames($filePath) {
    if (!file_exists($filePath)) return false;
    $contents = file_get_contents($filePath);
    return strpos($contents, '$namespaceNames') !== false;
}

function getFallbackLanguages($filePath) {
    $contents = file_get_contents($filePath);
    if (preg_match("/\\\$fallback\s*=\s*['\"]([^'\"]+)['\"]\s*;/", $contents, $matches)) {
        return array_map('trim', explode(',', $matches[1]));
    }
    return [];
}

$languages = array_flip(
    array_map(
        fn (array $arr): string => $arr['code'],
        array_filter(
            json_decode(
                file_get_contents('https://meta.wikimedia.org/w/api.php?format=json&formatversion=2&action=sitematrix&smtype=language&smlangprop=code'),
                true
            )['sitematrix'],
            fn (string $key): bool => $key !== 'count',
            ARRAY_FILTER_USE_KEY
        )
    )
);

$dir = opendir($directory);
$countedLangs = [];

echo "Starting check...\n\n";

while (($file = readdir($dir)) !== false) {
    if (preg_match('/^Messages([a-zA-Z_-]+)\.php$/', $file, $matches)) {
        $rawLangCode = $matches[1];
        $langCode = strtolower(str_replace('_', '-', $rawLangCode));
        $filePath = "$directory/$file";

        echo "🔍 Checking: $file (langCode: $langCode)\n";

        $hasWiki = array_key_exists($langCode, $languages);
        echo "    🌐 Wiki exists? " . ($hasWiki ? "Yes" : "No") . "\n";

        if (hasNamespaceNames($filePath)) {
            echo "    ✅ Contains \$namespaceNames — skipping\n\n";
            continue;
        } else {
            echo "    ⚠️ No \$namespaceNames in $file\n";
        }

        $fallbacks = getFallbackLanguages($filePath);
        echo "    🔁 Fallbacks found: " . (empty($fallbacks) ? "None" : implode(', ', $fallbacks)) . "\n";

        $namespaceInFallback = false;

        foreach ($fallbacks as $fallbackCode) {
            $parts = explode('-', $fallbackCode);
            $main = ucfirst($parts[0]);
            $variant = isset($parts[1]) ? '_' . strtolower($parts[1]) : '';
            $fallbackFile = "$directory/Messages{$main}{$variant}.php";

            echo "        ↳ Checking fallback file: Messages{$main}{$variant}.php... ";

            if (file_exists($fallbackFile)) {
                if (hasNamespaceNames($fallbackFile)) {
                    echo "✅ has \$namespaceNames\n";
                    $namespaceInFallback = true;
                    break;
                } else {
                    echo "❌ does NOT have \$namespaceNames\n";
                }
            } else {
                echo "❓ file does not exist\n";
            }
        }

        if ($namespaceInFallback) {
            echo "    🔄 Found namespace names in fallback — skipping\n\n";
            continue;
        }

        if ($hasWiki) {
            echo "    🚨 Counted: Missing \$namespaceNames + wiki exists + no fallback with namespaces\n\n";
	    $countedLangs[] = $langCode;
        } else {
            echo "    ✅ Skipped: No wiki exists\n\n";
        }
    }
}

closedir($dir);
printf(
    "✅ Total missing \$namespaceNames (with wiki, no fallback support – %d languages): %s\n",
    count($countedLangs),
    implode(', ', $countedLangs)
);

Thanks @Tacsipacsi for considering all the edge cases and helping to improve the script! :)

Change #1147872 had a related patch set uploaded (by Srishakatux; author: Srishakatux):

[mediawiki/core@master] Add namespace translations for Fulfulde

https://gerrit.wikimedia.org/r/1147872