| Modul ini dinilai sebagai modul beta, dan siap digunakan secara luas. Modul ini masih baru dan harus digunakan dengan hati-hati untuk memastikan bahwa hasilnya sesuai dengan yang diharapkan. |
| Modul Lua ini digunakan pada sekitar 129.000 halaman. Untuk mencegah suntingan mengganggu skala besar dan beban peladen, setiap perubahan harus diuji di subhalaman /bak pasir atau /kasus uji Modul:I18n, atau bak pasir modul Anda. Perubahan yang telah diuji kemudian dapat ditambahkan ke halaman ini dalam satu suntingan. Pertimbangkan untuk mendiskusikan perubahan di halaman pembicaraan sebelum mengimplementasikannya. |
UsageUsage
{{#invoke:I18n|function_name}}
Dokumentasi di atas ditransklusikan dari Modul:I18n/doc. (sunting | riwayat)
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
--- I18n library for message storage in Lua datastores. -- The module is designed to enable message separation from modules & -- templates. It has support for handling language fallbacks. This -- module is a Lua port of [[wikia:dev:I18n-js]] and i18n modules that can be loaded -- by it are editable through [[wikia:dev:I18nEdit]]. -- -- On Wikimedia projects, i18n messages are editable -- through [[c:Special:PrefixIndex/Data:i18n/|Data:i18n/]] subpages on -- Wikimedia Commons. -- -- @module i18n -- @version 1.4.0 -- @require Module:Entrypoint -- @require Module:Fallbacklist -- @author [[wikia:dev:User:KockaAdmiralac|KockaAdmiralac]] (original Fandom implementation) -- @author [[wikia:dev:User:Speedit|Speedit]] (original Fandom implementation) -- @author [[User:Awesome Aasim|Awesome Aasim]] (Wikimedia port) -- @attribution [[wikia:dev:User:Cqm|Cqm]] -- @release beta -- @see [[wikia:dev:I18n|I18n guide]] -- @see [[wikia:dev:I18n-js]] -- @see [[wikia:dev:I18nEdit]] -- <nowiki> locali18n,_i18n={},{} -- Module variables & dependencies. localtitle=mw.title.getCurrentTitle() localfallbacks=require('Module:Fallbacklist') localentrypoint=require('Module:Entrypoint') localuselang --- Argument substitution as $n where n > 0. -- @function _i18n.handleArgs -- @param {string} msg Message to substitute arguments into. -- @param {table} args Arguments table to substitute. -- @return {string} Resulting message. -- @local function_i18n.handleArgs(msg,args) fori,ainipairs(args)do msg=(string.gsub(msg,'%$'..tostring(i),tostring(a))) end returnmsg end --- Checks whether a language code is valid. -- @function _i18n.isValidCode -- @param {string} code Language code to check. -- @return {boolean} Whether the language code is valid. -- @local function_i18n.isValidCode(code) returntype(code)=='string'and#mw.language.fetchLanguageName(code)~=0 end --- Checks whether a message contains unprocessed wikitext. -- Used to optimise message getter by not preprocessing pure text. -- @function _i18n.isWikitext -- @param {string} msg Message to check. -- @return {boolean} Whether the message contains wikitext. function_i18n.isWikitext(msg) return type(msg)=='string'and ( msg:find('%-%-%-%-')or msg:find('%f[^\n%z][;:*#] ')or msg:find('%f[^\n%z]==* *[^\n|]+ =*=%f[\n]')or msg:find('%b<>')ormsg:find('\'\'')or msg:find('%[%b[]%]')ormsg:find('{%b{}}') ) end --- I18n datastore class. -- This is used to control language translation and access to individual -- messages. The datastore instance provides language and message -- getter-setter methods, which can be used to internationalize Lua modules. -- The language methods (any ending in `Lang`) are all **chainable**. -- @type Data localData={} Data.__index=Data --- Datastore message getter utility. -- This method returns localized messages from the datastore corresponding -- to a `key`. These messages may have `$n` parameters, which can be -- replaced by optional argument strings supplied by the `msg` call. -- -- This function supports [[mw:Extension:Scribunto/Lua reference manual#named_arguments|named -- arguments]]. The named argument syntax is more versatile despite its -- verbosity; it can be used to select message language & source(s). -- @function Data:msg -- @usage -- -- ds:msg{ -- key = 'message-name', -- lang = '', -- args = {...}, -- sources = {} -- } -- -- @usage -- -- ds:msg('message-name', ...) -- -- @param {string|table} opts Message configuration or key. -- @param[opt] {string} opts.key Message key to return from the -- datastore. -- @param[opt] {table} opts.args Arguments to substitute into the -- message (`$n`). -- @param[opt] {table} opts.sources Source names to limit to (see -- `Data:fromSources`). -- @param[opt] {table} opts.lang Temporary language to use (see -- `Data:inLang`). -- @param[opt] {string} ... Arguments to substitute into the message -- (`$n`). -- @error[115] {string} 'missing arguments in Data:msg' -- @return {string} Localised datastore message or `'<key>'`. functionData:msg(opts,...) localframe=mw.getCurrentFrame() -- Argument normalization. ifnotselfornotoptsthen error('missing arguments in Data:msg') end localkey=type(opts)=='table'andopts.keyoropts localargs=opts.argsor{...} -- Configuration parameters. ifopts.sourcesthen self:fromSources(unpack(opts.sources)) end ifopts.langthen self:inLang(opts.lang) end -- Source handling. localsource_n=self.tempSourcesorself._sources localsource_i={} forn,iinpairs(source_n)do source_i[i]=n end self.tempSources=nil -- Language handling. locallang=self.tempLangorself.defaultLang self.tempLang=nil -- Message fetching. localmsg fori,messagesinipairs(self._messages)do -- Message data. localmsg=(messages[lang]or{})[key] -- Fallback support (experimental). for_,linipairs((fallbacks[lang]or{}))do ifmsg==nilthen msg=(messages[l]or{})[key] end end -- Internal fallback to 'en'. msg=msg~=nilandmsgormessages.en[key] -- Handling argument substitution from Lua. ifmsgandsource_i[i]and#args>0then msg=_i18n.handleArgs(msg,args) end ifmsgandsource_i[i]andlang~='qqx'then returnframeand_i18n.isWikitext(msg) andframe:preprocess(mw.text.trim(msg)) ormw.text.trim(msg) end end return'⧼'..mw.text.nowiki(key)..'⧽' end --- Datastore template parameter getter utility. -- This method, given a table of arguments, tries to find a parameter's -- localized name in the datastore and returns its value, or nil if -- not present. -- -- This method always uses the wiki's content language. -- @function Data:parameter -- @param {string} parameter Parameter's key in the datastore -- @param {table} args Arguments to find the parameter in -- @error[176] {string} 'missing arguments in Data:parameter' -- @return {string|nil} Parameter's value or nil if not present functionData:parameter(key,args) -- Argument normalization. ifnotselfornotkeyornotargsthen error('missing arguments in Data:parameter') end localcontentLang=mw.language.getContentLanguage():getCode() -- Message fetching. fori,messagesinipairs(self._messages)do localmsg=(messages[contentLang]or{})[key] ifmsg~=nilandargs[msg]~=nilthen returnargs[msg] end for_,linipairs((fallbacks[contentLang]or{}))do ifmsg==nilorargs[msg]==nilthen -- Check next fallback. msg=(messages[l]or{})[key] else -- A localized message was found. returnargs[msg] end end -- Fallback to English. msg=messages.en[key] ifmsg~=nilandargs[msg]~=nilthen returnargs[msg] end end end --- Datastore temporary source setter to a specificed subset of datastores. -- By default, messages are fetched from the datastore in the same -- order of priority as `i18n.loadMessages`. -- @function Data:fromSource -- @param {string} ... Source name(s) to use. -- @return {Data} Datastore instance. functionData:fromSource(...) localc=select('#',...) ifc~=0then self.tempSources={} fori=1,cdo localn=select(i,...) iftype(n)=='string'andtype(self._sources[n])=='number'then self.tempSources[n]=self._sources[n] end end end returnself end --- Datastore default language getter. -- @function Data:getLang -- @return {string} Default language to serve datastore messages in. functionData:getLang() returnself.defaultLang end --- Datastore language setter to `wgUserLanguage`. -- @function Data:useUserLang -- @return {Data} Datastore instance. -- @note Scribunto only registers `wgUserLanguage` when an -- invocation is at the top of the call stack. functionData:useUserLang() self.defaultLang=i18n.getLang()orself.defaultLang returnself end --- Datastore language setter to `wgContentLanguage`. -- @function Data:useContentLang -- @return {Data} Datastore instance. functionData:useContentLang() self.defaultLang=mw.language.getContentLanguage():getCode() returnself end --- Datastore language setter to specificed language. -- @function Data:useLang -- @param {string} code Language code to use. -- @return {Data} Datastore instance. functionData:useLang(code) self.defaultLang=_i18n.isValidCode(code) andcode orself.defaultLang returnself end --- Temporary datastore language setter to `wgUserLanguage`. -- The datastore language reverts to the default language in the next -- @{Data:msg} call. -- @function Data:inUserLang -- @return {Data} Datastore instance. functionData:inUserLang() self.tempLang=i18n.getLang()orself.tempLang returnself end --- Temporary datastore language setter to `wgContentLanguage`. -- Only affects the next @{Data:msg} call. -- @function Data:inContentLang -- @return {Data} Datastore instance. functionData:inContentLang() self.tempLang=mw.language.getContentLanguage():getCode() returnself end --- Temporary datastore language setter to a specificed language. -- Only affects the next @{Data:msg} call. -- @function Data:inLang -- @param {string} code Language code to use. -- @return {Data} Datastore instance. functionData:inLang(code) self.tempLang=_i18n.isValidCode(code) andcode orself.tempLang returnself end -- Package functions. --- Localized message getter by key. -- Can be used to fetch messages in a specific language code through `uselang` -- parameter. Extra numbered parameters can be supplied for substitution into -- the datastore message. -- @function i18n.getMsg -- @param {table} frame Frame table from invocation. -- @param {table} frame.args Metatable containing arguments. -- @param {string} frame.args[1] ROOTPAGENAME of i18n submodule. -- @param {string} frame.args[2] Key of i18n message. -- @param[opt] {string} frame.args.lang Default language of message. -- @error[271] {string} 'missing arguments in i18n.getMsg' -- @return {string} I18n message in localised language. functioni18n.getMsg(frame) if notframeor notframe.argsor notframe.args[1]or notframe.args[2] then error('missing arguments in i18n.getMsg') end localsource=frame.args[1] localkey=frame.args[2] -- Pass through extra arguments. localrepl={} fori,ainipairs(frame.args)do ifi>=3then repl[i-2]=a end end -- Load message data. localds=i18n.loadMessages(source) -- Pass through language argument. ds:inLang(frame.args.uselang) -- Return message. returnds:msg{key=key,args=repl} end --- I18n message datastore loader. -- @function i18n.loadMessages -- @param {string} ... ROOTPAGENAME/path for target i18n -- submodules. -- @error[322] {string} 'no source supplied to i18n.loadMessages' -- @return {table} I18n datastore instance. -- @usage require('Module:I18n').loadMessages('1', '2') functioni18n.loadMessages(...) localds locali=0 locals={} forj=1,select('#',...)do localsource=select(j,...) iftype(source)=='string'andsource~=''then i=i+1 s[source]=i ifnotdsthen -- Instantiate datastore. ds={} ds._messages={} -- Set default language. setmetatable(ds,Data) ds:useUserLang() end source=string.gsub(source,'^.',mw.ustring.upper) localsuccess,messages=pcall(mw.loadData,mw.ustring.find(source,':') andsource or'Module:'..source..'/i18n') ifsuccessthen localmsgCopy={} locallangSecond=nil forlang_id,msgtblinpairs(messages)do iflangSecond==nilthen iflang_id=="qqq"orfallbacks[lang_id]~=nilthen langSecond=false else langSecond=true end end forid_lang,msginpairs(msgtbl)do iflangSecondthen msgCopy[id_lang]=msgCopy[id_lang]or{} msgCopy[id_lang][lang_id]=msg else msgCopy[lang_id]=msgCopy[lang_id]or{} msgCopy[lang_id][id_lang]=msg end end end ds._messages[i]=msgCopy end localtab=mw.ext.data.get('I18n/'..source..'.tab','_') localT={} ifnotsuccessandnottabthenerror("i18n for "..source.." is missing")end for_,rowinpairs(tab.data)do-- convert the output into a dictionary table localid,t=unpack(row) forlang,msginpairs(t)do ifnotT[lang]thenT[lang]={}end T[lang][id]=msg end end ifnotsuccessthen ds._messages[i]=T else forlang,msgTblinpairs(T)do ds._messages[i][lang]=ds._messages[i][lang]ormsgTbl end end end end ifnotdsthen error('no source supplied to i18n.loadMessages') else -- Attach source index map. ds._sources=s -- Return datastore instance. returnds end end --- Language code getter. -- Can validate a template's language code through `uselang` parameter. -- @function i18n.getLang -- @return {string} Language code. functioni18n.getLang() localframe=mw.getCurrentFrame()or{} localparentFrame=frame.getParentandframe:getParent()or{} localcode=mw.language.getContentLanguage():getCode() localsubPage=title.subpageText -- Language argument test. locallangOverride= (frame.argsor{}).uselangor (parentFrame.argsor{}).uselang if_i18n.isValidCode(langOverride)then code=langOverride -- Subpage language test. elseiftitle.isSubpageand_i18n.isValidCode(subPage)then code=_i18n.isValidCode(subPage)andsubPageorcode -- User language test. elseifparentFrame.preprocessorframe.preprocessthen uselang=uselang orparentFrame.preprocess andparentFrame:preprocess('{{int:lang}}') orframe:preprocess('{{int:lang}}') localdecodedLang=mw.text.decode(uselang) ifdecodedLang~='<lang>'anddecodedLang~='⧼lang⧽'then code=decodedLang=='(lang)' and'qqx' oruselang end end returncode end -- Credit to http://stackoverflow.com/a/1283608/2644759 -- cc-by-sa 3.0 localfunctiontableMerge(t1,t2,overwrite) fork,vinpairs(t2)do iftype(v)=="table"andtype(t1[k])=="table"then -- since type(t1[k]) == type(v) == "table", so t1[k] and v is true tableMerge(t1[k],v,overwrite)-- t2[k] == v else ifoverwriteort1[k]==nilthent1[k]=vend end end returnt1 end --- Given an i18n table instantiates the values (deprecated) -- @function i18n.loadI18n -- @param {string} name name of module with i18n -- @param {table} i18n_arg existing i18n functioni18n.loadI18n(name,i18n_arg) localexist,res=pcall(require,name) ifexistandnext(res)~=nilthen ifi18n_argthen tableMerge(i18n_arg,res.i18n,true) end end end --- Loads an i18n for a specific frame (deprecated) -- @function i18n.loadI18nFrame -- @param {string} name name of module with i18n -- @param {table} i18n_arg existing i18n functioni18n.loadI18nFrame(frame,i18n_arg) returni18n.loadI18n(frame:getTitle().."/i18n",i18n_arg) end --- Wrapper for the module. -- @function i18n.main -- @param {table} frame Frame invocation object. -- @return {string} Module output in template context. -- @usage {{#invoke:i18n|main}} i18n.main=entrypoint(i18n) returnrequire("Module:Deprecated")(i18n, { ["loadI18n"]={ deprecated=true, replacement="use <code>i18n.loadMessages</code>" }, ["loadI18nFrame"]={ deprecated=true, replacement="use <code>i18n.loadMessages</code>" } } ) -- </nowiki>