From Safer nicotine wiki

Documentation for this module may be created at Module:Core/doc

  __  __           _       _         ____               
 |  \/  | ___   __| |_   _| | ___ _ / ___|___  _ __ ___ 
 | |\/| |/ _ \ / _` | | | | |/ _ (_) |   / _ \| '__/ _ \
 | |  | | (_) | (_| | |_| | |  __/_| |__| (_) | | |  __/
 |_|  |_|\___/ \__,_|\__,_|_|\___(_)\____\___/|_|  \___|
Core is a meta-module that consists of common and useful Lua functions that can 
be used in many Lua scripts. It was writen as a core of several Lua 
modules for creating file infobox templates on Commons. Many of the functions
are bare-bones versions of full functions found in other modules.

Authors and maintainers:
* User:Jarekt  

local core = {}

Based on frame structure create "args" table with all the input parameters:
 * table keys - equivalent to template parameters are converted to lower case 
                so they will not be case-sensitive.
                Also underscored are treated the same way as speces. 
 * table values - input values are trimmed (whitespaces removed from the beggining 
                and the end) and empty string are converted to nils. 
If "lang" is not provided than we substitute user's prefered language.

This function collects inputs from both frame and frame's parent. See .
If both structures have the same field than value from "frame" takes priority.

	1) frame - frame objects see below for details

See also: Module:Arguments on enWiki - which is much larger single purpose module
function core.getArgs(frame)
	local function normalize_input_args(input_args, output_args)
		for name, value in pairs( input_args ) do 
			value = mw.text.trim(value) -- trim whitespaces from the beggining and the end of the string
			if value ~= '' then -- nuke empty strings
				if type(name)=='string' then 
					name = string.gsub( string.lower(name), ' ', '_')
				output_args[name] = value
		return output_args
	local args = {}
	args = normalize_input_args(frame:getParent().args, args)
	args = normalize_input_args(frame.args, args)
	if (args.lang and mw.language.isSupportedLanguage(args.lang)) then 
		args.lang = string.lower(args.lang)
		args.lang = frame:callParserFunction("int","lang")  -- get user's chosen language
	return args

Simplified code equivalent to

Example usage:
  text = langSwitch({en='text in english', pl='tekst po polsku'}, lang)

  1: args - table with translations by language
  2: lang - desired language (often user's native language)
  1: label - returned label
  2: lang  - language of the label (langSwitchWithLang only)
function core.langSwitchWithLang(args, lang)
	local langList = mw.language.getFallbacksFor(lang)
	for i,language in ipairs(langList) do
		if args[language] then
			return args[language], language

function core.langSwitch(args, lang)
	local label, lang = core.langSwitchWithLang(args, lang)
	return label

display a language followed by a message. Like "English: Hello" with extensive HTML marking
Code equivalent to 
  1) text_lang - language code for the above text, also used as a name of the CSS formating class
  2) text - description text to display
  3) args -  additional optional arguments. Numbers in perenthesis are parameter numbers in the original template.
	   * hover    - (3) hover aka mouseover aka tooltip text
	   * lang_tag - (4) standard code for lang tag in HTML (optional, default is same as text_lang)
	   * ext      - (5) extension text shown after the language name before colon (optional, default is empty)
       * inline - Optional, default is false. When set to true, forces the template to be displayed 
            inline, so that it does not break the current paragraph (that makes possible to put several 
	        descriptions side by side on a single line)	   
function core.langWrapper(text_lang, text, args) 
	local dir, space, colon, lang_name, hover
	local inline    = core.yesno(args.inline, false) and 'inline' or nil 
	if 	mw.language.isKnownLanguageTag(text_lang) then -- supported language
		local langObj = text_lang )
		dir       = langObj:getDir()          -- text direction
		space     = "Word-separator" ):inLanguage(text_lang):plain() 
		colon     = "Colon" ):inLanguage(text_lang):plain() 
		hover     = mw.language.fetchLanguageName( text_lang, args.user_lang or 'en')
		lang_name = mw.language.fetchLanguageName( text_lang, text_lang)
		lang_name = langObj:ucfirst(lang_name)
	else -- unsuported language
		local RTL_LUT = {['fa-af']=1, prd=1, ydd=1}
		dir   = (RTL_LUT[text_lang]==1 or text_lang:gsub('-arab', '')~=text_lang) and 'rtl' or 'ltr'
		space = ' '
		colon = ':'
		hover = args.hover
		lang_name = text_lang or 'Unknown'
	lang_name = args.lang_name or lang_name-- user provided args.lang_name takes presedent
	lang_name = '<b>' .. lang_name .. (args.ext or '') .. colon .. '</b>'
	-- create HTML
	local ltag = mw.html.create('span')  -- bold language name string
		:addClass('language')  -- class: "language" 
		:addClass(text_lang)   -- class:  "en", "de" etc.	
		:attr('title', hover)  -- add hover aka mouseover aka tooltip text
	local dtag = mw.html.create('div')
		:addClass('description')      -- div.description is tracked by mw:Extension:CommonsMetadata
		:addClass('mw-content-'..dir) -- mw-content-rtl and mw-content-ltr are defined in mediawiki-code (
		:addClass(text_lang)          -- not sure where "en", "de" etc. are defined
		:attr('dir', dir)
		:attr('lang', text_lang)
		:css('display', inline) 
		:wikitext(tostring(ltag) .. space .. text)
	return tostring(dtag)

Function allowing for consistent treatment of boolean-like wikitext input.
  1) val - value to be evaluated, outputs as a function of values:
		true  : true  (boolean), 1 (number), or strings: "yes", "y", "true", "1"
		false : false (boolean), 0 (number), or strings: "no", "n", "false", "0"
  2) default - value to return otherwise
See Also: It works similarly to Module:Yesno
function core.yesno(val, default)
	if type(val) == 'boolean' then
		return val
	elseif type(val) == 'number' then
		val = tostring(val)
	if type(val) == 'string' then
		local LUT = {
			yes=true , y=true , ['true'] =true , t=true , ['1']=true , on =true,
			no =false, n=false, ['false']=false, f=false, ['0']=false, off=false }
	    val = LUT[mw.ustring.lower(val)]  -- put in lower case
	    if (val~=nil) then
			return val
    return default

Read Commons dataset and look for message identified by a 
"key" in a language "lang". See editAtWikidata for an example. It uses

 1) dataset - name of commons page in "data" namespace. for example "I18n/" 
	for c:Data:I18n/
 2) key - which message to pull
 3) lang - desired language of the message
Output: message as a string
function core.formatMessage(dataset, key, lang)
	for _, row in pairs(, lang).data) do
		local id, msg = unpack(row)
		if id == key then
			return mw.message.newRawMessage(msg):plain()
	error('Invalid message key "' .. key .. '"')

Assembles the "Edit at Wikidata" pen icon with a link to Wikidata page or specific 
property and returns it as wikitext string.
  1) entityID - wikidata entity object for a given page (output of wikibase.getEntity( id ))
  2) propertyID - string like 'P31' so the link will point to that specific property. Use "" 
     to link to the whole page. 
  3) lang - language of the "Edit at Wikidata"  message
Dependencies: Data:I18n/
See Also: en:Module:EditAtWikidata
function core.editAtWikidata(entityID, propertyID, lang)
	local msg  = core.formatMessage('I18n/', 'EditAtWikidata', lang)
	local link = '' .. entityID .. (propertyID == "" and "" or ("#" .. propertyID))
	return "&nbsp;[[File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt="..msg.."|link=""|"..msg.."]]"

Assembles the "Edit at SDC" pen icon with a link to a property in SDC part of the current file 
page, and returns it as wikitext string.
  2) propertyID - string like 'P31' so the link will point to that specific property. Use 'ooui-php-4' 
     to link to the label section. 
  3) lang - language of the "Edit at Wikidata"  message
Dependencies: Data:I18n/
See Also: en:Module:EditAtWikidata
function core.editAtSDC(propertyID, lang)
	local msg  = core.formatMessage('I18n/', 'EditAtSDC', lang)
	local link =  mw.title.getCurrentTitle():fullUrl() .. (propertyID == "" and "" or ("#" .. propertyID))
	return "&nbsp;[[File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt="..msg.."|link=""|"..msg.."]]"

This function returns a label translated to desired language, created based on wikidata
Code equivalent to require("Module:Wikidata label")._getLabel

	1: item - wikidata's item's q-id or entity class
	2: userLang - desired language of the label
function core.getLabel(item, userLang) 
	local label, link
	-- build language fallback list
	local langList = mw.language.getFallbacksFor(userLang)
	table.insert(langList, 1, userLang) 
	-- get label
	for _, lang in ipairs(langList) do  -- loop over language fallback list looking for label in the specific language
		label = mw.wikibase.getLabelByLang(item, lang)
		if label then break end                    -- label found and we are done
	label = label or item -- fallback value
	-- get link
	for _, lang in ipairs(langList) do  -- loop over language fallback list looking for label in the specific language
		link =  mw.wikibase.getSitelink(item, lang .. 'wiki')
		if link then
			link = mw.ustring.format('w:%s:%s', lang, link)
	link = link or 'd:'..item -- fallback value
	-- look for description
	local desc = mw.wikibase.getDescription(item)
	if desc then  -- add description if we have one
		desc  = mw.text.nowiki(desc) -- add description as hover text
		label = '<span title="' .. desc .. '">' .. label .. '</span>'
   return '[[''|'..label..']]'

Core component of many "get property value" functions
Example: (core.parse_statements(entity:getBestStatements( prop ), nil) or {nil})[1] would 
return the first best statement
 1: statements - can be provided by:
   * entity:getBestStatements( prop )
   * entity:getAllStatements( prop )
   * mw.wikibase.getBestStatements( item, prop )
   * mw.wikibase.getAllStatements( item, prop )
 2: lang - language code (like "en"), if provided than item IDs will be 
     changed to a label
 * table of strings or nil
function core.parseStatements(statements, lang)
	local output = {}
	for _, statement in ipairs(statements) do
		if (statement.mainsnak.snaktype == "value") and (statement.rank ~= 'deprecated')  then
			local val = statement.mainsnak.datavalue.value
			if then 
				val =
				if lang ~= nil then
					val = core.getLabel(val, lang)
			elseif val.text then
				val = val.text
			elseif val.amount then
				val = tonumber(val.amount)
			table.insert(output, val)
	if #output==0 then return nil end
	return output

return core
Cookies help us deliver our services. By using our services, you agree to our use of cookies.