최신판 |
당신의 편집 |
1번째 줄: |
1번째 줄: |
| local this = {} | | local this = {} |
|
| |
|
| function this.checkLanguage(subpage, default) | | function this.getLanguageSubpage() |
| --[[Check first if there's an any invalid character that would cause the
| | -- Get the last subpage of the current page if it is a translation |
| mw.language.isKnownLanguageTag function() to throw an exception:
| | local subpage = mw.title.getCurrentTitle().subpageText |
| - all ASCII controls in [\000-\031\127],
| | return this.checkLanguage(subpage,'') |
| - double quote ("), sharp sign (#), ampersand (&), apostrophe ('),
| |
| - slash (/), colon (:), semicolon (;), lower than (<), greater than (>),
| |
| - brackets and braces ([, ], {, }), pipe (|), backslash (\\)
| |
| All other characters are accepted, including space and all non-ASCII
| |
| characters (including \192, which is invalid in UTF-8).
| |
| --]]
| |
| if mw.language.isValidCode(subpage) and mw.language.isKnownLanguageTag(subpage)
| |
| --[[However "SupportedLanguages" are too restrictive, as they discard many | |
| valid BCP47 script variants (only because MediaWiki still does not
| |
| define automatic transliterators for them, e.g. "en-dsrt" or
| |
| "fr-brai" for French transliteration in Braille), and country variants,
| |
| (useful in localized data, even if they are no longer used for
| |
| translations, such as zh-cn, also useful for legacy codes).
| |
| We want to avoid matching subpagenames containing any uppercase letter,
| |
| (even if they are considered valid in BCP 47, in which they are
| |
| case-insensitive; they are not "SupportedLanguages" for MediaWiki, so
| |
| they are not "KnownLanguageTags" for MediaWiki).
| |
| To be more restrictive, we exclude any character
| |
| * that is not ASCII and not a lowercase letter, minus-hyphen, or digit,
| |
| or does not start by a letter or does not finish by a letter or digit;
| |
| * or that has more than 8 characters between hyphens;
| |
| * or that has two hyphens;
| |
| * or with specific uses in template subpages and unusable as languages.
| |
| --]]
| |
| or string.find(subpage, "^[%l][%-%d%l]*[%d%l]$") ~= nil
| |
| and string.find(subpage, "[%d%l][%d%l][%d%l][%d%l][%d%l][%d%l][%d%l][%d%l][%d%l]") == nil
| |
| and string.find(subpage, "%-%-") == nil
| |
| and subpage ~= "doc"
| |
| and subpage ~= "layout"
| |
| and subpage ~= "sandbox"
| |
| and subpage ~= "testcases"
| |
| and subpage ~= "init"
| |
| and subpage ~= "preload"
| |
| and subpage ~= "subpage"
| |
| and subpage ~= "subpage2"
| |
| and subpage ~= "sub-subpage"
| |
| and subpage ~= "sub-sub-subpage"
| |
| and subpage ~= "sub-sub-sub-subpage"
| |
| then
| |
| return subpage
| |
| end
| |
| -- Otherwise there's currently no known language subpage
| |
| return default
| |
| end
| |
| | |
| --[[Get the last subpage of an arbitrary page if it is a translation.
| |
| To be used from templates.
| |
| ]] | |
| function this.getLanguageSubpage(frame)
| |
| local title = frame and frame.args[1]
| |
| if not title or title == '' then
| |
| title = mw.title.getCurrentTitle()
| |
| end
| |
| return this._getLanguageSubpage(title)
| |
| end
| |
| | |
| --[[Get the last subpage of an arbitrary page if it is a translation.
| |
| To be used from Lua. | |
| ]]
| |
| function this._getLanguageSubpage(title)
| |
| if type(title) == 'string' then
| |
| title = mw.title.new(title)
| |
| end
| |
| if not title then
| |
| -- invalid title
| |
| return mw.language.getContentLanguage():getCode()
| |
| end
| |
| --[[This code does not work in all namespaces where the Translate tool works.
| |
| -- It works in the main namespace on Meta because it allows subpages there
| |
| -- It would not work in the main namespace of English Wikipedia (but the
| |
| -- articles are monolignual on that wiki).
| |
| -- On Meta-Wiki the main space uses subpages and its pages are translated.
| |
| -- The Translate tool allows translatng pages in all namespaces, even if
| |
| -- the namespace officially does not have subpages.
| |
| -- On Meta-Wiki the Category namespace still does not have subpages enabled,
| |
| -- even if they would be very useful for categorizing templates, that DO have
| |
| -- subpages (for documentatio and tstboxes pages). This is a misconfiguration
| |
| -- bug of Meta-Wiki. The work-around is to split the full title and then
| |
| -- get the last titlepart.
| |
| local subpage = title.subpageText
| |
| --]]
| |
| local titleparts = mw.text.split(title.fullText, '/')
| |
| local subpage = titleparts[#titleparts]
| |
| return this.checkLanguage(subpage, mw.language.getContentLanguage():getCode())
| |
| end
| |
| | |
| --[[Get the last subpage of the current page if it is a translation.
| |
| ]]
| |
| function this.getCurrentLanguageSubpage()
| |
| return this._getLanguageSubpage(mw.title.getCurrentTitle())
| |
| end | | end |
| | | |
| --[[Get the first part of the language code of the subpage, before the '-'.
| |
| ]]
| |
| function this.getMainLanguageSubpage()
| |
| parts = mw.text.split( this.getCurrentLanguageSubpage(), '-' )
| |
| return parts[1]
| |
| end
| |
| | |
| --[[Get the last subpage of the current frame if it is a translation.
| |
| Not used locally.
| |
| ]]
| |
| function this.getFrameLanguageSubpage(frame) | | function this.getFrameLanguageSubpage(frame) |
| return this._getLanguageSubpage(frame:getParent():getTitle())
| | -- Get the last subpage of the current frame if it is a translation |
| | local titleparts = mw.text.split(frame:getParent():getTitle(),'/') |
| | local subpage = titleparts[#titleparts] |
| | return this.checkLanguage(subpage,'') |
| end | | end |
| | | |
| --[[Get the language of the current page.
| |
| Not used locally.
| |
| ]]
| |
| function this.getLanguage() | | function this.getLanguage() |
| | -- Get the language of the current page |
| local subpage = mw.title.getCurrentTitle().subpageText | | local subpage = mw.title.getCurrentTitle().subpageText |
| return this.checkLanguage(subpage, mw.language.getContentLanguage():getCode()) | | return this.checkLanguage(subpage,mw.language.getContentLanguage():getCode()) |
| end | | end |
| | | |
| --[[Get the language of the current frame.
| |
| Not used locally.
| |
| ]]
| |
| function this.getFrameLanguage(frame) | | function this.getFrameLanguage(frame) |
| local titleparts = mw.text.split(frame:getParent():getTitle(), '/') | | -- Get the language of the current frame |
| | local titleparts = mw.text.split(frame:getParent():getTitle(),'/') |
| local subpage = titleparts[#titleparts] | | local subpage = titleparts[#titleparts] |
| return this.checkLanguage(subpage, mw.language.getContentLanguage():getCode()) | | return this.checkLanguage(subpage,mw.language.getContentLanguage():getCode()) |
| end | | end |
| | | |
| function this.title(namespace, basepagename, subpage) | | function this.checkLanguage(subpage,default) |
| local message, title
| | --[[Check first if there's an apostrophe, because they break the isKnownLanguageTag |
| local pagename = basepagename
| | function. This test does not work with regexps, use plain search instead (no need |
| if (subpage or '') ~= ''
| | to use Unicode parser, apostrophes can only appear isolated as one byte in UTF-8). |
| then | |
| pagename = pagename .. '/' .. subpage
| |
| end
| |
| local valid, title = xpcall(function()
| |
| return mw.title.new(pagename, namespace) -- costly
| |
| end, function(msg) -- catch undocumented exception (!?)
| |
| -- thrown when namespace does not exist. The doc still
| |
| -- says it should return a title, even in that case...
| |
| message = msg
| |
| end)
| |
| if valid and title ~= nil and (title.id or 0) ~= 0
| |
| then
| |
| return title
| |
| end
| |
| return { -- "pseudo" mw.title object with id = nil in case of error
| |
| prefixedText = pagename, -- the only property we need below
| |
| message = message -- only for debugging | |
| }
| |
| end
| |
| | |
| --[[If on a translation subpage (like Foobar/de), this function returns
| |
| a given template in the same language, if the translation is available.
| |
| Otherwise, the template is returned in its default language, without
| |
| modification.
| |
| This is aimed at replacing the current implementation of Template:TNTN.
| |
| | |
| This version does not expand the returned template name: this solves the
| |
| problem of self-recursion in TNT when translatable templates need themselves
| |
| to transclude other translable templates (such as Tnavbar).
| |
| ]]
| |
| function this.getTranslatedTemplate(frame, withStatus)
| |
| local args = frame.args
| |
| local pagename = args['template']
| |
|
| |
| --[[Check whether the pagename is actually in the Template namespace, or
| |
| if we're transcluding a main-namespace page.
| |
| (added for backward compatibility of Template:TNT)
| |
| ]] | | ]] |
| local title
| | if (string.find(subpage, "'", 1, true) == nil) |
| local namespace = args['tntns'] or ''
| |
| if (namespace ~= '') -- Checks for tntns parameter for custom ns. | |
| then
| |
| title = this.title(namespace, pagename) -- Costly
| |
| else -- Supposes that set page is in ns10.
| |
| namespace = 'Template'
| |
| title = this.title(namespace, pagename) -- Costly
| |
| if title.id == nil
| |
| then -- not found in the Template namespace, assume the main namespace (for backward compatibility)
| |
| namespace = ''
| |
| title = this.title(namespace, pagename) -- Costly
| |
| end
| |
| end
| |
|
| |
| -- Get the last subpage and check if it matches a known language code.
| |
| local subpage = args['uselang'] or ''
| |
| if (subpage == '')
| |
| then
| |
| subpage = this.getCurrentLanguageSubpage()
| |
| end
| |
| if (subpage == '')
| |
| then | | then |
| -- Check if a translation of the pagename exists in English | | -- Return the subpage only if it is a valid language code. |
| local newtitle = this.title(namespace, pagename, 'en') -- Costly
| | if (mw.language.isKnownLanguageTag(subpage)) |
| -- Use the translation when it exists
| |
| if newtitle.id ~= nil | |
| then
| |
| title = newtitle
| |
| end
| |
| else
| |
| -- Check if a translation of the pagename exists in that language
| |
| local newtitle = this.title(namespace, pagename, subpage) -- Costly
| |
| if newtitle.id == nil
| |
| then
| |
| -- Check if a translation of the pagename exists in English
| |
| newtitle = this.title(namespace, pagename, 'en') -- Costly
| |
| end
| |
| -- Use the translation when it exists
| |
| if newtitle.id ~= nil
| |
| then | | then |
| title = newtitle | | return subpage |
| end | | end |
| end | | end |
| -- At this point the title should exist | | -- Otherwise there's currently no known language subpage |
| if withStatus then | | return default |
| -- status returned to Lua function below
| |
| return title.prefixedText, title.id ~= nil
| |
| else
| |
| -- returned directly to MediaWiki
| |
| return title.prefixedText
| |
| end
| |
| end | | end |
|
| |
|
229번째 줄: |
49번째 줄: |
| modification. | | modification. |
| This is aimed at replacing the current implementation of Template:TNT. | | This is aimed at replacing the current implementation of Template:TNT. |
|
| |
| Note that translatable templates cannot transclude themselves other
| |
| translatable templates, as it will recurse on TNT. Use TNTN instead
| |
| to return only the effective template name to expand externally, with
| |
| template parameters also provided externally.
| |
| ]] | | ]] |
| function this.renderTranslatedTemplate(frame) | | function this.renderTranslatedTemplate(frame) |
| local title, found = this.getTranslatedTemplate(frame, true)
| | local template = frame.args['template'] |
| -- At this point the title should exist prior to performing the expansion
| |
| -- of the template, otherwise render a red link to the missing page
| |
| -- (resolved in its assumed namespace). If we don't tet this here, a
| |
| -- script error would be thrown. Returning a red link is consistant with
| |
| -- MediaWiki behavior when attempting to transclude inexistant templates.
| |
| if not found then
| |
| return '[[' .. title .. ']]'
| |
| end
| |
|
| |
|
| -- Copy args pseudo-table to a proper table so we can feed it to expandTemplate. | | --[[Check whether the template is actually in the Template namespace, or |
| -- Then render the pagename.
| | if we're transcluding a main-namespace page. |
| local args = frame.args
| | (added for backward compatibility of Template:TNT) |
| local pargs = (frame:getParent() or {}).args
| | ]] |
| local arguments = {} | | local namespace = 'Template' |
| if (args['noshift'] or '') == '' | | if (frame.args['namespace']~='')--checks for namespace parameter for custom ns |
| then | | then |
| for k, v in pairs(pargs) do
| | namespace = frame.args['namespace'] |
| -- numbered args >= 1 need to be shifted
| | else--supposes that set page is in ns10 |
| local n = tonumber(k) or 0
| | local templateFullTitle = mw.title.new(template, namespace) |
| if (n > 0)
| | if (templateFullTitle.id == 0) |
| then
| | then -- not found in the Template namespace, assume the main namespace |
| if (n >= 2)
| | namespace = '' |
| then
| |
| arguments[n - 1] = v
| |
| end
| |
| else | |
| arguments[k] = v
| |
| end
| |
| end | | end |
| else -- special case where TNT is used as autotranslate | | end |
| -- (don't shift again what is shifted in the invokation)
| | |
| for k, v in pairs(pargs) do | | -- Get the last subpage and check if it matches a known language code |
| arguments[k] = v | | local langcode = 'en' -- default language template subpage to render |
| | local subpage = this.getLanguageSubpage() |
| | if (subpage ~= '') |
| | then |
| | -- Check if a translation of the template exists in that language; if so, put it in langcode |
| | local translation = mw.title.new(template .. '/' .. subpage, namespace) |
| | if (translation.id ~= 0) |
| | then |
| | langcode = subpage |
| end | | end |
| end | | end |
| arguments['template'] = title -- override the existing parameter of the base template name supplied with the full name of the actual template expanded
| |
| arguments['tntns'] = nil -- discard the specified namespace override
| |
| arguments['uselang'] = args['uselang'] -- argument forwarded into parent frame
| |
| arguments['noshift'] = args['noshift'] -- argument forwarded into parent frame
| |
|
| |
| return frame:expandTemplate{title = ':' .. title, args = arguments}
| |
| end
| |
|
| |
|
| --[[A helper for mocking TNT in Special:TemplateSandbox. TNT breaks | | -- Copy args pseudo-table to a proper table so we can feed it to expandTemplate |
| TemplateSandbox; mocking it with this method means templates won't be
| | -- Then render the template |
| localized but at least TemplateSandbox substitutions will work properly. | |
| Won't work with complex uses.
| |
| ]]
| |
| function this.mockTNT(frame)
| |
| local pargs = (frame:getParent() or {}).args
| |
| local arguments = {} | | local arguments = {} |
| for k, v in pairs(pargs) do | | for k, v in pairs((frame:getParent() or {}).args) do |
| -- numbered args >= 1 need to be shifted | | -- numbered args >= 1 need to be shifted |
| local n = tonumber(k) or 0
| | local n = tonumber(k) or 0 |
| if (n > 0)
| | if (n > 0) |
| then
| | then |
| if (n >= 2)
| | if (n >= 2) |
| then
| | then |
| arguments[n - 1] = v | | arguments[n - 1] = v |
| end | | end |
301번째 줄: |
98번째 줄: |
| end | | end |
| end | | end |
| if not pargs[1]
| | return frame:expandTemplate{title = namespace .. ':' .. template .. '/' .. langcode, args = arguments} |
| then
| |
| return ''
| |
| end
| |
| return frame:expandTemplate{title = 'Template:' .. pargs[1], args = arguments} | |
| end | | end |
|
| |
|
| return this | | return this |