Module:Core



From Wikimedia Commons, the free media repository



Jump to navigation  Jump to search  

Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

This module is intended as collection of core functions shared among several Lua modules creating infobox templates on Commons. It is used by

Please do not modify or add to without discussing it first.

Translations of "edit at Wikidata" and "edit at SDC" from Data:I18n/EditAt.tab

Code

--[[  
  __  __           _       _         ____               
 |  \/  | ___   __| |_   _| | ___ _ / ___|___  _ __ ___ 
 | |\/| |/ _ \ / _` | | | | |/ _ (_) |   / _ \| '__/ _ \
 | |  | | (_) | (_| | |_| | |  __/_| |__| (_) | | |  __/
 |_|  |_|\___/ \__,_|\__,_|_|\___(_)\____\___/|_|  \___|
                                                        
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 
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#frame:getParent .
If both structures have the same field than value from "frame" takes priority.

Inputs:
1) frame - frame objects see below for details
 https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#frame-object

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), ' ', '_')
    end
    output_args[name] = value
   end
  end
  return output_args
 end
 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)
 else
  args.lang = frame:callParserFunction("int","lang")  -- get user's chosen language
 end
 return args
end

------------------------------------------------------------------------------
--[[
Simplified code equivalent to https://commons.wikimedia.org/wiki/Template:LangSwitch

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

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

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

------------------------------------------------------------------------------
--[[
display a language followed by a message. Like "English: Hello" with extensive HTML marking
Code equivalent to https://commons.wikimedia.org/wiki/Template:Description 
Inputs:
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 = mw.language.new( text_lang )
  dir       = langObj:getDir()          -- text direction
  space     = mw.message.new( "Word-separator" ):inLanguage(text_lang):plain() 
  colon     = mw.message.new( "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'
 end
 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
  :wikitext(lang_name)
 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 (https://gerrit.wikimedia.org/r/c/mediawiki/core/+/208332)
  :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)
end

------------------------------------------------------------------------------
--[[
Function allowing for consistent treatment of boolean-like wikitext input.
Inputs:
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)
 end
 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
  end
    end
    return default
end

------------------------------------------------------------------------------
--[[
Read Commons Data:SOMENAME.tab dataset and look for message identified by a 
"key" in a language "lang". See editAtWikidata for an example. It uses
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#mw.ext.data

Inputs:
1) dataset - name of commons page in "data" namespace. for example "I18n/EditAt.tab" 
 for c:Data:I18n/EditAt.tab
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(mw.ext.data.get(dataset, lang).data) do
  local id, msg = unpack(row)
  if id == key then
   return mw.message.newRawMessage(msg):plain()
  end
 end
 error('Invalid message key "' .. key .. '"')
end

------------------------------------------------------------------------------
--[[
Assembles the "Edit at Wikidata" pen icon with a link to Wikidata page or specific 
property and returns it as wikitext string.
Inputs:
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/EditAt.tab
See Also: en:Module:EditAtWikidata
]]
-------------------------------------------------------------------------------
function core.editAtWikidata(entityID, propertyID, lang)
 local msg  = core.formatMessage('I18n/EditAt.tab', 'EditAtWikidata', lang)
 local link = 'https://www.wikidata.org/wiki/' .. entityID .. (propertyID == "" and "" or ("#" .. propertyID))
 return "&nbsp;[[File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt="..msg.."|link="..link.."|"..msg.."]]"
end

------------------------------------------------------------------------------
--[[
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.
Inputs:
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/EditAt.tab
See Also: en:Module:EditAtWikidata
]]
function core.editAtSDC(propertyID, lang)
 local msg  = core.formatMessage('I18n/EditAt.tab', '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="..link.."|"..msg.."]]"
end

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

Inputs:
 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
 end 
 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)
   break
  end
 end
 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>'
 end
   return '[['..link..'|'..label..']]'
end

-------------------------------------------------------------------------------
--[[
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
Inputs:
 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
Output:
 * 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
   table.insert(output, core.parseSnak(statement.mainsnak, lang))
  end
 end
 if #output==0 then return nil end
 return output
end

-------------------------------------------------------------------------------
--[[
parse part of the statement called "snak"

Inputs:
 1: snak - 
 2: lang - language code (like "en"), if provided than item IDs will be 
     changed to a label
Output:
 * string
]]
function core.parseSnak(snak, lang)
 local val = snak.datavalue.value
 if val.id then 
  val = val.id
  if lang ~= nil then
   val = core.getLabel(val, lang)
  end
 elseif val.text then
  val = val.text
 elseif val.amount then
  val = tonumber(val.amount)
 elseif val.time then -- handle most dates (use [[Module:Wikidata date]] for the rest
  local gregorian = 'http://www.wikidata.org/entity/Q1985727'
  if (val.calendarmodel==gregorian) and (mw.ustring.sub(val.time,1,1)=='+') and val.precision >= 9 then 
   local trim = 3*math.min(val.precision,11) - 22 -- day (11)->11, month (10)->8, year (9)->5
   val = mw.ustring.sub(val.time, 2, trim)    -- return YYYY-MM-DD, YYYY-MM or YYYY depending on precission
  end
 end
 return val
end

return core

Retrieved from "https://commons.wikimedia.org/w/index.php?title=Module:Core&oldid=649356850"

Categories: 
Modules for general use
Modules subject to page protection
 


Navigation menu


Personal tools  




English
Not logged in
Talk
Contributions
Create account
Log in
 


Namespaces  




Module
Discussion