Module:Msg
Appearance
This module supports a system of templates that render links to messages in message documentation. See Template:Msg-meta for the more detailed explanation.
Tests
Basic feature support:
- Wikibase-cancel [not capitalised] (“
cancel
”) - cancel [namespace with lowercase titles] (“
Cancel
”) - Translating:MediaWiki/Basic glossary/publish--term [subpages in title] (“
publish
”) - Word-separator [empty message in Chinese](空)
- Sitejspreview [RTL support test] (“
<strong>{{GENDER:|זכור שאתה רק עושה|זכרי שאת רק עושה|נא לזכור שזוהי רק}} תצוגה מקדימה של קוד ה־JavaScript הזה. הוא עדיין לא פורסם!</strong>
”)
Multi-line messages
- Movepagetext-noredirectfixer (“
Using the form below will rename a page, moving all of its history to the new name. The old title will become a redirect page to the new title. Be sure to check for [[Special:DoubleRedirects|double]] or [[Special:BrokenRedirects|broken redirects]]. You are responsible for making sure that links continue to point where they are supposed to go.
”)
Note that the page will <strong>not</strong> be moved if there is already a page at the new title, unless it is a redirect and has no past edit history. This means that you can rename a page back to where it was renamed from if you make a mistake, and you cannot overwrite an existing page.
<strong>Note:</strong> This can be a drastic and unexpected change for a popular page; please be sure you understand the consequences of this before proceeding. - Abusefilter-warning (“
'''Warning:''' This action has been automatically identified as harmful. Unconstructive actions will be quickly reverted, and egregious or repeated unconstructive editing will result in your account or IP address being blocked. If you believe this action to be constructive, you may submit it again to confirm it. A brief description of the abuse rule which your action matched is: $1
”)
With keywords
- Rollback-success (“
Reverted edits by {{GENDER:$3|$1}}; changed back to last revision by {{GENDER:$4|$2}}.
”) - Pagecategories (“
{{PLURAL:$1|Category|Categories}}
”)
Optional messages
- Quotes (page does not exist)
- Word-separator [does not exist in most languages] (“
 
”)
Missing/invalid input
- This-message-does-not-exist [exists check enabled] (page does not exist)
- {{msg-meta}} error: Invalid title "Abcdefg:Test"
- {{msg-mw}} error: No message key passed
- {{msg-mw}} error: No message key passed
- {{msg-mw}} error: Invalid title "MediaWiki:this-message-does-not-exist]]"
- {{msg-mw}} error: Message key starts with namespace: "MediaWiki:MediaWiki:Quiz legend error"
- {{msg-mw}} error: Invalid language code "qxx"
--
-- Port [[Template:Msg-meta]] to Lua
--
require( 'strict' )
local p = {}
local relevantLanguage = require( 'Module:RelevantLanguage' )._main
-- [[Module:Msg/styles.css]]
local stylesPage = 'Module:Msg/styles.css'
-- See [[:Category:Message maintenance]]
local errorCat = '[[Category:Message maintenance/msg-%s|%s]]'
local currentTitle = mw.title.getCurrentTitle()
local nsNumber = currentTitle.namespace
-- Do not add error categories in main/user/thread/module namespaces
local errorCatEnabled = nsNumber ~= 0
and not currentTitle:inNamespace( 'User' )
and not currentTitle:inNamespace( 'User talk' )
and not currentTitle:inNamespace( 'Thread' )
and not currentTitle:inNamespace( 'Module' )
-- Do not check for existence in main/thread/talk namespaces
local existCheckAllowed = nsNumber ~= 0
and not currentTitle:inNamespace( 'Thread' )
and not mw.site.namespaces[ nsNumber ].isTalk
local function isEmpty( str )
return str == nil or str == ''
end
local function useMwMessage( key, lang, ... )
if isEmpty( key ) then
return ''
end
if isEmpty( lang ) then
lang = 'en'
end
return mw.message.new( key ):inLanguage( lang ):params( arg ):plain()
end
local function useMwTitle( key, lang, ns )
local pageName = string.format( '%s/%s', key, lang )
local success, result = pcall( mw.title.makeTitle, ns, pageName )
if not success then
return nil
end
return result
end
local function useMwTitleExists( mwTitle )
local success, result = pcall( function()
return mwTitle ~= nil and mwTitle.exists
end )
if not success then
return true
end
return result
end
local function getErrorCat( meta, key )
meta = meta or 'meta'
key = key or '*'
if errorCatEnabled then
return string.format( errorCat, meta, key )
end
return ''
end
local function getError( err, meta, str )
meta = meta or 'meta'
if not isEmpty( str ) then
err = string.format( '%s "%s"', err, str )
end
local errText = string.format(
'[[Template:Msg-%s|{{msg-%s}}]] error: %s',
meta,
meta,
err
)
local result = mw.html.create( 'strong' )
:addClass( 'error msg-' .. meta )
:attr( 'lang', 'en' )
:attr( 'dir', 'ltr' )
:wikitext( errText )
return tostring( result ) .. getErrorCat( meta )
end
local function getComment( comment, lang )
if isEmpty( comment ) then
return ''
end
return useMwMessage( 'Word-separator', lang ) .. useMwMessage( 'Brackets', lang, comment )
end
-- Accepts mw.title object
local function getLink( title, wikilink )
local linkText = title.baseText
if wikilink then
return string.format(
'[[:%s|%s]]',
title.fullText,
title.baseText
)
end
return string.format(
'[%s %s]',
title:fullUrl( 'action=edit' ),
title.baseText
)
end
-- Accepts full page title
local function getText( pageTitle, lang, frame )
-- frame:preprocess is used here to handle fallbacks correctly
local text = frame:preprocess(
string.format( '{{msgnw:%s}}', pageTitle )
)
-- msgnw: outputs [[:MediaWiki:Example/ru]] code if there is no message
if mw.ustring.find( text, pageTitle, 1, true ) ~= nil then
return false
end
local result = ''
if text == '' then
-- Empty messages get [[MediaWiki:Historyempty]]
result = useMwMessage( 'Historyempty', lang )
else
text = mw.text.trim( text )
-- Replace line breaks to render multi-line messages
text = mw.ustring.gsub( text, '\n ', '<br>' )
text = mw.ustring.gsub( text, '\n', ' ' )
result = useMwMessage( 'Quotes', lang, string.format( '<code>%s</code>', text ) )
end
return useMwMessage( 'Word-separator', lang ) .. useMwMessage( 'Parentheses', lang, result )
end
function p._main( key, ns, comment, lang, config )
local title = useMwTitle( key, lang, ns )
local class = not isEmpty( config.meta ) and 'msg-' .. config.meta or ''
local frame = config.frame or mw.getCurrentFrame()
-- Return an error for false language codes
if not mw.language.isSupportedLanguage( lang ) then
return getError( 'Invalid language code', config.meta, lang )
end
-- Return an error if the key starts with namespace name
local titlePrefix = mw.ustring.sub( mw.ustring.lower( key ), 1, mw.ustring.len( ns ) + 1 )
if titlePrefix == mw.ustring.lower( ns ) .. ':' then
return getError( 'Message key starts with namespace:', config.meta, string.format( '%s:%s', ns, key ) )
end
-- Check if link is valid after title is known for sure
if title == nil then
return getError( 'Invalid title', config.meta, string.format( '%s:%s', ns, key ) )
end
local mwLang = mw.language.new( lang )
local result = mw.html.create( 'span' )
:addClass( 'plainlinks ts-msg ' .. class )
:attr( 'lang', mwLang:toBcp47Code() )
:attr( 'dir', mwLang:getDir() )
-- Optionally check for existence of English message
local doesNotExist = false
if config.checkIfExists then
local origTitle = useMwTitle( key, 'en', ns )
doesNotExist = not useMwTitleExists( origTitle )
if origTitle ~= nil and doesNotExist then
-- Missing links link to English version for log access
title = origTitle
result:addClass( 'ts-msg-missing' )
result:wikitext( getErrorCat( config.meta, key ) )
mw.addWarning(
'[[Module:Msg]]: ' ..
useMwMessage( 'Red-link-title', lang, string.format( '[[%s]]', title.fullText ) )
)
end
end
local link = mw.html.create( 'var' )
:attr( 'lang', 'zxx' )
:attr( 'dir', 'ltr' )
local linkText = getLink( title, doesNotExist )
comment = getComment( comment )
if not config.noText then
local text = getText( title.fullText, lang, frame )
if text == false then
linkText = getLink( title, true )
link:wikitext( linkText )
text = tostring( link ) .. comment
result:wikitext( useMwMessage( 'Red-link-title', lang, text ) )
else
link:wikitext( linkText )
result
:node( link )
:wikitext( comment )
:wikitext( text )
end
else
link:wikitext( linkText )
result
:node( link )
:wikitext( comment )
end
local templatestyles = frame:extensionTag{
name = 'templatestyles',
args = { src = stylesPage },
}
return templatestyles .. tostring( result )
end
function p.main( frame )
local args = require('Module:Arguments').getArgs( frame )
local key = args[ 1 ]
local comment = args[ 2 ]
local ns = args[ 'namespace' ]
local lang = args[ 'lang' ]
local config = {
frame = frame,
meta = args[ 'meta' ],
checkIfExists = existCheckAllowed and isEmpty( args[ 'exist' ] ),
noText = not isEmpty( args[ 'notext' ] ),
}
if isEmpty( key ) or key:find( '{{{' ) == 1 then
return getError( 'No message key passed', config.meta )
end
-- Use relevant language depending on the namespace/subpage name
if isEmpty( lang ) then
lang = relevantLanguage( frame )
end
return p._main( key, ns, comment, lang, config )
end
return p