Module:LinkPhone

--[[ 	Source script:	https://it.wikivoyage.org/wiki/Modulo:LinkPhone 	Maintainer:		Andyrom75 ]] local i18n = require( 'Module:LinkPhone/i18n' )  local function _t9Map(s) 	-- Mappa le lettere A–Z in cifre T9 	s = mw.ustring.gsub(s, "[A-C]", "2") 	s = mw.ustring.gsub(s, "[D-F]", "3") 	s = mw.ustring.gsub(s, "[G-I]", "4") 	s = mw.ustring.gsub(s, "[J-L]", "5") 	s = mw.ustring.gsub(s, "[M-O]", "6") 	s = mw.ustring.gsub(s, "[P-S]", "7") 	s = mw.ustring.gsub(s, "[T-V]", "8") 	s = mw.ustring.gsub(s, "[W-Z]", "9") 	return s end  -- controlla se le prime 3, 4 e 5 cifre di un numero telefonico corrispondono a quelle di un numero verde local function _isTollfreeNumber(telNumber, telType)     for i = 3, 5 do         local prefix = mw.ustring.sub(telNumber, 1, i)         if i18n.tollfreePrefixes[prefix] then             return true         end     end     if i18n.tollfreeTypes[telType] then         return true     end     return false end   local function _addCategory(catprefix, cat, msg)     return '[[' .. catprefix .. 'Category:' .. cat .. ']]<span class="phoneinfo debuginfo">' .. msg .. '</span>' end  local function _LinkOnePhone(txt, demo, fax, tollfree) 	local othertxt = "" 	local catprefix = demo == 'true' and ':' or '' 	local catMissingCountryCode, catFormatIssue = '', '' 	local output  	-- any other text in brackets at the end is stored separately and ignored for the dialing number 	local base, tail = mw.ustring.match(txt, "^(.-)( %b())$") 	if tail ~= nil then 	    txt, othertxt = base, tail 	end 	local link = txt 	-- Don't include "ext NNNN" (or equivalent in other languages) in the link 	for _, pattern in ipairs(i18n.extRegEx) do 		link = mw.ustring.gsub(link, " +" .. pattern .. " +%d+$", "") 	end 	-- Don't include " xNNNN" in the link 	link = mw.ustring.gsub(link, " +x%d+$", "") 	link = mw.ustring.gsub(link, "[ '%s]", "") 	if link == "" then 		return "" 	end 	if mw.ustring.sub(link, 1, 1) ~= '+' and mw.ustring.len(link) > 4 then 		-- Del potenziale numero telefonico tengo solo le cifre 		local normalizedDigits = mw.ustring.gsub(link, "[^%d]", "") 		-- Del potenziale tipo di numero elimino spazi di troppo e le parentesi che lo racchiudono 		local normalizedDescription = string.lower(mw.text.trim((othertxt or "")):gsub("[%(%)]", "")) 		if tollfree and _isTollfreeNumber(normalizedDigits, normalizedDescription)  then 			output = '<span class="plainlinks nourlexpansion">[tel:' .. normalizedDigits .. ' ' .. txt .. ']</span>' .. othertxt 			return output 		else 			catMissingCountryCode = _addCategory(catprefix, i18n.categories.noCountryCode, i18n.errorMsg.noCountryCode) 		end 	end 	if mw.ustring.match(link,"^%+[%d-() ]+$") ~= nil then 		local htmlTel = fax and txt or ('[tel:' .. link .. ' ' .. txt .. ']') 		output = '<span class="plainlinks nourlexpansion">' .. htmlTel .. '</span>' .. othertxt 	elseif mw.ustring.match(link,"^%+[%d%u- ]+$") ~= nil then 		local extra = mw.ustring.match(link, "%u[%d%u- ]+") 		link = _t9Map(link) 		extra = _t9Map(extra) 		local htmlTel = fax and (' (' .. extra .. ')') or ('[tel:' .. link .. ' ' .. txt .. ' (' .. extra .. ')' .. ']') 		output = '<span class="plainlinks nourlexpansion">' .. htmlTel .. '</span>' .. othertxt 	else 		-- evito di sovrascrivere i numeri verdi ben formattati 		output = output or txt .. othertxt 		if mw.ustring.match('+' .. link,"^%+[%d-() ]+$") == nil then 			catFormatIssue = _addCategory(catprefix, i18n.categories.wrongTelFormat, i18n.errorMsg.wrongTelFormat) 		end 	end 	if mw.ustring.match(link,"%(0%)") ~= nil then 		catFormatIssue = _addCategory(catprefix, i18n.categories.wrongTelFormat, i18n.errorMsg.wrongTelFormat) 	end 	if mw.title.getCurrentTitle().namespace == 0 or demo == 'true' then 		output = output .. catFormatIssue .. catMissingCountryCode 	end 	return output end  local function _LinkPhone(frame, extraArgs) 	local txtall = frame.args[1] or '' .. ',' 	local demo = frame.args['demo'] or '' 	local fax = extraArgs and extraArgs.fax     local tollfree = extraArgs and extraArgs.tollfree 	local txt = '' 	local result = '' 	-- replace or / and with comma 	txtall = mw.ustring.gsub(txtall, ' ' .. i18n.msg._or_ .. ' %+', ', +') 	txtall = mw.ustring.gsub(txtall, ' ' .. i18n.msg._and_ .. ' %+', ', +') 	for txt in mw.ustring.gmatch(txtall, '([^,]+)') do 		result = result .. ', ' .. _LinkOnePhone(txt, demo, fax, tollfree) 	end 	result = mw.ustring.sub(result, 3, mw.ustring.len(result) ) 	return result end  local function _LinkOneEmail(txt, demo)     local othertxt = ""     local catprefix = demo == 'true' and ':' or ''     local catFormatIssue = ''     local output     -- any other text in brackets at the end is stored separately and ignored for the dialing number     txt, othertxt = mw.ustring.match(txt, "^(.-) (%b())$") or txt, ""     txt = mw.ustring.gsub(txt, " ", "")     output = '[mailto:' .. txt .. ' ' .. txt .. ']' .. othertxt     if  mw.ustring.match(txt,"@.+@")      or mw.ustring.match(txt,"@[^.]+%.%.")      or mw.ustring.match(txt,"@") == nil      or mw.ustring.match(txt,"@[^.]+%.[^.]+") == nil then         catFormatIssue = _addCategory(catprefix, i18n.categories.wrongMailFormat, i18n.errorMsg.wrongMailFormat)     end     if mw.title.getCurrentTitle().namespace == 0 or demo == 'true' then         output = output .. catFormatIssue     end     return output end  local p = {}   function p.LinkPhone(frame) 	return _LinkPhone(frame, {fax=false, tollfree=false}) end   function p.LinkFax(frame) 	return _LinkPhone(frame, {fax=true, tollfree=false}) end   function p.LinkTollfree(frame) 	return _LinkPhone(frame, {fax=false, tollfree=true}) end   function p.LinkEmail(frame)     local txtall = frame.args[1] or '' .. ','     local demo = frame.args["demo"] or ''     local txt = ""     local result = ""     -- replace semicolon with comma     txtall = mw.ustring.gsub(txtall, "; ", ", ")     for txt in mw.ustring.gmatch(txtall, "([^,]+)") do         result = result .. ", " .. _LinkOneEmail(txt, demo)     end     result = mw.ustring.sub(result, 3, mw.ustring.len(result) )     return result end   return p