Module:Languages: Difference between revisions
Jump to navigation
Jump to search
Mediawiki>ExE Boss m (Fix Docbunto documentation) |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 16: | Line 16: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local l = {} | local l = {} | ||
local getArgs = require(' | local getArgs = require('Module:Arguments').getArgs | ||
local fallbacks = mw.loadData(' | local fallbacks = mw.loadData('Module:Fallbacklist') | ||
local i18n = require(' | local i18n = require('Module:I18n').loadMessages('Common') | ||
local contentLang = mw.getContentLanguage():getCode() | local contentLang = mw.getContentLanguage():getCode() | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
Line 282: | Line 282: | ||
div | div | ||
:tag('strong') | :tag('strong') | ||
:wikitext(frame and frame:preprocess('[[w:c: | :wikitext(frame and frame:preprocess('[[w:c:Module:Languages|{{int:interlang-section-header-desktop}}]]') or 'Languages:') | ||
:done() | :done() | ||
:wikitext(' ') | :wikitext(' ') |
Latest revision as of 05:25, 2 May 2021
See Global Lua Modules/Languages
- Subpages {{#dpl: | namespace = Module | titlematch = Languages/% | skipthispage = false | nottitlematch = Languages/i18n|Languages/i18n/% }}
-- <nowiki> -------------------------------------------------------------------------------- -- Lua templating and link generation for language subpages. -- -- @module languages -- @alias l -- @release stable -- @require [[w:c:dev:Global Lua Modules/Arguments|Module:Arguments]] -- @require [[w:c:dev:Global Lua Modules/I18n|Module:I18n]] -- @require [[w:c:dev:Module:Fallbacklist|Module:Fallbacklist]] -- @require [[w:c:dev:Module:Common/i18n|Module:Common/i18n]] -- @author [[User:Nanaki|Nanaki]] - original version -- @author [[User:KockaAdmiralac|KockaAdmiralac]] -- @author [[User:MACH-59330|MACH-59330]] -- @see [[project:Internationalization]] -------------------------------------------------------------------------------- local l = {} local getArgs = require('Module:Arguments').getArgs local fallbacks = mw.loadData('Module:Fallbacklist') local i18n = require('Module:I18n').loadMessages('Common') local contentLang = mw.getContentLanguage():getCode() local title = mw.title.getCurrentTitle() local function intOrI18n(msg, ...) local frame = mw.getCurrentFrame() if not frame then return nil end local hasArgs = false local args = {} for i = 1, select('#', ...) do hasArgs = true local val = select(i, ...) val = val == nil and '' or tostring(val) args[i] = val end local text = frame:preprocess('{{int:' .. msg .. (hasArgs and '|' .. table.concat(args, '|')) .. '}}') if text == '<' .. msg .. '>' or text == '⧼' .. msg .. '⧽' then text = frame:preprocess(i18n:msg{ key = msg, args = args, }) end return text end local function escRx(text, spaces) text = text:gsub('[\\().+*?^$-/=!:]', '\\%0') if spaces then text = text:gsub(' ', '_') end return text end local function makeRedLink(page, text, query) page = mw.ustring.gsub(tostring(page), '^:*', '') local frame = mw.getCurrentFrame() local title = frame and frame:preprocess('{{int:red-link-title|{{ucfirst:' .. page .. '}}}}') or '' query = query or {} query.action = 'edit' query.redlink = 1 return mw.html.create('span') :addClass('redlink') :attr('title', title) :wikitext('[' .. tostring(mw.uri.fullUrl(page, query)) .. ' ' .. text .. ']') end local function makeBlueLink(page, text) page = mw.ustring.gsub(tostring(page), '^:*', '') return mw.html.create('') :wikitext('[[:' .. page .. '|' .. text .. ']]') end local function getAttr(t, name) for i, attr in ipairs(t.attributes) do if attr.name == name then return attr.val end end end -------------------------------------------------------------------------------- -- @type Links -------------------------------------------------------------------------------- -- @property {table} Links.list -------------------------------------------------------------------------------- -- @property {table} Links.keys -------------------------------------------------------------------------------- -- @function prepLinks -- @param {string} root -- @param {table} list -- @param {table} order -- @param[opt] {string} editintro -- @return {Links} -------------------------------------------------------------------------------- local function prepLinks(root, list, order, editintro) local links = { list = {}, keys = {} } editintro = editintro or 'Template:I18ndoc/editintro' for _, k in ipairs(order) do local lang = mw.language.fetchLanguageName(k) if lang ~= '' then local obj = { lang = k } if list[k] then if type(list[k]) == 'string' then obj.link = makeBlueLink(list[k], lang) obj.page = list[k] elseif k == contentLang then obj.link = makeBlueLink(root, lang) obj.page = root else obj.link = makeBlueLink(root .. '/' .. k, lang) obj.page = root .. '/' .. k end else local options = { editintro = editintro, preload = 'Template:I18ndoc', summary = 'Automatic generation of i18n documentation' } obj.link = makeRedLink(root .. '/' .. k, lang, options) obj.page = root .. '/' .. k obj.new = true end table.insert(links.list, obj) links.keys[k] = obj end end return links end -------------------------------------------------------------------------------- -- @function l.userLang -- @return {Lang} -------------------------------------------------------------------------------- function l.userLang() local frame = mw.getCurrentFrame() local lang if frame == nil then mw.log('userLang(): can\'t get user\'s language without frame object, returning content language for now (' .. mw.language.fetchLanguageName(contentLang) .. ')') return mw.getContentLanguage() end local code = frame:preprocess('{{int:lang}}') if mw.language.fetchLanguageName(code) == '' then mw.log('userLang(): unrecognised language code, returning content language (' .. mw.language.fetchLanguageName(contentLang) .. ')') return mw.getContentLanguage() end return mw.language.new(code) end -------------------------------------------------------------------------------- -- @function l.pageLink -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @return {table} -------------------------------------------------------------------------------- function l.pageLink(links, args1, args2) local keys = links.keys local frame = mw.getCurrentFrame() local link = {} local pageLang = #mw.language.fetchLanguageName(title.subpageText) ~= 0 and title.subpageText or contentLang local userLang = frame and l.userLang():getCode() or 'szl' if pageLang == contentLang then link = keys[userLang] for i, l in ipairs(fallbacks[userLang] or {}) do if not link and keys[l] and not keys[l].new then link = keys[l] break end end end link = (link and not link.new) and link or keys[pageLang] if link.new then local langs = {} for l, _ in pairs(keys) do table.insert(langs, l) end table.sort(langs) link = keys[langs[1]] end do local lastPart = (link.page or ''):match('[^/]+$') or '' link.lang = mw.language.fetchLanguageName(lastPart) ~= '' and lastPart or contentLang end return link end -------------------------------------------------------------------------------- -- @function l.editData -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @return {table} -------------------------------------------------------------------------------- function l.editData(links, args1, args2) local frame = mw.getCurrentFrame() local userLang = frame:preprocess('{{int:lang}}') local pageLang = #mw.language.fetchLanguageName(title.subpageText) ~= 0 and title.subpageText or l.pageLink(links, args1, args2).lang return tostring(mw.html.create('span') :attr('class', 'lang-select-data wds-is-hidden') -- Start LangSelect.js attributes. :attr('data-lang', pageLang) :attr('data-lang-name', mw.language.fetchLanguageName(pageLang)) :attr('data-userlang-name', mw.language.fetchLanguageName(userLang)) :attr('data-userlang-exists', tostring(not (links.keys[userLang] or {}).new)) -- End LangSelect.js attributes. ) end l.formats = {} -------------------------------------------------------------------------------- -- @function l.formats.default -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @param {string} root -- @return {table} -------------------------------------------------------------------------------- function l.formats.default(links, args1, args2, uselangs) local frame = mw.getCurrentFrame() local div = mw.html.create('div') :addClass(args1.class) if frame and mw.ustring.lower(frame:preprocess('{{int:rte-ck-dir}}')) == 'rtl' then div:attr('dir', 'rtl') end div :tag('strong') :wikitext(frame and frame:preprocess('[[w:c:Module:Languages|{{int:interlang-section-header-desktop}}]]') or 'Languages:') :done() :wikitext(' ') local separator = frame and frame:preprocess('{{int:pipe-separator}}') or '|' local highlight = mw.ustring.lower(args1.highlight or '') for i, v in ipairs(links.list) do if i > 1 then div:wikitext(' ' .. separator .. ' ') end local link = v.link link.tagName = 'span' link:attr('data-lang', v.lang) if highlight == v.lang then link:addClass('highlight') end div:node(link) end local selected = mw.ustring.lower(args1.select or '') if selected ~= '' then local flag = false if links.keys[selected] and not links.keys[selected].new then links.keys[selected].link:addClass('selected') flag = true else for i, v in ipairs(fallbacks[selected] or {}) do if links.keys[v] and not links.keys[v].new then links.keys[v].link:addClass('selected') flag = true break end end end if not flag then links.keys.en.link:addClass('selected') end end if not uselangs then div = tostring(div) .. l.editData(links, args1, args2) end return div end -------------------------------------------------------------------------------- -- @function l.formats.uselangs -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @param {string} root -- @return {table} -------------------------------------------------------------------------------- function l.formats.uselangs(links, args1, args2, root) local div = l.formats.default(links, args1, args2, root, true) for i, v in ipairs(div.nodes) do local node = div.nodes[i] if node.tagName ~= nil and getAttr(node, 'data-lang') then local lang = getAttr(node, 'data-lang') local langName = mw.language.fetchLanguageName(lang) if langName ~= '' then node.nodes = {} node:wikitext('[' .. tostring(mw.uri.fullUrl(root, {uselang = lang})) .. ' ' .. langName .. ']') end end end div = tostring(div) .. l.editData(links, args1, args2) return div end -------------------------------------------------------------------------------- -- @function l.formats.list -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @return {table} -------------------------------------------------------------------------------- function l.formats.list(links, args1, args2) local frame = mw.getCurrentFrame() local ul = mw.html.create('ul') :addClass(args1.class) if frame and mw.ustring.lower(frame:preprocess('{{int:rte-ck-dir}}')) == 'rtl' then ul:attr('dir', 'rtl') end local highlight = mw.ustring.lower(args1.highlight or '') for i, v in ipairs(links.list) do local link = v.link link.tagName = 'li' link:attr('data-lang', v.lang) if highlight == v.lang then link:addClass('highlight') end ul:node(link):newline() end local selected = mw.ustring.lower(args1.select or '') if selected ~= '' then local flag = false if links.keys[selected] and not links.keys[selected].new then links.keys[selected].link:addClass('selected') flag = true else for i, v in ipairs(fallbacks[selected] or {}) do if links.keys[v] and not links.keys[v].new then links.keys[v].link:addClass('selected') flag = true break end end end if not flag then links.keys.en.link:addClass('selected') end end return ul end -------------------------------------------------------------------------------- -- @function l.formats.transclude -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @return {table} -------------------------------------------------------------------------------- function l.formats.transclude(links, args1, args2) local frame = mw.getCurrentFrame() local lang = frame and l.userLang():getCode() or 'szl' local link = l.pageLink(links, args1, args2) local res = mw.html.create('') local notice = mw.ustring.lower(args1.notice or '') if notice == 'top' or notice == 'both' then res :tag('div') :addClass('transclude-notice transclude-notice-top') :wikitext(intOrI18n('custom-languages-notice', link.page, tostring(mw.uri.fullUrl(link.page, 'action=edit')), '') or 'Here goes the notice') :done() :newline() end if frame then if not pcall(function () res:wikitext(frame:expandTemplate{ title = mw.ustring.gsub(link.page, '^:*', ':') }) end) then return args1.missing or '[[:' .. link.page .. ']]' end else res:wikitext('Here goes the transcluded page: ' .. mw.ustring.gsub(link.page, '^:*', ':')) end if notice == 'bottom' or notice == 'both' then res :newline() :tag('div') :addClass('transclude-notice transclude-notice-bottom') :wikitext(intOrI18n('custom-languages-notice', link.page, tostring(mw.uri.fullUrl(link.page, 'action=edit')), '*') or 'Here goes the notice') end if frame and mw.ustring.lower(frame:preprocess('{{int:rte-ck-dir}}')) == 'rtl' then ul:attr('dir', 'rtl') end return res end -------------------------------------------------------------------------------- -- @function l.formats.interwiki -- @param {Links} links -- @param {table} args1 -- @param {table} args2 -- @param {string} prefixedRoot -- @return {table} -------------------------------------------------------------------------------- function l.formats.interwiki(links, args1, args2, prefixedRoot) local str = '' local frame = mw.getCurrentFrame() for k, v in ipairs(links.list) do if not v.new and v.lang ~= contentLang then str = str .. '[[' .. v.lang .. ':' .. prefixedRoot .. '/' .. v.lang .. ']]' end end str = str .. l.editData(links, args1, args2) return frame and frame:preprocess(str) or mw.text.nowiki(str) end -------------------------------------------------------------------------------- -- @function l.subpages -- @param {string} page -- @param[opt] {string} namespace -- @return {table} -------------------------------------------------------------------------------- function l.subpages(page, namespace) local frame = mw.getCurrentFrame() if frame == nil then return {'en', 'fr', 'pl', 'es', 'de', 'bad-code'} end local existing = mw.ustring.lower(frame:preprocess('{{#dpl:namespace=' .. (namespace or '') .. '|titleregexp=^' .. escRx(page, true) .. '\\/[a-z-]+$|replaceintitle=/^' .. escRx(page, false) .. '\\//,|redirects=include|skipthispage=no|format=¦,%TITLE%¦|noresultsheader=¦¦}}')) existing = select(3, mw.ustring.find(existing, '^%s*%|([%|a-z-]*)%|%s*$')) if existing then return mw.text.split(existing, '%s*|%s*') end end -------------------------------------------------------------------------------- -- @function l.langs -- @param {Frame} frame -- @return {string} -------------------------------------------------------------------------------- function l.langs(frame) -- Invoke-only parameters local args1 = getArgs(frame, { trim = true, removeBlanks = true, frameOnly = true, readOnly = true }) -- Overwritable parameters local args2 = getArgs(frame, { trim = true, removeBlanks = true, parentFirst = true, readOnly = true }) -- Get the root page name local root local rootTitle = args1.page and mw.title.new(args1.page) or mw.title.getCurrentTitle() if mw.ustring.find(rootTitle.subpageText, '[a-z-]+') and mw.language.fetchLanguageName(rootTitle.subpageText) ~= '' then root = rootTitle.baseText else root = rootTitle.text end local prefixedRoot = rootTitle.nsText prefixedRoot = mw.ustring.gsub(prefixedRoot .. ':' .. root, '^:*', '') -- Must-have languages local langs = {} for i, v in ipairs(args1 or {}) do v = mw.ustring.lower(mw.text.trim(v or '')) if v ~= '' then langs[v] = false end end langs[contentLang] = true -- Go over subpages of root local existing = l.subpages(root, rootTitle.nsText) or {} for i, v in ipairs(existing) do if v ~= '' then if v == contentLang then -- English has a separate subpage langs[contentLang] = mw.ustring.gsub(rootTitle.nsText .. ':' .. root, '^:', '') .. '/' .. contentLang else langs[v] = true end end end -- Look for parameters overriding language pages for k, v in pairs(args2) do if type(k) == 'string' and mw.language.fetchLanguageName(k) ~= '' then langs[k] = v end end -- Get a list of langs sorted by code local ordered = {} for k, v in pairs(langs) do if k ~= contentLang then ordered[#ordered + 1] = k end end table.sort(ordered) table.insert(ordered, 1, contentLang) -- with English being first -- Get list of links local links = prepLinks(prefixedRoot, langs, ordered, args1.editintro) -- Pass to format function local format = mw.ustring.lower(args1.format or 'interwiki') return l.formats[format](links, args1, args2, prefixedRoot) end -------------------------------------------------------------------------------- -- Preload function for i18n documentation -- -- @function l.preload -- @param {Frame} frame -- @return {string} -------------------------------------------------------------------------------- function l.preload(frame) -- Fetch page local page = frame.args[1] local txt = mw.title.new(page):getContent():gsub('<!%-(.-)%->', '') -- Generate untranslated doc local ret = '{{Untranslated}}\n' local tbl, i18n -- Temporary parsing of legacy i18n local LANGSELECT = '{{LangSelect}}' local LANGUAGES = '{{Languages}}' local txtInline = mw.text.trim((txt:gsub('\n', ''))) if txtInline == LANGSELECT or txtInline == LANGSELECT .. LANGUAGES or txtInline == LANGUAGES .. LANGSELECT then ret = ret .. mw.title.new(page .. '/en'):getContent():gsub('<!%-(.-)%->', '') elseif not txt:find('{{{') then ret = ret .. frame:preprocess(txt) -- Parsing parameter defaults in base page else ret = ret .. '{{:' .. page for en in txt:gmatch('{{%b{}}}') do en = en:match('^{{{(.-)}}}$') tbl = mw.text.split(en, '|') i18n = { key = en:match('^([^|]+)') or '', val = en:match('^[^|]+|*(.*)$') or '' } if not ret:find('| ' .. (i18n.key:gsub('%-', '%%-')) .. ' = ') then ret = ret .. '\n| ' .. i18n.key .. ' = ' .. i18n.val end end ret = ret .. '\n}}' end return ret end return l