Khác biệt giữa các bản “Mô đun:Wikidata”
(Tạo trang mới với nội dung “-- vim: set noexpandtab ft=lua ts=4 sw=4: require('Module:No globals') local p = {} local debug = false -----------------------------------------------…”) |
n |
||
| Dòng 1: | Dòng 1: | ||
| − | |||
require('Module:No globals') | require('Module:No globals') | ||
local p = {} | local p = {} | ||
| − | local | + | local lang = mw.getContentLanguage() |
| − | + | -- module local variables | |
| − | + | local wiki = | |
| − | -- module local variables | ||
| − | |||
| − | local wiki = | ||
{ | { | ||
langcode = mw.language.getContentLanguage().code | langcode = mw.language.getContentLanguage().code | ||
| Dòng 15: | Dòng 11: | ||
-- internationalisation | -- internationalisation | ||
| − | local i18n = | + | local i18n = { |
| − | { | + | ["errors"] = { |
| − | + | ["property-not-found"] = "Không tìm thấy thuộc tính.", | |
| − | + | ["entity-not-found"] = "Không tìm thấy thực thể.", | |
| − | + | ["unknown-claim-type"] = "Kiểu tuyên bố không rõ.", | |
| − | + | ["unknown-snak-type"] = "Kiểu quan hệ không rõ.", | |
| − | + | ["unknown-datavalue-type"] = "Kiểu dữ liệu giá trị không rõ.", | |
| − | + | ["unknown-entity-type"] = "Kiểu thực thể không rõ.", | |
| − | + | ["qualifier-not-found"] = "Từ hạn định không rõ.", | |
| − | + | ["site-not-found"] = "Không tìm thấy dự án Wikimedia.", | |
| − | + | }, | |
| − | + | ["somevalue"] = "Giá trị nào đó", | |
| − | + | ["novalue"] = "Vô giá trị", | |
| − | + | ["datetime"] = | |
{ | { | ||
-- $1 is a placeholder for the actual number | -- $1 is a placeholder for the actual number | ||
| − | [0] = "$1 | + | [0] = "$1 tỷ năm", -- precision: billion years |
| − | [1] = "$100 | + | [1] = "$100 triệu năm", -- precision: hundred million years |
| − | [2] = "$10 | + | [2] = "$10 triệu năm", -- precision: ten million years |
| − | [3] = "$1 | + | [3] = "$1 triệu năm", -- precision: million years |
| − | [4] = "$100 | + | [4] = "$100.000 năm", -- precision: hundred thousand years |
| − | [5] = "$10 | + | [5] = "$10.000 năm", -- precision: ten thousand years |
| − | [6] = "$1 | + | [6] = "thiên niên kỷ $1", -- precision: millennium |
| − | [7] = "$1 | + | [7] = "thế kỷ $1", -- precision: century |
| − | [8] = "$ | + | [8] = "thập niên $1", -- precision: decade |
-- the following use the format of #time parser function | -- the following use the format of #time parser function | ||
| − | [9] = "Y", -- precision: year, | + | [9] = "Y", -- precision: year, |
| − | [10] = " | + | [10] = 'F "năm" Y', -- precision: month |
| − | [11] = " | + | [11] = 'j F "năm" Y', -- precision: day |
| − | [12] = " | + | [12] = 'j F "năm" Y lúc G "giờ"', -- precision: hour |
| − | [13] = " | + | [13] = 'j F "năm" Y lúc G:i', -- precision: minute |
| − | [14] = " | + | [14] = 'j F "năm" Y lúc G:i:s', -- precision: second |
| − | ["beforenow"] = "$1 | + | ["beforenow"] = "$1 trước", -- how to format negative numbers for precisions 0 to 5 |
| − | ["afternow"] = "$1 | + | ["afternow"] = "$1 sau", -- how to format positive numbers for precisions 0 to 5 |
| − | ["bc"] = '$1 " | + | ["bc"] = '$1 "TCN"', -- how print negative years |
| − | ["ad"] = "$1" | + | ["ad"] = "$1" -- how print positive years |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
}, | }, | ||
["monolingualtext"] = '<span lang="%language">%text</span>', | ["monolingualtext"] = '<span lang="%language">%text</span>', | ||
| − | ["warnDump"] = "[[ | + | ["warnDump"] = "[[Thể loại:Mô đun Wikidata gọi hàm Dump]]" |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | local function printError(code) | |
| − | -- | + | return '<span class="error">' .. (i18n.errors[code] or code) .. '</span>' |
| − | -- | + | end |
| − | + | ||
| − | + | function p.descriptionIn(frame) | |
| + | local langcode = frame.args[1] | ||
| + | local id = frame.args[2] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration | ||
| + | -- return description of a Wikidata entity in the given language or the default language of this Wikipedia site | ||
| + | return mw.wikibase.getEntityObject(id).descriptions[langcode or wiki.langcode].value | ||
| + | end | ||
| + | |||
| + | function p.labelIn(frame) | ||
| + | local langcode = frame.args[1] | ||
| + | local id = frame.args[2] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration | ||
| + | -- return label of a Wikidata entity in the given language or the default language of this Wikipedia site | ||
| + | return mw.wikibase.getEntityObject(id).labels[langcode or wiki.langcode].value | ||
| + | end | ||
| + | |||
| + | -- This is used to get a value, or a comma separated list of them if multiple values exist | ||
| + | p.getValue = function(frame, fetch_wikidata) | ||
| + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | ||
| + | local input_parm = mw.text.trim(frame.args[2] or "") | ||
| + | if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then | ||
| + | local entity = mw.wikibase.getEntityObject() | ||
| + | local claims | ||
| + | if entity and entity.claims then | ||
| + | claims = entity.claims[propertyID] | ||
| + | end | ||
| + | if claims then | ||
| + | -- if wiki-linked value output as link if possible | ||
| + | if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then | ||
| + | local out = {} | ||
| + | for k, v in pairs(claims) do | ||
| + | local id = v.mainsnak.datavalue.value["numeric-id"] | ||
| + | local qid = "Q" .. id | ||
| + | |||
| + | local sitelink = mw.wikibase.sitelink(qid) | ||
| + | local label = mw.wikibase.label(qid) | ||
| + | |||
| + | if sitelink then | ||
| + | table.insert(out, mw.ustring.format("[[%s|%s]]", sitelink, lang:ucfirst(label) or sitelink)) | ||
| + | elseif label then | ||
| + | table.insert(out, mw.ustring.format("[[d:%s|%s]]", qid, lang:ucfirst(label))) | ||
| + | else | ||
| + | table.insert(out, "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]<abbr title='Wiki này chưa có bài về thực thể này'>[*]</abbr>") | ||
| + | end | ||
| + | end | ||
| + | return table.concat(out, ", ") | ||
| + | else | ||
| + | -- just return best values | ||
| + | return entity:formatPropertyValues(propertyID).value | ||
| + | end | ||
| + | else | ||
| + | return "" | ||
| + | end | ||
else | else | ||
| − | + | return input_parm | |
end | end | ||
| − | |||
end | end | ||
| − | -- | + | -- This is used to get a value, or a comma separated list of them if multiple values exist |
| − | -- | + | -- from an arbitrary entry by using its QID. |
| − | -- | + | -- Use : {{#gọi:Wikidata|getValueFromID|<ID>|<Property>|FETCH_WIKIDATA}} |
| − | local | + | -- E.g.: {{#gọi:Wikidata|getValueFromID|Q151973|P26|FETCH_WIKIDATA}} - to fetch value of 'người phối ngẫu' (P26) from 'Richard Burton' (Q151973) |
| − | local | + | -- Please use sparingly - this is an *expensive call*. |
| − | if | + | p.getValueFromID = function(frame) |
| − | + | local itemID = mw.text.trim(frame.args[1] or "") | |
| − | + | local propertyID = mw.text.trim(frame.args[2] or "") | |
| − | + | local input_parm = mw.text.trim(frame.args[3] or "") | |
| − | + | if input_parm == "FETCH_WIKIDATA" then | |
| − | + | local entity = mw.wikibase.getEntity(itemID) | |
| + | local claims = entity.claims[propertyID] | ||
| + | if claims then | ||
| + | -- if wiki-linked value output as link if possible | ||
| + | if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then | ||
| + | local out = {} | ||
| + | for k, v in pairs(claims) do | ||
| + | local sitelink = mw.wikibase.sitelink("Q" .. v.mainsnak.datavalue.value["numeric-id"]) | ||
| + | local label = mw.wikibase.label("Q" .. v.mainsnak.datavalue.value["numeric-id"]) | ||
| + | if label == nil then label = "Q" .. v.mainsnak.datavalue.value["numeric-id"] end | ||
| + | |||
| + | if sitelink then | ||
| + | out[#out + 1] = "[[" .. sitelink .. "|" .. label .. "]]" | ||
| + | else | ||
| + | out[#out + 1] = "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]<abbr title='Wiki này chưa có bài về thực thể này'>[*]</abbr>" | ||
| + | end | ||
| + | end | ||
| + | return table.concat(out, ", ") | ||
| + | else | ||
| + | return entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value | ||
| + | end | ||
| + | else | ||
| + | return "" | ||
| + | end | ||
| + | else | ||
| + | return input_parm | ||
end | end | ||
| − | + | end | |
| − | + | ||
| − | if | + | p.getQualifierValue = function(frame) |
| − | + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | |
| + | local qualifierID = mw.ustring.upper(mw.text.trim(frame.args[2] or "")) | ||
| + | local input_parm = mw.text.trim(frame.args[3] or "") | ||
| + | if input_parm == "FETCH_WIKIDATA" then | ||
| + | local entity = mw.wikibase.getEntityObject() | ||
| + | if entity.claims[propertyID] ~= nil then | ||
| + | local out = {} | ||
| + | for k, v in pairs(entity.claims[propertyID]) do | ||
| + | for k2, v2 in pairs(v.qualifiers[qualifierID]) do | ||
| + | if v2.snaktype == 'value' then | ||
| + | if (mw.wikibase.sitelink("Q" .. v2.datavalue.value["numeric-id"])) then | ||
| + | out[#out + 1] = "[[" .. mw.wikibase.sitelink("Q" .. v2.datavalue.value["numeric-id"]) .. "]]" | ||
| + | else | ||
| + | out[#out + 1] = "[[:d:Q" .. v2.datavalue.value["numeric-id"] .. "|" .. mw.wikibase.label("Q" .. v2.datavalue.value["numeric-id"]) .. "]]<abbr title='Wiki này chưa có bài về thực thể này'>[*]</abbr>" | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | return table.concat(out, ", ") | ||
| + | else | ||
| + | return "" | ||
| + | end | ||
| + | else | ||
| + | return input_parm | ||
end | end | ||
| − | |||
end | end | ||
| − | + | -- This is used to get a value like 'male' (for property p21) which won't be linked and numbers without the thousand separators | |
| − | + | p.getRawValue = function(frame, fetch_wikidata) | |
| − | + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | |
| − | + | local input_parm = mw.text.trim(frame.args[2] or "") | |
| − | local | + | if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then |
| − | + | local entity = mw.wikibase.getEntityObject() | |
| − | local | + | local claims |
| − | local | + | if entity then claims = entity.claims[propertyID] end |
| − | + | if claims then | |
| − | + | local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value | |
| − | if | + | |
| − | + | -- if number type: remove thousand separators, bounds and units | |
| − | + | if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "quantity") then | |
| − | + | result = mw.ustring.gsub(result, "(%d),(%d)", "%1%2") | |
| − | -- | + | result = mw.ustring.gsub(result, "(%d)±.*", "%1") |
| − | + | end | |
| − | + | return result | |
| + | else | ||
| + | return "" | ||
end | end | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
else | else | ||
| − | return | + | return input_parm |
end | end | ||
end | end | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | function p.getFormattedValue(frame, fetch_wikidata) | |
| − | + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | |
| − | + | local input_parm = mw.text.trim(frame.args[2] or "") | |
| − | + | if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then | |
| − | + | local entity = mw.wikibase.getEntityObject() | |
| − | local | + | if entity.claims and entity.claims[propertyID] ~= nil then |
| − | + | local claim = mw.wikibase.getEntityObject():formatPropertyValues(propertyID) | |
| − | return | + | return claim and claim.value |
| + | else | ||
| + | return "" | ||
| + | end | ||
else | else | ||
| − | return | + | return input_parm |
end | end | ||
end | end | ||
| − | + | p.getRawQualifierValue = function(frame) | |
| − | + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | |
| − | local | + | local qualifierID = mw.ustring.upper(mw.text.trim(frame.args[2] or "")) |
| − | local | + | local input_parm = mw.text.trim(frame.args[3] or "") |
| − | + | if input_parm == "FETCH_WIKIDATA" then | |
| − | + | local entity = mw.wikibase.getEntityObject() | |
| − | + | if entity.claims[propertyID] ~= nil then | |
| − | + | local out = {} | |
| − | + | for k, v in pairs(entity.claims[propertyID]) do | |
| − | + | for k2, v2 in pairs(v.qualifiers[qualifierID]) do | |
| − | + | if v2.snaktype == 'value' then | |
| + | if v2.datavalue.value["numeric-id"] then | ||
| + | out[#out + 1] = mw.wikibase.label("Q" .. v2.datavalue.value["numeric-id"]) | ||
| + | else | ||
| + | out[#out + 1] = v2.datavalue.value | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | local ret = table.concat(out, ", ") | ||
| + | return string.upper(string.sub(ret, 1, 1)) .. string.sub(ret, 2) | ||
| + | else | ||
| + | return "" | ||
| + | end | ||
| + | else | ||
| + | return input_parm | ||
end | end | ||
| + | end | ||
| − | + | -- This is used to get a date value for date_of_birth (P569), etc. which won't | |
| − | + | -- be linked -- consolidate by testing if entity.claims[propertyID].mainsnak.datavalue.type | |
| − | local | + | -- is "time". Dates and times are stored in ISO 8601 format. |
| − | + | p.getDateValue = function(frame, fetch_wikidata) | |
| − | return "" | + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) |
| + | local input_parm = mw.text.trim(frame.args[2] or "") | ||
| + | local date_format = mw.text.trim(frame.args[3] or "dmy") | ||
| + | local date_suffix = mw.text.trim(frame.args[4] or "TCN") | ||
| + | if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then | ||
| + | local entity = mw.wikibase.getEntityObject() | ||
| + | if entity.claims[propertyID] ~= nil then | ||
| + | local out = {} | ||
| + | local dt = {} | ||
| + | for k, v in pairs(entity.claims[propertyID]) do | ||
| + | if v.mainsnak.snaktype == 'value' then | ||
| + | local d = v.mainsnak.datavalue.value.time | ||
| + | dt.year = string.sub(d, 1, 5) | ||
| + | dt.month = string.sub(d, 7, 8) | ||
| + | dt.day = string.sub(d, 10, 11) | ||
| + | if date_format == "ymd" then | ||
| + | table.insert(out, lang:formatDate("Y-m-d", os.time(dt))) | ||
| + | elseif date_format == "my" then | ||
| + | table.insert(out, lang:formatDate('"tháng" n "năm" Y', os.time(dt))) | ||
| + | elseif date_format == "y" then | ||
| + | table.insert(out, lang:formatDate('Y', os.time(dt))) | ||
| + | else | ||
| + | table.insert(out, lang:formatDate('j "tháng" n "năm" Y', os.time(dt))) | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | return table.concat(out, ", ") | ||
| + | else | ||
| + | return "" | ||
| + | end | ||
| + | else | ||
| + | return input_parm | ||
end | end | ||
| + | end | ||
| − | + | p.getQualifierDateValue = function(frame) | |
| − | + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | |
| − | + | local qualifierID = mw.ustring.upper(mw.text.trim(frame.args[2] or "")) | |
| − | local | + | local input_parm = mw.text.trim(frame.args[3] or "") |
| − | local | + | local date_format = mw.text.trim(frame.args[4] or "dmy") |
| − | + | if input_parm == "FETCH_WIKIDATA" then | |
| − | + | local entity = mw.wikibase.getEntityObject() | |
| − | + | if entity.claims[propertyID] ~= nil then | |
| + | local out = {} | ||
| + | local dt = {} | ||
| + | for k, v in pairs(entity.claims[propertyID]) do | ||
| + | for k2, v2 in pairs(v.qualifiers[qualifierID]) do | ||
| + | if v2.snaktype == 'value' then | ||
| + | local d = v2.datavalue.value.time | ||
| + | dt.year = string.sub(d, 1, 5) | ||
| + | dt.month = string.sub(d, 7, 8) | ||
| + | dt.day = string.sub(d, 10, 11) | ||
| + | if date_format == "ymd" then | ||
| + | table.insert(out, lang:formatDate("Y-m-d", os.time(dt))) | ||
| + | elseif date_format == "my" then | ||
| + | table.insert(out, lang:formatDate('"tháng" n "năm" Y', os.time(dt))) | ||
| + | elseif date_format == "y" then | ||
| + | table.insert(out, lang:formatDate('Y', os.time(dt))) | ||
| + | else | ||
| + | table.insert(out, lang:formatDate('j "tháng" n "năm" Y', os.time(dt))) | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | return table.concat(out, ", ") | ||
else | else | ||
| − | + | return "" | |
end | end | ||
| − | return | + | else |
| + | return input_parm | ||
end | end | ||
| + | end | ||
| − | + | -- This is used to fetch all of the images with a particular property, e.g. hình ảnh (P18), hình GeneAtlas (P692), etc. | |
| − | + | -- Parameters are | propertyID | value / FETCH_WIKIDATA / nil | separator (default=space) | size (default=220px) | |
| − | + | -- It will return a standard wiki-markup [[File:Filename | size]] for each image with a selectable size and separator (which may be html) | |
| − | + | -- e.g. {{#gọi:Wikidata|getImages|P18|FETCH_WIKIDATA}} | |
| − | + | -- e.g. {{#gọi:Wikidata|getImages|P18|FETCH_WIKIDATA|<br>|250px}} | |
| − | + | -- If a property is chosen that is not of type "commonsMedia", it will return empty text. | |
| − | + | p.getImages = function(frame) | |
| − | + | local propertyID = mw.text.trim(frame.args[1] or "") | |
| − | + | local input_parm = mw.text.trim(frame.args[2] or "") | |
| − | + | local sep = mw.text.trim(frame.args[3] or " ") | |
| − | if | + | local imgsize = mw.text.trim(frame.args[4] or "220px") |
| − | + | if input_parm == "FETCH_WIKIDATA" then | |
| − | + | local entity = mw.wikibase.getEntityObject() | |
| − | + | local claims | |
| − | + | if entity and entity.claims then | |
| − | + | claims = entity.claims[propertyID] | |
| + | end | ||
| + | if claims then | ||
| + | if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then | ||
| + | local out = {} | ||
| + | for k, v in pairs(claims) do | ||
| + | local filename = v.mainsnak.datavalue.value | ||
| + | out[#out + 1] = "[[Tập tin:" .. filename .. "|" .. imgsize .. "]]" | ||
| + | end | ||
| + | return table.concat(out, sep) | ||
| + | else | ||
| + | return "" | ||
| + | end | ||
else | else | ||
| − | + | return "" | |
end | end | ||
| − | return | + | else |
| + | return input_parm | ||
end | end | ||
| + | end | ||
| − | local | + | -- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323) |
| − | + | -- which are then linked to http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm | |
| − | + | -- uses the newer mw.wikibase calls instead of directly using the snaks | |
| − | if | + | -- formatPropertyValues returns a table with the P1323 values concatenated with ", " so we have to split them out into a table in order to construct the return string |
| − | + | p.getTAValue = function(frame) | |
| + | local ent = mw.wikibase.getEntityObject() | ||
| + | local props = ent:formatPropertyValues('P1323') | ||
| + | local out = {} | ||
| + | local t = {} | ||
| + | for k, v in pairs(props) do | ||
| + | if k == 'value' then | ||
| + | t = mw.text.split( v, ", ") | ||
| + | for k2, v2 in pairs(t) do | ||
| + | out[#out + 1] = "[http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]" | ||
| + | end | ||
end | end | ||
| − | |||
| − | |||
| − | |||
end | end | ||
| + | local ret = table.concat(out, "<br> ") | ||
| + | if #ret == 0 then | ||
| + | ret = "TA không hợp lệ" | ||
| + | end | ||
| + | return ret | ||
| + | end | ||
| + | |||
| + | -- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata | ||
| + | function p.pageId(frame) | ||
| + | local entity = mw.wikibase.getEntityObject() | ||
| + | if not entity then return nil else return entity.id end | ||
end | end | ||
| Dòng 230: | Dòng 397: | ||
local function orderedpairs(array, order) | local function orderedpairs(array, order) | ||
if not order then return pairs(array) end | if not order then return pairs(array) end | ||
| − | + | ||
-- return iterator function | -- return iterator function | ||
| − | + | local i = 0 | |
| − | + | return function() | |
| − | + | i = i + 1 | |
| − | + | if order[i] then | |
| − | + | return order[i], array[order[i]] | |
| − | + | end | |
| − | + | end | |
end | end | ||
| Dòng 255: | Dòng 422: | ||
local date, year = normalizeDate(date) | local date, year = normalizeDate(date) | ||
if year == 0 and precision <= 9 then return "" end | if year == 0 and precision <= 9 then return "" end | ||
| − | + | ||
| − | + | -- precision is 10000 years or more | |
if precision <= 5 then | if precision <= 5 then | ||
local factor = 10 ^ ((5 - precision) + 4) | local factor = 10 ^ ((5 - precision) + 4) | ||
| Dòng 265: | Dòng 432: | ||
else | else | ||
relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative) | relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative) | ||
| − | end | + | end |
return relative | return relative | ||
end | end | ||
| − | + | ||
| − | + | -- precision is decades, centuries and millennia | |
local era | local era | ||
if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end | if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end | ||
| Dòng 279: | Dòng 446: | ||
return era | return era | ||
end | end | ||
| − | + | ||
| − | + | -- precision is year | |
| − | + | if precision == 9 then | |
| − | + | return year | |
| − | + | end | |
| − | + | ||
-- precision is less than years | -- precision is less than years | ||
if precision > 9 then | if precision > 9 then | ||
| Dòng 291: | Dòng 458: | ||
if timezone and timezone ~= 0 then | if timezone and timezone ~= 0 then | ||
timezone = -timezone | timezone = -timezone | ||
| − | timezone = | + | timezone = mw.ustring.format("%.2d%.2d", timezone / 60, timezone % 60) |
if timezone[1] ~= '-' then timezone = "+" .. timezone end | if timezone[1] ~= '-' then timezone = "+" .. timezone end | ||
date = mw.text.trim(date, "Z") .. " " .. timezone | date = mw.text.trim(date, "Z") .. " " .. timezone | ||
end | end | ||
]]-- | ]]-- | ||
| − | + | ||
local formatstr = i18n.datetime[precision] | local formatstr = i18n.datetime[precision] | ||
if year == 0 then formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], "") | if year == 0 then formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], "") | ||
| Dòng 313: | Dòng 480: | ||
-- data fields: entity-type [string], numeric-id [int, Wikidata id] | -- data fields: entity-type [string], numeric-id [int, Wikidata id] | ||
local id | local id | ||
| − | + | ||
if data["entity-type"] == "item" then id = "Q" .. data["numeric-id"] | if data["entity-type"] == "item" then id = "Q" .. data["numeric-id"] | ||
elseif data["entity-type"] == "property" then id = "P" .. data["numeric-id"] | elseif data["entity-type"] == "property" then id = "P" .. data["numeric-id"] | ||
else return printError("unknown-entity-type") | else return printError("unknown-entity-type") | ||
end | end | ||
| − | + | ||
if parameter then | if parameter then | ||
if parameter == "link" then | if parameter == "link" then | ||
| − | local linkTarget = mw.wikibase. | + | local linkTarget = mw.wikibase.sitelink(id) |
| − | local linkName = mw.wikibase. | + | local linkName = mw.wikibase.label(id) |
if linkTarget then | if linkTarget then | ||
-- if there is a local Wikipedia article link to it using the label or the article title | -- if there is a local Wikipedia article link to it using the label or the article title | ||
| − | return "[[" .. linkTarget .. "|" .. (linkName or linkTarget) .. "]]" | + | return "[[" .. linkTarget .. "|" .. (linkName or linkTarget) .. "]]" |
else | else | ||
-- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label | -- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label | ||
| Dòng 334: | Dòng 501: | ||
end | end | ||
else | else | ||
| − | return mw.wikibase. | + | return mw.wikibase.label(id) or id |
end | end | ||
end | end | ||
| Dòng 363: | Dòng 530: | ||
local function findClaims(entity, property) | local function findClaims(entity, property) | ||
if not property or not entity or not entity.claims then return end | if not property or not entity or not entity.claims then return end | ||
| − | + | ||
if mw.ustring.match(property, "^P%d+$") then | if mw.ustring.match(property, "^P%d+$") then | ||
-- if the property is given by an id (P..) access the claim list by this id | -- if the property is given by an id (P..) access the claim list by this id | ||
| Dòng 388: | Dòng 555: | ||
return mw.wikibase.renderSnak(snak) | return mw.wikibase.renderSnak(snak) | ||
end | end | ||
| − | + | ||
local function getQualifierSnak(claim, qualifierId) | local function getQualifierSnak(claim, qualifierId) | ||
-- a "snak" is Wikidata terminology for a typed key/value pair | -- a "snak" is Wikidata terminology for a typed key/value pair | ||
| Dòng 405: | Dòng 572: | ||
end | end | ||
end | end | ||
| − | + | ||
local function getValueOfClaim(claim, qualifierId, parameter) | local function getValueOfClaim(claim, qualifierId, parameter) | ||
local error | local error | ||
| Dòng 426: | Dòng 593: | ||
if refparts then refparts = refparts .. ", " else refparts = "" end | if refparts then refparts = refparts .. ", " else refparts = "" end | ||
-- output the label of the property of the reference part, e.g. "imported from" for P143 | -- output the label of the property of the reference part, e.g. "imported from" for P143 | ||
| − | refparts = refparts .. tostring(mw.wikibase. | + | refparts = refparts .. tostring(mw.wikibase.label(snakkey)) .. ": " |
-- output all values of this reference part, e.g. "German Wikipedia" and "English Wikipedia" if the referenced claim was imported from both sites | -- output all values of this reference part, e.g. "German Wikipedia" and "English Wikipedia" if the referenced claim was imported from both sites | ||
for snakidx = 1, #snakval do | for snakidx = 1, #snakval do | ||
| Dòng 436: | Dòng 603: | ||
end | end | ||
return result | return result | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
function p.claim(frame) | function p.claim(frame) | ||
local property = frame.args[1] or "" | local property = frame.args[1] or "" | ||
| − | local id = frame.args["id"] | + | local id = frame.args["id"] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration |
local qualifierId = frame.args["qualifier"] | local qualifierId = frame.args["qualifier"] | ||
local parameter = frame.args["parameter"] | local parameter = frame.args["parameter"] | ||
| Dòng 876: | Dòng 615: | ||
local default = frame.args["default"] | local default = frame.args["default"] | ||
if default then showerrors = nil end | if default then showerrors = nil end | ||
| − | + | ||
-- get wikidata entity | -- get wikidata entity | ||
| − | local entity = mw.wikibase. | + | local entity = mw.wikibase.getEntityObject(id) |
if not entity then | if not entity then | ||
if showerrors then return printError("entity-not-found") else return default end | if showerrors then return printError("entity-not-found") else return default end | ||
| Dòng 887: | Dòng 626: | ||
if showerrors then return printError("property-not-found") else return default end | if showerrors then return printError("property-not-found") else return default end | ||
end | end | ||
| − | + | ||
-- get initial sort indices | -- get initial sort indices | ||
local sortindices = {} | local sortindices = {} | ||
| Dòng 896: | Dòng 635: | ||
local comparator = function(a, b) | local comparator = function(a, b) | ||
local rankmap = { deprecated = 2, normal = 1, preferred = 0 } | local rankmap = { deprecated = 2, normal = 1, preferred = 0 } | ||
| − | local ranka = rankmap[claims[a].rank or "normal"] .. | + | local ranka = rankmap[claims[a].rank or "normal"] .. mw.ustring.format("%08d", a) |
| − | local rankb = rankmap[claims[b].rank or "normal"] .. | + | local rankb = rankmap[claims[b].rank or "normal"] .. mw.ustring.format("%08d", b) |
return ranka < rankb | return ranka < rankb | ||
| − | + | end | |
table.sort(sortindices, comparator) | table.sort(sortindices, comparator) | ||
| − | + | ||
local result | local result | ||
local error | local error | ||
| Dòng 910: | Dòng 649: | ||
for idx in pairs(claims) do | for idx in pairs(claims) do | ||
local claim = claims[sortindices[idx]] | local claim = claims[sortindices[idx]] | ||
| − | value, error = getValueOfClaim(claim, qualifierId, parameter) | + | value, error = getValueOfClaim(claim, qualifierId, parameter) |
if not value and showerrors then value = error end | if not value and showerrors then value = error end | ||
if value and references then value = value .. getReferences(frame, claim) end | if value and references then value = value .. getReferences(frame, claim) end | ||
| Dòng 917: | Dòng 656: | ||
result = table.concat(result, list) | result = table.concat(result, list) | ||
else | else | ||
| − | -- return first element | + | -- return first element |
local claim = claims[sortindices[1]] | local claim = claims[sortindices[1]] | ||
result, error = getValueOfClaim(claim, qualifierId, parameter) | result, error = getValueOfClaim(claim, qualifierId, parameter) | ||
if result and references then result = result .. getReferences(frame, claim) end | if result and references then result = result .. getReferences(frame, claim) end | ||
end | end | ||
| − | + | ||
if result then return result else | if result then return result else | ||
if showerrors then return error else return default end | if showerrors then return error else return default end | ||
| Dòng 930: | Dòng 669: | ||
-- look into entity object | -- look into entity object | ||
function p.ViewSomething(frame) | function p.ViewSomething(frame) | ||
| − | + | local data = mw.wikibase.getEntityObject() | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | local data = mw.wikibase. | ||
if not data then | if not data then | ||
return nil | return nil | ||
end | end | ||
| + | |||
| + | local f = frame.args[1] and frame or frame:getParent() | ||
local i = 1 | local i = 1 | ||
| Dòng 950: | Dòng 686: | ||
end | end | ||
end | end | ||
| − | + | ||
data = data[index] or data[tonumber(index)] | data = data[index] or data[tonumber(index)] | ||
if not data then | if not data then | ||
return | return | ||
end | end | ||
| − | + | ||
i = i + 1 | i = i + 1 | ||
end | end | ||
| Dòng 979: | Dòng 715: | ||
function p.Dump(frame) | function p.Dump(frame) | ||
local f = (frame.args[1] or frame.args.id) and frame or frame:getParent() | local f = (frame.args[1] or frame.args.id) and frame or frame:getParent() | ||
| − | local data = mw.wikibase. | + | local data = mw.wikibase.getEntityObject(f.args.id) |
if not data then | if not data then | ||
return i18n.warnDump | return i18n.warnDump | ||
| Dòng 998: | Dòng 734: | ||
i = i + 1 | i = i + 1 | ||
end | end | ||
| + | end | ||
| + | |||
| + | function p.withFallback(frame) | ||
| + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | ||
| + | local input_parm = mw.text.trim(frame.args[2] or "") | ||
| + | if #input_parm == 0 or input_parm == "FETCH_WIKIDATA" then | ||
| + | local get = frame.args.get and p["get" .. lang:ucfirst(frame.args.get)] | ||
| + | return get and get(frame, true) | ||
| + | end | ||
| + | return input_parm | ||
| + | end | ||
| + | |||
| + | function p.withEditButton(frame) | ||
| + | local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or "")) | ||
| + | local input_parm = mw.text.trim(frame.args[2] or "") | ||
| + | if #input_parm == 0 or input_parm == "FETCH_WIKIDATA" then | ||
| + | local get = frame.args.get and p["get" .. lang:ucfirst(frame.args.get)] | ||
| + | local value = get and get(frame, true) | ||
| + | if value then | ||
| + | local edit_button = frame:expandTemplate{ | ||
| + | title = "Sửa dữ liệu", | ||
| + | args = { | ||
| + | p = propertyID:match("%d+"), | ||
| + | }, | ||
| + | } | ||
| + | return mw.ustring.format("%s %s", value, edit_button) | ||
| + | end | ||
| + | end | ||
| + | return input_parm | ||
end | end | ||
return p | return p | ||
Bản hiện tại lúc 21:33, ngày 24 tháng 10 năm 2020
Có thể viết tài liệu về mô đun này tại Mô đun:Wikidata/tài liệu.
require('Module:No globals')
local p = {}
local lang = mw.getContentLanguage()
-- module local variables
local wiki =
{
langcode = mw.language.getContentLanguage().code
}
-- internationalisation
local i18n = {
["errors"] = {
["property-not-found"] = "Không tìm thấy thuộc tính.",
["entity-not-found"] = "Không tìm thấy thực thể.",
["unknown-claim-type"] = "Kiểu tuyên bố không rõ.",
["unknown-snak-type"] = "Kiểu quan hệ không rõ.",
["unknown-datavalue-type"] = "Kiểu dữ liệu giá trị không rõ.",
["unknown-entity-type"] = "Kiểu thực thể không rõ.",
["qualifier-not-found"] = "Từ hạn định không rõ.",
["site-not-found"] = "Không tìm thấy dự án Wikimedia.",
},
["somevalue"] = "Giá trị nào đó",
["novalue"] = "Vô giá trị",
["datetime"] =
{
-- $1 is a placeholder for the actual number
[0] = "$1 tỷ năm", -- precision: billion years
[1] = "$100 triệu năm", -- precision: hundred million years
[2] = "$10 triệu năm", -- precision: ten million years
[3] = "$1 triệu năm", -- precision: million years
[4] = "$100.000 năm", -- precision: hundred thousand years
[5] = "$10.000 năm", -- precision: ten thousand years
[6] = "thiên niên kỷ $1", -- precision: millennium
[7] = "thế kỷ $1", -- precision: century
[8] = "thập niên $1", -- precision: decade
-- the following use the format of #time parser function
[9] = "Y", -- precision: year,
[10] = 'F "năm" Y', -- precision: month
[11] = 'j F "năm" Y', -- precision: day
[12] = 'j F "năm" Y lúc G "giờ"', -- precision: hour
[13] = 'j F "năm" Y lúc G:i', -- precision: minute
[14] = 'j F "năm" Y lúc G:i:s', -- precision: second
["beforenow"] = "$1 trước", -- how to format negative numbers for precisions 0 to 5
["afternow"] = "$1 sau", -- how to format positive numbers for precisions 0 to 5
["bc"] = '$1 "TCN"', -- how print negative years
["ad"] = "$1" -- how print positive years
},
["monolingualtext"] = '<span lang="%language">%text</span>',
["warnDump"] = "[[Thể loại:Mô đun Wikidata gọi hàm Dump]]"
}
local function printError(code)
return '<span class="error">' .. (i18n.errors[code] or code) .. '</span>'
end
function p.descriptionIn(frame)
local langcode = frame.args[1]
local id = frame.args[2] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration
-- return description of a Wikidata entity in the given language or the default language of this Wikipedia site
return mw.wikibase.getEntityObject(id).descriptions[langcode or wiki.langcode].value
end
function p.labelIn(frame)
local langcode = frame.args[1]
local id = frame.args[2] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration
-- return label of a Wikidata entity in the given language or the default language of this Wikipedia site
return mw.wikibase.getEntityObject(id).labels[langcode or wiki.langcode].value
end
-- This is used to get a value, or a comma separated list of them if multiple values exist
p.getValue = function(frame, fetch_wikidata)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local input_parm = mw.text.trim(frame.args[2] or "")
if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
local claims
if entity and entity.claims then
claims = entity.claims[propertyID]
end
if claims then
-- if wiki-linked value output as link if possible
if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
local out = {}
for k, v in pairs(claims) do
local id = v.mainsnak.datavalue.value["numeric-id"]
local qid = "Q" .. id
local sitelink = mw.wikibase.sitelink(qid)
local label = mw.wikibase.label(qid)
if sitelink then
table.insert(out, mw.ustring.format("[[%s|%s]]", sitelink, lang:ucfirst(label) or sitelink))
elseif label then
table.insert(out, mw.ustring.format("[[d:%s|%s]]", qid, lang:ucfirst(label)))
else
table.insert(out, "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]<abbr title='Wiki này chưa có bài về thực thể này'>[*]</abbr>")
end
end
return table.concat(out, ", ")
else
-- just return best values
return entity:formatPropertyValues(propertyID).value
end
else
return ""
end
else
return input_parm
end
end
-- This is used to get a value, or a comma separated list of them if multiple values exist
-- from an arbitrary entry by using its QID.
-- Use : {{#gọi:Wikidata|getValueFromID|<ID>|<Property>|FETCH_WIKIDATA}}
-- E.g.: {{#gọi:Wikidata|getValueFromID|Q151973|P26|FETCH_WIKIDATA}} - to fetch value of 'người phối ngẫu' (P26) from 'Richard Burton' (Q151973)
-- Please use sparingly - this is an *expensive call*.
p.getValueFromID = function(frame)
local itemID = mw.text.trim(frame.args[1] or "")
local propertyID = mw.text.trim(frame.args[2] or "")
local input_parm = mw.text.trim(frame.args[3] or "")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntity(itemID)
local claims = entity.claims[propertyID]
if claims then
-- if wiki-linked value output as link if possible
if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
local out = {}
for k, v in pairs(claims) do
local sitelink = mw.wikibase.sitelink("Q" .. v.mainsnak.datavalue.value["numeric-id"])
local label = mw.wikibase.label("Q" .. v.mainsnak.datavalue.value["numeric-id"])
if label == nil then label = "Q" .. v.mainsnak.datavalue.value["numeric-id"] end
if sitelink then
out[#out + 1] = "[[" .. sitelink .. "|" .. label .. "]]"
else
out[#out + 1] = "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]<abbr title='Wiki này chưa có bài về thực thể này'>[*]</abbr>"
end
end
return table.concat(out, ", ")
else
return entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
end
else
return ""
end
else
return input_parm
end
end
p.getQualifierValue = function(frame)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local qualifierID = mw.ustring.upper(mw.text.trim(frame.args[2] or ""))
local input_parm = mw.text.trim(frame.args[3] or "")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
if entity.claims[propertyID] ~= nil then
local out = {}
for k, v in pairs(entity.claims[propertyID]) do
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if v2.snaktype == 'value' then
if (mw.wikibase.sitelink("Q" .. v2.datavalue.value["numeric-id"])) then
out[#out + 1] = "[[" .. mw.wikibase.sitelink("Q" .. v2.datavalue.value["numeric-id"]) .. "]]"
else
out[#out + 1] = "[[:d:Q" .. v2.datavalue.value["numeric-id"] .. "|" .. mw.wikibase.label("Q" .. v2.datavalue.value["numeric-id"]) .. "]]<abbr title='Wiki này chưa có bài về thực thể này'>[*]</abbr>"
end
end
end
end
return table.concat(out, ", ")
else
return ""
end
else
return input_parm
end
end
-- This is used to get a value like 'male' (for property p21) which won't be linked and numbers without the thousand separators
p.getRawValue = function(frame, fetch_wikidata)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local input_parm = mw.text.trim(frame.args[2] or "")
if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
local claims
if entity then claims = entity.claims[propertyID] end
if claims then
local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
-- if number type: remove thousand separators, bounds and units
if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "quantity") then
result = mw.ustring.gsub(result, "(%d),(%d)", "%1%2")
result = mw.ustring.gsub(result, "(%d)±.*", "%1")
end
return result
else
return ""
end
else
return input_parm
end
end
function p.getFormattedValue(frame, fetch_wikidata)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local input_parm = mw.text.trim(frame.args[2] or "")
if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
if entity.claims and entity.claims[propertyID] ~= nil then
local claim = mw.wikibase.getEntityObject():formatPropertyValues(propertyID)
return claim and claim.value
else
return ""
end
else
return input_parm
end
end
p.getRawQualifierValue = function(frame)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local qualifierID = mw.ustring.upper(mw.text.trim(frame.args[2] or ""))
local input_parm = mw.text.trim(frame.args[3] or "")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
if entity.claims[propertyID] ~= nil then
local out = {}
for k, v in pairs(entity.claims[propertyID]) do
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if v2.snaktype == 'value' then
if v2.datavalue.value["numeric-id"] then
out[#out + 1] = mw.wikibase.label("Q" .. v2.datavalue.value["numeric-id"])
else
out[#out + 1] = v2.datavalue.value
end
end
end
end
local ret = table.concat(out, ", ")
return string.upper(string.sub(ret, 1, 1)) .. string.sub(ret, 2)
else
return ""
end
else
return input_parm
end
end
-- This is used to get a date value for date_of_birth (P569), etc. which won't
-- be linked -- consolidate by testing if entity.claims[propertyID].mainsnak.datavalue.type
-- is "time". Dates and times are stored in ISO 8601 format.
p.getDateValue = function(frame, fetch_wikidata)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local input_parm = mw.text.trim(frame.args[2] or "")
local date_format = mw.text.trim(frame.args[3] or "dmy")
local date_suffix = mw.text.trim(frame.args[4] or "TCN")
if fetch_wikidata or input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
if entity.claims[propertyID] ~= nil then
local out = {}
local dt = {}
for k, v in pairs(entity.claims[propertyID]) do
if v.mainsnak.snaktype == 'value' then
local d = v.mainsnak.datavalue.value.time
dt.year = string.sub(d, 1, 5)
dt.month = string.sub(d, 7, 8)
dt.day = string.sub(d, 10, 11)
if date_format == "ymd" then
table.insert(out, lang:formatDate("Y-m-d", os.time(dt)))
elseif date_format == "my" then
table.insert(out, lang:formatDate('"tháng" n "năm" Y', os.time(dt)))
elseif date_format == "y" then
table.insert(out, lang:formatDate('Y', os.time(dt)))
else
table.insert(out, lang:formatDate('j "tháng" n "năm" Y', os.time(dt)))
end
end
end
return table.concat(out, ", ")
else
return ""
end
else
return input_parm
end
end
p.getQualifierDateValue = function(frame)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local qualifierID = mw.ustring.upper(mw.text.trim(frame.args[2] or ""))
local input_parm = mw.text.trim(frame.args[3] or "")
local date_format = mw.text.trim(frame.args[4] or "dmy")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
if entity.claims[propertyID] ~= nil then
local out = {}
local dt = {}
for k, v in pairs(entity.claims[propertyID]) do
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if v2.snaktype == 'value' then
local d = v2.datavalue.value.time
dt.year = string.sub(d, 1, 5)
dt.month = string.sub(d, 7, 8)
dt.day = string.sub(d, 10, 11)
if date_format == "ymd" then
table.insert(out, lang:formatDate("Y-m-d", os.time(dt)))
elseif date_format == "my" then
table.insert(out, lang:formatDate('"tháng" n "năm" Y', os.time(dt)))
elseif date_format == "y" then
table.insert(out, lang:formatDate('Y', os.time(dt)))
else
table.insert(out, lang:formatDate('j "tháng" n "năm" Y', os.time(dt)))
end
end
end
end
return table.concat(out, ", ")
else
return ""
end
else
return input_parm
end
end
-- This is used to fetch all of the images with a particular property, e.g. hình ảnh (P18), hình GeneAtlas (P692), etc.
-- Parameters are | propertyID | value / FETCH_WIKIDATA / nil | separator (default=space) | size (default=220px)
-- It will return a standard wiki-markup [[File:Filename | size]] for each image with a selectable size and separator (which may be html)
-- e.g. {{#gọi:Wikidata|getImages|P18|FETCH_WIKIDATA}}
-- e.g. {{#gọi:Wikidata|getImages|P18|FETCH_WIKIDATA|<br>|250px}}
-- If a property is chosen that is not of type "commonsMedia", it will return empty text.
p.getImages = function(frame)
local propertyID = mw.text.trim(frame.args[1] or "")
local input_parm = mw.text.trim(frame.args[2] or "")
local sep = mw.text.trim(frame.args[3] or " ")
local imgsize = mw.text.trim(frame.args[4] or "220px")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntityObject()
local claims
if entity and entity.claims then
claims = entity.claims[propertyID]
end
if claims then
if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then
local out = {}
for k, v in pairs(claims) do
local filename = v.mainsnak.datavalue.value
out[#out + 1] = "[[Tập tin:" .. filename .. "|" .. imgsize .. "]]"
end
return table.concat(out, sep)
else
return ""
end
else
return ""
end
else
return input_parm
end
end
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
-- which are then linked to http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm
-- uses the newer mw.wikibase calls instead of directly using the snaks
-- formatPropertyValues returns a table with the P1323 values concatenated with ", " so we have to split them out into a table in order to construct the return string
p.getTAValue = function(frame)
local ent = mw.wikibase.getEntityObject()
local props = ent:formatPropertyValues('P1323')
local out = {}
local t = {}
for k, v in pairs(props) do
if k == 'value' then
t = mw.text.split( v, ", ")
for k2, v2 in pairs(t) do
out[#out + 1] = "[http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]"
end
end
end
local ret = table.concat(out, "<br> ")
if #ret == 0 then
ret = "TA không hợp lệ"
end
return ret
end
-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
function p.pageId(frame)
local entity = mw.wikibase.getEntityObject()
if not entity then return nil else return entity.id end
end
-- the "qualifiers" and "snaks" field have a respective "qualifiers-order" and "snaks-order" field
-- use these as the second parameter and this function instead of the built-in "pairs" function
-- to iterate over all qualifiers and snaks in the intended order.
local function orderedpairs(array, order)
if not order then return pairs(array) end
-- return iterator function
local i = 0
return function()
i = i + 1
if order[i] then
return order[i], array[order[i]]
end
end
end
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
local function normalizeDate(date)
date = mw.text.trim(date, "+")
-- extract year
local yearstr = mw.ustring.match(date, "^\-?%d+")
local year = tonumber(yearstr)
-- remove leading zeros of year
return year .. mw.ustring.sub(date, #yearstr + 1), year
end
local function formatDate(date, precision, timezone)
precision = precision or 11
local date, year = normalizeDate(date)
if year == 0 and precision <= 9 then return "" end
-- precision is 10000 years or more
if precision <= 5 then
local factor = 10 ^ ((5 - precision) + 4)
local y2 = math.ceil(math.abs(year) / factor)
local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
if year < 0 then
relative = mw.ustring.gsub(i18n.datetime.beforenow, "$1", relative)
else
relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative)
end
return relative
end
-- precision is decades, centuries and millennia
local era
if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end
if precision == 7 then era = mw.ustring.gsub(i18n.datetime[7], "$1", tostring(math.floor((math.abs(year) - 1) / 100) + 1)) end
if precision == 8 then era = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(math.floor(math.abs(year) / 10) * 10)) end
if era then
if year < 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
elseif year > 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era) end
return era
end
-- precision is year
if precision == 9 then
return year
end
-- precision is less than years
if precision > 9 then
--[[ the following code replaces the UTC suffix with the given negated timezone to convert the global time to the given local time
timezone = tonumber(timezone)
if timezone and timezone ~= 0 then
timezone = -timezone
timezone = mw.ustring.format("%.2d%.2d", timezone / 60, timezone % 60)
if timezone[1] ~= '-' then timezone = "+" .. timezone end
date = mw.text.trim(date, "Z") .. " " .. timezone
end
]]--
local formatstr = i18n.datetime[precision]
if year == 0 then formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], "")
elseif year < 0 then
-- Mediawiki formatDate doesn't support negative years
date = mw.ustring.sub(date, 2)
formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.bc, "$1", i18n.datetime[9]))
elseif year > 0 and i18n.datetime.ad ~= "$1" then
formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.ad, "$1", i18n.datetime[9]))
end
return mw.language.new(wiki.langcode):formatDate(formatstr, date)
end
end
local function printDatavalueEntity(data, parameter)
-- data fields: entity-type [string], numeric-id [int, Wikidata id]
local id
if data["entity-type"] == "item" then id = "Q" .. data["numeric-id"]
elseif data["entity-type"] == "property" then id = "P" .. data["numeric-id"]
else return printError("unknown-entity-type")
end
if parameter then
if parameter == "link" then
local linkTarget = mw.wikibase.sitelink(id)
local linkName = mw.wikibase.label(id)
if linkTarget then
-- if there is a local Wikipedia article link to it using the label or the article title
return "[[" .. linkTarget .. "|" .. (linkName or linkTarget) .. "]]"
else
-- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label
if linkName then return linkName else return "[[:d:" .. id .. "|" .. id .. "]]" end
end
else
return data[parameter]
end
else
return mw.wikibase.label(id) or id
end
end
local function printDatavalueTime(data, parameter)
-- data fields: time [ISO 8601 time], timezone [int in minutes], before [int], after [int], precision [int], calendarmodel [wikidata URI]
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
-- calendarmodel: e.g. http://www.wikidata.org/entity/Q1985727 for the proleptic Gregorian calendar or http://www.wikidata.org/wiki/Q11184 for the Julian calendar]
if parameter then
if parameter == "calendarmodel" then data.calendarmodel = mw.ustring.match(data.calendarmodel, "Q%d+") -- extract entity id from the calendar model URI
elseif parameter == "time" then data.time = normalizeDate(data.time) end
return data[parameter]
else
return formatDate(data.time, data.precision, data.timezone)
end
end
local function printDatavalueMonolingualText(data, parameter)
-- data fields: language [string], text [string]
if parameter then
return data[parameter]
else
local result = mw.ustring.gsub(mw.ustring.gsub(i18n.monolingualtext, "%%language", data["language"]), "%%text", data["text"])
return result
end
end
local function findClaims(entity, property)
if not property or not entity or not entity.claims then return end
if mw.ustring.match(property, "^P%d+$") then
-- if the property is given by an id (P..) access the claim list by this id
return entity.claims[property]
else
property = mw.wikibase.resolvePropertyId(property)
if not property then return end
return entity.claims[property]
end
end
local function getSnakValue(snak, parameter)
if snak.snaktype == "value" then
-- call the respective snak parser
if snak.datavalue.type == "string" then return snak.datavalue.value
elseif snak.datavalue.type == "globecoordinate" then return printDatavalueCoordinate(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "quantity" then return printDatavalueQuantity(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "time" then return printDatavalueTime(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "wikibase-entityid" then return printDatavalueEntity(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "monolingualtext" then return printDatavalueMonolingualText(snak.datavalue.value, parameter)
end
end
return mw.wikibase.renderSnak(snak)
end
local function getQualifierSnak(claim, qualifierId)
-- a "snak" is Wikidata terminology for a typed key/value pair
-- a claim consists of a main snak holding the main information of this claim,
-- as well as a list of attribute snaks and a list of references snaks
if qualifierId then
-- search the attribute snak with the given qualifier as key
if claim.qualifiers then
local qualifier = claim.qualifiers[qualifierId]
if qualifier then return qualifier[1] end
end
return nil, printError("qualifier-not-found")
else
-- otherwise return the main snak
return claim.mainsnak
end
end
local function getValueOfClaim(claim, qualifierId, parameter)
local error
local snak
snak, error = getQualifierSnak(claim, qualifierId)
if snak then
return getSnakValue(snak, parameter)
else
return nil, error
end
end
local function getReferences(frame, claim)
local result = ""
-- traverse through all references
for ref in pairs(claim.references or {}) do
local refparts
-- traverse through all parts of the current reference
for snakkey, snakval in orderedpairs(claim.references[ref].snaks or {}, claim.references[ref]["snaks-order"]) do
if refparts then refparts = refparts .. ", " else refparts = "" end
-- output the label of the property of the reference part, e.g. "imported from" for P143
refparts = refparts .. tostring(mw.wikibase.label(snakkey)) .. ": "
-- output all values of this reference part, e.g. "German Wikipedia" and "English Wikipedia" if the referenced claim was imported from both sites
for snakidx = 1, #snakval do
if snakidx > 1 then refparts = refparts .. ", " end
refparts = refparts .. getSnakValue(snakval[snakidx])
end
end
if refparts then result = result .. frame:extensionTag("ref", refparts) end
end
return result
end
function p.claim(frame)
local property = frame.args[1] or ""
local id = frame.args["id"] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration
local qualifierId = frame.args["qualifier"]
local parameter = frame.args["parameter"]
local list = frame.args["list"]
local references = frame.args["references"]
local showerrors = frame.args["showerrors"]
local default = frame.args["default"]
if default then showerrors = nil end
-- get wikidata entity
local entity = mw.wikibase.getEntityObject(id)
if not entity then
if showerrors then return printError("entity-not-found") else return default end
end
-- fetch the first claim of satisfying the given property
local claims = findClaims(entity, property)
if not claims or not claims[1] then
if showerrors then return printError("property-not-found") else return default end
end
-- get initial sort indices
local sortindices = {}
for idx in pairs(claims) do
sortindices[#sortindices + 1] = idx
end
-- sort by claim rank
local comparator = function(a, b)
local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
local ranka = rankmap[claims[a].rank or "normal"] .. mw.ustring.format("%08d", a)
local rankb = rankmap[claims[b].rank or "normal"] .. mw.ustring.format("%08d", b)
return ranka < rankb
end
table.sort(sortindices, comparator)
local result
local error
if list then
local value
-- iterate over all elements and return their value (if existing)
result = {}
for idx in pairs(claims) do
local claim = claims[sortindices[idx]]
value, error = getValueOfClaim(claim, qualifierId, parameter)
if not value and showerrors then value = error end
if value and references then value = value .. getReferences(frame, claim) end
result[#result + 1] = value
end
result = table.concat(result, list)
else
-- return first element
local claim = claims[sortindices[1]]
result, error = getValueOfClaim(claim, qualifierId, parameter)
if result and references then result = result .. getReferences(frame, claim) end
end
if result then return result else
if showerrors then return error else return default end
end
end
-- look into entity object
function p.ViewSomething(frame)
local data = mw.wikibase.getEntityObject()
if not data then
return nil
end
local f = frame.args[1] and frame or frame:getParent()
local i = 1
while true do
local index = f.args[i]
if not index then
if type(data) == "table" then
return mw.text.jsonEncode(data, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_PRETTY)
else
return tostring(data)
end
end
data = data[index] or data[tonumber(index)]
if not data then
return
end
i = i + 1
end
end
-- getting sitelink of a given wiki
-- get sitelink of current item if qid not supplied
function p.getSiteLink(frame)
local qid = frame.args.qid
if qid == "" then qid = nil end
local f = mw.text.trim( frame.args[1] or "")
local entity = mw.wikibase.getEntity(qid)
if not entity then
return
end
local link = entity:getSitelink( f )
if not link then
return
end
return link
end
function p.Dump(frame)
local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()
local data = mw.wikibase.getEntityObject(f.args.id)
if not data then
return i18n.warnDump
end
local i = 1
while true do
local index = f.args[i]
if not index then
return "<pre>"..mw.dumpObject(data).."</pre>".. i18n.warnDump
end
data = data[index] or data[tonumber(index)]
if not data then
return i18n.warnDump
end
i = i + 1
end
end
function p.withFallback(frame)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local input_parm = mw.text.trim(frame.args[2] or "")
if #input_parm == 0 or input_parm == "FETCH_WIKIDATA" then
local get = frame.args.get and p["get" .. lang:ucfirst(frame.args.get)]
return get and get(frame, true)
end
return input_parm
end
function p.withEditButton(frame)
local propertyID = mw.ustring.upper(mw.text.trim(frame.args[1] or ""))
local input_parm = mw.text.trim(frame.args[2] or "")
if #input_parm == 0 or input_parm == "FETCH_WIKIDATA" then
local get = frame.args.get and p["get" .. lang:ucfirst(frame.args.get)]
local value = get and get(frame, true)
if value then
local edit_button = frame:expandTemplate{
title = "Sửa dữ liệu",
args = {
p = propertyID:match("%d+"),
},
}
return mw.ustring.format("%s %s", value, edit_button)
end
end
return input_parm
end
return p