Module:Languages
From ChaldeanWiki
Revision as of 11:04, 10 December 2014 by Rillke (Talk) (that's why test are soooo useful: Restoring language collation order)
--[=[ Not globally exposed. Internal function only. language_subpages( frame, transform, options ) Parameters frame: The frame that was passed to the method invoked. The first argument or the page argument will be respected. transform: A transform function. Example: function( basepagename, subpagename, code, langname ) end options: An object with options. Example: { abort= { on=function() end, time=0.8 } } Following options are available: abort: Aborts iterating over the subpages if one of the conditions is met. If the process is aborted, nil is returned! on: Function to be called if an abort-condition was met. cycles: The maximum number of subpages to run over. time: Maximum time to spend running over the subpages. ]=] function language_subpages( frame, transform, options ) local args, pargs, options = frame.args, ( frame:getParent() or {} ).args or {}, options or {}; local title = args.page or args[1] or pargs.page or pargs[1] or ""; local abort = options.abort or {}; local at, clock = type( abort.on ), os.clock(); local ac = function() if at == 'function' or ( at == 'table' and getmetatable(abort.on).__call ) then abort.on(); end end local tt = type( transform ); local page = require( 'Module:Page' ); title = page.clean(title); if tt == 'function' or ( tt == 'table' and getmetatable(transform).__call ) then local fetch, pages, langcode, langname = mw.language.fetchLanguageName, {}; for pg in page.subpages( title, { ignoreNS=true } ) do if abort.cycles then abort.cycles = abort.cycles - 1 if 0 == abort.cycles then return ac() end end if abort.time then if (os.clock() - clock) > abort.time then return ac() end end if mw.ustring.len( pg ) <= 12 then langcode = string.lower( pg ); langname = fetch( langcode ); if langname ~= '' then table.insert( pages, transform( title, pg, langcode, langname ) ); end end end return pages; end return {}; end function cloneArgs(frame) local args, pargs = {}, {} for k,v in pairs( frame.args ) do args[k] = v end if frame:getParent() then for k,v in pairs( frame:getParent().args ) do pargs[k] = v end end return args, pargs; end local p = {}; --[=[ Usage: {{#invoke:languages|internal|Template:Adjective}} ]=] function p.internal(frame) pages = language_subpages( frame, function( title, page, code, name ) return mw.ustring.format( '<span lang="%s" xml:lang="%s" class="language lang-%s"><bdi>[[%s/%s|%s]]</bdi></span>', code, code, code, title, page, name ); end); return table.concat( pages, ' · ' ); end --[=[ Usage: {{#invoke:languages|external|Template:Adjective}} ]=] function p.external(frame) pages = language_subpages( frame, function( title, page, code, name ) return mw.ustring.format( '<span lang="%s" xml:lang="%s" class="language lang-%s"><bdi>[%s/%s %s]</bdi></span>', code, code, code, tostring( mw.uri.fullUrl( title ) ), page:gsub( ' ', '_' ), name ); end); return table.concat( pages, ' | ' ); end --[=[ forEachLanguage This function iterates over all language codes known to MediaWiki based on a maintained list replacing patterns in a pattern-string for each language Usage: {{#invoke:Languages|forEachLanguage |pattern=patternstring |before=string to insert before iteration |after=string added after iteration |sep=separator string between iterations |inLang=langcode used for $lnTrP and $lnTrUC1 }} Parameters pattern: A pattern string which is processed for each language and which is concatenated at the end and returned as one string before: A string that is inserted before the concatenated result after: A string that is inserted after the concatenated result sep: A string that is inserted between each line created from the pattern while iterating (like ProcessedPattern_sep_ProcessedPattern_sep_ProcessedPattern) inLang: Langcode to use for $lnTrP and $lnTrUC1 Patterns: $lc - language code such as en or de $lnP - language name in own language (autonym) $lnUC1 - language name in own language (autonym), first letter upper case $lnTrP - language name translated to the language requested by language code passed to inLang $lnTrUC1 - language name translated to the language requested by language code passed to inLang, first letter upper case Example {{#invoke:Languages|forEachLanguage|pattern=<span lang="$lc" xml:lang="$lc" class="language lang-$lc">[[Page/$lc|$lnP]]</span>}} ]=] -- =p.forEachLanguage({ args= { pattern = "$lc - $lnTrP\n", inLang = "en" } }) function p.forEachLanguage(frame) local l = require( "Module:Languages/List" ) local ret = {} local lang = mw.language local contentLangInstance = mw.language.getContentLanguage() local langInstance = contentLangInstance --Quota hit here otherwise local line local pattern = frame.args.pattern or frame.args[1] or "" local prefix = frame.args.before or frame.args[2] or "" local postfix = frame.args.after or frame.args[3] or "" local sep = frame.args.sep or frame.args.separator or frame.args[4] or "" local inLang = frame.args.inLang or frame.args[5] or nil local langName local langNameUCFirst local langNameTranslated local langNameTranslatedUCFirst local langNameUCFirstReq = not not pattern:find( "$lnUC1", 1, true ) local langNameReq = not not pattern:find( "$lnP", 1, true ) or langNameUCFirstReq local langNameTranslatedUCFirstReq = not not pattern:find( "$lnTrUC1", 1, true ) local langNameTranslatedReq = not not pattern:find( "$lnTrP", 1, true ) or langNameTranslatedUCFirstReq local l, lTr if ( langNameReq ) then l = mw.language.fetchLanguageNames() end if ( langNameTranslatedReq ) then lTr = mw.language.fetchLanguageNames( inLang ) end local lcIdList = require( 'Module:Languages/List' ).getSortedList( l or lTr ) for i, lcId in pairs( lcIdList ) do line = pattern:gsub( "$lc", lcId ) if langNameReq then line = line:gsub( "$lnP", l[lcId] ) end if langNameUCFirstReq then --langInstance = mw.getLanguage( lcId ) --Quota hit here langNameUCFirst = langInstance:ucfirst( l[lcId] ) line = line:gsub( "$lnUC1", langNameUCFirst ) end if langNameTranslatedReq then langNameTranslated = lTr[lcId] line = line:gsub( "$lnTrP", langNameTranslated ) end if langNameTranslatedUCFirstReq then --if not langInstance then langInstance = mw.getLanguage( lcId ) end --Quota hit here langNameTranslatedUCFirst = langInstance:ucfirst( langNameTranslated ) line = line:gsub( "$lnTrUC1", langNameTranslatedUCFirst ) end --langInstance = nil table.insert(ret, line) end return prefix .. table.concat( ret, sep ) .. postfix end --[=[ Provide logic for [[Template:Lle]] (Language Links external, to be substituted) ]=] function p.lle(frame) local ret local pattern = "{{<includeonly/>subst:#ifexist:{{{1}}}/$lc|[{{fullurl:{{{1}}}/$lc}} $lnUC1] {{<includeonly/>subst:!}} <!--\n-->}}" ret = p.forEachLanguage({ args= { pattern = pattern } }) ret = frame:preprocess(ret) return ret end --[=[ Provide logic for [[Template:Ll]] (Language Links, to be substituted) ]=] function p.ll(frame) local ret local pattern = "{{<includeonly/>subst:#ifexist:{{{1}}}/$lc|[[{{{1}}}/$lc{{<includeonly/>subst:!}}$lnUC1]] {{<includeonly/>subst:!}} <!--\n-->}}" ret = p.forEachLanguage({ args= { pattern = pattern } }) ret = frame:preprocess(ret) return ret end -------------------------------------------------------- --- Different approaches for [[Template:Lang links]] --- -------------------------------------------------------- --[=[ Provide logic for [[Template:Lang links]] Using a cute Hybrid-Method: First check the subpages which is quite fast; if there are too many fall back to checking for each language page individually ]=] -- =p.langLinksNonExpensive({ args= { page='Commons:Picture of the Year/2010' }, getParent=function() end }) -- =p.langLinksNonExpensive({ args= { page='Main Page' }, getParent=function() end }) -- =p.langLinksNonExpensive({ args= { page='Template:No_source_since' }, getParent=function() end }) -- =p.langLinksNonExpensive({ args= { page='MediaWiki:Gadget-HotCat' }, getParent=function() end }) function p.langLinksNonExpensive(frame) local args, pargs = frame.args, ( frame:getParent() or {} ).args or {}; local title = args.page or args[1] or pargs.page or pargs[1] or ""; local contentLangInstance = mw.language.getContentLanguage(); local pages2 if frame.preprocess == nil then frame = mw.getCurrentFrame() end --[==[ local options = { abort= { time=3.5, on=function() pages2 = p.forEachLanguage({ args= { pattern = '{{#ifexist:' .. title .. '/$lc|[[' .. title .. '/$lc|$lnUC1]] | }}' } }) end } } local pages = language_subpages( frame, function( basepagename, subpagename, code, langname ) return mw.ustring.format( '<span lang="%s" xml:lang="%s" class="language lang-%s" style="white-space:nowrap"><bdi>[[%s/%s|%s]]</bdi></span> | ', code, code, code, basepagename, subpagename, contentLangInstance:ucfirst( langname ) ) end, options ); return pages2 and frame:preprocess(pages2) or table.concat( pages, '' ); ]==] return frame:preprocess( p.forEachLanguage({ args= { pattern = '{{#ifexist:' .. title .. '/$lc|[[' .. title .. '/$lc|$lnUC1]] | }}' } }) ) end --------------------------------------------------------- ----------------- [[Template:Autolang]] ----------------- --------------------------------------------------------- --[[ Works like {{autotranslate}} just allowing an unlimited number of arguments, even named arguments. It's doing Magic! No arguments should be passed to {{#invoke:}} ]] function p.autolang(frame) local args, pargs = cloneArgs( frame ) if nil == args.useargs then if not args.base then args = pargs end elseif 'both' == args.useargs then for k,v in pairs(args) do pargs[k] = v end args = pargs elseif 'parent' == args.useargs then args = pargs if pargs.base and not args.base then args.base = pargs.base end end local base = args.base local userlang = frame:preprocess( '{{int:lang}}' ) local tl, tlns = 'Template:', 10 local tlb, fallback1, currenttemplate local fallback, contentlang = mw.text.split( userlang, '-', true )[1], mw.language.getContentLanguage():getCode() local createReturn = function(title) local ret local tlargs = {} -- When LUA is invoked, templates are already expanded. This must be respected. return frame:expandTemplate{ title = title, args = args } end if not base then return ("'autolang' in [[Module:Languages]] was called but the 'base' parameter could not be found." .. "The base parameter specifies the template that's subpages will be sought for a suitable translation.") end tlb = tl .. base .. '/' currenttemplate = tlb .. userlang if mw.title.new( currenttemplate, tlns ).exists then return createReturn(currenttemplate) end fallback1 = frame:preprocess( '{{Fallback|1=' .. base .. '|2=' .. userlang .. '}}' ) if fallback1 ~= contentlang then return createReturn(tlb .. fallback1) end currenttemplate = tlb .. fallback if mw.title.new( currenttemplate, tlns ).exists then return createReturn(currenttemplate) end currenttemplate = tlb .. contentlang if mw.title.new( currenttemplate, tlns ).exists then return createReturn(currenttemplate) end return createReturn(tl .. base) end --[=[ Usage: {{#invoke:languages|isKnownLanguageTag|gsw}} -> 1 {{#invoke:languages|isKnownLanguageTag|doesNotExist}} -> ]=] function p.isKnownLanguageTag(frame) return mw.language.isKnownLanguageTag( frame.args[1] or frame.args.tag or frame.args.code or '' ) and '1' or '' end function p.file_languages(frame) local M_link = require( 'Module:Link' ) local contentLangInstance = mw.language.getContentLanguage() local pattern = frame.args.pattern or '%s (%s)' local original = frame.args.original or mw.title.getCurrentTitle().text local ext_start, _ = string.find( original, '\.%w+$' ) local file_ext = string.sub( original, ext_start ) original = string.sub( original, 0, ext_start-1 ) return frame:preprocess('<gallery>\n'..(table.concat(M_link.forEachLink( p.forEachLanguage( { args= { pattern = '[[$lc]]' } } ), function(linkInfo) local filename = mw.ustring.format( pattern, original, linkInfo.text ) .. file_ext if mw.title.new( filename, 6 ).exists then return mw.ustring.format( '%s|%s', filename, contentLangInstance:ucfirst( mw.language.fetchLanguageName( linkInfo.text ) ) ) else return nil end end ), '\n'))..'\n</gallery>') end function p.runTests() return p.langLinksNonExpensive({ args= { page='Module:Languages/testcases/test' }, getParent=function() end }) == "[[Module:Languages/testcases/test/de|Deutsch]] | [[Module:Languages/testcases/test/en|English]] | " end return p;