Jump to content

Module:Msg

From translatewiki.net

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

Missing/invalid input


--
-- 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 &#91;&#91;:MediaWiki:Example/ru&#93;&#93; 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&#10;', '<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