Module:Languages
Note to editors: Please don't categorize this template by editing it directly. Instead, place the category in its documentation page, in its "includeonly" section.
This module provides utilities for working with languages and language names. Most notably, it powers {{Languages}}, the language bar at the top of almost every page of this wiki.
sourceTitle
Returns the title of the source page corresponding to the given page name. If the page name is not specified as the first argument, then the current page name is used. In a set of translated pages that covers the same topic, the source page is the page written in the wiki's default content language, English.
A number of testcases verify the correctness of this function. Run the unit tests.
languages
Returns a flat list of links to translations of the current page, in wikitext format. The source page's name is inferred from the current page's name, but a page name can be specified as the first argument to override this behavior. The link order and labeling are defined by Module:Languages/config. This function is used by {{Languages}} and replaces {{Languages/div}}.
Parameters:
- |1 =
- (Optional) The name of the source page (the corresponding page in English). By default, the source page is inferred from the current page title, so this parameter is optional as long as the current page title is based on the English page's title.
- |defaultsort =
- (Optional) Set this parameter to
no
to omit theDEFAULTSORT
that would be added by default. It is normally unnecessary to set this parameter.
This function generally does not check whether a translation exists; it merely links to all the pages that would contain translations in the wiki's languages. Outside of the content namespaces, for any language that has its own language namespace, this function does check whether there exists a page in the form "Namespace:XY:Page name" or "Namespace:Xy:Page name", because both spellings are possible.
MediaWiki:Common.css and MediaWiki:Mobile.css hide redlinks by default; clicking the "Other languages" link unhides them so that the user can quickly begin translating.
If the page title begins with a language pseudonamespace, such as "El" for Greek, a DEFAULTSORT
omitting the pseudonamespace is appended to the return value of this method. Set |defaultsort = no to disable this behavior.
If a translation is missing in any language that has its own language namespace, this function automatically adds the current page to the corresponding tracking category. The current page's sort key in the category consists of the current page's language code and title.
See also
local p = {}
local config = mw.loadData("Module:Languages/config")
local siteLanguage = mw.getContentLanguage()
--- Returns the language pseudonamespace in the title of a page in the main
--- namespace, or nil if the title contains no pseudonamespace.
function p.pseudoNamespaceFromTitle(title)
local pseudoNS = title.text:match("^(%w%w%w?):") or
title.text:match("^(%w%w%w?%-%w%w%w?%w?):")
-- A few pseudonamespaces indicate topics rather than languages.
if pseudoNS and config.languageNamesByCode[pseudoNS:lower()] then
return pseudoNS
end
end
--- Infers and returns the given title’s page language, defaulting to the wiki’s
--- content language.
function p.languageFromTitle(title, fallback)
-- Language-specific namespace
local ns = title.subjectNsText
if config.namespacesByLanguage[ns:lower()] then
return ns:lower()
end
-- Pseudonamespace in the main namespace
local pseudoNS = p.pseudoNamespaceFromTitle(title)
return pseudoNS and pseudoNS:lower() or fallback or siteLanguage:getCode()
end
--- Guesses the source title from the given title, which may be the source or a
--- translation.
function p.sourceTitleFromTitle(title)
local pseudoNS = p.pseudoNamespaceFromTitle(title)
if pseudoNS then
local sourcePageName = title.text:sub(#pseudoNS + 2)
return mw.title.new(sourcePageName, title.nsText)
elseif config.namespacesByLanguage[title.subjectNsText:lower()] then
return mw.title.new(title.text, title.isTalkPage and 1 or 0)
else
return title
end
end
--- Quickly uppercases the first character of the string, disregarding Unicode.
local function ucfirst(s)
return s:sub(1, 1):upper() .. s:sub(2, -1)
end
--- Returns the page name of a translation in the given language.
--- If simulateLangNS is true and the page lies in a non-content namespace, the
--- pseudonamespace is capitalized to mimic a dedicated language namespace.
function p.translationPageName(languageCode, sourceTitle, simulateLangNS)
local isInMainNS = #sourceTitle.subjectNsText == 0
local pageNameParts = {
sourceTitle.text,
}
if isInMainNS and config.namespacesByLanguage[languageCode] then
local ns = config.namespacesByLanguage[languageCode]
if sourceTitle.isTalkPage then
ns = mw.site.namespaces[ns].talk.name
end
if #ns > 0 then
table.insert(pageNameParts, 1, ns)
end
else
local pseudoNS = ucfirst(languageCode)
local langNS = config.namespacesByLanguage[languageCode]
if langNS and (simulateLangNS or #langNS == 0) then
pseudoNS = langNS
end
if #pseudoNS > 0 then
table.insert(pageNameParts, 1, pseudoNS)
end
if #sourceTitle.nsText > 0 then
table.insert(pageNameParts, 1, sourceTitle.nsText)
end
end
return table.concat(pageNameParts, ":")
end
--- Returns a link to a wiki page.
local function listItem(languageCode, pageName, label)
local link = "<span dir=\"auto\" lang=\"" .. languageCode .. "\">[[:" .. pageName .. "| " .. label .. " ]]</span>"
-- By default, hlist inserts an interpunct as CSS generated content after
-- each list item. [[MediaWiki:Common.css]] hides redlinks but not the
-- interpuncts, which follow the redlinks visually but aren’t siblings.
-- This module uses hlist-with-seps, so hlist-sep gets the interpunct
-- instead of the list item. As a sibling of the redlink, hlist-sep gets
-- hidden along with the redlink.
local sep = mw.html.create("span")
sep:addClass("hlist-sep")
local li = mw.html.create("li")
li:wikitext(link)
return tostring(li)
end
p.listItem = listItem
--- Returns an unordered list of links to each possible translation page.
function p.languageList(currentTitle, sourceTitle)
local currentLanguage = p.languageFromTitle(currentTitle)
local isInMainNS = #sourceTitle.subjectNsText == 0
local listItems = {}
for i, code in ipairs(config.languageCodes) do
-- Link to the translation.
local pageName
if code == currentLanguage then
-- Translations’ page names may themselves be translated, so force
-- the current page to ensure that the link is boldfaced.
pageName = currentTitle.fullText
else
pageName = p.translationPageName(code, sourceTitle)
-- Languages with their own namespaces either uppercase or titlecase
-- pages in non-content namespaces.
if not isInMainNS and config.namespacesByLanguage[code]
and not mw.title.new(pageName, sourceTitle.nsText).exists then
pageName = p.translationPageName(code, sourceTitle, true)
end
end
local item = listItem(code, pageName, config.languageNamesByCode[code])
-- Add the current page to a tracking category if a translation is
-- unavailable in a language that has a dedicated namespace.
if config.namespacesByLanguage[code] and
not mw.title.new(pageName, sourceTitle.nsText).exists then
local category = "Category:" ..
config.unavailablePageCategoryNames[code]
local sortingKey = currentLanguage .. currentTitle.text
item = item .. "[[" .. category .. "|" .. sortingKey .. "]]"
end
table.insert(listItems, item)
end
return table.concat(listItems, "\n")
end
--- Returns the current page’s language based on either the page’s title or its
--- content language (specified by the pagelang argument).
function p.currentPageLanguage(frame)
local currentTitle = mw.title.getCurrentTitle()
return p.languageFromTitle(currentTitle, frame.args.pagelang)
end
--- Guesses the source title from the given title, which may be the source or a
--- translation.
function p.sourceTitle(frame)
local currentTitle = mw.title.getCurrentTitle()
local sourcePageName = #(frame.args[1] or "") > 0 and frame.args[1]
return sourcePageName and mw.title.new(sourcePageName) or
p.sourceTitleFromTitle(currentTitle)
end
--- Returns a flat list of links to translations of the current page, in
--- wikitext format.
function p.languages(frame)
local currentTitle = mw.title.getCurrentTitle()
local sourceTitle = p.sourceTitle(frame)
local languageList = p.languageList(currentTitle, sourceTitle)
local hlist = mw.html.create("div")
hlist:addClass("hlist"):addClass("hlist-with-seps"):wikitext(languageList)
local wikitext = tostring(hlist)
-- By default, sort the page in categories by the title sans pseudotitle.
if frame.args.defaultsort ~= "no" then
local pseudoNS = p.pseudoNamespaceFromTitle(currentTitle)
if pseudoNS then
local sortingKey = currentTitle.text:sub(#pseudoNS + 2)
-- If another DEFAULTSORT appeared earlier on the page, this
-- DEFAULTSORT has no effect. If a different DEFAULTSORT appears
-- later, it needs to specify “noerror” to suppress the error about
-- conflicting DEFAULTSORTs.
local defaultSort = frame:callParserFunction {
name = "DEFAULTSORT",
args = {
sortingKey,
"noreplace",
}
}
wikitext = wikitext .. defaultSort
end
end
return wikitext
end
return p