وحدة:ar-verb-infobox
المظهر
-- Module:ar-verb-infobox
-- By: Wael (User:ForzaGreen)
-- Creates an infobox for Arabic verbs with Wikidata integration
local p = {}
local ar_verb = require("Module:ar-verb")
-------------------------------------------------------------------------------
-- Constants and Mappings
-------------------------------------------------------------------------------
-- Map Wikidata QIDs to Arabic conjugation class names
-- Each entry has: [1] = Arabic display, [2] = internal code for ar-verb.lua
local CONJUGATION_CLASS_MAP = {
-- Form-I variants (6 vowel patterns)
["Q56070813"] = {"فعَل يفعُل", "I/u~u"}, -- ضرب يضرُب
["Q56070814"] = {"فعَل يفعِل", "I/a~i"}, -- فتح يفتِح
["Q56070815"] = {"فعَل يفعَل", "I/a~a"}, -- ذهب يذهَب
["Q56070816"] = {"فعِل يفعَل", "I/i~a"}, -- علم يعلَم
["Q136942429"] = {"فعَل يفعُل", "I/a~u"}, -- كتب يكتُب
["Q136942765"] = {"فعِل يفعِل", "I/i~i"}, -- حسب يحسِب
-- Forms II-XV
["Q56071242"] = {"فعّل", "II"},
["Q56071243"] = {"فاعل", "III"},
["Q56071244"] = {"أفعل", "IV"},
["Q56071245"] = {"تفعّل", "V"},
["Q124709192"] = {"تفاعل", "VI"},
["Q56071248"] = {"انفعل", "VII"},
["Q56071247"] = {"افتعل", "VIII"},
["Q136393994"] = {"افعلّ", "IX"},
["Q56071246"] = {"استفعل", "X"},
["Q56071249"] = {"افعالّ", "XI"},
["Q56071250"] = {"افعوعل", "XII"},
["Q56071251"] = {"افعوّل", "XIII"},
-- Quadriliteral
["Q135840786"] = {"فعلل", "Iq"},
["Q135840787"] = {"تفعلل", "IIq"},
["Q135840788"] = {"افعنلل", "IIIq"},
["Q135840789"] = {"افعللّ", "IVq"},
}
-- Special case: Ignore generic Form-I (must use specific variants)
local FORM_I_GENERIC = "Q56070812"
-- Arabic labels for fields
local FIELD_LABELS = {
root = "الجذر",
conjugation_class = "الوزن الصرفي",
transitivity = "التعدية",
verbal_noun = "المصدر",
active_participle = "اسم الفاعل",
passive_participle = "اسم المفعول",
}
-- Wikidata property IDs
local PROPERTIES = {
root = "P5920", -- جذر عربي
conjugation_class = "P5186", -- صنف التصريف
transitivity = "P9295", -- التعدية
}
-------------------------------------------------------------------------------
-- Helper Functions
-------------------------------------------------------------------------------
-- Map conjugation class QIDs to Arabic labels
-- Returns: display_string, first_arabic_wazn, first_internal_code
local function format_conjugation_classes(qids_string, add_links)
if not qids_string or qids_string == "" then
return nil, nil, nil
end
-- Parse QIDs (may be separated by <br/> or commas)
local qids = {}
for qid in qids_string:gmatch("(Q%d+)") do
table.insert(qids, qid)
end
local arabic_labels = {}
local internal_codes = {}
for _, qid in ipairs(qids) do
if qid ~= FORM_I_GENERIC then
local mapped = CONJUGATION_CLASS_MAP[qid]
if mapped then
local label = mapped[1]
if add_links then
label = "[[d:" .. qid .. "|" .. label .. "]]"
end
table.insert(arabic_labels, label)
table.insert(internal_codes, mapped[2])
end
end
end
if #arabic_labels == 0 then
return nil, nil, nil
end
return table.concat(arabic_labels, "، "), arabic_labels[1], internal_codes[1]
end
-- Generate derived forms (verbal noun, participles) using ar-verb module
local function generate_derived_forms(root_string, conj_wazn)
-- Remove spaces from root (Wikidata uses "ك ت ب", ar-verb needs "كتب")
local clean_root = root_string:gsub("%s+", "")
local word_spec = ar_verb.do_generate_forms({["جذر"] = clean_root, ["وزن"] = conj_wazn})
local vn = word_spec.forms.vn and word_spec.forms.vn[1] and word_spec.forms.vn[1].form
local ap = word_spec.forms.ap and word_spec.forms.ap[1] and word_spec.forms.ap[1].form
local pp = word_spec.forms.pp and word_spec.forms.pp[1] and word_spec.forms.pp[1].form
-- Convert empty strings or "?" to nil
if vn == "" or vn == "?" or vn == "؟" then vn = nil end
if ap == "" or ap == "?" or ap == "؟" then ap = nil end
if pp == "" or pp == "?" or pp == "؟" then pp = nil end
return vn, ap, pp
end
function p.do_generate_forms(params)
return generate_derived_forms(params["جذر"], params["وزن"])
end
function p.arverb_generate_forms(clean_root, conj_wazn)
return ar_verb.do_generate_forms({["جذر"] = clean_root, ["وزن"] = conj_wazn})
end
-- Debug functions:
p.format_conjugation_classes = format_conjugation_classes
p.generate_derived_forms = generate_derived_forms
-------------------------------------------------------------------------------
-- Main Function (called by template)
-------------------------------------------------------------------------------
function p.main(frame)
-- Get arguments
local args = frame.args
if frame.getParent then
local parent = frame:getParent()
if parent and parent.args then
for k, v in pairs(parent.args) do
if v and v ~= "" then
args[k] = v
end
end
end
end
local lid = args.wikidata or args["معرف ويكي بيانات"] or args[1]
if not lid or lid == "" then
return "خطأ: يجب توفير معرف ويكي بيانات"
end
-- Get entity directly
local entity = mw.wikibase.getEntity(lid)
if not entity then
return "خطأ: لا يمكن العثور على المدخل " .. lid
end
-- Get lemma
local lemma = "غير متوفر"
if entity.lemmas and entity.lemmas.ar then
lemma = entity.lemmas.ar.value
end
-- Get root directly from entity
local root_raw = nil
local root_display = "غير متوفر"
if entity.claims and entity.claims[PROPERTIES.root] then
local root_claim = entity.claims[PROPERTIES.root][1]
if root_claim and root_claim.mainsnak and root_claim.mainsnak.datavalue then
local root_id = root_claim.mainsnak.datavalue.value.id
-- Fetch the root entity and get its lemma
local root_entity = mw.wikibase.getEntity(root_id)
if root_entity and root_entity.lemmas and root_entity.lemmas.ar then
root_raw = root_entity.lemmas.ar.value
root_display = root_raw
end
end
end
-- Get conjugation classes directly from entity
local conj_qids = {}
if entity.claims and entity.claims[PROPERTIES.conjugation_class] then
for _, claim in ipairs(entity.claims[PROPERTIES.conjugation_class]) do
if claim.mainsnak and claim.mainsnak.datavalue then
local qid = claim.mainsnak.datavalue.value.id
if qid ~= FORM_I_GENERIC then
table.insert(conj_qids, qid)
end
end
end
end
-- Map conjugation classes - get plain text first for internal use
local conj_qids_string = table.concat(conj_qids, " ")
local conj_display_plain, conj_arabic, conj_code = format_conjugation_classes(conj_qids_string, false)
-- Then get version with Wikidata links for display
local conj_display_linked, _, _ = format_conjugation_classes(conj_qids_string, true)
-- Build conjugation display with edit icon
local conj_display_with_icon = nil
if conj_display_linked and conj_display_linked ~= "" then
-- Add edit icon manually
local edit_icon = ' <span class="penicon">'
.. "[[ملف:Arbcom ru editing.svg|10px|baseline|"
.. "تعديل في ويكي بيانات"
.. "|link=https://www.wikidata.org/wiki/Lexeme:" .. lid .. "?uselang=ar#" .. PROPERTIES.conjugation_class .. "]]"
.. "</span>"
conj_display_with_icon = conj_display_linked .. edit_icon
end
-- Get transitivity
local wikidata = require("Module:Wikidata.Ca")
local transitivity = wikidata.claim{
item = lid,
property = PROPERTIES.transitivity,
editicon = "no"
} or "غير متوفر"
-- Use plain Arabic wazn (not the linked version) for ar_verb functions
local verb_type = ar_verb.get_verb_type({["جذر"] = root_raw, ["وزن"] = conj_arabic})
-- Generate derived forms using the plain Arabic wazn from CONJUGATION_CLASS_MAP
local vn, ap, pp = generate_derived_forms(root_raw, conj_arabic)
-- Build simple infobox table using mw.html
local html = mw.html.create()
local infobox = html:tag('table')
:addClass('infobox')
:css('width', '22em')
:css('margin', '0.5em 0 0.5em 1em')
:css('float', 'left')
:css('clear', 'left')
:css('border', '1px solid')
:css('border-color', 'var(--border-color-base, #aaa)')
-- Title (increased from 120% to 150%)
-- Use inline style to let site CSS override for dark mode
infobox:tag('tr')
:tag('th')
:attr('colspan', '2')
:attr('style', 'text-align: center; background-color: #CEDEFF; font-size: 150%; font-weight: bold; padding: 0.5em;')
:wikitext(lemma)
-- Section header (increased from default to 115%)
infobox:tag('tr')
:tag('th')
:attr('colspan', '2')
:attr('style', 'text-align: center; background-color: #CEDEFF; font-size: 115%; padding: 0.3em;')
:wikitext(verb_type)
-- Helper function to get verbal nouns from Wikidata lexeme forms
local function get_verbal_nouns_from_wikidata()
if not entity.forms then
return nil, nil
end
local verbal_nouns = {}
local form_ids = {}
for _, form in ipairs(entity.forms) do
if form.grammaticalFeatures then
for _, feature in ipairs(form.grammaticalFeatures) do
if feature == "Q1350145" then -- Q1350145 = verbal noun
if form.representations and form.representations.ar then
table.insert(verbal_nouns, form.representations.ar.value)
table.insert(form_ids, form.id)
end
end
end
end
end
if #verbal_nouns == 0 then
return nil, nil
end
return verbal_nouns, form_ids
end
-- Helper function to add row
local function add_row(label, value, property_id, make_link, custom_value_with_icon, is_verbal_noun)
local row = infobox:tag('tr')
row:tag('th')
:css('text-align', 'right')
:css('vertical-align', 'top')
:css('padding', '0.3em 0.5em')
:css('font-weight', 'bold')
:wikitext(label)
local data_cell = row:tag('td')
:css('text-align', 'right')
:css('padding', '0.3em 0.5em')
-- If custom_value_with_icon is provided, use it directly (for conjugation class)
if custom_value_with_icon then
data_cell:wikitext(custom_value_with_icon)
-- If we have a property, get value from Wikidata with edit link
elseif property_id then
local full_value = wikidata.claim{
item = lid,
property = property_id,
editicon = "yes"
}
-- Use Wikidata value if available, otherwise use our computed value
if full_value and full_value ~= "" then
data_cell:wikitext(full_value)
elseif value and value ~= "" and value ~= "غير متوفر" then
if make_link then
data_cell:wikitext("[[" .. value .. "]]")
else
data_cell:wikitext(value)
end
else
data_cell:wikitext("؟")
end
else
-- No property, just use the value we computed
if value and value ~= "" and value ~= "غير متوفر" then
if make_link then
data_cell:wikitext("[[" .. value .. "]]")
else
data_cell:wikitext(value)
end
else
-- For verbal noun, try to fetch from Wikidata lexeme forms
if is_verbal_noun then
local vn_from_wds, form_ids = get_verbal_nouns_from_wikidata()
if vn_from_wds and #vn_from_wds > 0 then
-- Surround each verbal noun with [[ ]] and concatenate with Arabic comma
local linked_vns = {}
for _, vn in ipairs(vn_from_wds) do
table.insert(linked_vns, "[[" .. vn .. "]]")
end
local vn_wds_wikitext = table.concat(linked_vns, "، ")
local form_id = form_ids[1]
local wikidata_icon = ' <span class="penicon">'
.. "[[ملف:Arbcom ru editing.svg|10px|baseline|"
.. "تعديل في ويكي بيانات"
.. "|link=https://www.wikidata.org/entity/" .. form_id .. "?uselang=ar]]"
.. "</span>"
data_cell:wikitext(vn_wds_wikitext .. wikidata_icon)
else
data_cell:wikitext("؟")
end
else
data_cell:wikitext("؟")
end
end
end
end
-- Add rows
add_row(FIELD_LABELS.root, root_display, PROPERTIES.root)
add_row(FIELD_LABELS.conjugation_class, nil, nil, nil, conj_display_with_icon)
add_row(FIELD_LABELS.transitivity, transitivity, PROPERTIES.transitivity)
add_row(FIELD_LABELS.verbal_noun, vn, nil, true, nil, true) -- is_verbal_noun = true
add_row(FIELD_LABELS.active_participle, ap, nil, true)
add_row(FIELD_LABELS.passive_participle, pp, nil, true)
-- Footer with Wikidata link
local footer = infobox:tag('tr')
local footer_cell = footer:tag('td')
:attr('colspan', '2')
:css('text-align', 'left')
:css('border-top', '1px dotted #aaa')
:css('padding', '0.3em 0.5em')
:css('font-size', '85%')
-- Create Wikidata link that wraps both icon and ID
local wikidata_link = '[https://www.wikidata.org/wiki/Lexeme:' .. lid .. '?uselang=ar '
.. '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]'
.. ' <small>' .. lid .. '</small>]'
footer_cell:wikitext(wikidata_link)
-- Add category for pages using Wikidata
local output = tostring(html) .. '[[Category:صفحات تستخدم ويكي بيانات]]'
return output
end
return p
-- Debug examples:
-- =p.arverb_generate_forms("كتب", "I/a~u")
-- =p.main(mw.getCurrentFrame():newChild{args={[1]="L12100"}})