We have a concept of page content language, being the language of the content area div as opposed to the top-level language of the page. However, its awkward implementation (violating layer constraints) prohibits its use in special pages.
Currently, SkinTemplate::wrapHTML() inspects the request context action and title. If it is a view action, it calls Title::getPageViewLanguage(). If $wgPageLanguageUseDB is true, it loads the language from LinkCache (potentially causing a database query). If the title is a special page, it unconditionally sets the language to be the user language.
In other words, the skin is looking at the action parameter and reaches into the database, implementing various heuristics desired by unrelated modules.
Instead I would propose:
- Add OutputPage::setPageLanguage().
- Add OutputPage::getPageLanguage().
- In Article::view(), call OutputPage::setPageLanguage().
- For T36010 and T289220, call OutputPage::setPageLanguage() from the execute() method of the special page.
- There are two callers of Title::getPageLanguage() in OutputPage. Both are called late and so can get the language from the OutputPage state instead.
- In SkinTemplate::wrapHTML(), use OutputPage::getPageLanguage() instead of Title::getPageViewLanguage(). Note that there is SkinTemplate::getOutput() -- it's not necessary to break compatibility by adding an $outputPage parameter.
- Title::getPageViewLanguage() should probably be deprecated. The isSpecialPage() section is not relevant to non-skin callers. The getDbPageLanguageCode() method can be made public or can get a new public wrapper. ContentHandler::getPageViewLanguage() should probably be called directly since most callers already have a ContentHandler and Content.