ويكاموس arwiktionary https://ar.wiktionary.org/wiki/%D9%88%D9%8A%D9%83%D8%A7%D9%85%D9%88%D8%B3:%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9 MediaWiki 1.47.0-wmf.2 case-sensitive ميديا خاص نقاش مستخدم نقاش المستخدم ويكاموس نقاش ويكاموس ملف نقاش الملف ميدياويكي نقاش ميدياويكي قالب نقاش القالب مساعدة نقاش المساعدة تصنيف نقاش التصنيف ملحق نقاش الملحق مكنز نقاش المكنز TimedText TimedText talk وحدة نقاش الوحدة فعالية نقاش فعالية ويكاموس:GUS2Wiki 4 216488 1090025 1089955 2026-05-16T11:41:18Z Alexis Jazz 28437 Updating gadget usage statistics from [[Special:GadgetUsage]] ([[phab:T121049]]) 1090025 wikitext text/x-wiki {{#ifexist:Project:GUS2Wiki/top|{{/top}}|This page provides a historical record of [[Special:GadgetUsage]] through its page history. To get the data in CSV format, see wikitext. To customize this message or add categories, create [[/top]].}} البيانات التالية مخزنة، وكان آخر تحديث لها في 2026-05-16T05:08:40Z. العدد الأقصى للنتائج المخزنة هو {{PLURAL:5000||نتيجة واحدة|نتيجتان|5000 نتائج|5000 نتيجة}}. {| class="sortable wikitable" ! الإضافة !! data-sort-type="number" | عدد المستخدمين !! data-sort-type="number" | مستخدمين نشطين |- |AjaxEdit || 30 || 0 |- |BiDiEditing || 72 || 1 |- |Cat-a-lot || 10 || 0 |- |HotCat || 87 || 5 |- |JSL || 14 || 1 |- |Linkscount || 18 || 0 |- |MobileCategories || 14 || 1 |- |Numeral converter || 1 || 0 |- |Numeral-converter-toggle || 5 || 1 |- |ShortLink || 60 || 1 |- |UTCLiveClock || 84 || 0 |- |VE-wditem-input-loader || 11 || 2 |- |XTools-ArticleInfo || 2 || 0 |- |auto-cite-wikidata-loader || data-sort-value="Infinity" | افتراضي || data-sort-value="Infinity" | افتراضي |- |autocomplete || 27 || 0 |- |mobile-sidebar || 2 || 0 |- |newsectionbottom || 11 || 0 |- |searchlang || 22 || 0 |- |speed-deletion || 6 || 1 |- |userinfo-without-deletedcontribs || 22 || 1 |- |wikEd || 44 || 1 |} * [[خاص:GadgetUsage]] * [[m:Meta:GUS2Wiki/Script|GUS2Wiki]] <!-- data in CSV format: AjaxEdit,30,0 BiDiEditing,72,1 Cat-a-lot,10,0 HotCat,87,5 JSL,14,1 Linkscount,18,0 MobileCategories,14,1 Numeral converter,1,0 Numeral-converter-toggle,5,1 ShortLink,60,1 UTCLiveClock,84,0 VE-wditem-input-loader,11,2 XTools-ArticleInfo,2,0 auto-cite-wikidata-loader,default,default autocomplete,27,0 mobile-sidebar,2,0 newsectionbottom,11,0 searchlang,22,0 speed-deletion,6,1 userinfo-without-deletedcontribs,22,1 wikEd,44,1 --> ezdav33b0bzjlj0aof8u8hp5yues258 وحدة:معجمية ويكي بيانات 828 236469 1090001 1075653 2026-05-15T17:15:57Z Mdktb 25941 إزالة مسافات زائدة بين المراجع؛ تجاهل إضافة مسافة قبل علامات الاستبدال التي تبدأ بـ \127 (يولدها ميدياويكي لحماية المراجع أثناء الـ Parsing) 1090001 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Inline i18n configuration for Arabic local i18n = { -- Templates template_anchor = 'مرساة', -- anchor template template_wikipedia = 'ويكيبيديا', -- Wikipedia link template template_audio = 'نطق', -- Audio/pronunciation template template_lexeme = 'مدخل معجمي', -- Lexeme template -- Headings heading_meanings = 'المعاني', -- Meanings section heading_etymology = 'أصل الكلمة', -- Etymology section heading_pronunciation = 'النطق', -- Pronunciation section heading_references = 'المراجع', -- References section heading_external_links = 'وصلات خارجية', -- External links -- UI text edit_wikidata = 'عدل في ويكي بيانات', -- Missing senses text text_missing_senses = 'هذه الكلمة لا تحتوي على معانٍ في ويكي بيانات. ساهم بإضافة المعاني في', text_more_info = 'للمزيد من المعلومات راجع', help_page = 'ويكاموس:ويكي بيانات', -- Categories for Wikidata usage category_uses_wikidata = 'صفحات تستخدم ويكي بيانات', category_has_senses = 'معاني من ويكي بيانات', category_missing_senses = 'معاني فارغة من ويكي بيانات', -- Categories (Q13955 = Modern Standard Arabic) categories = { ['Q13955'] = { ['Q1084'] = 'أسماء عربية', -- Nouns ['Q24905'] = 'أفعال عربية', -- Verbs ['Q34698'] = 'صفات عربية', -- Adjectives ['Q380057'] = 'ظروف عربية', -- Adverbs ['_'] = 'كلمات عربية', -- Fallback for any other lexical category } }, -- Manual note keys (empty for now) manual_category = {}, manual_etymology = {}, manual_pronunciation = {}, manual_meaning = {}, manual_reference = {}, manual_external_link = {}, } -- Inline getArgs replacement local function getArgs(frame) local args = {} local parent_args = frame:getParent() and frame:getParent().args or {} -- Merge frame.args and parent_args for k, v in pairs(frame.args) do if v ~= '' then args[k] = v end end for k, v in pairs(parent_args) do if v ~= '' and args[k] == nil then args[k] = v end end return args end base_lang_code_labels = 'ar' -- Item labels/descriptions/aliases, sense descriptions base_lang_code_forms = 'ar' -- Lexeme lemmas, form spellings base_lang_wiki = 'arwiki' -- Wikipedia link formatter_urls = { -- https://w.wiki/ELuT -- Multilingual ['P11512'] = 'https://ids.clld.org/units/$1', ['P11055'] = 'https://diacl.uni-frankfurt.de/Lexeme/Details/$1', ['P13258'] = 'https://www.termania.net/slovarji/presisov-vecjezicni-slovar/$1/_', ['P5912'] = 'https://oqaasileriffik.gl/dict/?lex=$1', -- Q11051 ['P11350'] = 'http://udb.gov.pk/result_details.php?word=$1', ['P13175'] = 'https://www.cfilt.iitb.ac.in/hindishabdamitra/class/CBSE/1/1/$1/?page=1', -- Q56356571 ['P11328'] = 'https://dehkhoda.ut.ac.ir/fa/dictionary/detail/$1', ['P12326'] = 'https://vazhaju.tj/word/_/$1', ['P12519'] = 'https://qamosona.com/G3/index.php/term/57,$1.xhtml', ['P12845'] = 'https://farhang.ru/lexeme/$1.html', -- Q13955 (Arabic) ['P11038'] = 'https://ontology.birzeit.edu/lemma/$1', ['P11757'] = 'https://ontology.birzeit.edu/wordform/$1', ['P11761'] = 'https://corpus.quran.com/qurandictionary.jsp?q=$1', ['P12451'] = ' https://ontology.birzeit.edu/lexicalconcept/$1', ['P12901'] = 'http://arabiclexicon.hawramani.com/?p=$1', -- Q9072 ['P11138'] = 'https://sonaveeb.ee/worddetails/unif/$1', ['P13190'] = 'https://www.letonika.lv/groups/default.aspx?cid=$1&r=10611062', -- Q150 (French) ['P11118'] = 'https://www.larousse.fr/dictionnaires/francais/_/$1', ['P11284'] = 'https://www.dictionnaire-academie.fr/article/A1$1', ['P11285'] = 'https://www.dictionnaire-academie.fr/article/A2$1', ['P11286'] = 'https://www.dictionnaire-academie.fr/article/A3$1', ['P11287'] = 'https://www.dictionnaire-academie.fr/article/A4$1', ['P11288'] = 'https://www.dictionnaire-academie.fr/article/A5$1', ['P11289'] = 'https://www.dictionnaire-academie.fr/article/A6$1', ['P11290'] = 'https://www.dictionnaire-academie.fr/article/A7$1', ['P11291'] = 'https://www.dictionnaire-academie.fr/article/A8$1', ['P7732'] = 'https://www.dictionnaire-academie.fr/article/A9$1', -- Q58635 ['P7820'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fpunjabipedia.org%2Ftopic.aspx%3Ftxt%3D%251&exp=%28.%2A%29&id=$1', ['P7575'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.srigranth.org%2Fservlet%2Fgurbani.dictionary%3FParam%3D%251&exp=%28.%2A%29&id=$1', -- Q1860 (English) ['P5275'] = 'http://www.oed.com/view/Entry/$1', ['P12510'] = 'https://doi.org/10.1093/OED/$1', ['P12739'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780199571123.001.0001/m_en_gb$1', ['P12690'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195392883.001.0001/m_en_us$1', ['P12726'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195418163.001.0001/m_en_ca$1', ['P12718'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195517965.001.0001/m-en_au-msdict-00001-$1', ['P12724'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195584516.001.0001/m-en_nz-msdict-00001-$1', ['P11481'] = 'https://greensdictofslang.com/entry/$1', ['P12448'] = 'https://www.daredictionary.com/view/dare/$1', ['P11130'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.merriam-webster.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P11263'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.britannica.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P13163'] = 'https://ahdictionary.com/word/search.html?id=$1', -- Q188 (German) ['P11519'] = 'https://www.owid.de/artikel/$1', ['P11520'] = 'https://www.owid.de/artikel/$1', ['P11521'] = 'https://www.owid.de/artikel/$1', ['P11522'] = 'https://www.owid.de/artikel/$1', ['P11523'] = 'https://www.owid.de/artikel/$1', ['P11524'] = 'https://www.owid.de/artikel/$1', ['P8376'] = 'https://www.duden.de/rechtschreibung/$1', ['P9384'] = 'https://www.woerterbuchnetz.de/Adelung?lemid=$1', ['P9385'] = 'https://www.woerterbuchnetz.de/DWB?lemid=$1', ['P9386'] = 'https://www.woerterbuchnetz.de/DWB2?lemid=$1', ['P9387'] = 'https://www.woerterbuchnetz.de/GWB?lemid=$1', ['P9388'] = 'https://www.woerterbuchnetz.de/Meyers?lemid=$1', ['P9389'] = 'https://www.woerterbuchnetz.de/RDWB1?lemid=$1', ['P9390'] = 'https://www.woerterbuchnetz.de/Wander?lemid=$1', ['P9940'] = 'https://www.dwds.de/wb/$1', -- Q9035 (Danish) ['P10830'] = 'https://ordregister.dk/id/$1', ['P10831'] = 'https://ordregister.dk/id/$1', ['P9529'] = 'https://ordnet.dk/ddo/ordbog?query=wd&entry_id=$1', ['P9530'] = 'https://ordnet.dk/ddo/ordbog?query=wd&mselect=$1', ['P12828'] = 'https://iserasuaat.gl/daka/daka?f=lo&l=1&p=$1', ['P9962'] = 'https://ordnet.dk/ods/ordbog?query=wd&entry_id=$1', -- Q25167 (Norwegian Bokmål) ['P10042'] = 'https://ordbøkene.no/bm/$1', ['P9958'] = 'https://naob.no/ordbok/$1', -- Q25164 (Norwegian Nynorsk) ['P10041'] = 'https://ordbøkene.no/nn/$1', -- Q652 (Italian) ['P12826'] = 'https://api.tommaseobellini.it/api/text?delta=0&html=true&id=$1', ['P12825'] = 'http://tlio.ovi.cnr.it/voci/$1.htm', ['P5844'] = 'https://www.treccani.it/vocabolario/$1', ['P12420'] = 'https://dizionario.internazionale.it/parola/', ['P12862'] = 'https://www.dizionario.rai.it/p.aspx?nID=lemma&lID=$1', ['P12885'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739569.001.0001/b-it-en-00002-$1', -- Q1321 (Spanish) ['P12529'] = 'https://wikidata-externalid-url.toolforge.org/?p=12529&url_prefix=https://dle.rae.es/?id=&id=$1', ['P12821'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739538.001.0001/b-es-en-00008-$1', ['P12630'] = 'https://aragonario.aragon.es/words/$1', -- Q9027 (Swedish) ['P8478'] = 'https://www.saob.se/artikel/?unik=$1', ['P9837'] = 'https://svenska.se/so/?id=$1', ['P11838'] = 'https://svenska.se/saol/?id=$1', -- Q9072 (Finnish) ['P12032'] = 'https://kaino.kotus.fi/fo/?p=article&fo_id=FO_$1', -- Q8752 (Basque) ['P6838'] = 'https://hiztegiak.elhuyar.eus/eu/$1', } -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) template = '' stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end function getLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end function getLinkedLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end function getExamples( current_lexeme, sense_id, frame, references_seen ) examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for i, stmt in pairs(sense:getAllStatements(property_id)) do stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for i, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for i, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for i, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end first_sense_image = '' sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for i, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for i, v in ipairs(new_notes) do if i == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end function get_pronunciation_base_form( current_lexeme ) base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end function getPronunciation ( frame, current_lexeme ) local pronunciations = {} base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = True }) lexeme_id = args[1] current_lexeme = mw.wikibase.getEntity(lexeme_id) current_language = current_lexeme:getLanguage() current_category = current_lexeme:getLexicalCategory() references_seen = {} sections = {} cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) etymology = getEtymology ( current_lexeme ) combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) rcmlye0wratxuauhtjiw53ogkr9kzf7 1090002 1090001 2026-05-15T17:46:55Z Mdktb 25941 تصويب 1090002 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Inline i18n configuration for Arabic local i18n = { -- Templates template_anchor = 'مرساة', -- anchor template template_wikipedia = 'ويكيبيديا', -- Wikipedia link template template_audio = 'نطق', -- Audio/pronunciation template template_lexeme = 'مدخل معجمي', -- Lexeme template -- Headings heading_meanings = 'المعاني', -- Meanings section heading_etymology = 'أصل الكلمة', -- Etymology section heading_pronunciation = 'النطق', -- Pronunciation section heading_references = 'المراجع', -- References section heading_external_links = 'وصلات خارجية', -- External links -- UI text edit_wikidata = 'عدل في ويكي بيانات', -- Missing senses text text_missing_senses = 'هذه الكلمة لا تحتوي على معانٍ في ويكي بيانات. ساهم بإضافة المعاني في', text_more_info = 'للمزيد من المعلومات راجع', help_page = 'ويكاموس:ويكي بيانات', -- Categories for Wikidata usage category_uses_wikidata = 'صفحات تستخدم ويكي بيانات', category_has_senses = 'معاني من ويكي بيانات', category_missing_senses = 'معاني فارغة من ويكي بيانات', -- Categories (Q13955 = Modern Standard Arabic) categories = { ['Q13955'] = { ['Q1084'] = 'أسماء عربية', -- Nouns ['Q24905'] = 'أفعال عربية', -- Verbs ['Q34698'] = 'صفات عربية', -- Adjectives ['Q380057'] = 'ظروف عربية', -- Adverbs ['_'] = 'كلمات عربية', -- Fallback for any other lexical category } }, -- Manual note keys (empty for now) manual_category = {}, manual_etymology = {}, manual_pronunciation = {}, manual_meaning = {}, manual_reference = {}, manual_external_link = {}, } -- Inline getArgs replacement local function getArgs(frame) local args = {} local parent_args = frame:getParent() and frame:getParent().args or {} -- Merge frame.args and parent_args for k, v in pairs(frame.args) do if v ~= '' then args[k] = v end end for k, v in pairs(parent_args) do if v ~= '' and args[k] == nil then args[k] = v end end return args end base_lang_code_labels = 'ar' -- Item labels/descriptions/aliases, sense descriptions base_lang_code_forms = 'ar' -- Lexeme lemmas, form spellings base_lang_wiki = 'arwiki' -- Wikipedia link formatter_urls = { -- https://w.wiki/ELuT -- Multilingual ['P11512'] = 'https://ids.clld.org/units/$1', ['P11055'] = 'https://diacl.uni-frankfurt.de/Lexeme/Details/$1', ['P13258'] = 'https://www.termania.net/slovarji/presisov-vecjezicni-slovar/$1/_', ['P5912'] = 'https://oqaasileriffik.gl/dict/?lex=$1', -- Q11051 ['P11350'] = 'http://udb.gov.pk/result_details.php?word=$1', ['P13175'] = 'https://www.cfilt.iitb.ac.in/hindishabdamitra/class/CBSE/1/1/$1/?page=1', -- Q56356571 ['P11328'] = 'https://dehkhoda.ut.ac.ir/fa/dictionary/detail/$1', ['P12326'] = 'https://vazhaju.tj/word/_/$1', ['P12519'] = 'https://qamosona.com/G3/index.php/term/57,$1.xhtml', ['P12845'] = 'https://farhang.ru/lexeme/$1.html', -- Q13955 (Arabic) ['P11038'] = 'https://ontology.birzeit.edu/lemma/$1', ['P11757'] = 'https://ontology.birzeit.edu/wordform/$1', ['P11761'] = 'https://corpus.quran.com/qurandictionary.jsp?q=$1', ['P12451'] = ' https://ontology.birzeit.edu/lexicalconcept/$1', ['P12901'] = 'http://arabiclexicon.hawramani.com/?p=$1', -- Q9072 ['P11138'] = 'https://sonaveeb.ee/worddetails/unif/$1', ['P13190'] = 'https://www.letonika.lv/groups/default.aspx?cid=$1&r=10611062', -- Q150 (French) ['P11118'] = 'https://www.larousse.fr/dictionnaires/francais/_/$1', ['P11284'] = 'https://www.dictionnaire-academie.fr/article/A1$1', ['P11285'] = 'https://www.dictionnaire-academie.fr/article/A2$1', ['P11286'] = 'https://www.dictionnaire-academie.fr/article/A3$1', ['P11287'] = 'https://www.dictionnaire-academie.fr/article/A4$1', ['P11288'] = 'https://www.dictionnaire-academie.fr/article/A5$1', ['P11289'] = 'https://www.dictionnaire-academie.fr/article/A6$1', ['P11290'] = 'https://www.dictionnaire-academie.fr/article/A7$1', ['P11291'] = 'https://www.dictionnaire-academie.fr/article/A8$1', ['P7732'] = 'https://www.dictionnaire-academie.fr/article/A9$1', -- Q58635 ['P7820'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fpunjabipedia.org%2Ftopic.aspx%3Ftxt%3D%251&exp=%28.%2A%29&id=$1', ['P7575'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.srigranth.org%2Fservlet%2Fgurbani.dictionary%3FParam%3D%251&exp=%28.%2A%29&id=$1', -- Q1860 (English) ['P5275'] = 'http://www.oed.com/view/Entry/$1', ['P12510'] = 'https://doi.org/10.1093/OED/$1', ['P12739'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780199571123.001.0001/m_en_gb$1', ['P12690'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195392883.001.0001/m_en_us$1', ['P12726'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195418163.001.0001/m_en_ca$1', ['P12718'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195517965.001.0001/m-en_au-msdict-00001-$1', ['P12724'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195584516.001.0001/m-en_nz-msdict-00001-$1', ['P11481'] = 'https://greensdictofslang.com/entry/$1', ['P12448'] = 'https://www.daredictionary.com/view/dare/$1', ['P11130'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.merriam-webster.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P11263'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.britannica.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P13163'] = 'https://ahdictionary.com/word/search.html?id=$1', -- Q188 (German) ['P11519'] = 'https://www.owid.de/artikel/$1', ['P11520'] = 'https://www.owid.de/artikel/$1', ['P11521'] = 'https://www.owid.de/artikel/$1', ['P11522'] = 'https://www.owid.de/artikel/$1', ['P11523'] = 'https://www.owid.de/artikel/$1', ['P11524'] = 'https://www.owid.de/artikel/$1', ['P8376'] = 'https://www.duden.de/rechtschreibung/$1', ['P9384'] = 'https://www.woerterbuchnetz.de/Adelung?lemid=$1', ['P9385'] = 'https://www.woerterbuchnetz.de/DWB?lemid=$1', ['P9386'] = 'https://www.woerterbuchnetz.de/DWB2?lemid=$1', ['P9387'] = 'https://www.woerterbuchnetz.de/GWB?lemid=$1', ['P9388'] = 'https://www.woerterbuchnetz.de/Meyers?lemid=$1', ['P9389'] = 'https://www.woerterbuchnetz.de/RDWB1?lemid=$1', ['P9390'] = 'https://www.woerterbuchnetz.de/Wander?lemid=$1', ['P9940'] = 'https://www.dwds.de/wb/$1', -- Q9035 (Danish) ['P10830'] = 'https://ordregister.dk/id/$1', ['P10831'] = 'https://ordregister.dk/id/$1', ['P9529'] = 'https://ordnet.dk/ddo/ordbog?query=wd&entry_id=$1', ['P9530'] = 'https://ordnet.dk/ddo/ordbog?query=wd&mselect=$1', ['P12828'] = 'https://iserasuaat.gl/daka/daka?f=lo&l=1&p=$1', ['P9962'] = 'https://ordnet.dk/ods/ordbog?query=wd&entry_id=$1', -- Q25167 (Norwegian Bokmål) ['P10042'] = 'https://ordbøkene.no/bm/$1', ['P9958'] = 'https://naob.no/ordbok/$1', -- Q25164 (Norwegian Nynorsk) ['P10041'] = 'https://ordbøkene.no/nn/$1', -- Q652 (Italian) ['P12826'] = 'https://api.tommaseobellini.it/api/text?delta=0&html=true&id=$1', ['P12825'] = 'http://tlio.ovi.cnr.it/voci/$1.htm', ['P5844'] = 'https://www.treccani.it/vocabolario/$1', ['P12420'] = 'https://dizionario.internazionale.it/parola/', ['P12862'] = 'https://www.dizionario.rai.it/p.aspx?nID=lemma&lID=$1', ['P12885'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739569.001.0001/b-it-en-00002-$1', -- Q1321 (Spanish) ['P12529'] = 'https://wikidata-externalid-url.toolforge.org/?p=12529&url_prefix=https://dle.rae.es/?id=&id=$1', ['P12821'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739538.001.0001/b-es-en-00008-$1', ['P12630'] = 'https://aragonario.aragon.es/words/$1', -- Q9027 (Swedish) ['P8478'] = 'https://www.saob.se/artikel/?unik=$1', ['P9837'] = 'https://svenska.se/so/?id=$1', ['P11838'] = 'https://svenska.se/saol/?id=$1', -- Q9072 (Finnish) ['P12032'] = 'https://kaino.kotus.fi/fo/?p=article&fo_id=FO_$1', -- Q8752 (Basque) ['P6838'] = 'https://hiztegiak.elhuyar.eus/eu/$1', } -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) template = '' stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end function getLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end function getLinkedLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end function getExamples( current_lexeme, sense_id, frame, references_seen ) examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for i, stmt in pairs(sense:getAllStatements(property_id)) do stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for i, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for i, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for i, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end first_sense_image = '' sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for i, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for i, v in ipairs(new_notes) do if i == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end function get_pronunciation_base_form( current_lexeme ) base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end function getPronunciation ( frame, current_lexeme ) local pronunciations = {} base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) lexeme_id = args[1] current_lexeme = mw.wikibase.getEntity(lexeme_id) current_language = current_lexeme:getLanguage() current_category = current_lexeme:getLexicalCategory() references_seen = {} sections = {} cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) etymology = getEtymology ( current_lexeme ) combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) 4apxlu95b36kuiqvxbp29bvnt5v60zi 1090003 1090002 2026-05-15T18:15:57Z Mdktb 25941 دوال يفترض أن تكون local 1090003 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Inline i18n configuration for Arabic local i18n = { -- Templates template_anchor = 'مرساة', -- anchor template template_wikipedia = 'ويكيبيديا', -- Wikipedia link template template_audio = 'نطق', -- Audio/pronunciation template template_lexeme = 'مدخل معجمي', -- Lexeme template -- Headings heading_meanings = 'المعاني', -- Meanings section heading_etymology = 'أصل الكلمة', -- Etymology section heading_pronunciation = 'النطق', -- Pronunciation section heading_references = 'المراجع', -- References section heading_external_links = 'وصلات خارجية', -- External links -- UI text edit_wikidata = 'عدل في ويكي بيانات', -- Missing senses text text_missing_senses = 'هذه الكلمة لا تحتوي على معانٍ في ويكي بيانات. ساهم بإضافة المعاني في', text_more_info = 'للمزيد من المعلومات راجع', help_page = 'ويكاموس:ويكي بيانات', -- Categories for Wikidata usage category_uses_wikidata = 'صفحات تستخدم ويكي بيانات', category_has_senses = 'معاني من ويكي بيانات', category_missing_senses = 'معاني فارغة من ويكي بيانات', -- Categories (Q13955 = Modern Standard Arabic) categories = { ['Q13955'] = { ['Q1084'] = 'أسماء عربية', -- Nouns ['Q24905'] = 'أفعال عربية', -- Verbs ['Q34698'] = 'صفات عربية', -- Adjectives ['Q380057'] = 'ظروف عربية', -- Adverbs ['_'] = 'كلمات عربية', -- Fallback for any other lexical category } }, -- Manual note keys (empty for now) manual_category = {}, manual_etymology = {}, manual_pronunciation = {}, manual_meaning = {}, manual_reference = {}, manual_external_link = {}, } -- Inline getArgs replacement local function getArgs(frame) local args = {} local parent_args = frame:getParent() and frame:getParent().args or {} -- Merge frame.args and parent_args for k, v in pairs(frame.args) do if v ~= '' then args[k] = v end end for k, v in pairs(parent_args) do if v ~= '' and args[k] == nil then args[k] = v end end return args end base_lang_code_labels = 'ar' -- Item labels/descriptions/aliases, sense descriptions base_lang_code_forms = 'ar' -- Lexeme lemmas, form spellings base_lang_wiki = 'arwiki' -- Wikipedia link formatter_urls = { -- https://w.wiki/ELuT -- Multilingual ['P11512'] = 'https://ids.clld.org/units/$1', ['P11055'] = 'https://diacl.uni-frankfurt.de/Lexeme/Details/$1', ['P13258'] = 'https://www.termania.net/slovarji/presisov-vecjezicni-slovar/$1/_', ['P5912'] = 'https://oqaasileriffik.gl/dict/?lex=$1', -- Q11051 ['P11350'] = 'http://udb.gov.pk/result_details.php?word=$1', ['P13175'] = 'https://www.cfilt.iitb.ac.in/hindishabdamitra/class/CBSE/1/1/$1/?page=1', -- Q56356571 ['P11328'] = 'https://dehkhoda.ut.ac.ir/fa/dictionary/detail/$1', ['P12326'] = 'https://vazhaju.tj/word/_/$1', ['P12519'] = 'https://qamosona.com/G3/index.php/term/57,$1.xhtml', ['P12845'] = 'https://farhang.ru/lexeme/$1.html', -- Q13955 (Arabic) ['P11038'] = 'https://ontology.birzeit.edu/lemma/$1', ['P11757'] = 'https://ontology.birzeit.edu/wordform/$1', ['P11761'] = 'https://corpus.quran.com/qurandictionary.jsp?q=$1', ['P12451'] = ' https://ontology.birzeit.edu/lexicalconcept/$1', ['P12901'] = 'http://arabiclexicon.hawramani.com/?p=$1', -- Q9072 ['P11138'] = 'https://sonaveeb.ee/worddetails/unif/$1', ['P13190'] = 'https://www.letonika.lv/groups/default.aspx?cid=$1&r=10611062', -- Q150 (French) ['P11118'] = 'https://www.larousse.fr/dictionnaires/francais/_/$1', ['P11284'] = 'https://www.dictionnaire-academie.fr/article/A1$1', ['P11285'] = 'https://www.dictionnaire-academie.fr/article/A2$1', ['P11286'] = 'https://www.dictionnaire-academie.fr/article/A3$1', ['P11287'] = 'https://www.dictionnaire-academie.fr/article/A4$1', ['P11288'] = 'https://www.dictionnaire-academie.fr/article/A5$1', ['P11289'] = 'https://www.dictionnaire-academie.fr/article/A6$1', ['P11290'] = 'https://www.dictionnaire-academie.fr/article/A7$1', ['P11291'] = 'https://www.dictionnaire-academie.fr/article/A8$1', ['P7732'] = 'https://www.dictionnaire-academie.fr/article/A9$1', -- Q58635 ['P7820'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fpunjabipedia.org%2Ftopic.aspx%3Ftxt%3D%251&exp=%28.%2A%29&id=$1', ['P7575'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.srigranth.org%2Fservlet%2Fgurbani.dictionary%3FParam%3D%251&exp=%28.%2A%29&id=$1', -- Q1860 (English) ['P5275'] = 'http://www.oed.com/view/Entry/$1', ['P12510'] = 'https://doi.org/10.1093/OED/$1', ['P12739'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780199571123.001.0001/m_en_gb$1', ['P12690'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195392883.001.0001/m_en_us$1', ['P12726'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195418163.001.0001/m_en_ca$1', ['P12718'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195517965.001.0001/m-en_au-msdict-00001-$1', ['P12724'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195584516.001.0001/m-en_nz-msdict-00001-$1', ['P11481'] = 'https://greensdictofslang.com/entry/$1', ['P12448'] = 'https://www.daredictionary.com/view/dare/$1', ['P11130'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.merriam-webster.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P11263'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.britannica.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P13163'] = 'https://ahdictionary.com/word/search.html?id=$1', -- Q188 (German) ['P11519'] = 'https://www.owid.de/artikel/$1', ['P11520'] = 'https://www.owid.de/artikel/$1', ['P11521'] = 'https://www.owid.de/artikel/$1', ['P11522'] = 'https://www.owid.de/artikel/$1', ['P11523'] = 'https://www.owid.de/artikel/$1', ['P11524'] = 'https://www.owid.de/artikel/$1', ['P8376'] = 'https://www.duden.de/rechtschreibung/$1', ['P9384'] = 'https://www.woerterbuchnetz.de/Adelung?lemid=$1', ['P9385'] = 'https://www.woerterbuchnetz.de/DWB?lemid=$1', ['P9386'] = 'https://www.woerterbuchnetz.de/DWB2?lemid=$1', ['P9387'] = 'https://www.woerterbuchnetz.de/GWB?lemid=$1', ['P9388'] = 'https://www.woerterbuchnetz.de/Meyers?lemid=$1', ['P9389'] = 'https://www.woerterbuchnetz.de/RDWB1?lemid=$1', ['P9390'] = 'https://www.woerterbuchnetz.de/Wander?lemid=$1', ['P9940'] = 'https://www.dwds.de/wb/$1', -- Q9035 (Danish) ['P10830'] = 'https://ordregister.dk/id/$1', ['P10831'] = 'https://ordregister.dk/id/$1', ['P9529'] = 'https://ordnet.dk/ddo/ordbog?query=wd&entry_id=$1', ['P9530'] = 'https://ordnet.dk/ddo/ordbog?query=wd&mselect=$1', ['P12828'] = 'https://iserasuaat.gl/daka/daka?f=lo&l=1&p=$1', ['P9962'] = 'https://ordnet.dk/ods/ordbog?query=wd&entry_id=$1', -- Q25167 (Norwegian Bokmål) ['P10042'] = 'https://ordbøkene.no/bm/$1', ['P9958'] = 'https://naob.no/ordbok/$1', -- Q25164 (Norwegian Nynorsk) ['P10041'] = 'https://ordbøkene.no/nn/$1', -- Q652 (Italian) ['P12826'] = 'https://api.tommaseobellini.it/api/text?delta=0&html=true&id=$1', ['P12825'] = 'http://tlio.ovi.cnr.it/voci/$1.htm', ['P5844'] = 'https://www.treccani.it/vocabolario/$1', ['P12420'] = 'https://dizionario.internazionale.it/parola/', ['P12862'] = 'https://www.dizionario.rai.it/p.aspx?nID=lemma&lID=$1', ['P12885'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739569.001.0001/b-it-en-00002-$1', -- Q1321 (Spanish) ['P12529'] = 'https://wikidata-externalid-url.toolforge.org/?p=12529&url_prefix=https://dle.rae.es/?id=&id=$1', ['P12821'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739538.001.0001/b-es-en-00008-$1', ['P12630'] = 'https://aragonario.aragon.es/words/$1', -- Q9027 (Swedish) ['P8478'] = 'https://www.saob.se/artikel/?unik=$1', ['P9837'] = 'https://svenska.se/so/?id=$1', ['P11838'] = 'https://svenska.se/saol/?id=$1', -- Q9072 (Finnish) ['P12032'] = 'https://kaino.kotus.fi/fo/?p=article&fo_id=FO_$1', -- Q8752 (Basque) ['P6838'] = 'https://hiztegiak.elhuyar.eus/eu/$1', } -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) template = '' stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for i, stmt in pairs(sense:getAllStatements(property_id)) do stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for i, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for i, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for i, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end first_sense_image = '' sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for i, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for i, v in ipairs(new_notes) do if i == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end local function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) lexeme_id = args[1] current_lexeme = mw.wikibase.getEntity(lexeme_id) current_language = current_lexeme:getLanguage() current_category = current_lexeme:getLexicalCategory() references_seen = {} sections = {} cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) etymology = getEtymology ( current_lexeme ) combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) jsh2hk8vt24fbdb64o5xmpkqkidv9db نقاش الوحدة:معجمية ويكي بيانات 829 237682 1090004 2026-05-15T19:14:59Z Mdktb 25941 /* استعمال وحدة:Arguments */ قسم جديد 1090004 wikitext text/x-wiki == استعمال وحدة:Arguments == مرحبًا @[[مستخدم:ForzaGreen|ForzaGreen]]، مجرد استفسار، أليس الأفضل أن تُستدعى وحدة [[وحدة:Arguments|Arguments]] لمعالجة وسائط القالب، حاليًا فراغ بسيط قبل أو بعد معرّف المعجمية يُظهر فشلا ورسالة خطأ --[[مستخدم:Mdktb|Mdktb]] ([[نقاش المستخدم:Mdktb|نقاش]]) 19:14، 15 مايو 2026 (ت ع م) qhb9unwubkm84e51qfmmkz3kxp43lm1 1090005 1090004 2026-05-15T19:20:20Z Mdktb 25941 /* استعمال وحدة:Arguments */ 1090005 wikitext text/x-wiki == استعمال وحدة:Arguments == مرحبًا @[[مستخدم:ForzaGreen|ForzaGreen]]، مجرد استفسار، أليس الأفضل أن تُستدعى وحدة [[وحدة:Arguments|Arguments]] لمعالجة وسائط القالب، حاليًا فراغ بسيط قبل أو بعد معرّف المعجمية يُظهر فشلا ورسالة خطأ، كذلك الخيارات مثل [[خاص:وصلة دائمة/1090003#L-920|<code>{ parentOnly = true }</code>]] لا تعمل، وغير مدعومة --[[مستخدم:Mdktb|Mdktb]] ([[نقاش المستخدم:Mdktb|نقاش]]) 19:14، 15 مايو 2026 (ت ع م) oo40bmytovyiptv67sxq2u7cfa2p9it 1090018 1090005 2026-05-15T22:31:25Z ForzaGreen 28665 /* استعمال وحدة:Arguments */ ردّ 1090018 wikitext text/x-wiki == استعمال وحدة:Arguments == مرحبًا @[[مستخدم:ForzaGreen|ForzaGreen]]، مجرد استفسار، أليس الأفضل أن تُستدعى وحدة [[وحدة:Arguments|Arguments]] لمعالجة وسائط القالب، حاليًا فراغ بسيط قبل أو بعد معرّف المعجمية يُظهر فشلا ورسالة خطأ، كذلك الخيارات مثل [[خاص:وصلة دائمة/1090003#L-920|<code>{ parentOnly = true }</code>]] لا تعمل، وغير مدعومة --[[مستخدم:Mdktb|Mdktb]] ([[نقاش المستخدم:Mdktb|نقاش]]) 19:14، 15 مايو 2026 (ت ع م) :مرحبا @[[مستخدم:Mdktb|Mdktb]]، شكرا لك على الرسالة. أظن أنك تقصد قالب {{قا|معجمية}}. في الحقيقة لم أكن أعرف [[وحدة:Arguments]]، وليس لي مانع في استعمالها. [[مستخدم:ForzaGreen|وائل]] ([[نقاش المستخدم:ForzaGreen|نقاش]]) 22:31، 15 مايو 2026 (ت ع م) kejq0we6j52tqf1wjavu1zxyyia2hgt 1090019 1090018 2026-05-15T22:40:58Z Mdktb 25941 /* استعمال وحدة:Arguments */ ردّ 1090019 wikitext text/x-wiki == استعمال وحدة:Arguments == مرحبًا @[[مستخدم:ForzaGreen|ForzaGreen]]، مجرد استفسار، أليس الأفضل أن تُستدعى وحدة [[وحدة:Arguments|Arguments]] لمعالجة وسائط القالب، حاليًا فراغ بسيط قبل أو بعد معرّف المعجمية يُظهر فشلا ورسالة خطأ، كذلك الخيارات مثل [[خاص:وصلة دائمة/1090003#L-920|<code>{ parentOnly = true }</code>]] لا تعمل، وغير مدعومة --[[مستخدم:Mdktb|Mdktb]] ([[نقاش المستخدم:Mdktb|نقاش]]) 19:14، 15 مايو 2026 (ت ع م) :مرحبا @[[مستخدم:Mdktb|Mdktb]]، شكرا لك على الرسالة. أظن أنك تقصد قالب {{قا|معجمية}}. في الحقيقة لم أكن أعرف [[وحدة:Arguments]]، وليس لي مانع في استعمالها. [[مستخدم:ForzaGreen|وائل]] ([[نقاش المستخدم:ForzaGreen|نقاش]]) 22:31، 15 مايو 2026 (ت ع م) ::@[[مستخدم:ForzaGreen|ForzaGreen]] أقصد في هذه الوحدة، لاحظ هذا [[خاص:فرق/1090017|التعديل]] في صفحة الملعب، كذلك صديقي يوجد العديد من المتغيرات غير معرفّة local، بل وبعضها يُستعمل بذات الاسم في دوال مختلفة، وكنت افكر بوجود صفحة وحدة فرعية تحوي i18n و formatter_urls والمتغيرات التي تبدأ بـ base_lang_ ويجري استدعائها، مجرد فصل تنظيمي لا أكثر، تحياتي --[[مستخدم:Mdktb|Mdktb]] ([[نقاش المستخدم:Mdktb|نقاش]]) 22:40، 15 مايو 2026 (ت ع م) dn0rvg8bll44kj5p2ivdaxev02de4ld أَمَدَّ 0 237683 1090006 2026-05-15T19:37:17Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090006 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1483787}} === المعاني === '''أَمَدَّ''' {{أفعل}} {{معجمية|L1483787|معاني}} === النطق === * {{أصد-عر|أَمَدَّ}} {{-}} === التصريفات === {{تصريف|جذر=مدد|وزن=أفعل}} === المراجع === {{مراجع}} k1qb6o1doi0r12nw0m1nbev1e0nuig0 أَطَرَّ 0 237684 1090007 2026-05-15T19:39:11Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090007 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1538083}} === المعاني === '''أَطَرَّ''' {{أفعل}} {{معجمية|L1538083|معاني}} === النطق === * {{أصد-عر|أَطَرَّ}} {{-}} === التصريفات === {{تصريف|جذر=طرر|وزن=أفعل}} === المراجع === {{مراجع}} i8bgk49euwy5p3m5grlu6fclt65054e جَحْدَلَ 0 237685 1090008 2026-05-15T20:02:44Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090008 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1533741}} === المعاني === '''جَحْدَلَ''' {{فعلل}} {{معجمية|L1533741|معاني}} === النطق === * {{أصد-عر|جَحْدَلَ}} {{-}} === التصريفات === {{تصريف|جذر=جحدل|وزن=فعلل}} === المراجع === {{مراجع}} eympqnzz8yr6omglkva6buxugytnzhl ثَقَفَ 0 237686 1090009 2026-05-15T20:04:33Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090009 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1480566}} === المعاني === '''ثَقَفَ''' {{نصر}} {{معجمية|L1480566|معاني}} === النطق === * {{أصد-عر|ثَقَفَ}} {{-}} === التصريفات === {{تصريف|جذر=ثقف|وزن=فعَل يفعُل}} === المراجع === {{مراجع}} srkwci37fa58k6b4y2f290xw704z9lu تَثَقَّفَ 0 237687 1090010 2026-05-15T20:05:27Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090010 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1497691}} === المعاني === '''تَثَقَّفَ''' {{تفعّل}} {{معجمية|L1497691|معاني}} === النطق === * {{أصد-عر|تَثَقَّفَ}} {{-}} === التصريفات === {{تصريف|جذر=ثقف|وزن=تفعّل}} === المراجع === {{مراجع}} 228kdw481hdcdp9wvg2qzylc0mfs3j5 تَثَاقَفَ 0 237688 1090011 2026-05-15T20:06:20Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090011 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1485017}} === المعاني === '''تَثَاقَفَ''' {{تفاعل}} {{معجمية|L1485017|معاني}} === النطق === * {{أصد-عر|تَثَاقَفَ}} {{-}} === التصريفات === {{تصريف|جذر=ثقف|وزن=تفاعل}} === المراجع === {{مراجع}} exu3kmvfbajxmut6mnhewfqy359tlhn تَتَايَعَ 0 237689 1090012 2026-05-15T20:08:23Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090012 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1533508}} === المعاني === '''تَتَايَعَ''' {{تفاعل}} {{معجمية|L1533508|معاني}} === النطق === * {{أصد-عر|تَتَايَعَ}} {{-}} === التصريفات === {{تصريف|جذر=تيع|وزن=تفاعل}} === المراجع === {{مراجع}} bj3p8uo4l3qtojg35ex8kirhu5wflli تَاجَ 0 237690 1090013 2026-05-15T20:09:10Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090013 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1544250}} === المعاني === '''تَاجَ''' {{نصر}} {{معجمية|L1544250|معاني}} === النطق === * {{أصد-عر|تَاجَ}} {{-}} === التصريفات === {{تصريف|جذر=توج|وزن=فعَل يفعُل}} === المراجع === {{مراجع}} gdap8otz68dkcxgvgkivvnuxbtsyukj بَيْقَرَ 0 237691 1090014 2026-05-15T20:13:59Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090014 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1533359}} === المعاني === '''بَيْقَرَ''' {{فعلل}} {{معجمية|L1533359|معاني}} === النطق === * {{أصد-عر|بَيْقَرَ}} {{-}} === التصريفات === {{تصريف|جذر=بيقر|وزن=فعلل}} === المراجع === {{مراجع}} s18ppehsjns76nux4onpo6gb3nau0ru بَيَّضَ 0 237692 1090015 2026-05-15T20:15:48Z رِفْد 37814 إنشاء صفحة فعل من بيانات المعاجم (ar-senses tool) 1090015 wikitext text/x-wiki == {{اللغة|عربية}} == {{صندوق معلومات فعل|L1487286}} === المعاني === '''بَيَّضَ''' {{فعّل}} {{معجمية|L1487286|معاني}} === النطق === * {{أصد-عر|بَيَّضَ}} {{-}} === التصريفات === {{تصريف|جذر=بيض|وزن=فعّل}} === المراجع === {{مراجع}} 5ihl2oaztdkrsxjwfskcngq1stpbgtv وحدة:معجمية ويكي بيانات/ملعب 828 237693 1090016 2026-05-15T20:24:01Z Mdktb 25941 + جلب من [[خاص:وصلة دائمة/1090003|الوحدة]] 1090016 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Inline i18n configuration for Arabic local i18n = { -- Templates template_anchor = 'مرساة', -- anchor template template_wikipedia = 'ويكيبيديا', -- Wikipedia link template template_audio = 'نطق', -- Audio/pronunciation template template_lexeme = 'مدخل معجمي', -- Lexeme template -- Headings heading_meanings = 'المعاني', -- Meanings section heading_etymology = 'أصل الكلمة', -- Etymology section heading_pronunciation = 'النطق', -- Pronunciation section heading_references = 'المراجع', -- References section heading_external_links = 'وصلات خارجية', -- External links -- UI text edit_wikidata = 'عدل في ويكي بيانات', -- Missing senses text text_missing_senses = 'هذه الكلمة لا تحتوي على معانٍ في ويكي بيانات. ساهم بإضافة المعاني في', text_more_info = 'للمزيد من المعلومات راجع', help_page = 'ويكاموس:ويكي بيانات', -- Categories for Wikidata usage category_uses_wikidata = 'صفحات تستخدم ويكي بيانات', category_has_senses = 'معاني من ويكي بيانات', category_missing_senses = 'معاني فارغة من ويكي بيانات', -- Categories (Q13955 = Modern Standard Arabic) categories = { ['Q13955'] = { ['Q1084'] = 'أسماء عربية', -- Nouns ['Q24905'] = 'أفعال عربية', -- Verbs ['Q34698'] = 'صفات عربية', -- Adjectives ['Q380057'] = 'ظروف عربية', -- Adverbs ['_'] = 'كلمات عربية', -- Fallback for any other lexical category } }, -- Manual note keys (empty for now) manual_category = {}, manual_etymology = {}, manual_pronunciation = {}, manual_meaning = {}, manual_reference = {}, manual_external_link = {}, } -- Inline getArgs replacement local function getArgs(frame) local args = {} local parent_args = frame:getParent() and frame:getParent().args or {} -- Merge frame.args and parent_args for k, v in pairs(frame.args) do if v ~= '' then args[k] = v end end for k, v in pairs(parent_args) do if v ~= '' and args[k] == nil then args[k] = v end end return args end base_lang_code_labels = 'ar' -- Item labels/descriptions/aliases, sense descriptions base_lang_code_forms = 'ar' -- Lexeme lemmas, form spellings base_lang_wiki = 'arwiki' -- Wikipedia link formatter_urls = { -- https://w.wiki/ELuT -- Multilingual ['P11512'] = 'https://ids.clld.org/units/$1', ['P11055'] = 'https://diacl.uni-frankfurt.de/Lexeme/Details/$1', ['P13258'] = 'https://www.termania.net/slovarji/presisov-vecjezicni-slovar/$1/_', ['P5912'] = 'https://oqaasileriffik.gl/dict/?lex=$1', -- Q11051 ['P11350'] = 'http://udb.gov.pk/result_details.php?word=$1', ['P13175'] = 'https://www.cfilt.iitb.ac.in/hindishabdamitra/class/CBSE/1/1/$1/?page=1', -- Q56356571 ['P11328'] = 'https://dehkhoda.ut.ac.ir/fa/dictionary/detail/$1', ['P12326'] = 'https://vazhaju.tj/word/_/$1', ['P12519'] = 'https://qamosona.com/G3/index.php/term/57,$1.xhtml', ['P12845'] = 'https://farhang.ru/lexeme/$1.html', -- Q13955 (Arabic) ['P11038'] = 'https://ontology.birzeit.edu/lemma/$1', ['P11757'] = 'https://ontology.birzeit.edu/wordform/$1', ['P11761'] = 'https://corpus.quran.com/qurandictionary.jsp?q=$1', ['P12451'] = ' https://ontology.birzeit.edu/lexicalconcept/$1', ['P12901'] = 'http://arabiclexicon.hawramani.com/?p=$1', -- Q9072 ['P11138'] = 'https://sonaveeb.ee/worddetails/unif/$1', ['P13190'] = 'https://www.letonika.lv/groups/default.aspx?cid=$1&r=10611062', -- Q150 (French) ['P11118'] = 'https://www.larousse.fr/dictionnaires/francais/_/$1', ['P11284'] = 'https://www.dictionnaire-academie.fr/article/A1$1', ['P11285'] = 'https://www.dictionnaire-academie.fr/article/A2$1', ['P11286'] = 'https://www.dictionnaire-academie.fr/article/A3$1', ['P11287'] = 'https://www.dictionnaire-academie.fr/article/A4$1', ['P11288'] = 'https://www.dictionnaire-academie.fr/article/A5$1', ['P11289'] = 'https://www.dictionnaire-academie.fr/article/A6$1', ['P11290'] = 'https://www.dictionnaire-academie.fr/article/A7$1', ['P11291'] = 'https://www.dictionnaire-academie.fr/article/A8$1', ['P7732'] = 'https://www.dictionnaire-academie.fr/article/A9$1', -- Q58635 ['P7820'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fpunjabipedia.org%2Ftopic.aspx%3Ftxt%3D%251&exp=%28.%2A%29&id=$1', ['P7575'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.srigranth.org%2Fservlet%2Fgurbani.dictionary%3FParam%3D%251&exp=%28.%2A%29&id=$1', -- Q1860 (English) ['P5275'] = 'http://www.oed.com/view/Entry/$1', ['P12510'] = 'https://doi.org/10.1093/OED/$1', ['P12739'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780199571123.001.0001/m_en_gb$1', ['P12690'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195392883.001.0001/m_en_us$1', ['P12726'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195418163.001.0001/m_en_ca$1', ['P12718'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195517965.001.0001/m-en_au-msdict-00001-$1', ['P12724'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195584516.001.0001/m-en_nz-msdict-00001-$1', ['P11481'] = 'https://greensdictofslang.com/entry/$1', ['P12448'] = 'https://www.daredictionary.com/view/dare/$1', ['P11130'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.merriam-webster.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P11263'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.britannica.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P13163'] = 'https://ahdictionary.com/word/search.html?id=$1', -- Q188 (German) ['P11519'] = 'https://www.owid.de/artikel/$1', ['P11520'] = 'https://www.owid.de/artikel/$1', ['P11521'] = 'https://www.owid.de/artikel/$1', ['P11522'] = 'https://www.owid.de/artikel/$1', ['P11523'] = 'https://www.owid.de/artikel/$1', ['P11524'] = 'https://www.owid.de/artikel/$1', ['P8376'] = 'https://www.duden.de/rechtschreibung/$1', ['P9384'] = 'https://www.woerterbuchnetz.de/Adelung?lemid=$1', ['P9385'] = 'https://www.woerterbuchnetz.de/DWB?lemid=$1', ['P9386'] = 'https://www.woerterbuchnetz.de/DWB2?lemid=$1', ['P9387'] = 'https://www.woerterbuchnetz.de/GWB?lemid=$1', ['P9388'] = 'https://www.woerterbuchnetz.de/Meyers?lemid=$1', ['P9389'] = 'https://www.woerterbuchnetz.de/RDWB1?lemid=$1', ['P9390'] = 'https://www.woerterbuchnetz.de/Wander?lemid=$1', ['P9940'] = 'https://www.dwds.de/wb/$1', -- Q9035 (Danish) ['P10830'] = 'https://ordregister.dk/id/$1', ['P10831'] = 'https://ordregister.dk/id/$1', ['P9529'] = 'https://ordnet.dk/ddo/ordbog?query=wd&entry_id=$1', ['P9530'] = 'https://ordnet.dk/ddo/ordbog?query=wd&mselect=$1', ['P12828'] = 'https://iserasuaat.gl/daka/daka?f=lo&l=1&p=$1', ['P9962'] = 'https://ordnet.dk/ods/ordbog?query=wd&entry_id=$1', -- Q25167 (Norwegian Bokmål) ['P10042'] = 'https://ordbøkene.no/bm/$1', ['P9958'] = 'https://naob.no/ordbok/$1', -- Q25164 (Norwegian Nynorsk) ['P10041'] = 'https://ordbøkene.no/nn/$1', -- Q652 (Italian) ['P12826'] = 'https://api.tommaseobellini.it/api/text?delta=0&html=true&id=$1', ['P12825'] = 'http://tlio.ovi.cnr.it/voci/$1.htm', ['P5844'] = 'https://www.treccani.it/vocabolario/$1', ['P12420'] = 'https://dizionario.internazionale.it/parola/', ['P12862'] = 'https://www.dizionario.rai.it/p.aspx?nID=lemma&lID=$1', ['P12885'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739569.001.0001/b-it-en-00002-$1', -- Q1321 (Spanish) ['P12529'] = 'https://wikidata-externalid-url.toolforge.org/?p=12529&url_prefix=https://dle.rae.es/?id=&id=$1', ['P12821'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739538.001.0001/b-es-en-00008-$1', ['P12630'] = 'https://aragonario.aragon.es/words/$1', -- Q9027 (Swedish) ['P8478'] = 'https://www.saob.se/artikel/?unik=$1', ['P9837'] = 'https://svenska.se/so/?id=$1', ['P11838'] = 'https://svenska.se/saol/?id=$1', -- Q9072 (Finnish) ['P12032'] = 'https://kaino.kotus.fi/fo/?p=article&fo_id=FO_$1', -- Q8752 (Basque) ['P6838'] = 'https://hiztegiak.elhuyar.eus/eu/$1', } -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) template = '' stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for i, stmt in pairs(sense:getAllStatements(property_id)) do stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for i, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for i, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for i, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end first_sense_image = '' sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for i, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for i, v in ipairs(new_notes) do if i == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end local function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) lexeme_id = args[1] current_lexeme = mw.wikibase.getEntity(lexeme_id) current_language = current_lexeme:getLanguage() current_category = current_lexeme:getLexicalCategory() references_seen = {} sections = {} cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) etymology = getEtymology ( current_lexeme ) combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) jsh2hk8vt24fbdb64o5xmpkqkidv9db 1090017 1090016 2026-05-15T20:28:36Z Mdktb 25941 الاعتماد على وحدة Arguments 1090017 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Inline i18n configuration for Arabic local i18n = { -- Templates template_anchor = 'مرساة', -- anchor template template_wikipedia = 'ويكيبيديا', -- Wikipedia link template template_audio = 'نطق', -- Audio/pronunciation template template_lexeme = 'مدخل معجمي', -- Lexeme template -- Headings heading_meanings = 'المعاني', -- Meanings section heading_etymology = 'أصل الكلمة', -- Etymology section heading_pronunciation = 'النطق', -- Pronunciation section heading_references = 'المراجع', -- References section heading_external_links = 'وصلات خارجية', -- External links -- UI text edit_wikidata = 'عدل في ويكي بيانات', -- Missing senses text text_missing_senses = 'هذه الكلمة لا تحتوي على معانٍ في ويكي بيانات. ساهم بإضافة المعاني في', text_more_info = 'للمزيد من المعلومات راجع', help_page = 'ويكاموس:ويكي بيانات', -- Categories for Wikidata usage category_uses_wikidata = 'صفحات تستخدم ويكي بيانات', category_has_senses = 'معاني من ويكي بيانات', category_missing_senses = 'معاني فارغة من ويكي بيانات', -- Categories (Q13955 = Modern Standard Arabic) categories = { ['Q13955'] = { ['Q1084'] = 'أسماء عربية', -- Nouns ['Q24905'] = 'أفعال عربية', -- Verbs ['Q34698'] = 'صفات عربية', -- Adjectives ['Q380057'] = 'ظروف عربية', -- Adverbs ['_'] = 'كلمات عربية', -- Fallback for any other lexical category } }, -- Manual note keys (empty for now) manual_category = {}, manual_etymology = {}, manual_pronunciation = {}, manual_meaning = {}, manual_reference = {}, manual_external_link = {}, } -- Fetch arguments local getArgs = require('Module:Arguments').getArgs base_lang_code_labels = 'ar' -- Item labels/descriptions/aliases, sense descriptions base_lang_code_forms = 'ar' -- Lexeme lemmas, form spellings base_lang_wiki = 'arwiki' -- Wikipedia link formatter_urls = { -- https://w.wiki/ELuT -- Multilingual ['P11512'] = 'https://ids.clld.org/units/$1', ['P11055'] = 'https://diacl.uni-frankfurt.de/Lexeme/Details/$1', ['P13258'] = 'https://www.termania.net/slovarji/presisov-vecjezicni-slovar/$1/_', ['P5912'] = 'https://oqaasileriffik.gl/dict/?lex=$1', -- Q11051 ['P11350'] = 'http://udb.gov.pk/result_details.php?word=$1', ['P13175'] = 'https://www.cfilt.iitb.ac.in/hindishabdamitra/class/CBSE/1/1/$1/?page=1', -- Q56356571 ['P11328'] = 'https://dehkhoda.ut.ac.ir/fa/dictionary/detail/$1', ['P12326'] = 'https://vazhaju.tj/word/_/$1', ['P12519'] = 'https://qamosona.com/G3/index.php/term/57,$1.xhtml', ['P12845'] = 'https://farhang.ru/lexeme/$1.html', -- Q13955 (Arabic) ['P11038'] = 'https://ontology.birzeit.edu/lemma/$1', ['P11757'] = 'https://ontology.birzeit.edu/wordform/$1', ['P11761'] = 'https://corpus.quran.com/qurandictionary.jsp?q=$1', ['P12451'] = ' https://ontology.birzeit.edu/lexicalconcept/$1', ['P12901'] = 'http://arabiclexicon.hawramani.com/?p=$1', -- Q9072 ['P11138'] = 'https://sonaveeb.ee/worddetails/unif/$1', ['P13190'] = 'https://www.letonika.lv/groups/default.aspx?cid=$1&r=10611062', -- Q150 (French) ['P11118'] = 'https://www.larousse.fr/dictionnaires/francais/_/$1', ['P11284'] = 'https://www.dictionnaire-academie.fr/article/A1$1', ['P11285'] = 'https://www.dictionnaire-academie.fr/article/A2$1', ['P11286'] = 'https://www.dictionnaire-academie.fr/article/A3$1', ['P11287'] = 'https://www.dictionnaire-academie.fr/article/A4$1', ['P11288'] = 'https://www.dictionnaire-academie.fr/article/A5$1', ['P11289'] = 'https://www.dictionnaire-academie.fr/article/A6$1', ['P11290'] = 'https://www.dictionnaire-academie.fr/article/A7$1', ['P11291'] = 'https://www.dictionnaire-academie.fr/article/A8$1', ['P7732'] = 'https://www.dictionnaire-academie.fr/article/A9$1', -- Q58635 ['P7820'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fpunjabipedia.org%2Ftopic.aspx%3Ftxt%3D%251&exp=%28.%2A%29&id=$1', ['P7575'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.srigranth.org%2Fservlet%2Fgurbani.dictionary%3FParam%3D%251&exp=%28.%2A%29&id=$1', -- Q1860 (English) ['P5275'] = 'http://www.oed.com/view/Entry/$1', ['P12510'] = 'https://doi.org/10.1093/OED/$1', ['P12739'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780199571123.001.0001/m_en_gb$1', ['P12690'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195392883.001.0001/m_en_us$1', ['P12726'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195418163.001.0001/m_en_ca$1', ['P12718'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195517965.001.0001/m-en_au-msdict-00001-$1', ['P12724'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195584516.001.0001/m-en_nz-msdict-00001-$1', ['P11481'] = 'https://greensdictofslang.com/entry/$1', ['P12448'] = 'https://www.daredictionary.com/view/dare/$1', ['P11130'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.merriam-webster.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P11263'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.britannica.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P13163'] = 'https://ahdictionary.com/word/search.html?id=$1', -- Q188 (German) ['P11519'] = 'https://www.owid.de/artikel/$1', ['P11520'] = 'https://www.owid.de/artikel/$1', ['P11521'] = 'https://www.owid.de/artikel/$1', ['P11522'] = 'https://www.owid.de/artikel/$1', ['P11523'] = 'https://www.owid.de/artikel/$1', ['P11524'] = 'https://www.owid.de/artikel/$1', ['P8376'] = 'https://www.duden.de/rechtschreibung/$1', ['P9384'] = 'https://www.woerterbuchnetz.de/Adelung?lemid=$1', ['P9385'] = 'https://www.woerterbuchnetz.de/DWB?lemid=$1', ['P9386'] = 'https://www.woerterbuchnetz.de/DWB2?lemid=$1', ['P9387'] = 'https://www.woerterbuchnetz.de/GWB?lemid=$1', ['P9388'] = 'https://www.woerterbuchnetz.de/Meyers?lemid=$1', ['P9389'] = 'https://www.woerterbuchnetz.de/RDWB1?lemid=$1', ['P9390'] = 'https://www.woerterbuchnetz.de/Wander?lemid=$1', ['P9940'] = 'https://www.dwds.de/wb/$1', -- Q9035 (Danish) ['P10830'] = 'https://ordregister.dk/id/$1', ['P10831'] = 'https://ordregister.dk/id/$1', ['P9529'] = 'https://ordnet.dk/ddo/ordbog?query=wd&entry_id=$1', ['P9530'] = 'https://ordnet.dk/ddo/ordbog?query=wd&mselect=$1', ['P12828'] = 'https://iserasuaat.gl/daka/daka?f=lo&l=1&p=$1', ['P9962'] = 'https://ordnet.dk/ods/ordbog?query=wd&entry_id=$1', -- Q25167 (Norwegian Bokmål) ['P10042'] = 'https://ordbøkene.no/bm/$1', ['P9958'] = 'https://naob.no/ordbok/$1', -- Q25164 (Norwegian Nynorsk) ['P10041'] = 'https://ordbøkene.no/nn/$1', -- Q652 (Italian) ['P12826'] = 'https://api.tommaseobellini.it/api/text?delta=0&html=true&id=$1', ['P12825'] = 'http://tlio.ovi.cnr.it/voci/$1.htm', ['P5844'] = 'https://www.treccani.it/vocabolario/$1', ['P12420'] = 'https://dizionario.internazionale.it/parola/', ['P12862'] = 'https://www.dizionario.rai.it/p.aspx?nID=lemma&lID=$1', ['P12885'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739569.001.0001/b-it-en-00002-$1', -- Q1321 (Spanish) ['P12529'] = 'https://wikidata-externalid-url.toolforge.org/?p=12529&url_prefix=https://dle.rae.es/?id=&id=$1', ['P12821'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739538.001.0001/b-es-en-00008-$1', ['P12630'] = 'https://aragonario.aragon.es/words/$1', -- Q9027 (Swedish) ['P8478'] = 'https://www.saob.se/artikel/?unik=$1', ['P9837'] = 'https://svenska.se/so/?id=$1', ['P11838'] = 'https://svenska.se/saol/?id=$1', -- Q9072 (Finnish) ['P12032'] = 'https://kaino.kotus.fi/fo/?p=article&fo_id=FO_$1', -- Q8752 (Basque) ['P6838'] = 'https://hiztegiak.elhuyar.eus/eu/$1', } -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) template = '' stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for i, stmt in pairs(sense:getAllStatements(property_id)) do stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for i, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for i, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for i, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end first_sense_image = '' sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for i, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for i, v in ipairs(new_notes) do if i == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end local function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) lexeme_id = args[1] current_lexeme = mw.wikibase.getEntity(lexeme_id) current_language = current_lexeme:getLanguage() current_category = current_lexeme:getLexicalCategory() references_seen = {} sections = {} cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) etymology = getEtymology ( current_lexeme ) combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) r8xx2mcyyl2n8uglq1o2sw9wyz2rt2l 1090021 1090017 2026-05-15T23:43:15Z Mdktb 25941 فصل عن الوحدة في صفحة فرعية 1090021 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Configuration local config = require('Module:معجمية ويكي بيانات/ضبط/ملعب') local i18n = config.i18n local formatter_urls = config.formatter_urls local base_lang_code_labels = config.base_lang.labels local base_lang_code_forms = config.base_lang.forms local base_lang_wiki = config.base_lang.wiki -- Fetch arguments local getArgs = require('Module:Arguments').getArgs -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) template = '' stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for i, stmt in pairs(sense:getAllStatements(property_id)) do stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for i, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for i, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for i, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end first_sense_image = '' sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for i, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for i, v in ipairs(new_notes) do if i == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end local function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) lexeme_id = args[1] current_lexeme = mw.wikibase.getEntity(lexeme_id) current_language = current_lexeme:getLanguage() current_category = current_lexeme:getLexicalCategory() references_seen = {} sections = {} cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) etymology = getEtymology ( current_lexeme ) combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) p49jdd5sgdo1wqp8dox8x4vv4mthn23 1090022 1090021 2026-05-16T00:15:30Z Mdktb 25941 حل إشكاليات متغيرات يفترض أن تكون local وإشكاليات for loop 1090022 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Configuration local config = require('Module:معجمية ويكي بيانات/ضبط/ملعب') local i18n = config.i18n local formatter_urls = config.formatter_urls local base_lang_code_labels = config.base_lang.labels local base_lang_code_forms = config.base_lang.forms local base_lang_wiki = config.base_lang.wiki -- Fetch arguments local getArgs = require('Module:Arguments').getArgs -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) local template = '' local stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) local article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense local stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense local stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do local property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value if next(property_source) ~= nil then local source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else local source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility local formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') local new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) local lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) local lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) local examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks local example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') local example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then local example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end local example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks local example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') local example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then local example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end local example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end local meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for s, stmt in pairs(sense:getAllStatements(property_id)) do local stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do local stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for s, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for s, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for s, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end local first_sense_image = '' local sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end local externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} local sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for s, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for s, v in ipairs(new_notes) do if s == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end local examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) local base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end local function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} local base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do local stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end local pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do local stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA local pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) local lexeme_id = args[1] local current_lexeme = mw.wikibase.getEntity(lexeme_id) local current_language = current_lexeme:getLanguage() local current_category = current_lexeme:getLexicalCategory() local references_seen = {} local sections = {} local cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) local etymology = getEtymology ( current_lexeme ) local combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) local pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) local meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end local external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) hwdyx976zta3w4yirf3ft3e2ea6w6fh 1090023 1090022 2026-05-16T00:45:51Z Mdktb 25941 تحسين تعريفات متغيرات ودوال 1090023 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Configuration local config = require('Module:معجمية ويكي بيانات/ضبط/ملعب') local i18n = config.i18n local formatter_urls = config.formatter_urls local base_lang_code_labels = config.base_lang.labels local base_lang_code_forms = config.base_lang.forms local base_lang_wiki = config.base_lang.wiki -- Fetch arguments local getArgs = require('Module:Arguments').getArgs -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) local template = '' local stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) local article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense local stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense local stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do local property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value local source_name if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility local formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') local new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) local lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) local lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) local examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks local example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') local example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then local example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end local example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks local example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') local example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then local example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end local example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end local meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for s, stmt in pairs(sense:getAllStatements(property_id)) do local stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do local stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for s, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for s, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for s, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end local first_sense_image = '' local sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end local externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} local sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for s, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for s, v in ipairs(new_notes) do if s == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end local examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) local base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local getEtymology local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} local base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do local stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end local pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do local stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA local pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) local lexeme_id = args[1] local current_lexeme = mw.wikibase.getEntity(lexeme_id) local current_language = current_lexeme:getLanguage() local current_category = current_lexeme:getLexicalCategory() local references_seen = {} local sections = {} local cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) local etymology = getEtymology ( current_lexeme ) local combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) local pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) local meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end local external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) 6q9ztply458rypto72t61svmnzj175h 1090024 1090023 2026-05-16T10:22:03Z Mdktb 25941 أوفر في الذاكرة 1090024 Scribunto text/plain -- وحدة:معجمية ويكي بيانات -- 🚧 Work in progress 🚧 -- By: Wael (User:ForzaGreen) -- Imports data from Wikidata lexemes for Arabic entries in Wiktionary. -- TODOs: -- - ✅ Handle missing senses. Edit icon to wikidata lexeme's senses + page link to Wiktionary:Wikidata -- - ✅ Categories: add categories for pages with/without senses -- - ✅ References: group references when they are identical -- - ✅ References: use references from "usage example" -- - ✅ Create "ويكاموس:ويكي بيانات" page -- - ✅ Template for wikidata meanings: قالب:معجمية, and docs -- - Test Etymology -- - Test Pronunciation -- - Test External links -- - (later) Add module/template for "Wikidata has a lexeme related to 'word' (Lxxxx)" -- - (later) Display "quotations" (issue: different from "gloss quote"), "synonyms", ... local p = {} -- Configuration local config = mw.loadData('Module:معجمية ويكي بيانات/ضبط/ملعب') local i18n = config.i18n local formatter_urls = config.formatter_urls local base_lang_code_labels = config.base_lang.labels local base_lang_code_forms = config.base_lang.forms local base_lang_wiki = config.base_lang.wiki -- Fetch arguments local getArgs = require('Module:Arguments').getArgs -- Return the first form of the lexeme which has exactly the given grammatical feature. local function formWithSingleGrammaticalFeature( lexeme, item_id ) for i, form in pairs( lexeme:getForms() ) do local grammaticalFeatures = form:getGrammaticalFeatures() if #grammaticalFeatures == 1 and grammaticalFeatures[1] == item_id then return form end end return nil end -- Return the representation of the form in the given language code, -- or the first representation otherwise. local function representationInLanguage( form, language_code ) for i, representation in pairs( form:getRepresentations() ) do if representation[2] == language_code then return representation end end return form:getRepresentations()[1] end local function getArticleLinkTemplate(frame, stmt_value) local template = '' local stmt_item = mw.wikibase.getEntity(stmt_value) if stmt_item:getSitelink(base_lang_wiki) ~= nil then template = frame:expandTemplate{ title=i18n['template_wikipedia'], args={stmt_item:getSitelink(base_lang_wiki)} } end return template end local function getArticleLinks ( frame, sense ) local article_links = '' for i, stmt in pairs(sense:getAllStatements('P5137')) do -- Item for this sense local stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end for i, stmt in pairs(sense:getAllStatements('P9970')) do -- Predicate for this sense local stmt_value = stmt.mainsnak.datavalue.value.id article_links = article_links .. getArticleLinkTemplate(frame, stmt_value) end return article_links end local function getExternalLinks ( lexeme ) local external_links = {} for property_id, formatter_url in pairs(formatter_urls) do for i, stmt in ipairs(lexeme:getAllStatements(property_id)) do local property_source = mw.wikibase.getBestStatements(property_id, 'P9073') -- Applicable 'stated in' value local source_name if next(property_source) ~= nil then source_name = mw.wikibase.getLabel(property_source[1].mainsnak.datavalue.value.id) if source_name == nil then source_name = property_source[1].mainsnak.datavalue.value.id end else source_name = mw.wikibase.getLabel(property_id) if source_name == nil then source_name = property_id end end -- Encode spaces in URLs as + signs for better URL compatibility local formatted_link = mw.ustring.gsub(mw.ustring.gsub(formatter_url, '$1', stmt.mainsnak.datavalue.value), ' ', '+') local new_link = '* [' .. formatted_link .. ' ' .. source_name .. ']' table.insert(external_links, new_link) end end return table.concat(external_links, '\n') end local function termSpan( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( text ) return tostring( span ) end local function termLink( term ) local text = term[1] local lang = term[2] local dir = mw.language.new( lang ):getDir() local span = mw.html.create( 'span' ) span:attr( 'lang', lang ) :attr( 'dir', dir ) :wikitext( '[[' .. text .. ']]' ) return tostring( span ) end local function getLemmata( current_lexeme ) local lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termSpan(rep) else lemma_string = lemma_string .. '/' .. termSpan(rep) end end return lemma_string end local function getLinkedLemmata( current_lexeme ) local lemma_string = '' for i, rep in pairs(current_lexeme:getLemmas()) do if lemma_string == '' then lemma_string = termLink(rep) else lemma_string = lemma_string .. '/' .. termLink(rep) end end return lemma_string end -- Helper function to generate a unique reference ID based on source and qualifiers local function generateReferenceId(source_id, qualifiers) local id_parts = {source_id} if qualifiers then -- Include volume (P478) in ID if qualifiers['P478'] then table.insert(id_parts, 'v' .. qualifiers['P478'][1].datavalue.value) end -- Include page(s) (P304) in ID if qualifiers['P304'] then table.insert(id_parts, 'p' .. qualifiers['P304'][1].datavalue.value) end end return table.concat(id_parts, '-') end -- Helper function to format a Wikidata reference using استشهاد بويكي بيانات template -- Can accept either a statement (for P1343) or a reference object (for P8394 references) local function formatWikidataReference(frame, source_id, qualifiers) local ref_args = {source_id} -- Add qualifiers if present if qualifiers then -- P478 = volume (ج) if qualifiers['P478'] then ref_args['ج'] = qualifiers['P478'][1].datavalue.value end -- P304 = page(s) (ص) if qualifiers['P304'] then ref_args['ص'] = qualifiers['P304'][1].datavalue.value end end return frame:expandTemplate{ title='استشهاد بويكي بيانات', args=ref_args } end local function getExamples( current_lexeme, sense_id, frame, references_seen ) local examples = mw.html.create('dl') for i, stmt in pairs(current_lexeme:getAllStatements('P5831')) do -- Usage example if stmt.qualifiers and stmt.qualifiers['P6072'] and stmt.qualifiers['P6072'][1].datavalue.value.id == sense_id then -- Lexeme sense for this example -- Support multi-line examples by converting ' / ' to line breaks local example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') local example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then local example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end local example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end end for i, stmt in pairs(mw.wikibase.getAllStatements(sense_id, 'P5831')) do -- Usage example -- Support multi-line examples by converting ' / ' to line breaks local example_text = mw.ustring.gsub(stmt.mainsnak.datavalue.value.text, ' / ','<br/>') local example_lang = stmt.mainsnak.datavalue.value.language -- Highlight the form if P5830 (subject lexeme form) is present if stmt.qualifiers and stmt.qualifiers['P5830'] and stmt.qualifiers['P5830'][1] then local example_form = mw.wikibase.getEntity(stmt.qualifiers['P5830'][1].datavalue.value.id) -- Lexeme form for this example -- Try P1810 qualifier first (title/name qualifier as string), then representation local example_form_str = nil if stmt.qualifiers['P1810'] ~= nil then example_form_str = stmt.qualifiers['P1810'][1].datavalue.value end if example_form_str == nil then example_form_str = example_form:getRepresentation(base_lang_code_forms) end if example_form_str == nil then example_form_str = example_form:getRepresentations()[1][1] end example_text = mw.ustring.gsub(example_text, example_form_str, "'''" .. example_form_str .. "'''") end local example_str = termSpan({example_text, example_lang}) -- Add references if present local example_refs = '' if frame and references_seen and stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) if references_seen[ref_id] then -- Reference already exists, use named reference without content example_refs = frame:extensionTag('ref', '', {name = ref_id}) else -- First occurrence, create named reference with content references_seen[ref_id] = true example_refs = frame:extensionTag('ref', citation, {name = ref_id}) end end end examples:tag('dd'):wikitext("''" .. example_str .. "''" .. example_refs):done() end return tostring(examples) end local function getLanguageForCategories ( frame, lang_id ) -- No special handling needed for Arabic return lang_id end local function getCategory ( frame, current_lexeme ) local lang_id = current_lexeme:getLanguage() local cat_id = current_lexeme:getLexicalCategory() local cat_text = mw.wikibase.getLabelByLang( cat_id, base_lang_code_labels ) lang_id = getLanguageForCategories(frame , lang_id) if i18n['categories'][lang_id] ~= nil then if i18n['categories'][lang_id][cat_id] ~= nil then cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id][cat_id] .. ']]' elseif i18n['categories'][lang_id]['_'] ~= nil then -- Fallback category if specific category not found cat_text = cat_text .. '[[Category:' .. i18n['categories'][lang_id]['_'] .. ']]' end end return cat_text end -- Add category for pages using Wikidata local function addWikidataUsageCategory() return '[[Category:' .. i18n['category_uses_wikidata'] .. ']]' end local createicon = function(langcode, entityID, propertyID) langcode = langcode or "" propertyID = propertyID or "" local icon = "&nbsp;<span class='penicon autoconfirmed-show'>[[" -- "&nbsp;<span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge .. "File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" .. i18n['edit_wikidata'] .. "|link=https://www.wikidata.org/entity/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n['edit_wikidata'] .. "]]</span>" return icon end local function getMeanings ( frame, args, current_lexeme, references_seen ) if #current_lexeme:getSenses() == 0 then local lexeme_id = current_lexeme:getId() -- Build Wikidata logo icon (similar to ar-verb-infobox.lua footer) local wikidata_logo = '[[ملف:Wikidata-logo.svg|15px|class=skin-invert|ويكي بيانات|link=]]' -- Build edit icon that links directly to the senses section local edit_icon = '&nbsp;<span class="penicon autoconfirmed-show">[[' .. 'File:OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=' .. i18n['edit_wikidata'] .. '|link=https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' .. '|' .. i18n['edit_wikidata'] .. ']]</span>' -- Build external link to Wikidata senses section (same as edit icon) local wikidata_senses_url = 'https://www.wikidata.org/wiki/Lexeme:' .. lexeme_id .. '?uselang=ar#senses' local missing_senses_html = mw.html.create('div') :addClass('wikidata-missing-senses') :css('font-style', 'italic') :wikitext(i18n['text_missing_senses'] .. ' ') :wikitext(wikidata_logo .. ' ') :wikitext('[' .. wikidata_senses_url .. ' ' .. lexeme_id .. ']') :wikitext(edit_icon .. '. ') :wikitext(i18n['text_more_info'] .. ' ') :wikitext('[[' .. i18n['help_page'] .. ']].') :wikitext('[[Category:' .. i18n['category_missing_senses'] .. ']]') return tostring(missing_senses_html) end local meanings = mw.html.create( 'ol' ) for i, sense in pairs(current_lexeme:getSenses()) do local gloss_text_parts = {} local main_gloss_text = frame:expandTemplate{ title=i18n['template_anchor'], args={sense:getId()} } local specifiers = {} for k, property_id in ipairs({'P6084', 'P6191', 'P9488'}) do -- Location where sense is used, register in which sense is used, field of usage for s, stmt in pairs(sense:getAllStatements(property_id)) do local stmt_value = stmt.mainsnak.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end if #specifiers > 0 then main_gloss_text = main_gloss_text .. "(''" .. table.concat(specifiers, "'', ''") .. "'') " end if sense:getGloss( base_lang_code_labels ) ~= nil then main_gloss_text = main_gloss_text .. sense:getGloss( base_lang_code_labels) else local other_gloss_text = nil local other_gloss_lang = nil -- First try to get labels from P5137 (item for this sense) local item_label_gloss_parts = {} for k, stmt in pairs(sense:getAllStatements('P5137')) do local stmt_value = stmt.mainsnak.datavalue.value.id local stmt_label = mw.wikibase.getLabelByLang(stmt_value, base_lang_code_labels) if stmt_label ~= nil then table.insert(item_label_gloss_parts, '[[:d:' .. stmt_value .. '|' .. stmt_label .. ']]') end end if #item_label_gloss_parts > 0 then other_gloss_text = table.concat(item_label_gloss_parts, '; ') end -- If no item labels found, try fallback languages if other_gloss_text == nil then for s, fallback_lang in ipairs(mw.language.getFallbacksFor( base_lang_code_labels )) do if sense:getGloss( fallback_lang ) ~= nil then other_gloss_text, other_gloss_lang = sense:getGloss( fallback_lang ) end end if other_gloss_lang == nil then local glosses = sense:getGlosses() for j, gloss in pairs(glosses) do other_gloss_text = gloss[1] other_gloss_lang = gloss[2] break end end main_gloss_text = main_gloss_text .. other_gloss_text .. "<sup><em>" .. mw.language.fetchLanguageName(other_gloss_lang, base_lang_code_labels) .. "</em></sup>" else main_gloss_text = main_gloss_text .. "''" .. other_gloss_text .. "''" end end table.insert(gloss_text_parts, main_gloss_text .. createicon(base_lang_code_labels, sense:getId())) for s, stmt in pairs(sense:getAllStatements('P8394')) do -- P8394 = gloss quote local quote_text = termSpan({stmt.mainsnak.datavalue.value.text, stmt.mainsnak.datavalue.value.language}) table.insert(gloss_text_parts, '"' .. quote_text .. '"') -- Format citation using استشهاد بويكي بيانات template if references exist if stmt.references and stmt.references[1] ~= nil then local ref = stmt.references[1] -- Try to find P248 (stated in) in the reference snaks if ref.snaks and ref.snaks['P248'] and ref.snaks['P248'][1] then local source_id = ref.snaks['P248'][1].datavalue.value.id local ref_id = generateReferenceId(source_id, ref.snaks) local citation = formatWikidataReference(frame, source_id, ref.snaks) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end end end for s, stmt in pairs(sense:getAllStatements('P1343')) do -- P1343 = described by source local source_id = stmt.mainsnak.datavalue.value.id local citation = formatWikidataReference(frame, source_id, stmt.qualifiers) local ref_id = generateReferenceId(source_id, stmt.qualifiers) -- Track and group references if references_seen then if references_seen[ref_id] then -- Reference already exists, use named reference without content table.insert(gloss_text_parts, frame:extensionTag('ref', '', {name = ref_id})) else -- First occurrence, create named reference with content references_seen[ref_id] = true table.insert(gloss_text_parts, frame:extensionTag('ref', citation, {name = ref_id})) end else -- No tracking, just add the reference table.insert(gloss_text_parts, frame:extensionTag('ref', citation)) end end local first_sense_image = '' local sense_images = sense:getAllStatements('P18') if next(sense_images) ~= nil then first_sense_image = sense_images[1].mainsnak.datavalue.value end if first_sense_image ~= '' then table.insert(gloss_text_parts, '[[File:' .. first_sense_image .. "|thumb|'''" .. getLemmata(current_lexeme) .. "'''—" .. main_gloss_text .. ']]') end local externallinks = getArticleLinks(frame, sense) if externallinks ~= '' then table.insert(gloss_text_parts, '— ' .. externallinks) end local new_notes = {} local sense_keys = { sense:getId(), string.sub(sense:getId(), string.find(sense:getId(), '-')+1) } for s, v in ipairs(sense_keys) do if args[v] ~= nil then table.insert(new_notes, args[v]) end end if #new_notes > 0 then for s, v in ipairs(new_notes) do if s == 1 then table.insert(gloss_text_parts, '<br/>' .. v) else table.insert(gloss_text_parts, v) end end end local examples = getExamples ( current_lexeme, sense:getId(), frame, references_seen ) -- Join gloss parts with spaces for inline elements like refs, newlines for block elements local gloss_text = '' for idx, part in ipairs(gloss_text_parts) do if idx == 1 then gloss_text = part elseif part:match('^<br/>') or part:match('^%[%[File:') then -- Block-level elements get newlines gloss_text = gloss_text .. '\n' .. part elseif part:match('^\127') or part:match('^<ref') then -- Strip markers starting with \127 or explicit <ref> tags gloss_text = gloss_text .. part else -- Inline elements (refs, quotes) get spaces gloss_text = gloss_text .. ' ' .. part end end meanings:tag('li'):wikitext(gloss_text):wikitext(examples) end -- Add category for lexemes with senses meanings:wikitext('[[Category:' .. i18n['category_has_senses'] .. ']]') return meanings end local function get_pronunciation_base_form( current_lexeme ) local base_form = nil -- (!) Words in other languages with different base forms can be added here with new if statements. -- For Arabic, use the first available form if base_form == nil then for i, form in pairs(current_lexeme:getForms()) do base_form = form break end end return base_form end local getEtymology local function getCombines ( current_lexeme ) local combines = '' local index_mappings = {} for i, stmt in pairs(current_lexeme:getAllStatements('P5238')) do if stmt.qualifiers and stmt.qualifiers['P1545'] ~= nil then -- Series ordinal local current_index = tonumber(stmt.qualifiers['P1545'][1].datavalue.value) index_mappings[current_index] = stmt end end if #index_mappings ~= 0 then for i, stmt in ipairs(index_mappings) do local part_lexeme_id = stmt.mainsnak.datavalue.value.id local part_lexeme = mw.wikibase.getEntity(part_lexeme_id) local current_substring = getLinkedLemmata(part_lexeme) -- Add recursive etymology for compound parts local part_etymology = getEtymology(part_lexeme) if part_etymology ~= '' then current_substring = current_substring .. ' (← ' .. part_etymology .. ')' end if combines == '' then combines = current_substring else combines = combines .. ' + ' .. current_substring end end end return combines end function getEtymology ( current_lexeme ) -- Recursive etymology support (no depth limit) local etymology = '' local current_combines = getCombines(current_lexeme) if #current_lexeme:getAllStatements('P5191') == 0 then return current_combines end for i, stmt in pairs(current_lexeme:getAllStatements('P5191')) do local origin_lexeme = mw.wikibase.getEntity(stmt.mainsnak.datavalue.value.id) local origin_lexeme_lang = origin_lexeme:getLanguage() local origin_origin = getEtymology(origin_lexeme) -- Recursive call local new_etymology_string = '' if origin_origin ~= '' then new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ') ← ' .. origin_origin else new_etymology_string = getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end if etymology == '' then etymology = new_etymology_string else etymology = etymology .. ' ' .. getLinkedLemmata(origin_lexeme) .. ' (' .. mw.wikibase.getLabel(origin_lexeme_lang) .. ')' end end if current_combines ~= '' then etymology = etymology .. '<br/>(' .. current_combines .. ')' end return etymology end local function getPronunciation ( frame, current_lexeme ) local pronunciations = {} local base_form = get_pronunciation_base_form(current_lexeme) if base_form ~= nil then -- P443 = Audio pronunciation for i, stmt in pairs(base_form:getAllStatements('P443')) do local pronunciation_file = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do local stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end local pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. frame:expandTemplate{ title= i18n['template_audio'], args = {current_lexeme:getLemmas()[1][2], pronunciation_file } -- TODO: find situations where the proper category is not added }) end -- P898 = IPA transcription for i, stmt in pairs(base_form:getAllStatements('P898')) do local ipa_text = stmt.mainsnak.datavalue.value local specifier_text = '' local specifiers = {} if stmt.qualifiers ~= nil then for k, property_id in ipairs({'P5237'}) do -- P5237 = Pronunciation manner if stmt.qualifiers[property_id] then for l, qual in pairs(stmt.qualifiers[property_id]) do local stmt_value = qual.datavalue.value.id table.insert(specifiers, mw.wikibase.getLabel(stmt_value)) end end end end if #specifiers > 0 then specifier_text = "(''" .. table.concat(specifiers, "'', ''") .. "'') " end -- Use IPA template if available, otherwise just format as IPA local pronunciation = table.insert(pronunciations, '* ' .. specifier_text .. '{{آيبا|ar|' .. ipa_text .. '}}') end end return table.concat(pronunciations, '\n') end local function heading_level(text, level) local heading_delimiter = string.rep('=', level) return heading_delimiter .. ' ' .. text .. ' ' .. heading_delimiter end local function get_any_notes(sections, args, keys) local notes = {} for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(notes, args[v]) end end return notes end local function add_specific_notes(sections, notes) for i, v in ipairs(notes) do table.insert(sections, v) end end local function add_any_notes(sections, args, keys) for i, v in ipairs(keys) do if args[v] ~= nil then table.insert(sections, args[v]) end end end -- Public function: Display meanings/senses only -- Usage: {{#invoke:معجمية ويكي بيانات|meanings|L12345}} function p.meanings(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return '<span class="error">خطأ: يجب تحديد معرف المدخل المعجمي من ويكي بيانات (مثال: L12345)</span>' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return '<span class="error">خطأ: لم يتم العثور على المدخل المعجمي ' .. lexeme_id .. ' في ويكي بيانات</span>' end -- Check if it's Arabic (Q13955) local lang_id = current_lexeme:getLanguage() if lang_id ~= 'Q13955' then local lang_name = mw.wikibase.getLabel(lang_id) or lang_id return '<span class="error">تحذير: هذا المدخل للغة ' .. lang_name .. ' وليس العربية (Q13955)</span>' end local sections = {} local references_seen = {} -- Add meanings section local meanings = getMeanings(frame, args, current_lexeme, references_seen) table.insert(sections, tostring(meanings)) -- -- Only show references section if there are references -- W: don't show references. It's to be added outside with {{مراجع}} -- if next(references_seen) ~= nil then -- table.insert(sections, frame:extensionTag('references')) -- end -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections, '\n\n') end -- Public function: Debug information -- Usage: {{#invoke:معجمية ويكي بيانات|debug|L12345}} function p.debug(frame) local args = getArgs(frame) local lexeme_id = args[1] if not lexeme_id or lexeme_id == '' then return 'Error: No lexeme ID provided' end local current_lexeme = mw.wikibase.getEntity(lexeme_id) if not current_lexeme then return 'Error: Lexeme ' .. lexeme_id .. ' not found' end local debug_info = {} table.insert(debug_info, '=== Debug Info for ' .. lexeme_id .. ' ===') table.insert(debug_info, 'Language: ' .. (mw.wikibase.getLabel(current_lexeme:getLanguage()) or current_lexeme:getLanguage())) table.insert(debug_info, 'Lexical Category: ' .. (mw.wikibase.getLabel(current_lexeme:getLexicalCategory()) or current_lexeme:getLexicalCategory())) table.insert(debug_info, 'Lemmas: ' .. getLemmata(current_lexeme)) table.insert(debug_info, 'Number of senses: ' .. #current_lexeme:getSenses()) table.insert(debug_info, 'Number of forms: ' .. #current_lexeme:getForms()) return '<pre>' .. table.concat(debug_info, '\n') .. '</pre>' end function p.all( frame ) local args = getArgs(frame, { parentOnly = true }) local lexeme_id = args[1] local current_lexeme = mw.wikibase.getEntity(lexeme_id) local current_language = current_lexeme:getLanguage() local current_category = current_lexeme:getLexicalCategory() local references_seen = {} local sections = {} local cat_text = '===' .. getCategory ( frame, current_lexeme ) .. frame:expandTemplate{ title=i18n['template_anchor'], args={lexeme_id} } .. '===' table.insert(sections, cat_text) table.insert(sections, frame:expandTemplate{ title= i18n['template_lexeme'], args = {lexeme_id} }) add_any_notes(sections, args, i18n['manual_category']) local etymology = getEtymology ( current_lexeme ) local combines = getCombines ( current_lexeme ) if etymology ~= '' or combines ~= '' then table.insert(sections, heading_level(i18n['heading_etymology'], 4)) if etymology ~= '' then table.insert(sections, tostring(etymology)) end if combines ~= '' then table.insert(sections, tostring(combines)) end end add_any_notes(sections, args, i18n['manual_etymology']) local pronunciation = getPronunciation ( frame, current_lexeme ) if pronunciation ~= '' then table.insert(sections, heading_level(i18n['heading_pronunciation'], 4)) table.insert(sections, tostring(pronunciation)) end add_any_notes(sections, args, i18n['manual_pronunciation']) local meanings, sense_sources = getMeanings ( frame, args, current_lexeme, references_seen ) table.insert(sections, heading_level(i18n['heading_meanings'], 4)) table.insert(sections, tostring(meanings)) add_any_notes(sections, args, i18n['manual_meaning']) -- Only show references section if there are references or manual reference notes local reference_notes = get_any_notes(sections, args, i18n['manual_reference']) local has_references = next(references_seen) ~= nil if has_references or #reference_notes > 0 then table.insert(sections, heading_level(i18n['heading_references'], 4)) table.insert(sections, frame:extensionTag('references')) add_specific_notes(sections, reference_notes) end local external_links = getExternalLinks ( current_lexeme ) if external_links ~= '' then table.insert(sections, heading_level(i18n['heading_external_links'], 4)) table.insert(sections, external_links) end add_any_notes(sections, args, i18n['manual_external_link']) -- Add Wikidata usage category table.insert(sections, addWikidataUsageCategory()) return table.concat(sections,"\n\n") end -- Arabic wrapper functions for template interface p['معاني'] = function(frame) return p.meanings(frame) end return p -- Debug usage examples: -- =p.meanings(mw.getCurrentFrame():newChild{args={'L12100'}}) -- =p.meanings(mw.getCurrentFrame():newChild{args={'L1478139'}}) -- =p['معاني'](mw.getCurrentFrame():newChild{args={'L12100'}}) 6xhhkey2pfuta84j5unlsnzewnzzswi وحدة:معجمية ويكي بيانات/ضبط/ملعب 828 237694 1090020 2026-05-15T23:37:53Z Mdktb 25941 + جلب جزئي من [[خاص:وصلة دائمة/1090003|الوحدة]] 1090020 Scribunto text/plain local config = {} config.base_lang = { labels = 'ar', forms = 'ar', wiki = 'ar' } config.i18n = { -- Templates template_anchor = 'مرساة', -- anchor template template_wikipedia = 'ويكيبيديا', -- Wikipedia link template template_audio = 'نطق', -- Audio/pronunciation template template_lexeme = 'مدخل معجمي', -- Lexeme template -- Headings heading_meanings = 'المعاني', -- Meanings section heading_etymology = 'أصل الكلمة', -- Etymology section heading_pronunciation = 'النطق', -- Pronunciation section heading_references = 'المراجع', -- References section heading_external_links = 'وصلات خارجية', -- External links -- UI text edit_wikidata = 'عدل في ويكي بيانات', -- Missing senses text text_missing_senses = 'هذه الكلمة لا تحتوي على معانٍ في ويكي بيانات. ساهم بإضافة المعاني في', text_more_info = 'للمزيد من المعلومات راجع', help_page = 'ويكاموس:ويكي بيانات', -- Categories for Wikidata usage category_uses_wikidata = 'صفحات تستخدم ويكي بيانات', category_has_senses = 'معاني من ويكي بيانات', category_missing_senses = 'معاني فارغة من ويكي بيانات', -- Categories (Q13955 = Modern Standard Arabic) categories = { ['Q13955'] = { ['Q1084'] = 'أسماء عربية', -- Nouns ['Q24905'] = 'أفعال عربية', -- Verbs ['Q34698'] = 'صفات عربية', -- Adjectives ['Q380057'] = 'ظروف عربية', -- Adverbs ['_'] = 'كلمات عربية', -- Fallback for any other lexical category } }, -- Manual note keys (empty for now) manual_category = {}, manual_etymology = {}, manual_pronunciation = {}, manual_meaning = {}, manual_reference = {}, manual_external_link = {}, } config.formatter_urls = { -- https://w.wiki/ELuT -- Multilingual ['P11512'] = 'https://ids.clld.org/units/$1', ['P11055'] = 'https://diacl.uni-frankfurt.de/Lexeme/Details/$1', ['P13258'] = 'https://www.termania.net/slovarji/presisov-vecjezicni-slovar/$1/_', ['P5912'] = 'https://oqaasileriffik.gl/dict/?lex=$1', -- Q11051 ['P11350'] = 'http://udb.gov.pk/result_details.php?word=$1', ['P13175'] = 'https://www.cfilt.iitb.ac.in/hindishabdamitra/class/CBSE/1/1/$1/?page=1', -- Q56356571 ['P11328'] = 'https://dehkhoda.ut.ac.ir/fa/dictionary/detail/$1', ['P12326'] = 'https://vazhaju.tj/word/_/$1', ['P12519'] = 'https://qamosona.com/G3/index.php/term/57,$1.xhtml', ['P12845'] = 'https://farhang.ru/lexeme/$1.html', -- Q13955 (Arabic) ['P11038'] = 'https://ontology.birzeit.edu/lemma/$1', ['P11757'] = 'https://ontology.birzeit.edu/wordform/$1', ['P11761'] = 'https://corpus.quran.com/qurandictionary.jsp?q=$1', ['P12451'] = ' https://ontology.birzeit.edu/lexicalconcept/$1', ['P12901'] = 'http://arabiclexicon.hawramani.com/?p=$1', -- Q9072 ['P11138'] = 'https://sonaveeb.ee/worddetails/unif/$1', ['P13190'] = 'https://www.letonika.lv/groups/default.aspx?cid=$1&r=10611062', -- Q150 (French) ['P11118'] = 'https://www.larousse.fr/dictionnaires/francais/_/$1', ['P11284'] = 'https://www.dictionnaire-academie.fr/article/A1$1', ['P11285'] = 'https://www.dictionnaire-academie.fr/article/A2$1', ['P11286'] = 'https://www.dictionnaire-academie.fr/article/A3$1', ['P11287'] = 'https://www.dictionnaire-academie.fr/article/A4$1', ['P11288'] = 'https://www.dictionnaire-academie.fr/article/A5$1', ['P11289'] = 'https://www.dictionnaire-academie.fr/article/A6$1', ['P11290'] = 'https://www.dictionnaire-academie.fr/article/A7$1', ['P11291'] = 'https://www.dictionnaire-academie.fr/article/A8$1', ['P7732'] = 'https://www.dictionnaire-academie.fr/article/A9$1', -- Q58635 ['P7820'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fpunjabipedia.org%2Ftopic.aspx%3Ftxt%3D%251&exp=%28.%2A%29&id=$1', ['P7575'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.srigranth.org%2Fservlet%2Fgurbani.dictionary%3FParam%3D%251&exp=%28.%2A%29&id=$1', -- Q1860 (English) ['P5275'] = 'http://www.oed.com/view/Entry/$1', ['P12510'] = 'https://doi.org/10.1093/OED/$1', ['P12739'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780199571123.001.0001/m_en_gb$1', ['P12690'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195392883.001.0001/m_en_us$1', ['P12726'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195418163.001.0001/m_en_ca$1', ['P12718'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195517965.001.0001/m-en_au-msdict-00001-$1', ['P12724'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780195584516.001.0001/m-en_nz-msdict-00001-$1', ['P11481'] = 'https://greensdictofslang.com/entry/$1', ['P12448'] = 'https://www.daredictionary.com/view/dare/$1', ['P11130'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.merriam-webster.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P11263'] = 'https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fwww.britannica.com%2Fdictionary%2F%251&exp=%28.%2A%29&id=$1', ['P13163'] = 'https://ahdictionary.com/word/search.html?id=$1', -- Q188 (German) ['P11519'] = 'https://www.owid.de/artikel/$1', ['P11520'] = 'https://www.owid.de/artikel/$1', ['P11521'] = 'https://www.owid.de/artikel/$1', ['P11522'] = 'https://www.owid.de/artikel/$1', ['P11523'] = 'https://www.owid.de/artikel/$1', ['P11524'] = 'https://www.owid.de/artikel/$1', ['P8376'] = 'https://www.duden.de/rechtschreibung/$1', ['P9384'] = 'https://www.woerterbuchnetz.de/Adelung?lemid=$1', ['P9385'] = 'https://www.woerterbuchnetz.de/DWB?lemid=$1', ['P9386'] = 'https://www.woerterbuchnetz.de/DWB2?lemid=$1', ['P9387'] = 'https://www.woerterbuchnetz.de/GWB?lemid=$1', ['P9388'] = 'https://www.woerterbuchnetz.de/Meyers?lemid=$1', ['P9389'] = 'https://www.woerterbuchnetz.de/RDWB1?lemid=$1', ['P9390'] = 'https://www.woerterbuchnetz.de/Wander?lemid=$1', ['P9940'] = 'https://www.dwds.de/wb/$1', -- Q9035 (Danish) ['P10830'] = 'https://ordregister.dk/id/$1', ['P10831'] = 'https://ordregister.dk/id/$1', ['P9529'] = 'https://ordnet.dk/ddo/ordbog?query=wd&entry_id=$1', ['P9530'] = 'https://ordnet.dk/ddo/ordbog?query=wd&mselect=$1', ['P12828'] = 'https://iserasuaat.gl/daka/daka?f=lo&l=1&p=$1', ['P9962'] = 'https://ordnet.dk/ods/ordbog?query=wd&entry_id=$1', -- Q25167 (Norwegian Bokmål) ['P10042'] = 'https://ordbøkene.no/bm/$1', ['P9958'] = 'https://naob.no/ordbok/$1', -- Q25164 (Norwegian Nynorsk) ['P10041'] = 'https://ordbøkene.no/nn/$1', -- Q652 (Italian) ['P12826'] = 'https://api.tommaseobellini.it/api/text?delta=0&html=true&id=$1', ['P12825'] = 'http://tlio.ovi.cnr.it/voci/$1.htm', ['P5844'] = 'https://www.treccani.it/vocabolario/$1', ['P12420'] = 'https://dizionario.internazionale.it/parola/', ['P12862'] = 'https://www.dizionario.rai.it/p.aspx?nID=lemma&lID=$1', ['P12885'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739569.001.0001/b-it-en-00002-$1', -- Q1321 (Spanish) ['P12529'] = 'https://wikidata-externalid-url.toolforge.org/?p=12529&url_prefix=https://dle.rae.es/?id=&id=$1', ['P12821'] = 'https://www.oxfordreference.com/display/10.1093/acref/9780191739538.001.0001/b-es-en-00008-$1', ['P12630'] = 'https://aragonario.aragon.es/words/$1', -- Q9027 (Swedish) ['P8478'] = 'https://www.saob.se/artikel/?unik=$1', ['P9837'] = 'https://svenska.se/so/?id=$1', ['P11838'] = 'https://svenska.se/saol/?id=$1', -- Q9072 (Finnish) ['P12032'] = 'https://kaino.kotus.fi/fo/?p=article&fo_id=FO_$1', -- Q8752 (Basque) ['P6838'] = 'https://hiztegiak.elhuyar.eus/eu/$1', } return config 0cri709ssqa66b04niwcis25zg0j0fa