From core perspective, ParserOutput::setLanguageLinks() should accept an array of LinkTargets. What happens now is that Parser has a LinkTarget, formats it to prefixed text, then Skin/Api (basically all usages of it) parses it again into Title, or even worse implements its own custom parsing, like LinksUpdate.
Currently accepts an array of the form:
$languageLinks[$languageCode] = $languageCode . ':' . $siteLink->getPageName();
Should probably have an API like:
public function addLanguageLink(string $langCode, LinkTarget page);
Note that core does not seem to use ::setLanguageLinks() at all any more. Perhaps this entire method should be deprecated and removed instead?
The ::addLanguageLink() method, on the other hand, is significantly used. It should also take a LinkTarget argument.
Note also that includes/deferred/LinksUpdate/LangLinksTable.php in mediawiki-core also has its own ideas about the ParserOuput format for language links.
*UPDATE* The ParserOutput::addLanguageLink function looks like this:
public function addLanguageLink( $t ): void { if ( $t instanceof ParsoidLinkTarget ) { // language links are unusual in using 'text' rather than 'db key' $t = Title::newfromLinkTarget( $t )->getFullText(); } $this->mLanguageLinks[] = $t; }
Note that most link-related metadata is stored like:
$this->mTemplates[$ns][$dbk] = ....;
By using a numeric namespace as the first-level array key we don't have to use a TitleFormatter or Title to convert the namespace ID to a string. And then the second-level array key is the *db key* form of the title, not the *full text* form (ie, it uses underscores instead of spaces).
We should make the storage representation of language links consistent with the [$ns][$dbkey] = .... style of the other metadata properties, which will avoid needing a TitleFormatter and/or to convert the LinkTarget into a full Title before we can store it in the ParserOutput.