Mô đun Lua này được sử dụng ở khoảng 232.000 trang. Để tránh gây lỗi trên quy mô lớn và tải máy chủ không cần thiết, tất cả thay đổi cần được thử nghiệm ở trang con /sandbox, /testcases của mô đun, hoặc ở chỗ thử mô đun. Các thay đổi đã được thử nghiệm có thể thêm vào mô đun bằng một sửa đổi duy nhất. Xin hãy thảo luận các thay đổi tại trang thảo luận trước khi áp dụng sửa đổi.
Mô đun Lua này được sử dụng trong thông báo hệ thống, và ở khoảng 232.000 trang. Thay đổi đến nó có thể dẫn đến thay đổi ngay lập tức giao diện người dùng Wikipedia. Để tránh gây lỗi trên quy mô lớn và tải máy chủ không cần thiết, tất cả thay đổi cần được thử nghiệm ở trang con /sandbox, /testcases của mô đun, hoặc ở chỗ thử mô đun. Các thay đổi đã được thử nghiệm có thể thêm vào mô đun bằng một sửa đổi duy nhất. Xin hãy thảo luận các thay đổi tại trang thảo luận trước khi áp dụng sửa đổi.
Mô-đun này là loại cần được khóa. Nó là một mô-đun nhìn thấy rõ được sử dụng bởi một số lượng lớn các trang, hoặc là các thay thế rất thường xuyên. Bởi vì phá hoại hoặc lỗi sai khi sửa sẽ ảnh hưởng đến nhiều trang và thậm chí chỉnh sửa tầm thường có thể gây ra tải đáng kể cho các máy chủ, nó được khóa bảo vệ hạn chế sửa đổi.
This is a meta-module that implements the message box templates {{mbox}}, {{ambox}}, {{cmbox}}, {{fmbox}}, {{imbox}}, {{ombox}}, and {{tmbox}}. It is intended to be used from Lua modules, and should not be used directly from wiki pages. If you want to use this module's functionality from a wiki page, please use the individual message box templates instead.
Usage
To use this module from another Lua module, first you need to load it.
localmessageBox=require('Module:Message box')
To create a message box, use the main function. It takes two parameters: the first is the box type (as a string), and the second is a table containing the message box parameters.
localbox=messageBox.main(boxType,{param1=param1,param2=param2,-- More parameters...})
See the template page of each box type for the available parameters.
Usage from #invoke
As well as the main function, this module has separate functions for each box type. They are accessed using the code {{#invoke:Message box|mbox|...}}, {{#invoke:Message box|ambox|...}}, etc. These will work when called from other modules, but they access code used to process arguments passed from #invoke, and so calling them will be less efficient than calling main.
Technical details
The module uses the same basic code for each of the templates listed above; the differences between each of them are configured using the data at Module:Message box/configuration. Here are the various configuration options and what they mean:
types - a table containing data used by the type parameter of the message box. The table keys are the values that can be passed to the type parameter, and the table values are tables containing the class and the image used by that type.
default - the type to use if no value was passed to the type parameter, or if an invalid value was specified.
showInvalidTypeError - whether to show an error if the value passed to the type parameter was invalid.
allowBlankParams - usually blank values are stripped from parameters passed to the module. However, whitespace is preserved for the parameters included in the allowBlankParams table.
allowSmall - whether a small version of the message box can be produced with "small=yes".
smallParam - a custom name for the small parameter. For example, if set to "left" you can produce a small message box using "small=left".
smallClass - the class to use for small message boxes.
substCheck - whether to perform a subst check or not.
classes - an array of classes to use with the message box.
imageEmptyCell - whether to use an empty <td>...</td> cell if there is no image set. This is used to preserve spacing for message boxes with a width of less than 100% of the screen.
imageEmptyCellStyle - whether empty image cells should be styled.
imageCheckBlank - whether "image=blank" results in no image being displayed.
imageSmallSize - usually, images used in small message boxes are set to 30x30px. This sets a custom size.
imageCellDiv - whether to enclose the image in a div enforcing a maximum image size.
useCollapsibleTextFields - whether to use text fields that can be collapsed, i.e. "issue", "fix", "talk", etc. Currently only used in ambox.
imageRightNone - whether imageright=none results in no image being displayed on the right-hand side of the message box.
sectionDefault - the default name for the "section" parameter. Depends on useCollapsibleTextFields.
allowMainspaceCategories - allow categorisation in the main namespace.
templateCategory - the name of a category to be placed on the template page.
templateCategoryRequireName - whether the name parameter is required to display the template category.
templateErrorCategory - the name of the error category to be used on the template page.
templateErrorParamsToCheck - an array of parameter names to check. If any are absent, the templateErrorCategory is applied to the template page.
-- This is a meta-module for producing message box templates, including-- {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.-- Load necessary modules.require('strict')localgetArgslocalyesno=require('Mô đun:Yesno')-- Get a language object for formatDate and ucfirst.locallang=mw.language.getContentLanguage()-- Define constantslocalCONFIG_MODULE='Mô đun:Message box/configuration'localDEMOSPACES={talk='tmbox',image='imbox',file='imbox',category='cmbox',article='ambox',main='ambox'}localviArgs={["kiểu"]="style",["kiểu chữ"]="textstyle",["loại"]="type",["hình"]="image",["chữ"]="text",["hình phải"]="imageright",["tên"]="name",["thế"]="subst",["lớp"]="class",["vấn đề"]="issue",["giải quyết"]="fix",["khắc phục"]="fix",["dưới"]="below",}---------------------------------------------------------------------------------- Helper functions--------------------------------------------------------------------------------localfunctionviMapArgs(args)localnewArgs={}fork,vinpairs(args)donewArgs[viArgs[k]ork]=vendreturnnewArgsendlocalfunctiongetTitleObject(...)-- Get the title object, passing the function through pcall-- in case we are over the expensive function count limit.localsuccess,title=pcall(mw.title.new,...)ifsuccessthenreturntitleendendlocalfunctionunion(t1,t2)-- Returns the union of two arrays.localvals={}fori,vinipairs(t1)dovals[v]=trueendfori,vinipairs(t2)dovals[v]=trueendlocalret={}forkinpairs(vals)dotable.insert(ret,k)endtable.sort(ret)returnretendlocalfunctiongetArgNums(args,prefix)localnums={}fork,vinpairs(args)dolocalnum=mw.ustring.match(tostring(k),'^'..prefix..'([1-9]%d*)$')ifnumthentable.insert(nums,tonumber(num))endendtable.sort(nums)returnnumsend---------------------------------------------------------------------------------- Box class definition--------------------------------------------------------------------------------localMessageBox={}MessageBox.__index=MessageBoxfunctionMessageBox.new(boxType,args,cfg)args=argsor{}localobj={}-- Set the title object and the namespace.obj.title=getTitleObject(args.page)ormw.title.getCurrentTitle()-- Set the config for our box type.obj.cfg=cfg[boxType]ifnotobj.cfgthenlocalns=obj.title.namespace-- boxType is "mbox" or invalid inputifargs.demospaceandargs.demospace~=''then-- implement demospace parameter of mboxlocaldemospace=string.lower(args.demospace)ifDEMOSPACES[demospace]then-- use template from DEMOSPACESobj.cfg=cfg[DEMOSPACES[demospace]]elseifstring.find(demospace,'talk')then-- demo as a talk pageobj.cfg=cfg.tmboxelse-- default to omboxobj.cfg=cfg.omboxendelseifns==0thenobj.cfg=cfg.ambox-- main namespaceelseifns==6thenobj.cfg=cfg.imbox-- file namespaceelseifns==14thenobj.cfg=cfg.cmbox-- category namespaceelselocalnsTable=mw.site.namespaces[ns]ifnsTableandnsTable.isTalkthenobj.cfg=cfg.tmbox-- any talk namespaceelseobj.cfg=cfg.ombox-- other namespaces or invalid inputendendend-- Set the arguments, and remove all blank arguments except for the ones-- listed in cfg.allowBlankParams.dolocalnewArgs={}fork,vinpairs(args)doifv~=''thennewArgs[k]=vendendfori,paraminipairs(obj.cfg.allowBlankParamsor{})donewArgs[param]=args[param]endobj.args=newArgsend-- Define internal data structure.obj.categories={}obj.classes={}-- For lazy loading of [[Module:Category handler]].obj.hasCategories=falsereturnsetmetatable(obj,MessageBox)endfunctionMessageBox:addCat(ns,cat,sort)ifnotcatthenreturnnilendifsortthencat=string.format('[[Thể loại:%s|%s]]',cat,sort)elsecat=string.format('[[Thể loại:%s]]',cat)endself.hasCategories=trueself.categories[ns]=self.categories[ns]or{}table.insert(self.categories[ns],cat)endfunctionMessageBox:addClass(class)ifnotclassthenreturnnilendtable.insert(self.classes,class)endfunctionMessageBox:setParameters()localargs=self.argslocalcfg=self.cfg-- Get type data.self.type=args.typelocaltypeData=cfg.types[self.type]self.invalidTypeError=cfg.showInvalidTypeErrorandself.typeandnottypeDatatypeData=typeDataorcfg.types[cfg.default]self.typeClass=typeData.classself.typeImage=typeData.imageself.typeImageNeedsLink=typeData.imageNeedsLink-- Find if the box has been wrongly substituted.self.isSubstituted=cfg.substCheckandargs.subst=='SUBST'-- Find whether we are using a small message box.self.isSmall=cfg.allowSmalland(cfg.smallParamandargs.small==cfg.smallParamornotcfg.smallParamandyesno(args.small))-- Add attributes, classes and styles.self.id=args.idself.name=args.nameifself.namethenself:addClass('box-'..string.gsub(self.name,' ','_'))endifyesno(args.plainlinks)~=falsethenself:addClass('plainlinks')endfor_,classinipairs(cfg.classesor{})doself:addClass(class)endifself.isSmallthenself:addClass(cfg.smallClassor'mbox-small')endself:addClass(self.typeClass)self:addClass(args.class)self.style=args.styleself.attrs=args.attrs-- Set text style.self.textstyle=args.textstyle-- Set image classes.self.imageRightClass=args.imagerightclassorargs.imageclassself.imageLeftClass=args.imageleftclassorargs.imageclass-- Find if we are on the template page or not. This functionality is only-- used if useCollapsibleTextFields is set, or if both cfg.templateCategory-- and cfg.templateCategoryRequireName are set.self.useCollapsibleTextFields=cfg.useCollapsibleTextFieldsifself.useCollapsibleTextFieldsorcfg.templateCategoryandcfg.templateCategoryRequireNamethenifself.namethenlocaltemplateName=mw.ustring.match(self.name,'^[bB][aẢ][nN][%s_]+[mM][ẫẪ][uU][%s_]*:[%s_]*(.*)$')orself.nametemplateName='Bản mẫu:'..templateNameself.templateTitle=getTitleObject(templateName)endself.isTemplatePage=self.templateTitleandmw.title.equals(self.title,self.templateTitle)end-- Process data for collapsible text fields. At the moment these are only-- used in {{ambox}}.ifself.useCollapsibleTextFieldsthen-- Get the self.issue value.ifself.isSmallandargs.smalltextthenself.issue=args.smalltextelselocalsectifargs.sect==''thensect=(lang:ucfirst(cfg.sectionDefault)or'Trang')..' này'elseiftype(args.sect)=='string'thensect=lang:ucfirst(args.sect)..' này'endlocalissue=args.issueissue=type(issue)=='string'andissue~=''andissueornillocaltext=args.texttext=type(text)=='string'andtextornillocalissues={}table.insert(issues,sect)table.insert(issues,issue)table.insert(issues,text)self.issue=table.concat(issues,' ')end-- Get the self.talk value.localtalk=args.talk-- Show talk links on the template page or template subpages if the talk-- parameter is blank.iftalk==''andself.templateTitleand(mw.title.equals(self.templateTitle,self.title)orself.title:isSubpageOf(self.templateTitle))thentalk='#'elseiftalk==''thentalk=nilendiftalkthen-- If the talk value is a talk page, make a link to that page. Else-- assume that it's a section heading, and make a link to the talk-- page of the current page with that section heading.localtalkTitle=getTitleObject(talk)localtalkArgIsTalkPage=trueifnottalkTitleornottalkTitle.isTalkPagethentalkArgIsTalkPage=falsetalkTitle=getTitleObject(self.title.text,mw.site.namespaces[self.title.namespace].talk.id)endiftalkTitleandtalkTitle.existsthenlocaltalkText='Có thể có thảo luận liên quan tại'iftalkArgIsTalkPagethentalkText=string.format('%s [[%s|%s]].',talkText,talk,talkTitle.prefixedText)elsetalkText=string.format('%s [[%s#%s|trang thảo luận]].',talkText,talkTitle.prefixedText,talk)endself.talk=talkTextendend-- Get other values.self.fix=args.fix~=''andargs.fixornillocaldateifargs.dateandargs.date~=''thendate=args.dateelseifargs.date==''andself.isTemplatePagethendate=lang:formatDate('"Tháng" n "năm" Y')endifdatethenself.date=string.format(" <span class='date-container'><i>(<span class='date'>%s</span>)</i></span>",date)endself.info=args.infoifyesno(args.removalnotice)thenself.removalNotice=cfg.removalNoticeendend-- Set the non-collapsible text field. At the moment this is used by all box-- types other than ambox, and also by ambox when small=yes.ifself.isSmallthenself.text=args.smalltextorargs.textelseself.text=args.textend-- Set the below row.self.below=cfg.belowandargs.below-- General image settings.self.imageCellDiv=notself.isSmallandcfg.imageCellDivself.imageEmptyCell=cfg.imageEmptyCell-- Left image settings.localimageLeft=self.isSmallandargs.smallimageorargs.imageifcfg.imageCheckBlankandimageLeft~='blank'andimageLeft~='none'andimageLeft~='không'ornotcfg.imageCheckBlankand(imageLeft~='none'andimageLeft~='không')thenself.imageLeft=imageLeftifnotimageLeftthenlocalimageSize=self.isSmalland(cfg.imageSmallSizeor'30x30px')or'40x40px'self.imageLeft=string.format('[[Tập tin:%s|%s%s|alt=]]',self.typeImageor'Information icon4.svg',imageSize,self.typeImageNeedsLinkand""or"|link=")endend-- Right image settings.localimageRight=self.isSmallandargs.smallimagerightorargs.imagerightifnot(cfg.imageRightNoneand(imageRight=='none'orimageRight=='không'))thenself.imageRight=imageRightend-- set templatestylesself.base_templatestyles=cfg.templatestylesself.templatestyles=args.templatestylesendfunctionMessageBox:setMainspaceCategories()localargs=self.argslocalcfg=self.cfgifnotcfg.allowMainspaceCategoriesthenreturnnilendlocalnums={}for_,prefixinipairs{'cat','category','all'}doargs[prefix..'1']=args[prefix]nums=union(nums,getArgNums(args,prefix))end-- The following is roughly equivalent to the old {{Ambox/category}}.localdate=args.datedate=type(date)=='string'anddatelocalpreposition='từ'for_,numinipairs(nums)dolocalmainCat=args['cat'..tostring(num)]orargs['category'..tostring(num)]localallCat=args['all'..tostring(num)]mainCat=type(mainCat)=='string'andmainCatallCat=type(allCat)=='string'andallCatifmainCatanddateanddate~=''thenlocalcatTitle=string.format('%s %s %s',mainCat,preposition,date)self:addCat(0,catTitle)catTitle=getTitleObject('Thể loại:'..catTitle)ifnotcatTitleornotcatTitle.existsthenself:addCat(0,'Tham số bản mẫu ngày tháng không hợp lệ')endelseifmainCatand(notdateordate=='')thenself:addCat(0,mainCat)endifallCatthenself:addCat(0,allCat)endendendfunctionMessageBox:setTemplateCategories()localargs=self.argslocalcfg=self.cfg-- Add template categories.ifcfg.templateCategorythenifcfg.templateCategoryRequireNamethenifself.isTemplatePagethenself:addCat(10,cfg.templateCategory)endelseifnotself.title.isSubpagethenself:addCat(10,cfg.templateCategory)endend-- Add template error categories.ifcfg.templateErrorCategorythenlocaltemplateErrorCategory=cfg.templateErrorCategorylocaltemplateCat,templateSortifnotself.nameandnotself.title.isSubpagethentemplateCat=templateErrorCategoryelseifself.isTemplatePagethenlocalparamsToCheck=cfg.templateErrorParamsToCheckor{}localcount=0fori,paraminipairs(paramsToCheck)doifnotargs[param]thencount=count+1endendifcount>0thentemplateCat=templateErrorCategorytemplateSort=tostring(count)endifself.categoryNumsand#self.categoryNums>0thentemplateCat=templateErrorCategorytemplateSort='C'endendself:addCat(10,templateCat,templateSort)endendfunctionMessageBox:setAllNamespaceCategories()-- Set categories for all namespaces.ifself.invalidTypeErrorthenlocalallSort=(self.title.namespace==0and'Main:'or'')..self.title.prefixedTextself:addCat('all','Tham số hộp thông báo Wikipedia cần sửa chữa',allSort)endifself.isSubstitutedthenself:addCat('all','Trang nhúng bản mẫu một cách không chính xác')endendfunctionMessageBox:setCategories()ifself.title.namespace==0thenself:setMainspaceCategories()elseifself.title.namespace==10thenself:setTemplateCategories()endself:setAllNamespaceCategories()endfunctionMessageBox:renderCategories()ifnotself.hasCategoriesthen-- No categories added, no need to pass them to Category handler so,-- if it was invoked, it would return the empty string.-- So we shortcut and return the empty string.return""end-- Convert category tables to strings and pass them through-- [[Module:Category handler]].returnrequire('Mô đun:Category handler')._main{main=table.concat(self.categories[0]or{}),template=table.concat(self.categories[10]or{}),all=table.concat(self.categories.allor{}),nocat=self.args.nocat,page=self.args.page}endfunctionMessageBox:export()localroot=mw.html.create()-- Add the subst check error.ifself.isSubstitutedandself.namethenroot:tag('b'):addClass('error'):wikitext(string.format('Bản mẫu <code>%s[[Bản mẫu:%s|%s]]%s</code> đã được thế sai quy cách.',mw.text.nowiki('{{'),self.name,self.name,mw.text.nowiki('}}')))endlocalframe=mw.getCurrentFrame()root:wikitext(frame:extensionTag{name='templatestyles',args={src=self.base_templatestyles},})-- Add support for a single custom templatestyles sheet. Undocumented as-- need should be limited and many templates using mbox are substed; we-- don't want to spread templatestyles sheets around to arbitrary placesifself.templatestylesthenroot:wikitext(frame:extensionTag{name='templatestyles',args={src=self.templatestyles},})end-- Create the box table.localboxTable=root:tag('table')boxTable:attr('id',self.idornil)fori,classinipairs(self.classesor{})doboxTable:addClass(classornil)endboxTable:cssText(self.styleornil):attr('role','presentation')ifself.attrsthenboxTable:attr(self.attrs)end-- Add the left-hand image.localrow=boxTable:tag('tr')ifself.imageLeftthenlocalimageLeftCell=row:tag('td'):addClass('mbox-image')ifself.imageCellDivthen-- If we are using a div, redefine imageLeftCell so that the image-- is inside it. Divs use style="width: 52px;", which limits the-- image width to 52px. If any images in a div are wider than that,-- they may overlap with the text or cause other display problems.imageLeftCell=imageLeftCell:tag('div'):addClass('mbox-image-div')endimageLeftCell:addClass(self.imageLeftClass):wikitext(self.imageLeftornil)elseifself.imageEmptyCellthen-- Some message boxes define an empty cell if no image is specified, and-- some don't. The old template code in templates where empty cells are-- specified gives the following hint: "No image. Cell with some width-- or padding necessary for text cell to have 100% width."row:tag('td'):addClass('mbox-empty-cell')end-- Add the text.localtextCell=row:tag('td'):addClass('mbox-text')ifself.useCollapsibleTextFieldsthen-- The message box uses advanced text parameters that allow things to be-- collapsible. At the moment, only ambox uses this.textCell:cssText(self.textstyleornil)localtextCellDiv=textCell:tag('div')textCellDiv:addClass('mbox-text-span'):wikitext(self.issueornil)if(self.talkorself.fix)thentextCellDiv:tag('span'):addClass('hide-when-compact'):wikitext(self.talkand(' '..self.talk)ornil):wikitext(self.fixand(' '..self.fix)ornil)endtextCellDiv:wikitext(self.dateand(' '..self.date)ornil)ifself.infoandnotself.isSmallthentextCellDiv:tag('span'):addClass('hide-when-compact'):wikitext(self.infoand(' '..self.info)ornil)endifself.removalNoticethentextCellDiv:tag('span'):addClass('hide-when-compact'):tag('i'):wikitext(string.format(" (%s)",self.removalNotice))endelse-- Default text formatting - anything goes.textCell:cssText(self.textstyleornil):wikitext(self.textornil)end-- Add the right-hand image.ifself.imageRightthenlocalimageRightCell=row:tag('td'):addClass('mbox-imageright')ifself.imageCellDivthen-- If we are using a div, redefine imageRightCell so that the image-- is inside it.imageRightCell=imageRightCell:tag('div'):addClass('mbox-image-div')endimageRightCell:addClass(self.imageRightClass):wikitext(self.imageRightornil)end-- Add the below row.ifself.belowthenboxTable:tag('tr'):tag('td'):attr('colspan',self.imageRightand'3'or'2'):addClass('mbox-text'):cssText(self.textstyleornil):wikitext(self.belowornil)end-- Add error message for invalid type parameters.ifself.invalidTypeErrorthenroot:tag('div'):addClass('mbox-invalid-type'):wikitext(string.format('Hộp thông báo này đang sử dụng một tham số "loại=%s" sai quy cách và cần được sửa chữa.',self.typeor''))end-- Add categories.root:wikitext(self:renderCategories()ornil)returntostring(root)end---------------------------------------------------------------------------------- Exports--------------------------------------------------------------------------------localp,mt={},{}functionp._exportClasses()-- For testing.return{MessageBox=MessageBox}endfunctionp.main(boxType,args,cfgTables)args=viMapArgs(args)localbox=MessageBox.new(boxType,args,cfgTablesormw.loadData(CONFIG_MODULE))box:setParameters()box:setCategories()returnbox:export()endfunctionmt.__index(t,k)returnfunction(frame)ifnotgetArgsthengetArgs=require('Mô đun:Arguments').getArgsendreturnt.main(k,getArgs(frame,{trim=false,removeBlanks=false}))endendreturnsetmetatable(p,mt)