Модул:Lang
Документация за този модул може да бъде създадена на Модул:Lang/doc
local p = {}
local data = mw.loadData('Модул:Lang/data')
local ns = mw.title.getCurrentTitle().namespace
local locale_names = data['локално_дефинирани']
local link_exceptions = data['изключения_препратки']
--[=[===========================================================================
========================= ОСНОВНИ СПОМАГАТЕЛНИ ФУНКЦИИ =========================
=============================================================================]=]
local function errorMessage(msg, cat)
local root = mw.html.create('strong')
root:addClass('error')
root:wikitext('Грешка в записа: ' .. msg)
root:done()
return tostring(root) .. (cat or '')
end
local function linkCheck(name)
-- проверка дали страницата съществува/е свързана с Уикиданни, за да се спести проверката с реурсоемката анализираща функция ifexist
local qid = mw.wikibase.getEntityIdForTitle(name .. ' език')
if qid then -- страницата следва традиционен формат на името "... език", съществува и е свързана с Уикиданни
return name .. ' език'
else
qid = mw.wikibase.getEntityIdForTitle(name .. ' (език)')
if qid then -- страницата следва традиционен формат на името "... (език)", съществува и е свързана с Уикиданни
return name .. ' (език)'
else -- страницата не следва традиционен формат на името
qid = mw.wikibase.getEntityIdForTitle(name) -- друга проверка за съществуващо име
if qid then -- страницата съществува и е свързана с Уикиданни
local instance = mw.wikibase.getAllStatements(qid, 'P31')
for i = 1, #instance do
local id = instance[i].mainsnak and instance[i].mainsnak.datavalue and instance[i].mainsnak.datavalue.value and instance[i].mainsnak.datavalue.value.id
if id then
local label = mw.ustring.lower(mw.wikibase.getLabel(id) or '')
if mw.ustring.match(label, '%f[%a][а-ъьюя]-език%f[%A]') or mw.ustring.match(label, '%f[%a][a-z]-language%f[%A]') then
return name -- обектът е екземпляр на език
end
end
end
local lang_properties = {
'P218', -- ISO 639-1
'P219', -- ISO 639-2
'P220', -- ISO 639-3
'P305', -- IETF
'P506', -- ISO 15924 aлфа-4
'P2620', -- ISO 15924 цифров
}
for i = 1, #lang_properties do
local value = mw.wikibase.getAllStatements(qid, lang_properties[i])
if #value > 0 then
-- обектът съдържа свойство, което го идентифицира като език
return name
end
end
end
end
end
-- страницата не е свързана с Уикиданни или е свързана, но обектът в УД не е екземпляр на език и/или не съдържа свойства, които да го идентифицират като език
return name .. (mw.ustring.match(name, '[жзсчцш]ки$') and ' език' or ' (език)')
end
local function createLink(pagelink, linktext)
if pagelink == linktext then
return '[[' .. pagelink .. ']]'
else
return '[[' .. pagelink .. '|' .. linktext .. ']]'
end
end
local function trimText(txt)
txt = txt or ''
txt = mw.ustring.gsub(txt, '^%s+', '')
txt = mw.ustring.gsub(txt, '%s+$', '')
return txt
end
local function charSet(...)
local result = ''
for i, v in pairs(arg) do
if type(v) == 'string' then
v = mw.ustring.gsub(v, '([^-]+)' , function(s)
if mw.ustring.match(s, '^%x+$') then
s = mw.ustring.char(tonumber('0x' .. s))
end
return s
end)
if mw.ustring.match(v, '^[^-]%-[^-]$') then
result = result .. v
end
end
end
return result
end
local function textWrap(code, dir, text, title)
local root
local regex = '^[%A'
.. charSet('0000-007F', '0080-00FF', '0100-017F', '0180-024F', '2C60-2C7F', 'A720-A7FF', 'AB30-AB6F', '10780-107BF', '1DF00-1DFFF', '1E00-1EFF', '0250-02AF' , '1D00-1D7F', '1D80-1DBF') -- латиница (без Latin Ligatures и Fullwidth Latin Letters)
.. charSet('0400-04FF', '0500-052F', '2DE0-2DFF', 'A640-A69F', '1C80-1C8F') -- кирилица
.. charSet('0370-03FF', '1F00-1FFF', '10140-1018F') -- гръцка азбука и числа
.. charSet('0300-036F', '1AB0-1AFF', '1DC0-1DFF') -- Combining Diacritical Marks, CDM Extended, CDM Supplement
.. ']+$' -- край на променливата regex; обхватите на символите са взети от https://unicode.org/charts/
title = trimText(title)
if title ~= '' then
root = mw.html.create('span'):attr('title', 'текст на ' .. title)
else
root = mw.html.create()
end
root:tag('span')
:attr('lang', code)
:attr('dir', dir)
:css('font-style', mw.ustring.match(text, regex) and 'italic' or 'normal') -- добавя курсив, само ако текстът е изцяло от горепосочените писмени системи или други неазбучни символи
:wikitext(text)
:done()
return tostring(root)
end
--[=[===========================================================================
====================== ФУНКЦИИ ЗА ТАБЛИЧНАТА ДОКУМЕНТАЦИЯ ======================
=============================================================================]=]
local function tableRow(celltag, width, background, str1, str2)
local row = mw.html.create('tr')
row:css('background-color', background)
row:tag(celltag):css('width', width):wikitext(str1):done()
row:tag(celltag):css('width', width):wikitext(str2):done()
row:done()
return row
end
local function tableCreate(child)
local div = mw.html.create('div')
:css('height', '400px')
:css('overflow', 'auto')
:css('border', '1px solid black')
:css('padding', '0')
:tag('table')
:addClass('wikitable sortable')
:css('width', '100%')
:css('margin', '0')
:newline()
:node(tableRow('th', '50%', nil, 'Език', 'Шаблон'))
:newline()
:node(child)
:allDone()
return tostring(div)
end
local function tempExample(val, background, oname)
local root = mw.html.create('code')
val = "{{lang|'''" .. val .. "'''}}"
root:css('background-color', background)
root:wikitext(val)
root:done()
return tostring(root) .. (oname and ' <small>(' .. oname .. ')</small>' or '')
end
function p.docTable(frame)
local translated = mw.html.create()
local not_translated = mw.html.create()
local link, background, original_name
local mediawiki_names = mw.language.fetchLanguageNames('bg', 'all')
local all_langs = {}
local repeated_names = {}
local already_added = {}
for k, v in pairs(mediawiki_names) do
if type(k) == 'string' and type(v) == 'string' then
background = nil
original_name = nil
if locale_names[k] then
if locale_names[k] == v then
background = '#ffdbd4'
else
background = '#dff9f9'
original_name = v
end
end
v = locale_names[k] or v
table.insert(all_langs, {k, v, background, original_name})
if not repeated_names[v] then
repeated_names[v] = {k}
else
if type(repeated_names[v]) == 'table' then
table.insert(repeated_names[v], k)
end
end
end
end
for k, v in pairs(locale_names) do
if type(k) == 'string' and type(v) == 'string' and not mediawiki_names[k] then
table.insert(all_langs, {k, v, '#daf7a6'})
if not repeated_names[v] then
repeated_names[v] = {k}
else
if type(repeated_names[v]) == 'table' then
table.insert(repeated_names[v], k)
end
end
end
end
table.sort(all_langs, function(a, b) return a[1] < b[1] end)
for i = 1, #all_langs do
local code = all_langs[i][1]
local name = all_langs[i][2]
local temp = tempExample(code, all_langs[i][3], all_langs[i][4])
if not already_added[code] then
if type(repeated_names[name]) == 'table' and #repeated_names[name] > 1 then
table.sort(repeated_names[name], function(a, b) return a < b end)
for j = 1, #repeated_names[name] do
if repeated_names[name][j] ~= code then
background = nil
original_name = nil
for k = 1, #all_langs do
if all_langs[k][1] == repeated_names[name][j] then
background = all_langs[k][3]
original_name = all_langs[k][4]
end
end
temp = temp .. '<hr>' .. tempExample(repeated_names[name][j], background, original_name)
already_added[repeated_names[name][j]] = true
end
end
end
if mw.ustring.match(mw.ustring.lower(name), '^[а-ъьюя%s%p]+$') then
link = link_exceptions[code] or linkCheck(name)
if link_exceptions[code] then
name = "''" .. name .. "''"
end
translated
:node(tableRow('td', nil, nil, createLink(link, name), temp))
:newline()
else
not_translated
:node(tableRow('td', nil, nil, name, temp))
:newline()
end
end
end
return '<h3>Преведени</h3>\n'
.. tableCreate(translated)
.. '\n<h3>Непреведени</h3>\n'
.. tableCreate(not_translated)
end
--[=[===========================================================================
================================ {{CITE-LANG}} =================================
=============================================================================]=]
function p.cite(frame)
local code = mw.ustring.lower(trimText(frame:getParent().args[1]))
if code == '' then return '' end
local name = locale_names[code] or mw.language.fetchLanguageName(code, 'bg')
if not name or name == '' then
return errorMessage('Неразпознат езиков код <code>' .. code ..'</code>')
end
return 'на ' .. name
end
--[=[===========================================================================
================================== {{LANG}} ====================================
=============================================================================]=]
function p.main(frame)
local args = frame:getParent().args
local code = mw.ustring.lower(trimText(args[1]))
local words = {}
if code == '' then
return ns == 0 and errorMessage('Празен първи позиционен параметър', '[[Категория:Страници с грешки]]') or ''
end
local name = locale_names[code] or mw.language.fetchLanguageName(code, 'bg')
if not name or name == '' then
return errorMessage('Неразпознат езиков код <code>' .. code ..'</code>', ns == 0 and '[[Категория:Страници с грешки]]')
end
-- ресурсоемка анализираща функция
local success, dir = pcall(function() return mw.language.new(code):getDir() end)
if not success then
dir = 'auto' -- при прехвърляне на лимита на ресурсоемките анализиращи функции
end
local link = link_exceptions[code] or linkCheck(name)
for k, v in pairs(args) do
k = tonumber(k)
if type(k) == 'number' and k > 1 then
v = trimText(v)
if v ~= '' then
table.insert(words, textWrap(code, dir, v))
end
end
end
local str = trimText((args['на'] or 'на') .. ' ' .. createLink(link, name))
if #words > 0 then
str = str .. ': ' .. mw.text.listToText(words, ', ', ' или ')
end
return str
end
--[=[===========================================================================
================================== {{LANG2}} ===================================
=============================================================================]=]
function p.main2(frame)
local args = frame:getParent().args
local code = mw.ustring.lower(trimText(args[1]))
local words = {}
if code == '' then
return ns == 0 and errorMessage('Празен първи позиционен параметър', '[[Категория:Страници с грешки]]') or ''
end
local name = locale_names[code] or mw.language.fetchLanguageName(code, 'bg')
if not name or name == '' then
return errorMessage('Неразпознат езиков код <code>' .. code ..'</code>', ns == 0 and '[[Категория:Страници с грешки]]')
end
-- ресурсоемка анализираща функция
local success, dir = pcall(function() return mw.language.new(code):getDir() end)
if not success then
dir = 'auto' -- при прехвърляне на лимита на ресурсоемките анализиращи функции
end
for k, v in pairs(args) do
k = tonumber(k)
if type(k) == 'number' and k > 1 then
v = trimText(v)
if v ~= '' then
table.insert(words, textWrap(code, dir, v, name))
end
end
end
if #words > 0 then
return mw.text.listToText(words, ', ', ' или ')
else
return str
end
end
return p