Module:Languages: Difference between revisions
>PJosepherum m 1 revision imported |
iw>Verdy p m catch the "too many costly function calls" errors in "mw.title.new().exists" (consider as if page is inexistant ) |
||
Line 12: | Line 12: | ||
cycles: The maximum number of subpages to run over. | cycles: The maximum number of subpages to run over. | ||
time: Maximum time to spend running over the subpages. | time: Maximum time to spend running over the subpages. | ||
]=] | ]=] | ||
function language_subpages( frame, transform, options ) | function language_subpages( frame, transform, options ) | ||
Line 26: | Line 26: | ||
local tt = type( transform ); | local tt = type( transform ); | ||
local page = require( 'Module:Page' ); | local page = require( 'Module:Page' ); | ||
title = page.clean(title); | title = page.clean(title); | ||
if tt == 'function' or ( tt == 'table' and getmetatable(transform).__call ) then | if tt == 'function' or ( tt == 'table' and getmetatable(transform).__call ) then | ||
local fetch, pages, langcode, langname = mw.language.fetchLanguageName, {}; | local fetch, pages, langcode, langname = mw.language.fetchLanguageName, {}; | ||
--[==[ | |||
/ \ | |||
/ | \ | |||
/ · \ | |||
¯¯¯¯¯¯¯ | |||
Page.subpages() no longer works because it attempted to parse the HTML content generated by | |||
calling the parser function "Special:Prefixindex:" which is no longer expanded in Lua but | |||
converted to a "stripped tag" (containing a unique identifier surrounded by ASCII DEL characters) | |||
representing the tag name and its parameters. | |||
The actual expansion of stripped tags can no longer be performed in Lua. | |||
Now unstripping these tags just kills ALL these tags (except "wiki" tags) instead of performing | |||
their expansion by running the extension code. Only MediaWiki can unstrip these tags in texts after | |||
they have been returned by Lua. | |||
For this reason, page.subpages() is now completely empty (Module:Page no longer works). | |||
This cannot be bypassed, except by using a Scribunto extension library if lifting the limits set by mw.unstrip. | |||
Note that "Special:Prefixindex:" is also costly, even if it just requires a single database query to | |||
get all subpages, instead of one costly #ifexist or one costly mw.title() property reading per | |||
tested subpage to know if it exists. | |||
For now there's still no reliable way to get a list of subpages, or performing queries similar to | |||
the [[Special:Prefixindex]] page or list members of a category like when viewing a category page. | |||
Ideally, there should exist a method for such queries on Title objects returned by the mw.title library; | |||
but for now there's none. | |||
In Lua now, the only expansion possible with an immediate effect is the expansion of standard templates, | |||
all special tags or special pages, or parser function extensions do not work (Only the #expr parser | |||
function is supported by using an external Scribunto library). | |||
--]==] | |||
for pg in page.subpages( title, { ignoreNS=true } ) do | for pg in page.subpages( title, { ignoreNS=true } ) do | ||
if abort.cycles then | if abort.cycles then | ||
Line 91: | Line 118: | ||
end | end | ||
--[=[ | --[=[ | ||
forEachLanguage | forEachLanguage | ||
This function iterates over all language codes known to MediaWiki based on a maintained list | This function iterates over all language codes known to MediaWiki based on a maintained list | ||
replacing patterns in a pattern-string for each language | replacing patterns in a pattern-string for each language | ||
Usage: | Usage: | ||
{{#invoke:Languages|forEachLanguage | {{#invoke:Languages|forEachLanguage | ||
Line 105: | Line 132: | ||
|inLang=langcode used for $lnTrP and $lnTrUC1 | |inLang=langcode used for $lnTrP and $lnTrUC1 | ||
}} | }} | ||
Parameters | Parameters | ||
pattern: A pattern string which is processed for each language and which is concatenated at the end and returned as one string | pattern: A pattern string which is processed for each language and which is concatenated at the end and returned as one string | ||
Line 112: | Line 139: | ||
sep: A string that is inserted between each line created from the pattern while iterating (like ProcessedPattern_sep_ProcessedPattern_sep_ProcessedPattern) | 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 | inLang: Langcode to use for $lnTrP and $lnTrUC1 | ||
Patterns: | Patterns: | ||
$lc - language code such as en or de | $lc - language code such as en or de | ||
Line 119: | Line 146: | ||
$lnTrP - language name translated to the language requested by language code passed to inLang | $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 | $lnTrUC1 - language name translated to the language requested by language code passed to inLang, first letter upper case | ||
Example | Example | ||
{{#invoke:Languages|forEachLanguage|pattern=<span lang="$lc" xml:lang="$lc" class="language lang-$lc">[[Page/$lc|$lnP]]</span>}} | {{#invoke:Languages|forEachLanguage|pattern=<span lang="$lc" xml:lang="$lc" class="language lang-$lc">[[Page/$lc|$lnP]]</span>}} | ||
Line 127: | Line 154: | ||
function p.forEachLanguage(frame) | function p.forEachLanguage(frame) | ||
local l = require( "Module:Languages/List" ) | local l = require( "Module:Languages/List" ) | ||
local ret = {} | local ret = {} | ||
local lang = mw.language | local lang = mw.language | ||
local line | local line | ||
local pattern = frame.args.pattern or frame.args[1] or "" | local pattern = frame.args.pattern or frame.args[1] or "" | ||
Line 138: | Line 163: | ||
local sep = frame.args.sep or frame.args.separator or frame.args[4] 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 inLang = frame.args.inLang or frame.args[5] or nil | ||
local langNameUCFirstReq = not not pattern:find( "$lnUC1", 1, true ) | local langNameUCFirstReq = not not pattern:find( "$lnUC1", 1, true ) | ||
Line 147: | Line 168: | ||
local langNameTranslatedUCFirstReq = not not pattern:find( "$lnTrUC1", 1, true ) | local langNameTranslatedUCFirstReq = not not pattern:find( "$lnTrUC1", 1, true ) | ||
local langNameTranslatedReq = not not pattern:find( "$lnTrP", 1, true ) or langNameTranslatedUCFirstReq | local langNameTranslatedReq = not not pattern:find( "$lnTrP", 1, true ) or langNameTranslatedUCFirstReq | ||
local | local contentLangInstance = mw.language.getContentLanguage() | ||
local inLangLangInstance | |||
local l = mw.language.fetchLanguageNames() -- autonyms | |||
local lTr | |||
local lcIdList = require( 'Module:Languages/List' ).getSortedList( l ) | |||
if langNameTranslatedReq then | |||
inLangLangInstance = --[==[ | |||
mw.getLanguage( inLang ) -- Quota hit in :ucfirst() if using too many langInstances | |||
--]==] contentLangInstance | |||
lTr = mw.language.fetchLanguageNames( inLang ) -- translated names | |||
end | |||
for | for _, lcId in pairs( lcIdList ) do | ||
local subst = lcId:gsub('%%', '%%%%') | |||
line = pattern:gsub( "%$lc", subst ) | |||
local langName, langInstance | |||
-- autonym (name of lcId in locale lcId) | |||
if langNameReq then | if langNameReq then | ||
line = line:gsub( "$lnP", | langName = l[lcId] | ||
subst = langName:gsub('%%', '%%%%') | |||
line = line:gsub( "%$lnP", subst ) | |||
end | end | ||
if langNameUCFirstReq then | if langNameUCFirstReq then | ||
-- | langInstance = --[==[ | ||
mw.getLanguage( lcId ) -- Quota hit in :ucfirst() if using too many langInstances | |||
line = line:gsub( "$lnUC1", | --]==] contentLangInstance | ||
langName = langInstance:ucfirst( langName ) | |||
subst = langName:gsub('%%', '%%%%') | |||
line = line:gsub( "%$lnUC1", subst ) | |||
end | end | ||
-- translated name (name of lcId in locale inLang) | |||
if langNameTranslatedReq then | if langNameTranslatedReq then | ||
langName = lTr[lcId] | |||
line = line:gsub( "$lnTrP", | subst = langName:gsub('%%', '%%%%') | ||
line = line:gsub( "%$lnTrP", subst ) | |||
end | end | ||
if langNameTranslatedUCFirstReq then | if langNameTranslatedUCFirstReq then | ||
langName = inLangLangInstance:ucfirst( langName ) | |||
subst = langName:gsub('%%', '%%%%') | |||
line = line:gsub( "$lnTrUC1", | line = line:gsub( "%$lnTrUC1", subst ) | ||
end | end | ||
table.insert(ret, line) | table.insert(ret, line) | ||
Line 228: | Line 260: | ||
local pages2 | local pages2 | ||
if frame.preprocess == nil then | if frame.preprocess == nil then | ||
frame = mw.getCurrentFrame() | |||
end | end | ||
--[==[ | --[==[ | ||
local options = { abort= { time=3.5, on=function() | local options = { abort= { time=3.5, on=function() | ||
pages2 = p.forEachLanguage({ args= { pattern = '{{#ifexist:' .. title .. '/$lc|[[' .. title .. '/$lc|$lnUC1]] | }}' } }) | pages2 = p.forEachLanguage({ args= { pattern = '{{#ifexist:' .. title .. '/$lc|[[' .. title .. '/$lc|$lnUC1]] | }}' } }) | ||
end } } | end } } | ||
Line 269: | Line 301: | ||
local tlb, fallback1, currenttemplate | local tlb, fallback1, currenttemplate | ||
local fallback, contentlang = mw.text.split( userlang, '-', true )[1], mw.language.getContentLanguage():getCode() | local fallback, contentlang = mw.text.split( userlang, '-', true )[1], mw.language.getContentLanguage():getCode() | ||
local createReturn = function(title) | local createReturn = function(title) | ||
local ret | local ret | ||
local tlargs = {} | local tlargs = {} | ||
Line 276: | Line 308: | ||
return frame:expandTemplate{ title = title, args = args } | return frame:expandTemplate{ title = title, args = args } | ||
end | end | ||
if not base then | if not base then | ||
return ("'autolang' in [[Module:Languages]] was called but the 'base' parameter could not be found." .. | 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.") | "The base parameter specifies the template that's subpages will be sought for a suitable translation.") | ||
end | end | ||
tlb = tl .. base .. '/' | tlb = tl .. base .. '/' | ||
currenttemplate = tlb .. userlang | currenttemplate = tlb .. userlang | ||
local ok, exists = pcall( function() | |||
return mw.title.new( currenttemplate, tlns ).exists | |||
end ) | |||
if ok and exists then | |||
return createReturn(currenttemplate) | return createReturn(currenttemplate) | ||
end | end | ||
fallback1 = frame:preprocess( '{{Fallback|1=' .. base .. '|2=' .. userlang .. '}}' ) | fallback1 = frame:preprocess( '{{Fallback|1=' .. base .. '|2=' .. userlang .. '}}' ) | ||
if fallback1 ~= contentlang then | if fallback1 ~= contentlang then | ||
return createReturn(tlb .. fallback1) | return createReturn(tlb .. fallback1) | ||
end | end | ||
currenttemplate = tlb .. fallback | currenttemplate = tlb .. fallback | ||
local ok, exists = pcall( function() | |||
return mw.title.new( currenttemplate, tlns ).exists | |||
end ) | |||
if ok and exists then | |||
return createReturn(currenttemplate) | return createReturn(currenttemplate) | ||
end | end | ||
currenttemplate = tlb .. contentlang | currenttemplate = tlb .. contentlang | ||
local ok, exists = pcall( function() | |||
return mw.title.new( currenttemplate, tlns ).exists | |||
end ) | |||
if ok and exists then | |||
return createReturn(currenttemplate) | return createReturn(currenttemplate) | ||
end | end | ||
Line 311: | Line 352: | ||
]=] | ]=] | ||
function p.isKnownLanguageTag(frame) | function p.isKnownLanguageTag(frame) | ||
return mw.language.isKnownLanguageTag( frame.args[1] or frame.args.tag or frame.args.code or '' ) and '1' or '' | |||
end | end | ||
Line 322: | Line 363: | ||
local file_ext = string.sub( original, ext_start ) | local file_ext = string.sub( original, ext_start ) | ||
original = string.sub( original, 0, ext_start-1 ) | original = string.sub( original, 0, ext_start-1 ) | ||
return frame:preprocess('<gallery>\n'..(table.concat(M_link.forEachLink( p.forEachLanguage( { args= { pattern = '[[$lc]]' } } ), | return frame:preprocess('<gallery>\n'..(table.concat(M_link.forEachLink( p.forEachLanguage( { args= { pattern = '[[$lc]]' } } ), | ||
function(linkInfo) | function(linkInfo) | ||
local filename = mw.ustring.format( pattern, original, linkInfo.text ) .. file_ext | local filename = mw.ustring.format( pattern, original, linkInfo.text ) .. file_ext | ||
local ok, exists = pcall( function() | |||
return mw.title.new( filename, 6 ).exists | |||
end ) | |||
if ok and exists then | |||
return mw.ustring.format( '%s|%s', filename, contentLangInstance:ucfirst( mw.language.fetchLanguageName( linkInfo.text ) ) ) | return mw.ustring.format( '%s|%s', filename, contentLangInstance:ucfirst( mw.language.fetchLanguageName( linkInfo.text ) ) ) | ||
else | else | ||
Line 335: | Line 379: | ||
function p.runTests() | 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 | end | ||
return p; | return p; |