Module:IPA#L-269

require('strict')

local p = {}

local function multiFind(s, patterns, init)

local i, j = mw.ustring.find(s, patterns[1], init)

for n = 2, #patterns do

local i2, j2 = mw.ustring.find(s, patterns[n], init)

if i2 and (not i or i2 < i) then

i, j = i2, j2

end

end

return i, j

end

local function wrapAtSpaces(s)

return mw.ustring.gsub(s, '(%s+)', '%1')

end

local function wrapAtSpacesSafely(s)

local patterns = {

'%[%[[^%]|]-%s[^%]|]-|', -- Piped links

']-%s[^>]->' -- HTML tags

}

s = mw.ustring.gsub(s, '%[%[([^%]|]-%s[^%]|]-)%]%]', '%1') -- Pipe all links

local t = {}

local init

while true do

local i, j = multiFind(s, patterns, init)

if not i then

break

end

local pre = wrapAtSpaces(mw.ustring.sub(s, init, i - 1)) -- What precedes the match

table.insert(t, pre)

table.insert(t, mw.ustring.sub(s, i, j)) -- The match

init = j + 1

end

local post = wrapAtSpaces(mw.ustring.sub(s, init)) -- What follows the last match

table.insert(t, post)

return table.concat(t)

end

local function checkNamespace(isDebug)

return isDebug or require('Module:Category handler').main({ true })

end

local function renderCats(cats, isDebug)

if not cats[1] or not checkNamespace(isDebug) then

return ''

end

local t = {}

for _, v in ipairs(cats) do

table.insert(t, string.format(

'%sCategory:%s',

isDebug and ':' or '',

v

))

end

return table.concat(t)

end

local function resolveSynonym(s)

return mw.loadData('Module:Lang/ISO 639 synonyms')[s] or s

end

local function splitTag(s)

local langCode = s:gsub('%-.*', ''):lower()

langCode = resolveSynonym(langCode)

local regionCode = s:match('%-(.+)')

local isPrivate = regionCode and regionCode:sub(1, 2) == 'x-'

return langCode, regionCode, isPrivate

end

local function getLangName(code, link, raw)

return require('Module:Lang')._name_from_tag({

code,

link = link,

raw = raw,

-- Without linking, "{{IPA}}" gets expanded in some contexts

template = 'IPA'

})

end

local function linkLang(name, target, link)

return link == 'yes' and string.format(

'%s',

target or name .. ' language',

name

) or name

end

function p._main(args)

local ret, cats = {}, {}

local isDebug = args.debug == 'yes'

local s, langCode, regionCode, isPrivate

-- Guide-linking mode

if args[2] and args[2] ~= '' then

local data = mw.loadData('Module:IPA/data')

local isGeneric = args.generic == 'yes'

s = args[2]

langCode, regionCode, isPrivate = splitTag(args[1])

local langData = data.langs[langCode] or {}

if regionCode then

if not isPrivate then

regionCode = regionCode:upper()

end

if langData.dialects and langData.dialects[regionCode] then

-- Overwrite language data with the dialect's

local newLangData = {}

for k, v in pairs(langData) do

if k ~= 'dialects' then

newLangData[k] = v

end

end

local dialectData = langData.dialects[regionCode]

if dialectData.aliasOf then

-- Use the canonical region code

regionCode = dialectData.aliasOf

isPrivate = regionCode:sub(1, 2) == 'x-'

dialectData = langData.dialects[regionCode]

end

-- Lowercase IANA variant

if dialectData.isVariant then

regionCode = regionCode:lower()

end

for k, v in pairs(dialectData) do

newLangData[k] = v

end

langData = newLangData

else

isGeneric = true

end

end

local fullLangCode = regionCode and langCode .. '-' .. regionCode

or langCode

local langName = langData.name

and linkLang(langData.name, langData.link, args.link)

or getLangName(fullLangCode, args.link)

if langName:sub(1, 5) == '

-- Module:Lang has returned an error

return langName .. renderCats({ 'IPA template errors' }, isDebug)

end

if args.cat ~= 'no' then

local catLangName = langData.name

or getLangName(fullLangCode, nil, 'yes')

if catLangName:sub(1, 5) == '

-- Module:Lang has returned an error, but it's not fatal

table.insert(cats, 'IPA template errors')

mw.addWarning(catLangName)

else

table.insert(cats, string.format('Pages with %s IPA', catLangName))

end

end

-- Label

local label = args.label

if not label then

local labelCode = args[3] and args[3]:lower()

or langData.defaultLabelCode

if labelCode == '' then

label = ''

else

local langText

if langData.text then

langText = linkLang(

langData.text,

mw.ustring.match(langName, '^%[%[([^|%]]+)'),

args.link

)

else

langText = mw.ustring.gsub(

langName,

'^%[%[(([^|]+) languages)%]%]$',

'%2'

)

langText = mw.ustring.gsub(

langText,

' languages(%]?%]?)$',

'%1'

)

end

if labelCode and data.labels[labelCode] then

label = data.labels[labelCode]:format(langText)

else

label = data.defaultLabel:format(langText)

end

end

end

if label and label ~= '' then

local span = mw.html.create('span')

:addClass('IPA-label')

:wikitext(label)

if args.small ~= 'no' then

span:addClass('IPA-label-small')

table.insert(ret, mw.getCurrentFrame():extensionTag({

name = 'templatestyles',

args = { src = 'Module:IPA/styles.css' }

}))

end

table.insert(ret, tostring(span) .. ' ')

end

-- Brackets

s = (not isGeneric and langData.format or '[%s]'):format(s)

-- Link to key

local key = not isGeneric and langData.key or data.defaultKey

s = string.format('%s', key, s)

else

-- Basic mode

s = args[1]

if args.lang and args.lang ~= '' then

langCode, regionCode, isPrivate = splitTag(args.lang)

end

if args.cat ~= 'no' then

table.insert(cats, 'Pages with plain IPA')

end

end

-- Transcription

do

local lang = (langCode or 'und') .. '-Latn'

if not isPrivate and regionCode then

lang = lang .. '-' .. regionCode

end

lang = lang .. '-fonipa'

local span = mw.html.create('span')

:addClass('IPA')

:addClass(args.class)

:attr('lang', lang)

-- wrap=all: Do nothing

-- wrap=none: Never break

-- Otherwise: Break at spaces only

if args.wrap ~= 'all' then

span:addClass('nowrap')

if args.wrap ~= 'none' then

s = wrapAtSpacesSafely(s)

end

end

if (not args[2] or args[2] == ) and args.tooltip ~= then

local tooltip = args.tooltip or

'Representation in the International Phonetic Alphabet (IPA)'

span:attr('title', tooltip)

end

s = tostring(span:wikitext(s))

table.insert(ret, s)

end

-- Audio

local audio = args.audio ~= and args.audio or args[4] ~= and args[4]

if audio then

local button = mw.getCurrentFrame():expandTemplate({

title = 'Audio',

args = { audio, '' }

})

table.insert(ret, ' ' .. button)

table.insert(cats, 'Pages including recorded pronunciations')

end

-- Categories

table.insert(ret, renderCats(cats, isDebug))

return table.concat(ret)

end

function p.main(frame)

local args = frame:getParent().args

if not args[1] then

return ''

end

for i, v in ipairs(args) do

args[i] = mw.text.trim(v)

end

return p._main(args)

end

return p