<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://petitplanet.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AI18n</id>
	<title>Module:I18n - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://petitplanet.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AI18n"/>
	<link rel="alternate" type="text/html" href="https://petitplanet.wiki/index.php?title=Module:I18n&amp;action=history"/>
	<updated>2026-04-08T07:33:47Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://petitplanet.wiki/index.php?title=Module:I18n&amp;diff=8&amp;oldid=prev</id>
		<title>Stevium: Created Module:I18n</title>
		<link rel="alternate" type="text/html" href="https://petitplanet.wiki/index.php?title=Module:I18n&amp;diff=8&amp;oldid=prev"/>
		<updated>2025-11-09T08:11:08Z</updated>

		<summary type="html">&lt;p&gt;Created Module:I18n&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Source: https://genshin-impact.fandom.com/wiki/Module:I18n&lt;br /&gt;
&lt;br /&gt;
--- I18n library for message storage in Lua datastores.&lt;br /&gt;
--  The module is designed to enable message separation from modules &amp;amp;&lt;br /&gt;
--  templates. It has support for handling language fallbacks. This&lt;br /&gt;
--  module is a Lua port of [[I18n-js]] and i18n modules that can be loaded&lt;br /&gt;
--  by it are editable through [[I18nEdit]].&lt;br /&gt;
--  &lt;br /&gt;
--  @module         i18n&lt;br /&gt;
--  @version        1.4.0&lt;br /&gt;
--  @require        Module:Entrypoint&lt;br /&gt;
--  @require        Module:Fallbacklist&lt;br /&gt;
--  @author         [[User:KockaAdmiralac|KockaAdmiralac]]&lt;br /&gt;
--  @author         [[User:Speedit|Speedit]]&lt;br /&gt;
--  @attribution    [[User:Cqm|Cqm]]&lt;br /&gt;
--  @release        stable&lt;br /&gt;
--  @see            [[I18n|I18n guide]]&lt;br /&gt;
--  @see            [[I18n-js]]&lt;br /&gt;
--  @see            [[I18nEdit]]&lt;br /&gt;
local i18n, _i18n = {}, {}&lt;br /&gt;
&lt;br /&gt;
--  Module variables &amp;amp; dependencies.&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
local fallbacks = require(&amp;#039;Module:Fallbacklist&amp;#039;)&lt;br /&gt;
local entrypoint = require(&amp;#039;Module:Entrypoint&amp;#039;)&lt;br /&gt;
local uselang&lt;br /&gt;
&lt;br /&gt;
--- Argument substitution as $n where n &amp;gt; 0.&lt;br /&gt;
--  @function           _i18n.handleArgs&lt;br /&gt;
--  @param              {string} msg Message to substitute arguments into.&lt;br /&gt;
--  @param              {table} args Arguments table to substitute.&lt;br /&gt;
--  @return             {string} Resulting message.&lt;br /&gt;
--  @local&lt;br /&gt;
function _i18n.handleArgs(msg, args)&lt;br /&gt;
    for i, a in ipairs(args) do&lt;br /&gt;
        msg = (string.gsub(msg, &amp;#039;%$&amp;#039; .. tostring(i), tostring(a)))&lt;br /&gt;
    end&lt;br /&gt;
    return msg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Checks whether a language code is valid.&lt;br /&gt;
--  @function           _i18n.isValidCode&lt;br /&gt;
--  @param              {string} code Language code to check.&lt;br /&gt;
--  @return             {boolean} Whether the language code is valid.&lt;br /&gt;
--  @local&lt;br /&gt;
function _i18n.isValidCode(code)&lt;br /&gt;
    return type(code) == &amp;#039;string&amp;#039; and #mw.language.fetchLanguageName(code) ~= 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Checks whether a message contains unprocessed wikitext.&lt;br /&gt;
--  Used to optimise message getter by not preprocessing pure text.&lt;br /&gt;
--  @function           _i18n.isWikitext&lt;br /&gt;
--  @param              {string} msg Message to check.&lt;br /&gt;
--  @return             {boolean} Whether the message contains wikitext.&lt;br /&gt;
function _i18n.isWikitext(msg)&lt;br /&gt;
    return&lt;br /&gt;
        type(msg) == &amp;#039;string&amp;#039; and&lt;br /&gt;
        (&lt;br /&gt;
            msg:find(&amp;#039;%-%-%-%-&amp;#039;) or&lt;br /&gt;
            msg:find(&amp;#039;%f[^\n%z][;:*#] &amp;#039;) or&lt;br /&gt;
            msg:find(&amp;#039;%f[^\n%z]==* *[^\n|]+ =*=%f[\n]&amp;#039;) or&lt;br /&gt;
            msg:find(&amp;#039;%b&amp;lt;&amp;gt;&amp;#039;) or msg:find(&amp;#039;\&amp;#039;\&amp;#039;&amp;#039;) or&lt;br /&gt;
            msg:find(&amp;#039;%[%b[]%]&amp;#039;) or msg:find(&amp;#039;{%b{}}&amp;#039;)&lt;br /&gt;
        )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- I18n datastore class.&lt;br /&gt;
--  This is used to control language translation and access to individual&lt;br /&gt;
--  messages. The datastore instance provides language and message&lt;br /&gt;
--  getter-setter methods, which can be used to internationalize Lua modules.&lt;br /&gt;
--  The language methods (any ending in `Lang`) are all **chainable**.&lt;br /&gt;
--  @type            Data&lt;br /&gt;
local Data = {}&lt;br /&gt;
Data.__index = Data&lt;br /&gt;
&lt;br /&gt;
--- Datastore message getter utility.&lt;br /&gt;
--  This method returns localized messages from the datastore corresponding&lt;br /&gt;
--  to a `key`. These messages may have `$n` parameters, which can be&lt;br /&gt;
--  replaced by optional argument strings supplied by the `msg` call.&lt;br /&gt;
--  &lt;br /&gt;
--  This function supports [[Lua reference manual#named_arguments|named&lt;br /&gt;
--  arguments]]. The named argument syntax is more versatile despite its&lt;br /&gt;
--  verbosity; it can be used to select message language &amp;amp; source(s).&lt;br /&gt;
--  @function           Data:msg&lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      ds:msg{&lt;br /&gt;
--          key = &amp;#039;message-name&amp;#039;,&lt;br /&gt;
--          lang = &amp;#039;&amp;#039;,&lt;br /&gt;
--          args = {...},&lt;br /&gt;
--          sources = {}&lt;br /&gt;
--      }&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      ds:msg(&amp;#039;message-name&amp;#039;, ...)&lt;br /&gt;
--  &lt;br /&gt;
--  @param              {string|table} opts Message configuration or key.&lt;br /&gt;
--  @param[opt]         {string} opts.key Message key to return from the&lt;br /&gt;
--                      datastore.&lt;br /&gt;
--  @param[opt]         {table} opts.args Arguments to substitute into the&lt;br /&gt;
--                      message (`$n`).&lt;br /&gt;
--  @param[opt]         {table} opts.sources Source names to limit to (see&lt;br /&gt;
--                      `Data:fromSources`).&lt;br /&gt;
--  @param[opt]         {table} opts.lang Temporary language to use (see&lt;br /&gt;
--                      `Data:inLang`).&lt;br /&gt;
--  @param[opt]         {string} ... Arguments to substitute into the message&lt;br /&gt;
--                      (`$n`).&lt;br /&gt;
--  @error[115]         {string} &amp;#039;missing arguments in Data:msg&amp;#039;&lt;br /&gt;
--  @return             {string} Localised datastore message or `&amp;#039;&amp;lt;key&amp;gt;&amp;#039;`.&lt;br /&gt;
function Data:msg(opts, ...)&lt;br /&gt;
    local frame = mw.getCurrentFrame()&lt;br /&gt;
    -- Argument normalization.&lt;br /&gt;
    if not self or not opts then&lt;br /&gt;
        error(&amp;#039;missing arguments in Data:msg&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    local key = type(opts) == &amp;#039;table&amp;#039; and opts.key or opts&lt;br /&gt;
    local args = opts.args or {...}&lt;br /&gt;
    -- Configuration parameters.&lt;br /&gt;
    if opts.sources then&lt;br /&gt;
        self:fromSources(unpack(opts.sources))&lt;br /&gt;
    end&lt;br /&gt;
    if opts.lang then&lt;br /&gt;
        self:inLang(opts.lang)&lt;br /&gt;
    end&lt;br /&gt;
    -- Source handling.&lt;br /&gt;
    local source_n = self.tempSources or self._sources&lt;br /&gt;
    local source_i = {}&lt;br /&gt;
    for n, i in pairs(source_n) do&lt;br /&gt;
        source_i[i] = n&lt;br /&gt;
    end&lt;br /&gt;
    self.tempSources = nil&lt;br /&gt;
    -- Language handling.&lt;br /&gt;
    local lang = self.tempLang or self.defaultLang&lt;br /&gt;
    self.tempLang = nil&lt;br /&gt;
    -- Message fetching.&lt;br /&gt;
    local msg&lt;br /&gt;
    for i, messages in ipairs(self._messages) do&lt;br /&gt;
        -- Message data.&lt;br /&gt;
        local msg = (messages[lang] or {})[key]&lt;br /&gt;
        -- Fallback support (experimental).&lt;br /&gt;
        for _, l in ipairs((fallbacks[lang] or {})) do&lt;br /&gt;
            if msg == nil then&lt;br /&gt;
                msg = (messages[l] or {})[key]&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        -- Internal fallback to &amp;#039;en&amp;#039;.&lt;br /&gt;
        msg = msg ~= nil and msg or messages.en[key]&lt;br /&gt;
        -- Handling argument substitution from Lua.&lt;br /&gt;
        if msg and source_i[i] and #args &amp;gt; 0 then&lt;br /&gt;
            msg = _i18n.handleArgs(msg, args)&lt;br /&gt;
        end&lt;br /&gt;
        if msg and source_i[i] and lang ~= &amp;#039;qqx&amp;#039; then&lt;br /&gt;
            return frame and _i18n.isWikitext(msg)&lt;br /&gt;
                and frame:preprocess(mw.text.trim(msg))&lt;br /&gt;
                or  mw.text.trim(msg)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return mw.text.nowiki(&amp;#039;&amp;lt;&amp;#039; .. key .. &amp;#039;&amp;gt;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore template parameter getter utility.&lt;br /&gt;
--  This method, given a table of arguments, tries to find a parameter&amp;#039;s&lt;br /&gt;
--  localized name in the datastore and returns its value, or nil if&lt;br /&gt;
--  not present.&lt;br /&gt;
--&lt;br /&gt;
--  This method always uses the wiki&amp;#039;s content language.&lt;br /&gt;
--  @function           Data:parameter&lt;br /&gt;
--  @param              {string} parameter Parameter&amp;#039;s key in the datastore&lt;br /&gt;
--  @param              {table} args Arguments to find the parameter in&lt;br /&gt;
--  @error[176]         {string} &amp;#039;missing arguments in Data:parameter&amp;#039;&lt;br /&gt;
--  @return             {string|nil} Parameter&amp;#039;s value or nil if not present&lt;br /&gt;
function Data:parameter(key, args)&lt;br /&gt;
    -- Argument normalization.&lt;br /&gt;
    if not self or not key or not args then&lt;br /&gt;
        error(&amp;#039;missing arguments in Data:parameter&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    local contentLang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
    -- Message fetching.&lt;br /&gt;
    for i, messages in ipairs(self._messages) do&lt;br /&gt;
        local msg = (messages[contentLang] or {})[key]&lt;br /&gt;
        if msg ~= nil and args[msg] ~= nil then&lt;br /&gt;
            return args[msg]&lt;br /&gt;
        end&lt;br /&gt;
        for _, l in ipairs((fallbacks[contentLang] or {})) do&lt;br /&gt;
            if msg == nil or args[msg] == nil then&lt;br /&gt;
                -- Check next fallback.&lt;br /&gt;
                msg = (messages[l] or {})[key]&lt;br /&gt;
            else&lt;br /&gt;
                -- A localized message was found.&lt;br /&gt;
                return args[msg]&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        -- Fallback to English.&lt;br /&gt;
        msg = messages.en[key]&lt;br /&gt;
        if msg ~= nil and args[msg] ~= nil then&lt;br /&gt;
            return args[msg]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore temporary source setter to a specificed subset of datastores.&lt;br /&gt;
--  By default, messages are fetched from the datastore in the same&lt;br /&gt;
--  order of priority as `i18n.loadMessages`.&lt;br /&gt;
--  @function           Data:fromSource&lt;br /&gt;
--  @param              {string} ... Source name(s) to use.&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
function Data:fromSource(...)&lt;br /&gt;
    local c = select(&amp;#039;#&amp;#039;, ...)&lt;br /&gt;
    if c ~= 0 then&lt;br /&gt;
        self.tempSources = {}&lt;br /&gt;
        for i = 1, c do&lt;br /&gt;
            local n = select(i, ...)&lt;br /&gt;
            if type(n) == &amp;#039;string&amp;#039; and type(self._sources[n]) == &amp;#039;number&amp;#039; then&lt;br /&gt;
                self.tempSources[n] = self._sources[n]&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore default language getter.&lt;br /&gt;
--  @function           Data:getLang&lt;br /&gt;
--  @return             {string} Default language to serve datastore messages in.&lt;br /&gt;
function Data:getLang()&lt;br /&gt;
    return self.defaultLang&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore language setter to `wgUserLanguage`.&lt;br /&gt;
--  @function           Data:useUserLang&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
--  @note               Scribunto only registers `wgUserLanguage` when an&lt;br /&gt;
--                      invocation is at the top of the call stack.&lt;br /&gt;
function Data:useUserLang()&lt;br /&gt;
    self.defaultLang = i18n.getLang() or self.defaultLang&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore language setter to `wgContentLanguage`.&lt;br /&gt;
--  @function           Data:useContentLang&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
function Data:useContentLang()&lt;br /&gt;
    self.defaultLang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Datastore language setter to specificed language.&lt;br /&gt;
--  @function           Data:useLang&lt;br /&gt;
--  @param              {string} code Language code to use.&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
function Data:useLang(code)&lt;br /&gt;
    self.defaultLang = _i18n.isValidCode(code)&lt;br /&gt;
        and code&lt;br /&gt;
        or  self.defaultLang&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Temporary datastore language setter to `wgUserLanguage`.&lt;br /&gt;
--  The datastore language reverts to the default language in the next&lt;br /&gt;
--  @{Data:msg} call.&lt;br /&gt;
--  @function           Data:inUserLang&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
function Data:inUserLang()&lt;br /&gt;
    self.tempLang = i18n.getLang() or self.tempLang&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Temporary datastore language setter to `wgContentLanguage`.&lt;br /&gt;
--  Only affects the next @{Data:msg} call.&lt;br /&gt;
--  @function           Data:inContentLang&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
function Data:inContentLang()&lt;br /&gt;
    self.tempLang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Temporary datastore language setter to a specificed language.&lt;br /&gt;
--  Only affects the next @{Data:msg} call.&lt;br /&gt;
--  @function           Data:inLang&lt;br /&gt;
--  @param              {string} code Language code to use.&lt;br /&gt;
--  @return             {Data} Datastore instance.&lt;br /&gt;
function Data:inLang(code)&lt;br /&gt;
    self.tempLang = _i18n.isValidCode(code)&lt;br /&gt;
        and code&lt;br /&gt;
        or  self.tempLang&lt;br /&gt;
    return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--  Package functions.&lt;br /&gt;
&lt;br /&gt;
--- Localized message getter by key.&lt;br /&gt;
--  Can be used to fetch messages in a specific language code through `uselang`&lt;br /&gt;
--  parameter. Extra numbered parameters can be supplied for substitution into&lt;br /&gt;
--  the datastore message.&lt;br /&gt;
--  @function           i18n.getMsg&lt;br /&gt;
--  @param              {table} frame Frame table from invocation.&lt;br /&gt;
--  @param              {table} frame.args Metatable containing arguments.&lt;br /&gt;
--  @param              {string} frame.args[1] ROOTPAGENAME of i18n submodule.&lt;br /&gt;
--  @param              {string} frame.args[2] Key of i18n message.&lt;br /&gt;
--  @param[opt]         {string} frame.args.lang Default language of message.&lt;br /&gt;
--  @error[271]         &amp;#039;missing arguments in i18n.getMsg&amp;#039;&lt;br /&gt;
--  @return             {string} I18n message in localised language.&lt;br /&gt;
--  @usage              {{i18n|getMsg|source|key|arg1|arg2|uselang {{=}} code}}&lt;br /&gt;
function i18n.getMsg(frame)&lt;br /&gt;
    if&lt;br /&gt;
        not frame or&lt;br /&gt;
        not frame.args or&lt;br /&gt;
        not frame.args[1] or&lt;br /&gt;
        not frame.args[2]&lt;br /&gt;
    then&lt;br /&gt;
        error(&amp;#039;missing arguments in i18n.getMsg&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    local source = frame.args[1]&lt;br /&gt;
    local key = frame.args[2]&lt;br /&gt;
    -- Pass through extra arguments.&lt;br /&gt;
    local repl = {}&lt;br /&gt;
    for i, a in ipairs(frame.args) do&lt;br /&gt;
        if i &amp;gt;= 3 then&lt;br /&gt;
            repl[i-2] = a&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- Load message data.&lt;br /&gt;
    local ds = i18n.loadMessages(source)&lt;br /&gt;
    -- Pass through language argument.&lt;br /&gt;
    ds:inLang(frame.args.uselang)&lt;br /&gt;
    -- Return message.&lt;br /&gt;
    return ds:msg { key = key, args = repl }&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
--- I18n message datastore loader.&lt;br /&gt;
--  @function           i18n.loadMessages&lt;br /&gt;
--  @param              {string} ... ROOTPAGENAME/path for target i18n&lt;br /&gt;
--                      submodules.&lt;br /&gt;
--  @error[322]         {string} &amp;#039;no source supplied to i18n.loadMessages&amp;#039;&lt;br /&gt;
--  @return             {table} I18n datastore instance.&lt;br /&gt;
--  @usage              require(&amp;#039;Dev:I18n&amp;#039;).loadMessages(&amp;#039;1&amp;#039;, &amp;#039;2&amp;#039;)&lt;br /&gt;
function i18n.loadMessages(...)&lt;br /&gt;
    local ds&lt;br /&gt;
    local i = 0&lt;br /&gt;
    local s = {}&lt;br /&gt;
    for j = 1, select(&amp;#039;#&amp;#039;, ...) do&lt;br /&gt;
        local source = select(j, ...)&lt;br /&gt;
        if type(source) == &amp;#039;string&amp;#039; and source ~= &amp;#039;&amp;#039; then&lt;br /&gt;
            i = i + 1&lt;br /&gt;
            s[source] = i&lt;br /&gt;
            if not ds then&lt;br /&gt;
                -- Instantiate datastore.&lt;br /&gt;
                ds = {}&lt;br /&gt;
                ds._messages = {}&lt;br /&gt;
                -- Set default language.&lt;br /&gt;
                setmetatable(ds, Data)&lt;br /&gt;
                ds:useUserLang()&lt;br /&gt;
            end&lt;br /&gt;
            source = string.gsub(source, &amp;#039;^.&amp;#039;, mw.ustring.upper)&lt;br /&gt;
            source = mw.ustring.find(source, &amp;#039;:&amp;#039;)&lt;br /&gt;
                and source&lt;br /&gt;
                or  &amp;#039;Module:&amp;#039; .. source .. &amp;#039;/i18n&amp;#039;&lt;br /&gt;
            ds._messages[i] = mw.loadData(source)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if not ds then&lt;br /&gt;
        error(&amp;#039;no source supplied to i18n.loadMessages&amp;#039;)&lt;br /&gt;
    else&lt;br /&gt;
        -- Attach source index map.&lt;br /&gt;
        ds._sources = s&lt;br /&gt;
        -- Return datastore instance.&lt;br /&gt;
        return ds&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Language code getter.&lt;br /&gt;
--  Can validate a template&amp;#039;s language code through `uselang` parameter.&lt;br /&gt;
--  @function           i18n.getLang&lt;br /&gt;
--  @usage              {{i18n|getLang|uselang {{=}} code}}&lt;br /&gt;
--  @return             {string} Language code.&lt;br /&gt;
function i18n.getLang()&lt;br /&gt;
    local frame = mw.getCurrentFrame() or {}&lt;br /&gt;
    local parentFrame = frame.getParent and frame:getParent() or {}&lt;br /&gt;
&lt;br /&gt;
    local code = mw.language.getContentLanguage():getCode()&lt;br /&gt;
    local subPage = title.subpageText&lt;br /&gt;
&lt;br /&gt;
    -- Language argument test.&lt;br /&gt;
    local langOverride =&lt;br /&gt;
        (frame.args or {}).uselang or&lt;br /&gt;
        (parentFrame.args or {}).uselang&lt;br /&gt;
    if _i18n.isValidCode(langOverride) then&lt;br /&gt;
        code = langOverride&lt;br /&gt;
&lt;br /&gt;
    -- Subpage language test.&lt;br /&gt;
    elseif title.isSubpage and _i18n.isValidCode(subPage) then&lt;br /&gt;
        code = _i18n.isValidCode(subPage) and subPage or code&lt;br /&gt;
&lt;br /&gt;
    -- User language test.&lt;br /&gt;
    elseif parentFrame.preprocess or frame.preprocess then&lt;br /&gt;
        uselang = uselang&lt;br /&gt;
            or  parentFrame.preprocess&lt;br /&gt;
                and parentFrame:preprocess(&amp;#039;{{int:lang}}&amp;#039;)&lt;br /&gt;
                or  frame:preprocess(&amp;#039;{{int:lang}}&amp;#039;)&lt;br /&gt;
        local decodedLang = mw.text.decode(uselang) &lt;br /&gt;
        if decodedLang ~= &amp;#039;&amp;lt;lang&amp;gt;&amp;#039; and decodedLang ~= &amp;#039;⧼lang⧽&amp;#039; then&lt;br /&gt;
            code = decodedLang == &amp;#039;(lang)&amp;#039;&lt;br /&gt;
                and &amp;#039;qqx&amp;#039;&lt;br /&gt;
                or  uselang&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return code&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Template wrapper for [[Template:I18n]].&lt;br /&gt;
--  @function           i18n.main&lt;br /&gt;
--  @param              {table} frame Frame invocation object.&lt;br /&gt;
--  @return             {string} Module output in template context.&lt;br /&gt;
--  @usage              {{#invoke:i18n|main}}&lt;br /&gt;
i18n.main = entrypoint(i18n)&lt;br /&gt;
&lt;br /&gt;
return i18n&lt;/div&gt;</summary>
		<author><name>Stevium</name></author>
	</entry>
</feed>