Wikiwordbōc angwiktionary https://ang.wiktionary.org/wiki/H%C4%93afodtramet MediaWiki 1.47.0-wmf.22 case-sensitive Media Syndrig Mōtung Brūcend Brūcendmōtung Wikiwordbōc Wikiwordbōcmōtung Ymele Ymelmōtung MediaWiki MediaWikimōtung Bysen Bysenmōtung Help Helpmōtung Flocc Floccmōtung Ætēaca Ætēacmōtung TimedText TimedText talk Module Module talk Event Event talk wordstǣr 0 1967 55110 52250 2026-10-01T15:51:13Z Deadend0914 7211 55110 wikitext text/x-wiki =={{sprǣc|ang}}== ===Rihstefn=== * IPA: /wordstæːr/ ===Wordstǣr=== *Þæs wordes [[word]] and [[stǣr]] === Nama === {{ang-noun|n|head=wordstǣr}} # (nīweword) Sēo stǣr sumes wordes, þæt is, hū þæt word ēode of his fruman tō his andweardlican ansīene. [[Flocc:Englisc nama]] [[Flocc:Englisc wīflic nama]] [[Flocc:Nīwe word]] b7ratwnwlc6ldd6z44wv94c3k1agn4e 55111 55110 2026-10-01T15:51:25Z Deadend0914 7211 55111 wikitext text/x-wiki =={{sprǣc|ang}}== ===Rihstefn=== * IPA: /wordstæːr/ ===Wordstǣr=== *Þæs wordes [[word]] and [[stǣr]] === Nama === {{ang-noun|n|head=wordstǣr}} # (nīweword) Sēo stǣr sumes wordes, þæt is, hū þæt word ēode of his fruman tō his andweardlican ansīene. detv9ne059o5ecd4rhcmshn70fjy8br beautiful 0 3027 55105 50739 2026-10-01T15:31:12Z Deadend0914 7211 /* Níwe Englisc */ 55105 wikitext text/x-wiki =={{sprǣc|en}}== ===Rihtstefn=== IPA:/ˈbjuːtɪ.fəl/ ===Tógeíecendlic=== {{en-adj}} #[[wlitig]] ##[[ælfscíene]] (wlitig swá [[ælf]]) ====Fruma==== ====Word mid gelícum Sweotolungum==== #[[gebléod]] ====Word mid ungelícum Sweotolungum==== #[[atol]], [[forlegenlic]], [[unfæger]], [[wliteléas]], [[yfellic]] ====Wendunga==== *[[Þéodisc]]: [[schön]] *[[Hebrēisc]]: יפה baao5t7mvojlj5i0l1qpqc70vuadjk7 55109 55105 2026-10-01T15:41:33Z Deadend0914 7211 /* {{sprǣc|en}} */ 55109 wikitext text/x-wiki =={{sprǣc|en}}== ===Rihtstefn=== IPA:/ˈbjuːtɪ.fəl/ ===Wordstǣr=== {{inh+|en|enm|bewteful}} ===Tógeíecendlic=== {{en-adj}} #[[wlitig]] ##[[ælfscíene]] (wlitig swá [[ælf]]) ====Word mid gelícum Sweotolungum==== #[[gebléod]] ====Word mid ungelícum Sweotolungum==== #[[atol]], [[forlegenlic]], [[unfæger]], [[wliteléas]], [[yfellic]] ====Wendunga==== *[[Þéodisc]]: [[schön]] *[[Hebrēisc]]: יפה t5x7bjhktvrc04a4seks5per04ccq6i Wikiwordbōc:Ealuhūs 4 5774 55104 54668 2026-10-01T12:42:29Z MediaWiki message delivery 2721 /* Wikidata Sitelink changes in Recent Changes and Watchlist */ new section 55104 wikitext text/x-wiki * ''Ealdhord: [[Wikiwordbōc:Ealuhūs/Hord 1|1]], [[Wikiwordbōc:Ealuhūs/Hord 2|2]], [[Wikiwordbōc:Ealuhūs/Hord 3|3]], [[Wikiwordbōc:Ealuhūs/Hord 4|4]], [[Wikiwordbōc:Ealuhūs/Hord 5|5]] == Launching! Join Us for Wiki Loves Ramadan 2025! == Dear All, We’re happy to announce the launch of [[m:Wiki Loves Ramadan 2025|Wiki Loves Ramadan 2025]], an annual international campaign dedicated to celebrating and preserving Islamic cultures and history through the power of Wikipedia. As an active contributor to the Local Wikipedia, you are specially invited to participate in the launch. This year’s campaign will be launched for you to join us write, edit, and improve articles that showcase the richness and diversity of Islamic traditions, history, and culture. * Topic: [[m:Event:Wiki Loves Ramadan 2025 Campaign Launch|Wiki Loves Ramadan 2025 Campaign Launch]] * When: Jan 19, 2025 * Time: 16:00 Universal Time UTC and runs throughout Ramadan (starting February 25, 2025). * Join Zoom Meeting: https://us02web.zoom.us/j/88420056597?pwd=NdrpqIhrwAVPeWB8FNb258n7qngqqo.1 * Zoom meeting hosted by [[m:Wikimedia Bangladesh|Wikimedia Bangladesh]] To get started, visit the [[m:Wiki Loves Ramadan 2025|campaign page]] for details, resources, and guidelines: Wiki Loves Ramadan 2025. Add [[m:Wiki Loves Ramadan 2025/Participant|your community here]], and organized Wiki Loves Ramadan 2025 in your local language. Whether you’re a first-time editor or an experienced Wikipedian, your contributions matter. Together, we can ensure Islamic cultures and traditions are well-represented and accessible to all. Feel free to invite your community and friends too. Kindly reach out if you have any questions or need support as you prepare to participate. Let’s make Wiki Loves Ramadan 2025 a success! For the [[m:Wiki Loves Ramadan 2025/Team|International Team]] 12:07, 16 Se Æfterra Gēola 2025 (UTC) <!-- Message sent by User:ZI Jony@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=27568454 --> == Universal Code of Conduct annual review: provide your comments on the UCoC and Enforcement Guidelines == <div lang="en" dir="ltr" class="mw-content-ltr"> My apologies for writing in English. {{Int:Please-translate}}. I am writing to you to let you know the annual review period for the Universal Code of Conduct and Enforcement Guidelines is open now. You can make suggestions for changes through 3 February 2025. This is the first step of several to be taken for the annual review. [[m:Special:MyLanguage/Universal_Code_of_Conduct/Annual_review|Read more information and find a conversation to join on the UCoC page on Meta]]. The [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] (U4C) is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review was planned and implemented by the U4C. For more information and the responsibilities of the U4C, [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Charter|you may review the U4C Charter]]. Please share this information with other members in your community wherever else might be appropriate. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 01:12, 24 Se Æfterra Gēola 2025 (UTC) </div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=27746256 --> == Reminder: first part of the annual UCoC review closes soon == <div lang="en" dir="ltr" class="mw-content-ltr"> My apologies for writing in English. {{Int:Please-translate}}. This is a reminder that the first phase of the annual review period for the Universal Code of Conduct and Enforcement Guidelines will be closing soon. You can make suggestions for changes through [[d:Q614092|the end of day]], 3 February 2025. This is the first step of several to be taken for the annual review. [[m:Special:MyLanguage/Universal_Code_of_Conduct/Annual_review|Read more information and find a conversation to join on the UCoC page on Meta]]. After review of the feedback, proposals for updated text will be published on Meta in March for another round of community review. Please share this information with other members in your community wherever else might be appropriate. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 00:49, 3 Solmonað 2025 (UTC) </div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28198931 --> == <span lang="en" dir="ltr"> Upcoming Language Community Meeting (Feb 28th, 14:00 UTC) and Newsletter</span> == <div lang="en" dir="ltr"> <section begin="message"/> Hello everyone! [[File:WP20Symbols WIKI INCUBATOR.svg|right|frameless|150x150px|alt=An image symbolising multiple languages]] We’re excited to announce that the next '''Language Community Meeting''' is happening soon, '''February 28th at 14:00 UTC'''! If you’d like to join, simply sign up on the '''[[mw:Wikimedia_Language_and_Product_Localization/Community_meetings#28_February_2025|wiki page]]'''. This is a participant-driven meeting where we share updates on language-related projects, discuss technical challenges in language wikis, and collaborate on solutions. In our last meeting, we covered topics like developing language keyboards, creating the Moore Wikipedia, and updates from the language support track at Wiki Indaba. '''Got a topic to share?''' Whether it’s a technical update from your project, a challenge you need help with, or a request for interpretation support, we’d love to hear from you! Feel free to '''reply to this message''' or add agenda items to the document '''[[etherpad:p/language-community-meeting-feb-2025|here]]'''. Also, we wanted to highlight that the sixth edition of the Language & Internationalization newsletter (January 2025) is available here: [[:mw:Special:MyLanguage/Wikimedia Language and Product Localization/Newsletter/2025/January|Wikimedia Language and Product Localization/Newsletter/2025/January]]. This newsletter provides updates from the October–December 2024 quarter on new feature development, improvements in various language-related technical projects and support efforts, details about community meetings, and ideas for contributing to projects. To stay updated, you can subscribe to the newsletter on its wiki page: [[:mw:Wikimedia Language and Product Localization/Newsletter|Wikimedia Language and Product Localization/Newsletter]]. We look forward to your ideas and participation at the language community meeting, see you there! <section end="message"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 08:30, 22 Solmonað 2025 (UTC) <!-- Message sent by User:SSethi (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28217779 --> == <span lang="en" dir="ltr">Migration to Parsoid</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Hello everyone! I am glad to inform you that as the next step in the [[mw:Special:MyLanguage/Parsoid/Parser Unification|Parser Unification]] project, Parsoid will soon be turned on as the default article renderer on your Wiktionary. We are gradually increasing the number of wikis using Parsoid, with the intention of making it the default wikitext parser for MediaWiki's next long-term support release. This will make our wikis more reliable and consistent for editors, readers, and tools to use, as well as making the development of future wikitext features easier. If this transition disrupts your workflow, don’t worry! You can still opt out through a user preference or turn Parsoid off on the current page using the Tools submenu, as described in the [[mw:Special:MyLanguage/Help:Extension:ParserMigration|Extension:ParserMigration]] documentation. There is [[mw:Special:MyLanguage/Parsoid/Parser_Unification/Confidence_Framework|more information about our roll-out strategy]] available, including the testing done before we turn on Parsoid for a new wiki. To report bugs and issues, please look at our [[mw:Special:MyLanguage/Parsoid/Parser Unification/Known Issues|known issues]] documentation and if you found a new bug please create a phab ticket and tag the [[phab:project/view/5846|Content Transform Team in Phabricator]]. <section end="announcement-content" /> </div> <section begin="signature"/> <em>[[m:Special:MyLanguage/Wikimedia Foundation/Product and Technology/Parsoid Read Views/Wiktionary Announcement|{{MediaWiki:Please-translate}}]]</em> <bdi lang="en" dir="ltr">[[mw:User:ABreault (WMF)|Content Transform Team]]</bdi> 00:24, 5 Hreðmonað 2025 (UTC) <section end="signature"/> <!-- Message sent by User:ABreault (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Wikimedia_Foundation/Product_and_Technology/Parsoid_Read_Views/2025-03-05_Wiktionaries&oldid=28340212 --> == Universal Code of Conduct annual review: proposed changes are available for comment == <div lang="en" dir="ltr" class="mw-content-ltr"> My apologies for writing in English. {{Int:Please-translate}}. I am writing to you to let you know that [[m:Special:MyLanguage/Universal_Code_of_Conduct/Annual_review/Proposed_Changes|proposed changes]] to the [[foundation:Special:MyLanguage/Policy:Universal_Code_of_Conduct/Enforcement_guidelines|Universal Code of Conduct (UCoC) Enforcement Guidelines]] and [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Charter|Universal Code of Conduct Coordinating Committee (U4C) Charter]] are open for review. '''[[m:Special:MyLanguage/Universal_Code_of_Conduct/Annual_review/Proposed_Changes|You can provide feedback on suggested changes]]''' through the [[d:Q614092|end of day]] on Tuesday, 18 March 2025. This is the second step in the annual review process, the final step will be community voting on the proposed changes. [[m:Special:MyLanguage/Universal_Code_of_Conduct/Annual_review|Read more information and find relevant links about the process on the UCoC annual review page on Meta]]. The [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] (U4C) is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review was planned and implemented by the U4C. For more information and the responsibilities of the U4C, [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Charter|you may review the U4C Charter]]. Please share this information with other members in your community wherever else might be appropriate. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] 18:52, 7 Hreðmonað 2025 (UTC) </div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28307738 --> == <span lang="en" dir="ltr">Your wiki will be in read-only soon</span> == <div lang="en" dir="ltr"> <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Read this message in another language]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] The [[foundation:|Wikimedia Foundation]] will switch the traffic between its data centers. This will make sure that Wikipedia and the other Wikimedia wikis can stay online even after a disaster. All traffic will switch on '''{{#time:j xg|2025-03-19|en}}'''. The switch will start at '''[https://zonestamp.toolforge.org/{{#time:U|2025-03-19T14:00|en}} {{#time:H:i e|2025-03-19T14:00}}]'''. Unfortunately, because of some limitations in [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], all editing must stop while the switch is made. We apologize for this disruption, and we are working to minimize it in the future. A banner will be displayed on all wikis 30 minutes before this operation happens. This banner will remain visible until the end of the operation. '''You will be able to read, but not edit, all wikis for a short period of time.''' *You will not be able to edit for up to an hour on {{#time:l j xg Y|2025-03-19|en}}. *If you try to edit or save during these times, you will see an error message. We hope that no edits will be lost during these minutes, but we can't guarantee it. If you see the error message, then please wait until everything is back to normal. Then you should be able to save your edit. But, we recommend that you make a copy of your changes first, just in case. ''Other effects'': *Background jobs will be slower and some may be dropped. Red links might not be updated as quickly as normal. If you create an article that is already linked somewhere else, the link will stay red longer than usual. Some long-running scripts will have to be stopped. * We expect the code deployments to happen as any other week. However, some case-by-case code freezes could punctually happen if the operation require them afterwards. * [[mw:Special:MyLanguage/GitLab|GitLab]] will be unavailable for about 90 minutes. This project may be postponed if necessary. You can [[wikitech:Switch_Datacenter|read the schedule at wikitech.wikimedia.org]]. Any changes will be announced in the schedule. '''Please share this information with your community.'''</div><section end="server-switch"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23:15, 14 Hreðmonað 2025 (UTC) <!-- Message sent by User:Quiddity (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=28307742 --> == Final proposed modifications to the Universal Code of Conduct Enforcement Guidelines and U4C Charter now posted == <div lang="en" dir="ltr" class="mw-content-ltr"> The proposed modifications to the [[foundation:Special:MyLanguage/Policy:Universal_Code_of_Conduct/Enforcement_guidelines|Universal Code of Conduct Enforcement Guidelines]] and the U4C Charter [[m:Universal_Code_of_Conduct/Annual_review/2025/Proposed_Changes|are now on Meta-wiki for community notice]] in advance of the voting period. This final draft was developed from the previous two rounds of community review. Community members will be able to vote on these modifications starting on 17 April 2025. The vote will close on 1 May 2025, and results will be announced no later than 12 May 2025. The U4C election period, starting with a call for candidates, will open immediately following the announcement of the review results. More information will be posted on [[m:Special:MyLanguage//Universal_Code_of_Conduct/Coordinating_Committee/Election|the wiki page for the election]] soon. Please be advised that this process will require more messages to be sent here over the next two months. The [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee (U4C)]] is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review was planned and implemented by the U4C. For more information and the responsibilities of the U4C, you may [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Charter|review the U4C Charter]]. Please share this message with members of your community so they can participate as well. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User_talk:Keegan (WMF)|talk]]) 02:05, 4 Eastermonað 2025 (UTC) </div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28469465 --> == Wikidata and Sister Projects: An online community event == ''(Apologies for posting in English)'' Hello everyone, I am excited to share news of an upcoming online event called '''[[d:Event:Wikidata_and_Sister_Projects|Wikidata and Sister Projects]]''' celebrating the different ways Wikidata can be used to support or enhance with another Wikimedia project. The event takes place over 4 days between '''May 29 - June 1st, 2025'''. We would like to invite speakers to present at this community event, to hear success stories, challenges, showcase tools or projects you may be working on, where Wikidata has been involved in Wikipedia, Commons, WikiSource and all other WM projects. If you are interested in attending, please [[d:Special:RegisterForEvent/1291|register here]]. If you would like to speak at the event, please fill out this Session Proposal template on the [[d:Event_talk:Wikidata_and_Sister_Projects|event talk page]], where you can also ask any questions you may have. I hope to see you at the event, in the audience or as a speaker, - [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 09:18, 11 Eastermonað 2025 (UTC) <!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_Send_List&oldid=28525705 --> == Vote now on the revised UCoC Enforcement Guidelines and U4C Charter == <div lang="en" dir="ltr" class="mw-content-ltr"> The voting period for the revisions to the Universal Code of Conduct Enforcement Guidelines ("UCoC EG") and the UCoC's Coordinating Committee Charter is open now through the end of 1 May (UTC) ([https://zonestamp.toolforge.org/1746162000 find in your time zone]). [[m:Special:MyLanguage/Universal_Code_of_Conduct/Annual_review/2025/Voter_information|Read the information on how to participate and read over the proposal before voting]] on the UCoC page on Meta-wiki. The [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee (U4C)]] is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review of the EG and Charter was planned and implemented by the U4C. Further information will be provided in the coming months about the review of the UCoC itself. For more information and the responsibilities of the U4C, you may [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Charter|review the U4C Charter]]. Please share this message with members of your community so they can participate as well. In cooperation with the U4C -- [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User_talk:Keegan (WMF)|talk]]) 00:35, 17 Eastermonað 2025 (UTC) </div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28469465 --> == <span lang="en" dir="ltr">Vote on proposed modifications to the UCoC Enforcement Guidelines and U4C Charter</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> The voting period for the revisions to the Universal Code of Conduct Enforcement Guidelines and U4C Charter closes on 1 May 2025 at 23:59 UTC ([https://zonestamp.toolforge.org/1746162000 find in your time zone]). [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2025/Voter information|Read the information on how to participate and read over the proposal before voting]] on the UCoC page on Meta-wiki. The [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Universal Code of Conduct Coordinating Committee (U4C)]] is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review was planned and implemented by the U4C. For more information and the responsibilities of the U4C, you may [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|review the U4C Charter]]. Please share this message with members of your community in your language, as appropriate, so they can participate as well. In cooperation with the U4C -- <section end="announcement-content" /> </div> <div lang="en" dir="ltr" class="mw-content-ltr"> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 03:42, 29 Eastermonað 2025 (UTC)</div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28618011 --> == We will be enabling the new Charts extension on your wiki soon! == ''(Apologies for posting in English)'' Hi all! We have good news to share regarding the ongoing problem with graphs and charts affecting all wikis that use them. As you probably know, the [[:mw:Special:MyLanguage/Extension:Graph|old Graph extension]] was disabled in 2023 [[listarchive:list/wikitech-l@lists.wikimedia.org/thread/EWL4AGBEZEDMNNFTM4FRD4MHOU3CVESO/|due to security reasons]]. We’ve worked in these two years to find a solution that could replace the old extension, and provide a safer and better solution to users who wanted to showcase graphs and charts in their articles. We therefore developed the [[:mw:Special:MyLanguage/Extension:Chart|Charts extension]], which will be replacing the old Graph extension and potentially also the [[:mw:Extension:EasyTimeline|EasyTimeline extension]]. After successfully deploying the extension on Italian, Swedish, and Hebrew Wikipedia, as well as on MediaWiki.org, as part of a pilot phase, we are now happy to announce that we are moving forward with the next phase of deployment, which will also include your wiki. The deployment will happen in batches, and will start from '''May 6'''. Please, consult [[:mw:Special:MyLanguage/Extension:Chart/Project#Deployment Timeline|our page on MediaWiki.org]] to discover when the new Charts extension will be deployed on your wiki. You can also [[:mw:Special:MyLanguage/Extension:Chart|consult the documentation]] about the extension on MediaWiki.org. If you have questions, need clarifications, or just want to express your opinion about it, please refer to the [[:mw:Special:MyLanguage/Extension_talk:Chart/Project|project’s talk page on Mediawiki.org]], or ping me directly under this thread. If you encounter issues using Charts once it gets enabled on your wiki, please report it on the [[:mw:Extension_talk:Chart/Project|talk page]] or at [[phab:tag/charts|Phabricator]]. Thank you in advance! -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 15:08, 6 Þrimilcemonað 2025 (UTC) <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=28663781 --> == <span lang="en" dir="ltr">Call for Candidates for the Universal Code of Conduct Coordinating Committee (U4C)</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> The results of voting on the Universal Code of Conduct Enforcement Guidelines and Universal Code of Conduct Coordinating Committee (U4C) Charter is [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2025#Results|available on Meta-wiki]]. You may now [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Election/2025/Candidates|submit your candidacy to serve on the U4C]] through 29 May 2025 at 12:00 UTC. Information about [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Election/2025|eligibility, process, and the timeline are on Meta-wiki]]. Voting on candidates will open on 1 June 2025 and run for two weeks, closing on 15 June 2025 at 12:00 UTC. If you have any questions, you can ask on [[m:Talk:Universal Code of Conduct/Coordinating Committee/Election/2025|the discussion page for the election]]. -- in cooperation with the U4C, </div><section end="announcement-content" /> </div> <bdi lang="en" dir="ltr">[[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User_talk:Keegan (WMF)|motung]])</bdi> 22:08, 15 Þrimilcemonað 2025 (UTC) <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28618011 --> == RfC ongoing regarding Abstract Wikipedia (and your project) == <div lang="en" dir="ltr" class="mw-content-ltr"> ''(Apologies for posting in English, if this is not your first language)'' Hello all! We opened a discussion on Meta about a very delicate issue for the development of [[:m:Special:MyLanguage/Abstract Wikipedia|Abstract Wikipedia]]: where to store the abstract content that will be developed through functions from Wikifunctions and data from Wikidata. Since some of the hypothesis involve your project, we wanted to hear your thoughts too. We want to make the decision process clear: we do not yet know which option we want to use, which is why we are consulting here. We will take the arguments from the Wikimedia communities into account, and we want to consult with the different communities and hear arguments that will help us with the decision. The decision will be made and communicated after the consultation period by the Foundation. You can read the various hypothesis and have your say at [[:m:Abstract Wikipedia/Location of Abstract Content|Abstract Wikipedia/Location of Abstract Content]]. Thank you in advance! -- [[User:Sannita (WMF)|Sannita (WMF)]] ([[User talk:Sannita (WMF)|<span class="signature-talk">{{int:Talkpagelinktext}}</span>]]) 15:27, 22 Þrimilcemonað 2025 (UTC) </div> <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=28768453 --> == <span lang="en" dir="ltr">Wikimedia Foundation Board of Trustees 2025 Selection & Call for Questions</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> :''[[m:Special:MyLanguage/Wikimedia Foundation elections/2025/Announcement/Selection announcement|{{int:interlanguage-link-mul}}]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-{{urlencode:Wikimedia Foundation elections/2025/Announcement/Selection announcement}}&language=&action=page&filter= {{int:please-translate}}]'' Dear all, This year, the term of 2 (two) Community- and Affiliate-selected Trustees on the Wikimedia Foundation Board of Trustees will come to an end [1]. The Board invites the whole movement to participate in this year’s selection process and vote to fill those seats. The Elections Committee will oversee this process with support from Foundation staff [2]. The Governance Committee, composed of trustees who are not candidates in the 2025 community-and-affiliate-selected trustee selection process (Raju Narisetti, Shani Evenstein Sigalov, Lorenzo Losa, Kathy Collins, Victoria Doronina and Esra’a Al Shafei) [3], is tasked with providing Board oversight for the 2025 trustee selection process and for keeping the Board informed. More details on the roles of the Elections Committee, Board, and staff are here [4]. Here are the key planned dates: * May 22 – June 5: Announcement (this communication) and call for questions period [6] * June 17 – July 1, 2025: Call for candidates * July 2025: If needed, affiliates vote to shortlist candidates if more than 10 apply [5] * August 2025: Campaign period * August – September 2025: Two-week community voting period * October – November 2025: Background check of selected candidates * Board’s Meeting in December 2025: New trustees seated Learn more about the 2025 selection process - including the detailed timeline, the candidacy process, the campaign rules, and the voter eligibility criteria - on this Meta-wiki page [[m:Special:MyLanguage/Wikimedia_Foundation_elections/2025|[link]]]. '''Call for Questions''' In each selection process, the community has the opportunity to submit questions for the Board of Trustees candidates to answer. The Election Committee selects questions from the list developed by the community for the candidates to answer. Candidates must answer all the required questions in the application in order to be eligible; otherwise their application will be disqualified. This year, the Election Committee will select 5 questions for the candidates to answer. The selected questions may be a combination of what’s been submitted from the community, if they’re alike or related. [[m:Special:MyLanguage/Wikimedia_Foundation_elections/2025/Questions_for_candidates|[link]]] '''Election Volunteers''' Another way to be involved with the 2025 selection process is to be an Election Volunteer. Election Volunteers are a bridge between the Elections Committee and their respective community. They help ensure their community is represented and mobilize them to vote. Learn more about the program and how to join on this Meta-wiki page [[m:Wikimedia_Foundation_elections/2025/Election_volunteers|[link].]] Thank you! [1] https://meta.wikimedia.org/wiki/Wikimedia_Foundation_elections/2022/Results [2] https://foundation.wikimedia.org/wiki/Committee:Elections_Committee_Charter [3] https://foundation.wikimedia.org/wiki/Resolution:Committee_Membership,_December_2024 [4] https://meta.wikimedia.org/wiki/Wikimedia_Foundation_elections_committee/Roles [5] https://meta.wikimedia.org/wiki/Wikimedia_Foundation_elections/2025/FAQ [6] https://meta.wikimedia.org/wiki/Wikimedia_Foundation_elections/2025/Questions_for_candidates Best regards, Victoria Doronina Board Liaison to the Elections Committee Governance Committee<section end="announcement-content" /> </div> [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 03:08, 28 Þrimilcemonað 2025 (UTC) <!-- Message sent by User:RamzyM (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28618011 --> == Vote now in the 2025 U4C Election == <div lang="en" dir="ltr" class="mw-content-ltr"> Apologies for writing in English. {{Int:Please-translate}} Eligible voters are asked to participate in the 2025 [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] election. More information–including an eligibility check, voting process information, candidate information, and a link to the vote–are available on Meta at the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2025|2025 Election information page]]. The vote closes on 17 June 2025 at [https://zonestamp.toolforge.org/1750161600 12:00 UTC]. Please vote if your account is eligible. Results will be available by 1 July 2025. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 23:01, 13 Sēremōnaþ 2025 (UTC) </div> <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28848819 --> == <span lang="en" dir="ltr">Wikimedia Foundation Board of Trustees 2025 - Call for Candidates</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> :''<div class="plainlinks">[[m:Special:MyLanguage/Wikimedia Foundation elections/2025/Announcement/Call for candidates|{{int:interlanguage-link-mul}}]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-{{urlencode:Wikimedia Foundation elections/2025/Announcement/Call for candidates}}&language=&action=page&filter= {{int:please-translate}}]</div> Hello all, The [[m:Special:MyLanguage/Wikimedia Foundation elections/2025|call for candidates for the 2025 Wikimedia Foundation Board of Trustees selection is now open]] from June 17, 2025 – July 2, 2025 at 11:59 UTC [1]. The Board of Trustees oversees the Wikimedia Foundation's work, and each Trustee serves a three-year term [2]. This is a volunteer position. This year, the Wikimedia community will vote in late August through September 2025 to fill two (2) seats on the Foundation Board. Could you – or someone you know – be a good fit to join the Wikimedia Foundation's Board of Trustees? [3] Learn more about what it takes to stand for these leadership positions and how to submit your candidacy on [[m:Special:MyLanguage/Wikimedia Foundation elections/2025/Candidate application|this Meta-wiki page]] or encourage someone else to run in this year's election. Best regards, Abhishek Suryawanshi<br /> Chair of the Elections Committee On behalf of the Elections Committee and Governance Committee [1] https://meta.wikimedia.org/wiki/Special:MyLanguage/Wikimedia_Foundation_elections/2025/Call_for_candidates [2] https://foundation.wikimedia.org/wiki/Legal:Bylaws#(B)_Term. [3] https://meta.wikimedia.org/wiki/Special:MyLanguage/Wikimedia_Foundation_elections/2025/Resources_for_candidates<section end="announcement-content" /> </div> [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 17:44, 17 Sēremōnaþ 2025 (UTC) <!-- Message sent by User:RamzyM (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=28866958 --> == <span lang="en" dir="ltr">Sister Projects Task Force reviews Wikispore and Wikinews</span> == <div lang="en" dir="ltr"> <section begin="message"/> Dear Wikimedia Community, The [[m:Wikimedia Foundation Community Affairs Committee|Community Affairs Committee (CAC)]] of the Wikimedia Foundation Board of Trustees assigned [[m:Wikimedia Foundation Community Affairs Committee/Sister Projects Task Force|the Sister Projects Task Force (SPTF)]] to update and implement a procedure for assessing the lifecycle of Sister Projects – wiki [[m:Wikimedia projects|projects supported by Wikimedia Foundation (WMF)]]. A vision of relevant, accessible, and impactful free knowledge has always guided the Wikimedia Movement. As the ecosystem of Wikimedia projects continues to evolve, it is crucial that we periodically review existing projects to ensure they still align with our goals and community capacity. Despite their noble intent, some projects may no longer effectively serve their original purpose. '''Reviewing such projects is not about giving up – it's about responsible stewardship of shared resources'''. Volunteer time, staff support, infrastructure, and community attention are finite, and the non-technical costs tend to grow significantly as our ecosystem has entered a different age of the internet than the one we were founded in. Supporting inactive projects or projects that didn't meet our ambitions can unintentionally divert these resources from areas with more potential impact. Moreover, maintaining projects that no longer reflect the quality and reliability of the Wikimedia name stands for, involves a reputational risk. An abandoned or less reliable project affects trust in the Wikimedia movement. Lastly, '''failing to sunset or reimagine projects that are no longer working can make it much harder to start new ones'''. When the community feels bound to every past decision – no matter how outdated – we risk stagnation. A healthy ecosystem must allow for evolution, adaptation, and, when necessary, letting go. If we create the expectation that every project must exist indefinitely, we limit our ability to experiment and innovate. Because of this, SPTF reviewed two requests concerning the lifecycle of the Sister Projects to work through and demonstrate the review process. We chose Wikispore as a case study for a possible new Sister Project opening and Wikinews as a case study for a review of an existing project. Preliminary findings were discussed with the CAC, and a community consultation on both proposals was recommended. === Wikispore === The [[m:Wikispore|application to consider Wikispore]] was submitted in 2019. SPTF decided to review this request in more depth because rather than being concentrated on a specific topic, as most of the proposals for the new Sister Projects are, Wikispore has the potential to nurture multiple start-up Sister Projects. After careful consideration, the SPTF has decided '''not to recommend''' Wikispore as a Wikimedia Sister Project. Considering the current activity level, the current arrangement allows '''better flexibility''' and experimentation while WMF provides core infrastructural support. We acknowledge the initiative's potential and seek community input on what would constitute a sufficient level of activity and engagement to reconsider its status in the future. As part of the process, we shared the decision with the Wikispore community and invited one of its leaders, Pharos, to an SPTF meeting. Currently, we especially invite feedback on measurable criteria indicating the project's readiness, such as contributor numbers, content volume, and sustained community support. This would clarify the criteria sufficient for opening a new Sister Project, including possible future Wikispore re-application. However, the numbers will always be a guide because any number can be gamed. === Wikinews === We chose to review Wikinews among existing Sister Projects because it is the one for which we have observed the highest level of concern in multiple ways. Since the SPTF was convened in 2023, its members have asked for the community's opinions during conferences and community calls about Sister Projects that did not fulfil their promise in the Wikimedia movement.[https://commons.wikimedia.org/wiki/File:WCNA_2024._Sister_Projects_-_opening%3F_closing%3F_merging%3F_splitting%3F.pdf <nowiki>[1]</nowiki>][https://meta.wikimedia.org/wiki/Wikimedia_Foundation_Community_Affairs_Committee/Sister_Projects_Task_Force#Wikimania_2023_session_%22Sister_Projects:_past,_present_and_the_glorious_future%22 <nowiki>[2]</nowiki>][https://meta.wikimedia.org/wiki/WikiConvention_francophone/2024/Programme/Quelle_proc%C3%A9dure_pour_ouvrir_ou_fermer_un_projet_%3F <nowiki>[3]</nowiki>] Wikinews was the leading candidate for an evaluation because people from multiple language communities proposed it. Additionally, by most measures, it is the least active Sister Project, with the greatest drop in activity over the years. While the Language Committee routinely opens and closes language versions of the Sister Projects in small languages, there has never been a valid proposal to close Wikipedia in major languages or any project in English. This is not true for Wikinews, where there was a proposal to close English Wikinews, which gained some traction but did not result in any action[https://meta.wikimedia.org/wiki/Proposals_for_closing_projects/Closure_of_English_Wikinews <nowiki>[4]</nowiki>][https://meta.wikimedia.org/wiki/WikiConvention_francophone/2024/Programme/Quelle_proc%C3%A9dure_pour_ouvrir_ou_fermer_un_projet_%3F <nowiki>[5]</nowiki>, see section 5] as well as a draft proposal to close all languages of Wikinews[https://meta.wikimedia.org/wiki/Talk:Proposals_for_closing_projects/Archive_2#Close_Wikinews_completely,_all_languages? <nowiki>[6]</nowiki>]. [[:c:File:Sister Projects Taskforce Wikinews review 2024.pdf|Initial metrics]] compiled by WMF staff also support the community's concerns about Wikinews. Based on this report, SPTF recommends a community reevaluation of Wikinews. We conclude that its current structure and activity levels are the lowest among the existing sister projects. SPTF also recommends pausing the opening of new language editions while the consultation runs. SPTF brings this analysis to a discussion and welcomes discussions of alternative outcomes, including potential restructuring efforts or integration with other Wikimedia initiatives. '''Options''' mentioned so far (which might be applied to just low-activity languages or all languages) include but are not limited to: *Restructure how Wikinews works and is linked to other current events efforts on the projects, *Merge the content of Wikinews into the relevant language Wikipedias, possibly in a new namespace, *Merge content into compatibly licensed external projects, *Archive Wikinews projects. Your insights and perspectives are invaluable in shaping the future of these projects. We encourage all interested community members to share their thoughts on the relevant discussion pages or through other designated feedback channels. === Feedback and next steps === We'd be grateful if you want to take part in a conversation on the future of these projects and the review process. We are setting up two different project pages: [[m:Public consultation about Wikispore|Public consultation about Wikispore]] and [[m:Public consultation about Wikinews|Public consultation about Wikinews]]. Please participate between 27 June 2025 and 27 July 2025, after which we will summarize the discussion to move forward. You can write in your own language. I will also host a community conversation 16th July Wednesday 11.00 UTC and 17th July Thursday 17.00 UTC (call links to follow shortly) and will be around at Wikimania for more discussions. <section end="message"/> </div> -- [[User:Victoria|Victoria]] on behalf of the Sister Project Task Force, 20:57, 27 Sēremōnaþ 2025 (UTC) <!-- Message sent by User:Johan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Johan_(WMF)/Sister_project_MassMassage_on_behalf_of_Victoria/Target_list&oldid=28911188 --> == Wikidata Item and Property labels soon displayed in Wiki Watchlist/Recent Changes == ''(Apologies for posting in English, you can help by translating into your language)'' Hello everyone, the [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Resolve_Labels|Wikidata For Wikimedia Projects]] team is excited to announce an upcoming change in how Wikidata edit changelogs are displayed in your [[Special:Watchlist|Watchlists]] and [[Special:RecentChanges|Recent Changes]] lists. If an edit is made on Wikidata that affects a page in another Wikimedia Project, the changelog will contain some information about the nature of the edit. This can include a QID (or Q-number), a PID (or P-number) and a value (which can be text, numbers, dates, or also QID or PID’s). Confused by these terms? See the [[d:Special:MyLanguage/Wikidata:Glossary|Wikidata:Glossary]] for further explanations. The upcoming change is scheduled for '''17.07.2025''', between '''1300 - 1500 UTC'''. The change will display the label (item name) alongside any QID or PIDs, as seen in the image below: [[File:Apr10 edit summary on Wikidata.png|An edit sum entry on Wikidata, labels display alongside their P- and Q-no.'s]] These changes will only be visible if you have Wikidata edits enabled in your User Preferences for Watchlists and Recent Changes, or have the active filter ‘Wikidata edits’ checkbox toggled on, directly on the Watchlist and Recent Changes pages. Your bot and gadget may be affected! There are thousands of bots, gadgets and user-scripts and whilst we have researched potential effects to many of them, we cannot guarantee there won’t be some that are broken or affected by this change. Further information and context about this change, including how your bot may be affected can be found on this [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Resolve_Labels|project task page]]. We welcome your questions and feedback, please write to us on this dedicated [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Resolve_Labels|Talk page]]. Thank you, - [[m:User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] on behalf of the Wikidata For Wikimedia Projects Team. [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 12:46, 14 Æfterra Liða 2025 (UTC) <!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_Test_List&oldid=28981877 --> == Wikifunctions will be deployed on your wiki on August 27 == <div lang="en" dir="ltr" class="mw-content-ltr"> ''Please, translate this message into your language.'' Hi all, we want to let you know that [[:f:|Wikifunctions]] is coming to your project soon! When enabled, you will be able to call functions from your project, and integrate them in your articles. A function is something that takes one or more inputs and transforms them into a desired output. Think of adding up two numbers, or converting miles into metres, or calculating how much time has passed since an event, or declining a word into a case. This is usually done with templates that are complicated to create or to import. With Wikifunctions, you will be able to do this with just a couple of clicks! Please check out [[:f:Wikifunctions:Introduction|these tutorials]] for more details. You’re also invited to [[:f:Special:CreateObject|create functions]] that you find useful, or [[:f:Wikifunctions:Suggest a function|ask for help from the Wikifunctions community]]. We would like to invite you to contribute to Wikifunctions, by translating the existing functions labels into your language, so that more users in your community can more easily reuse them on the project. You can also translate the messages for the Wikifunctions interface on TranslateWiki ([https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-wikilambda-ve&filter=%21translated&action=translate here for VisualEditor messages], and [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-wikilambda-user&filter=%21translated&action=translate here for the Wikifunctions interface proper]). Of course, we are happy to help in case there are questions or difficulties, and we are ready to listen to your feedback. Please ping me directly in case of necessity or reach out to me [[User talk:Sannita (WMF)|on my talk page]]. -- [[User:Sannita (WMF)|Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 13:25, 13 Weodmonað 2025 (UTC) </div> <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=29116867 --> == <span lang="en" dir="ltr">Temporary accounts will be rolled out soon</span> == <div lang="en" dir="ltr"> <section begin="body"/> Hello, we are the Wikimedia Foundation [[mw:Special:MyLanguage/Product Safety and Integrity|Product Safety and Integrity]] team. We would like to announce that '''we plan to enable [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts|temporary accounts]] for this wiki in the week of September 1'''. Temporary accounts are successfully live on 30 wikis, including many large ones like German, Japanese, and French. The change they bring is especially relevant to logged-out editors, who this feature is designed to protect. But it is also relevant to community members like mentors, patrollers, and admins – anyone who reverts edits, blocks users, or otherwise interacts with logged-out editors as part of keeping the wikis safe and accurate. '''Why we are building temporary accounts''' Our wikis should be safer to edit by default for logged-out editors. Temporary accounts allow people to continue editing the wikis without creating an account, while avoiding publicly tying their edits to their IP address. We believe this is in the best interest of our logged-out editors, who make valuable contributions to the wikis and who may later create accounts and grow our community of editors, admins, and other roles. Even though the wikis do warn logged-out editors that their IP address will be associated with their edit, many people may not understand what an IP address is, or that it could be used to connect them to other information about them in ways they might not expect. Additionally, our moderation software and tools rely too heavily on network origin (IP addresses) to identify users and patterns of activity, especially as IP addresses themselves are becoming less stable as identifiers. Temporary accounts allow for more precise interactions with logged-out editors, including more precise blocks, and can help limit how often we unintentionally end up blocking good-faith users who use the same IP addresses as bad-faith users. '''How temporary accounts work''' [[File:Temporary account banner and empty talk page.png|thumb]] Any time a logged-out user publishes an edit on this wiki, a cookie will be set in this user's browser, and a temporary account tied with this cookie will be automatically created. This account's name will follow the pattern: <code dir=ltr>~2025-12345-67</code> (a tilde, current year, a number). On pages like Recent Changes or page history, this name will be displayed. The cookie will expire 90 days after its creation. As long as it exists, all edits made from this device will be attributed to this temporary account. It will be the same account even if the IP address changes, unless the user clears their cookies or uses a different device or web browser. A record of the IP address used at the time of each edit will be stored for 90 days after the edit. However, only some logged-in users will be able to see it. '''What does this mean for different groups of users?''' '''For logged-out editors''' * This increases privacy: currently, if you do not use a registered account to edit, then everybody can see the IP address for the edits you made, even after 90 days. That will no longer be possible on this wiki. * If you use a temporary account to edit from different locations in the last 90 days (for example at home and at a coffee shop), the edit history and the IP addresses for all those locations will now be recorded together, for the same temporary account. Users who [[foundation:Special:MyLanguage/Policy:Access_to_temporary_account_IP_addresses|meet the relevant requirements]] will be able to view this data. If this creates any personal security concerns for you, please contact talktohumanrights at wikimedia.org for advice. '''For community members interacting with logged-out editors''' * A temporary account is uniquely linked to a device. In comparison, an IP address can be shared with different devices and people (for example, different people at school or at work might have the same IP address). * Compared to the current situation, it will be safer to assume that a temporary user's talk page belongs to only one person, and messages left there will be read by them. As you can see in the screenshot, temporary account users will receive notifications. It will also be possible to thank them for their edits, ping them in discussions, and invite them to get more involved in the community. '''For users who use IP address data to moderate and maintain the wiki''' * '''For patrollers''' who track persistent abusers, investigate violations of policies, etc.: Users who [[foundation:Special:MyLanguage/Policy:Access_to_temporary_account_IP_addresses|meet the requirements]] will be able to reveal temporary users' IP addresses and all contributions made by temporary accounts from a specific IP address or range ([[Special:IPContributions]]). They will also have access to useful information about the IP addresses thanks to the [[mw:Special:MyLanguage/Trust and Safety Product/IP Info|IP Info]] feature. Many other pieces of software have been built or adjusted to work with temporary accounts, including AbuseFilter, global blocks, Global User Contributions, and more. (For information for volunteer developers on how to update the code of your tools – see the last part of the message.) * '''For admins blocking logged-out editors''': ** It will be possible to block many abusers by just blocking their temporary accounts. A blocked person won't be able to create new temporary accounts quickly if the admin selects the [[mw:Special:MyLanguage/Autoblock|autoblock]] option. ** It will still be possible to block an IP address or IP range. * Temporary accounts will not be retroactively applied to contributions made before the deployment. On Special:Contributions, you will be able to see existing IP user contributions, but not new contributions made by temporary accounts on that IP address. Instead, you should use Special:IPContributions for this. '''Our requests for you, and next steps''' * If you know of any tools, bots, gadgets etc. using data about IP addresses or being available for logged-out users, you may want to test if they work on [[testwiki:Main_Page|testwiki]] or [[test2wiki:Main_Page|test2wiki]]. If you are a volunteer developer, [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts/For developers|read our documentation for developers]], and in particular, the section on [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts/For developers#How should I update my code?|how your code might need to be updated]]. * If you want to test the temporary account experience, for example just to check what it feels like, go to testwiki or test2wiki and edit without logging in. * Tell us if you know of any difficulties that need to be addressed. We will try to help, and if we are not able, we will consider the available options. * Look at our [[m:Meta:Babel#Temporary_Accounts:_access_to_IP_addresses_and_next_steps|previous message]] about requirements for users without extended rights who may need access to IP addresses. To learn more about the project, check out [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts/FAQ|our FAQ]] – you will find many useful answers there. You may also [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts/Updates|look at the updates]] (we have just posted one) and [[mw:Newsletter:Product Safety and Integrity|subscribe to our new newsletter]]. If you'd like to talk to me (Szymon) off-wiki, you will find me on Discord and Telegram. Thank you!<section end="body" /> </div> <bdi lang="en" dir="ltr">[[m:user:NKohli (WMF)|NKohli (WMF)]], [[m:user:SGrabarczuk (WMF)|SGrabarczuk (WMF)]]</bdi> 21:37, 26 Weodmonað 2025 (UTC) <!-- Message sent by User:Quiddity (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Quiddity_(WMF)/sandbox6&oldid=29181713 --> == <span lang="en" dir="ltr">Server switch - Your wiki will be read-only for a short time soon</span> == <div lang="en" dir="ltr"> <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Read this message in another language]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] The [[foundation:|Wikimedia Foundation]] will switch the traffic between its data centers. This will make sure that Wikipedia and the other Wikimedia wikis can stay online even after a disaster. All traffic will switch on '''{{#time:j xg|2025-09-24|en}}'''. The switch will start at '''[https://zonestamp.toolforge.org/{{#time:U|2025-09-24T15:00|en}} {{#time:H:i e|2025-09-24T15:00}}]'''. Unfortunately, because of some limitations in [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], all editing must stop while the switch is made. We apologize for this disruption, and we are working to minimize it in the future. A banner will be displayed on all wikis 30 minutes before this operation happens. This banner will remain visible until the end of the operation. You can contribute to the [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate translation or proofreading] of this banner text. '''You will be able to read, but not edit, all wikis for a short period of time.''' *You will not be able to edit for up to an hour on {{#time:l j xg Y|2025-09-24|en}}. *If you try to edit or save during these times, you will see an error message. We hope that no edits will be lost during these minutes, but we can't guarantee it. If you see the error message, then please wait until everything is back to normal. Then you should be able to save your edit. But, we recommend that you make a copy of your changes first, just in case. ''Other effects'': *Background jobs will be slower and some may be dropped. Red links might not be updated as quickly as normal. If you create an article that is already linked somewhere else, the link will stay red longer than usual. Some long-running scripts will have to be stopped. * We expect the code deployments to happen as any other week. However, some case-by-case code freezes could punctually happen if the operation require them afterwards. * [[mw:Special:MyLanguage/GitLab|GitLab]] will be unavailable for about 90 minutes. This project may be postponed if necessary. You can [[wikitech:Switch_Datacenter|read the schedule at wikitech.wikimedia.org]]. Any changes will be announced in the schedule. '''Please share this information with your community.'''</div><section end="server-switch"/> </div> <span dir=ltr>[[m:User:Trizek (WMF)|Trizek (WMF)]] ([[m:User talk:Trizek (WMF)|{{int:talk}}]])</span> 15:42, 18 Haligmonað 2025 (UTC) <!-- Message sent by User:Trizek (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29170715 --> == <span lang="en" dir="ltr">Have your say: vote for the 2025 Board of Trustees</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Hello all, The voting period for the [[m:Special:MyLanguage/Wikimedia Foundation elections/2025|2025 Board of Trustees election]] is now open. Candidates are running for two (2) seats on the Board. To check your voter eligibility, please visit the [[m:Special:MyLanguage/Wikimedia Foundation elections/2025/Voter eligibility guidelines|voter eligibility page]]. Learn more about them by [[m:Special:MyLanguage/Wikimedia Foundation elections/2025/Candidates|reading their application statements and watch their candidacy videos]]. When you are ready, go to the [[m:Special:SecurePoll/vote/405|SecurePoll voting page to vote]]. '''The vote is open from October 8 at 00:00 UTC to October 22 at 23:59 UTC.''' Best regards, Abhishek Suryawanshi<br />Chair, Elections Committee<section end="announcement-content" /> </div> [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 04:49, 9 Winterfylleð 2025 (UTC) <!-- Message sent by User:RamzyM (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29360896 --> == <span lang="en" dir="ltr">Help us decide the name of the new Abstract Wikipedia project</span> == <div lang="en" dir="ltr"> <section begin="function1"/> {{int:Hello}}. Please help pick a name for the new Abstract Wikipedia wiki project. This project will be a wiki that will enable users to combine functions from [[:f:|Wikifunctions]] and data from Wikidata in order to generate natural language sentences in any supported languages. These sentences can then be used by any Wikipedia (or elsewhere). There will be two rounds of voting, each followed by legal review of candidates, with votes beginning on 20 October and 17 November 2025. Our goal is to have a final project name selected on mid-December 2025. If you would like to participate, then '''[[m:Special:MyLanguage/Abstract Wikipedia/Abstract Wikipedia naming contest|please learn more and vote now]]''' at meta-wiki. {{Int:Feedback-thanks-title}} <section end="function1"/> </div> -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 11:44, 20 Winterfylleð 2025 (UTC) <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29432175 --> == <span lang="en" dir="ltr">Seeking volunteers to join several of the movement’s committees</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Each year, typically from October through December, several of the movement’s committees seek new volunteers. Read more about the committees on their Meta-wiki pages: * [[m:Special:MyLanguage/Affiliations Committee|Affiliations Committee (AffCom)]] * [[m:Special:MyLanguage/Ombuds commission|Ombuds commission (OC)]] * [[m:Special:MyLanguage/Wikimedia Foundation/Legal/Community Resilience and Sustainability/Trust and Safety/Case Review Committee|Case Review Committee (CRC)]] Applications for the committees open on October 30, 2025. Applications for the Affiliations Committee, Ombuds commission and the Case Review Committee close on December 11, 2025. Learn how to apply by [[m:Special:MyLanguage/Wikimedia Foundation/Legal/Committee appointments|visiting the appointment page on Meta-wiki]]. Post to the talk page or email cst[[File:At sign.svg|16x16px|link=|(_AT_)]]wikimedia.org with any questions you may have. For the Committee Support team, <section end="announcement-content" /> </div> -[[m:User:MKaur (WMF)| MKaur (WMF)]] 14:13, 30 Winterfylleð 2025 (UTC) <!-- Message sent by User:MKaur (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29517125 --> == <span lang="en" dir="ltr">Reminder: Help us decide the name of the new Abstract Wikipedia project</span> == <div lang="en" dir="ltr"> <section begin="function2"/> {{int:Hello}}. Reminder: Please help to choose name for the new Abstract Wikipedia wiki project. The finalist vote starts today. The finalists for the name are: <span lang="en" dir="ltr" class="mw-content-ltr">Abstract Wikipedia, Multilingual Wikipedia, Wikiabstracts, Wikigenerator, Proto-Wiki</span>. If you would like to participate, then '''[[m:Special:MyLanguage/Abstract Wikipedia/Abstract Wikipedia naming contest|please learn more and vote now]]''' at meta-wiki. {{Int:Feedback-thanks-title}} <section end="function2"/> </div> -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 14:23, 20 Blotmonað 2025 (UTC) <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29583860 --> == Thank You for Last Year – Join Wiki Loves Ramadan 2026 == Dear Wikimedia communities, We hope you are doing well, and we wish you a happy New Year. ''Last year, we captured light. This year, we’ll capture legacy.'' In 2025, communities around the world shared the glow of Ramadan nights and the warmth of collective iftars. In 2026, ''Wiki Loves Ramadan'' is expanding, bringing more stories, more cultures, and deeper global connections across Wikimedia projects. We invite you to explore the ''Wiki Loves Ramadan 2026'' [[m:Special:MyLanguage/Wiki Loves Ramadan 2026|Meta page]] to learn how you can participate and [[m:Special:MyLanguage/Wiki Loves Ramadan 2026/Participating communities|sign up]] your community. 📷 ''Photo campaign on '' [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan 2026|Wikimedia Commons]] If you have questions about the project, please refer to the FAQs: * [[m:Special:MyLanguage/Wiki Loves Ramadan/FAQ/|Meta-Wiki]] * [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan/FAQ|Wikimedia Commons]] ''Early registration for updates is now open via the '''[[m:Special:RegisterForEvent/2710|Event page]]''''' ''Stay connected and receive updates:'' * [https://t.me/WikiLovesRamadan Telegram channel] * [https://lists.wikimedia.org/postorius/lists/wikilovesramadan.lists.wikimedia.org/ Mailing list] We look forward to collaborating with you and your community. '''The Wiki Loves Ramadan 2026 Organizing Team''' 19:45, 16 Se Æfterra Gēola 2026 (UTC) <!-- Message sent by User:ZI Jony@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29879549 --> == <span lang="en" dir="ltr">Annual review of the Universal Code of Conduct and Enforcement Guidelines</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> I am writing to you to let you know the annual review period for the Universal Code of Conduct and Enforcement Guidelines is open now. You can make suggestions for changes through 9 February 2026. This is the first step of several to be taken for the annual review. [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2026|Read more information and find a conversation to join on the UCoC page on Meta]]. The [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Universal Code of Conduct Coordinating Committee]] (U4C) is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review was planned and implemented by the U4C. For more information and the responsibilities of the U4C, [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|you may review the U4C Charter]]. Please share this information with other members in your community wherever else might be appropriate. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]])<section end="announcement-content" /> </div> 21:02, 19 Se Æfterra Gēola 2026 (UTC) <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == Action Required: Update templates/modules for electoral maps (Migrating from P1846 to P14226) == Hello everyone, This is a notice regarding an ongoing data migration on Wikidata that may affect your election-related templates and Lua modules (such as <code>Module:Itemgroup/list</code>). '''The Change:'''<br /> Currently, many templates pull electoral maps from Wikidata using the property [[:d:Property:P1846|P1846]], combined with the qualifier [[:d:Property:P180|P180]]: [[:d:Q19571328|Q19571328]]. We are migrating this data (across roughly 4,000 items) to a newly created, dedicated property: '''[[:d:Property:P14226|P14226]]'''. '''What You Need To Do:'''<br /> To ensure your templates and infoboxes do not break or lose their maps, please update your local code to fetch data from [[:d:Property:P14226|P14226]] instead of the old [[:d:Property:P1846|P1846]] + [[:d:Property:P180|P180]] structure. A [[m:Wikidata/Property Migration: P1846 to P14226/List|list of pages]] was generated using Wikimedia Global Search. '''Deadline:'''<br /> We are temporarily retaining the old data on [[:d:Property:P1846|P1846]] to allow for a smooth transition. However, to complete the data cleanup on Wikidata, the old [[:d:Property:P1846|P1846]] statements will be removed after '''May 1, 2026'''. Please update your modules and templates before this date to prevent any disruption to your wiki's election articles. Let us know if you have any questions or need assistance with the query logic. Thank you for your help! [[User:ZI Jony|ZI Jony]] using [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 17:11, 3 Eastermonað 2026 (UTC) <!-- Message sent by User:ZI Jony@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29941252 --> == Request for comment (global AI policy) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies for writing in English. {{int:Please-translate}} A [[:m:Requests for comment/Artificial intelligence policy|request for comment]] is currently being held to decide on a global AI policy. {{int:Feedback-thanks-title}} [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 00:58, 26 Eastermonað 2026 (UTC) </bdi> <!-- Message sent by User:Codename Noreste@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30424282 --> == <span lang="en" dir="ltr">Vote now in the 2026 U4C election</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Eligible voters are asked to participate in the 2026 [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] election. More information–including an eligibility check, voting process information, candidate information, and a link to the vote–are available on Meta at the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|2026 Election information page]]. The vote closes on 2 June 2026 at [https://zonestamp.toolforge.org/1780358400 00:00 UTC]. Please vote if your account is eligible. Results will be available by 14 June 2026. -- In cooperation with the U4C,<section end="announcement-content" /> </div> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 17:15, 27 Þrimilcemonað 2026 (UTC) <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == RFC about AI-generated content in Wikimedia Commons == <bdi lang="en" dir="ltr">Apologies for writing in English, please help translate this message to your language. You are invited to participate in a [[c:Commons:Requests for comment/Policy update for AI content|request for comment on Wikimedia Commons about a policy update for AI content]]. This may affect files that are uploaded to Wikimedia Commons for use on this project. Thank you. [[m:User:Codename Noreste|Codename Noreste]] ([[m:User talk:Codename Noreste|motung]])</bdi> 17:12, 23 Sēremōnaþ 2026 (UTC) <!-- Message sent by User:Codename Noreste@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == <span lang="en" dir="ltr">Deployment of Legal and Safety Contacts Link in the Footer of Your Wiki</span> == <div lang="en" dir="ltr"> <section begin="Message"/> '''Legal & Safety Contacts''' Hello community, the Wikimedia Foundation has provided a [[wmf:Special:MyLanguage/Legal:Wikimedia Foundation Legal and Safety Contact Information|single legal and safety contact page]], to be linked in the footer of your wiki, to ensure access to accurate legal information. This is a regulatory requirement. We have already rolled out links to English, German, Italian, Spanish and other wikis and we will deploy to your wiki soon. [[m:Special:MyLanguage/Wikimedia_Foundation_Legal_and_Safety_Contacts_FAQ|Please read more on the project page]] and leave any comments in this thread or on the [[m:Special:MyLanguage/Talk:Wikimedia Foundation Legal and Safety Contacts FAQ|talk page]]. <section end="Message"/> </div> -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 13:31, 25 Sēremōnaþ 2026 (UTC) <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=30731267 --> == Request for comment (the future of Abstract Wikipedia) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies if this has not yet been translated into your wiki's language. {{int:Please-translate}} You are invited to voice your opinions in a [[:m:Requests for comment/The future of Abstract Wikipedia|request for comment about the future of Abstract Wikipedia]]. {{Int:Feedback-thanks-title}} [[:m:User:Kowal2701|Kowal2701]] ([[:m:User talk:Kowal2701|talk]]) 12:25, 24 Mædmonað 2026 (UTC) </bdi> <!-- Message sent by User:DreamRimmer@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == <span lang="en" dir="ltr">Server switch - Your wiki will be read-only for a short time soon</span> == <div lang="en" dir="ltr"> <section begin="server-switch"/><div class="plainlinks"> [[:m:Special:MyLanguage/Tech/Server switch|Read this message in another language]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}] The [[foundation:|Wikimedia Foundation]] will switch the traffic between its data centers. This will make sure that Wikipedia and the other Wikimedia wikis can stay online even after a disaster. All traffic will switch on '''{{#time:j xg|2026-09-23|en}}'''. The switch will start at '''[https://zonestamp.toolforge.org/{{#time:U|2026-09-23T14:00|en}} {{#time:H:i e|2026-09-23T14:00}}]'''. Unfortunately, because of some limitations in [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], all editing must stop while the switch is made. We apologize for this disruption, and we are working to minimize it in the future. A banner will be displayed on all wikis 30 minutes before this operation happens. This banner will remain visible until the end of the operation. You can contribute to the [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate translation or proofreading] of this banner text. '''You will be able to read, but not edit, all wikis for a short period of time.''' * You will not be able to edit for up to an hour on {{#time:l j xg Y|2026-09-23|en}}. * If you try to edit or save during these times, you will see an error message. We hope that no edits will be lost during these minutes, but we can't guarantee it. If you see the error message, then please wait until everything is back to normal. Then you should be able to save your edit. But, we recommend that you make a copy of your changes first, just in case. ''Other effects'': * Background jobs will be slower and some may be dropped. Red links might not be updated as quickly as normal. If you create an article that is already linked somewhere else, the link will stay red longer than usual. Some long-running scripts will have to be stopped. * We expect the code deployments to happen as any other week. However, some case-by-case code freezes could punctually happen if the operation require them afterwards. * [[mw:Special:MyLanguage/GitLab|GitLab]] will be unavailable for about 90 minutes. This project may be postponed if necessary. You can [[wikitech:Switch_Datacenter|read the schedule at wikitech.wikimedia.org]]. Any changes will be announced in the schedule. '''Please share this information with your community.'''</div><section end="server-switch"/> </div> [[m:user:Trizek (WMF)|Trizek (WMF)]] 12:58, 15 Haligmonað 2026 (UTC) <!-- Message sent by User:Trizek (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=30513874 --> == Your feedback wanted: Remove ''(Language link added:) and similar'' edits from Special:RecentChanges == ''(Apologies for posting in English. You can help by translating it)'' Hello, I’m Danny from [[:en:w:Wikimedia_Deutschland|Wikimedia Deutschland’s]] [[m:Wikidata_For_Wikimedia_Projects|Wikidata For Wikimedia Projects]] team.<br/> We have been investigating and examining how Wikidata’s use in the [[Special:RecentChanges]] and [[Special:Watchlist]] pages can be made to be more useful, or less ‘noisy’ (fewer edits that have little value to the reader). We are currently exploring to make a change in the volume and the type of Wikidata edits that appear in these pages, and '''we need your feedback''' to help us ensure this is a positive change for the Wikis and won’t disrupt your workflows.<br/> Language links are also known as sitelinks or interlanguage links and describe when a Wikidata item is connected to a Wiki, adding it to the language dropdown tool for other connected Wikis. [[File:Types of Lang Link changes.png|x350px|frame|A variety of "Language Link" edits as seen in the Recent Changes feed]] The request for feedback is whether you support the removal of these language link edits from the Recent Changes and Watchlist feed, or would you oppose such a change and if so, why? Please share you thoughts on the dedicated '''[[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|metawiki Talk page]]'''. Further information about this change: [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|m:Wikidata_For_Wikimedia_Projects/Hide_Language_Link_edits]] Thank you for any participation or feedback you give, -- [[m:User:Danny_Benjafield_(WMDE)|User:Danny Benjafield (WMDE)]] 12:48, 25 Haligmonað 2026 (UTC) <!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31081007 --> == Wikidata Sitelink changes in Recent Changes and Watchlist == ''(Apologies for cross-posting in English, translating it will help spread the message)'' Editors on group 1 wikis, including Wikiquote, Wikibooks, Wikiversity, Wikivoyage, and Wikisource, will no longer see notifications on [[Special:RecentChanges|Recent Changes]] and [[Special:Watchlist|Watchlist]] when a link to ''another'' language version of a page is added, removed, or changed in its Wikidata item. This change will begin on '''October 5 at 07:00 UTC''' as a two-week trial to reduce high-volume, low-value notifications and make higher-value changes easier to identify. Editors who rely on these notifications should be aware of the change and can share feedback or concerns on the [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|project]] or [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|talk page]].<br/>Please reach out if you have any questions, thank you! -- [[User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] ([[User_talk:Danny_Benjafield_(WMDE)|talk]]) sent via [[Brūcend:MediaWiki message delivery|MediaWiki message delivery]] ([[Brūcendmōtung:MediaWiki message delivery|motung]]) 12:42, 1 Winterfylleð 2026 (UTC) <!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31106967 --> 9wo3xu9wboveurqk2pr8v16b1tnilvm cyning 0 6412 55112 54782 2026-10-01T15:53:42Z Deadend0914 7211 /* Wordstǣr */ 55112 wikitext text/x-wiki =={{sprǣc|ang}}== ===Āwendednessa=== * cing, cicing, cyneg, cuning, cyng, cynig, cynincg, cyncg, cyngc ===Rihtstefn=== * /ˈkyninɡ/, [ˈkyniŋɡ] ===Wordstǣr=== Of {{inh|ang|gmw-pro|*kuning}}, of {{inh|ang|gem-pro|*kuningaz}}, of {{inh|ang|ine-pro|*ǵenh₁-}}. ====Sweostorword==== * Ealdnoren: [[konungr]] ** Denisc: [[konge]] * Ealdþēodisc: [[kuning]] ** Þēodisc: [[König]] * Niðerlendisc: [[koning]] ===Werlīc Nama=== {{ang-noun|wer|head=cyning}} # Werlīc wealdend landes oþþe folces. #: ''Se '''cyning''' wunode on þǣm castle.'' # Mihtig oþþe mǣre mann. #: ''On blindra lande biþ se ānēaga '''cyning'''. Swā ēac se ūþwita on þissum middangearde.'' ====Nīwenglisc Andgiet==== # [[king]], [[ruler]], [[leader]] # a powerful or important person ====Declīnung==== {{ang-decl-noun-a-m|cyning}} ====Gesibbword==== cynn = kin <br> cyninge = queen <br> cynnig = noble, of noble family <br> ====Gesetnyssum==== þēod-cyning, [[folc]]-cyning - Folk-king <br> Angel-cyning - English king <br> Ānwintre-cyning, æwintrecyning - One winter king <br> [[æfter]]-cyning - later king <br> [[æðel]]-cyning - noble king (Christ) <br> bryten-cyning - powerful king <br> [[Ēaland]]-cyning - Island king <br> [[Gāst]]-cyning - Ghost king, soul king, God <br> [[Gūð]]-cyning - warrior king, <br> [[Hæðen]]-cyning - Heathen king <br> [[Hēah]]-cyning - High King, God <br> [[Heofon]]-cyning - King of Heaven <br> Lēod-cyning - King, rule, leader <br> [[Mægen]]-cyning - Mighty king <br> [[Riht]]-cyning - Lawful king <br> [[Sæ]]-cyning - Sea king <br> þrym-cyning - glorious king, god, king of glory, <br> [[woruld]]-cyning - earthly king, earth king <br> ====Bōccræft Fruman==== Willelm Cyng: stæfræwa 7, 13, <br> Aeþelþryþ: stfa. 2, 7, <br> Ohthere and Wulfstan: stfa. 1, 18, 23, 54, 61, <br> Judiþ: stfa. 155, 190, <br> Beowulf fōresægdnes: stfa. 2, 8, <br> Cynewulf and Cyneheard: stfa. 4, 5, 6, 7, 9, 10, 13, 14, 17, <br> ====Wendunga==== * Crēacisc: [[βασιλιάς]] * Ealdīrisc: [[rí]] * Ealdciricanslafisc: [[цѣсарь]] * Finnisc: [[kuningas]] * Frencisc: [[roi]] ** Ealdfrencisc: [[reis]] * Hebrēisc: [[מלך]] * Hittisc: [[lugal]] * Italisc: [[re]] * Lǣden: [[rex]] * Persisc: [[پادشاه]] * Polisc: [[król]] * Portuglisc: [[rei]] * Russisc: [[король]] * Spēonisc: [[rey]] [[Flocc:Englisc nama]] [[Flocc:Englisce lēode]] cohyed038otl0b6zuksb5engxmae378 bearn 0 6429 55117 54823 2026-10-02T03:43:41Z Deadend0914 7211 /* {{sprǣc|ang}} */ 55117 wikitext text/x-wiki =={{sprǣc|ang}}== ===Āwendednesa=== * barn * beorn ===Rihtstefn=== * /bæɑrn/ ===Wordstǣr=== {{inh+|ang|gmw-pro|*barn}} ====Sweostorword==== * Denisc: [[barn]] * Noren: [[barn]] ====Nāhwæðer Nama==== # Hwæs [[cild]] #: Se Cyning nǣfde næfre '''bearn'''. ====Declīnung==== {{ang-decl-noun-a-n|bearn}} ====Gesetnyssum==== frum-bearn -first child <br> dryht-bearn - princely child, royal child <br> cyne-bearn - Christ, royal child <br> fréo-bearn - child of gentile birth <br> god-bearn - divine child, Christ, son of God, <br> wæpned-bearn - male child <br> sige-bearn - victorious child, victor child, <br> wūsc-bearn - little child <br> [[folc]]-bearn - folk child, child of man <br> bearn-cennicge "wf" - mother <br> bearn-cennung "wf" - childbirth <br> bearn-ēacen, bearn-ēacnigende, bearn-ēaca, bearn-ēacnung, baarn-eacnigen - "adj" pregnant, with child, <br> bearn-gebyrda "wf" - child bearing <br> bearn-lēas - "adj" childless <br> bearn-lēast "wf" - childlessness <br> bearn-myrðra "wr", bearnmyrðre "wr" - child murder, child murderer <br> sweostor-bearn - sister's child, nephew, niece, <br> ====Wendunga==== * Frencisc: [[enfant]] * Italisc: [[bambino]] * Lǣden: [[infans]] * Niðerlendisc: [[kind]] * Spēonisc: [[niño]] * Þēodisc: [[Kind]] [[Flocc:Englisc nama]] [[Flocc:Englisce lēode]] [[Flocc:Englisc mǣgþ]] 7u3ph32p54ja00ebhuihg6n1qm7wyqo Module:en-headword 828 8056 55107 55059 2026-10-01T15:36:45Z Deadend0914 7211 55107 Scribunto text/plain local export = {} local pos_functions = {} --[==[ Author from 2020 on: mostly Benwing2, with significant contributions from Theknightwho. Based on a prior version by Rua (by now mostly rewritten), with contributions from Erutuon and others (see history for full attribution). ]==] local force_cat = false -- for testing; if true, categories appear in non-mainspace pages local require = require local require_when_needed = require("Module:require when needed") local en_utilities_module = "Module:en-utilities" local headword_utilities_module = "Module:headword utilities" local headword_module = "Module:headword" local inflection_utilities_module = "Module:inflection utilities" local parse_utilities_module = "Module:parse utilities" local JSON_module = "Module:JSON" local labels_module = "Module:labels" local links_module = "Module:links" local parameters_module = "Module:parameters" local string_utilities_module = "Module:string utilities" local table_module = "Module:table" local utilities_module = "Module:utilities" local yesno_module = "Module:yesno" local iut = require_when_needed(inflection_utilities_module) local put = require_when_needed(parse_utilities_module) local m_headword_utilities = require_when_needed(headword_utilities_module) local add_links_to_multiword_term = require_when_needed(headword_utilities_module, "add_links_to_multiword_term") local add_suffix = require_when_needed(en_utilities_module, "add_suffix") local apply_link_modifiers = require_when_needed(headword_utilities_module, "apply_link_modifiers") local concat = table.concat local deepEquals = require_when_needed(table_module, "deepEquals") local dump = mw.dumpObject local format_categories = require_when_needed(utilities_module, "format_categories") local full_headword = require_when_needed(headword_module, "full_headword") local get_label_info = require_when_needed(labels_module, "get_label_info") local get_link_page = require_when_needed(links_module, "get_link_page") local glossary_link = require_when_needed(headword_utilities_module, "glossary_link") local insert = table.insert local insertIfNot = require_when_needed(table_module, "insertIfNot") local ipairs = ipairs local is_regular_plural = require_when_needed(en_utilities_module, "is_regular_plural") local list_to_set = require_when_needed(table_module, "listToSet") local pairs = pairs local process_params = require_when_needed(parameters_module, "process") local remove = table.remove local remove_links = require_when_needed(links_module, "remove_links") local replacement_escape = require_when_needed(string_utilities_module, "replacement_escape") local shallowCopy = require_when_needed(table_module, "shallowCopy") local singularize = require_when_needed(en_utilities_module, "singularize") local split = require_when_needed(string_utilities_module, "split") local toJSON = require_when_needed(JSON_module, "toJSON") local toNFD = mw.ustring.toNFD local type = type local ulen = require_when_needed(string_utilities_module, "len") local ulower = require_when_needed(string_utilities_module, "lower") local umatch = require_when_needed(string_utilities_module, "match") local u = require_when_needed(string_utilities_module, "char") local ugsub = require_when_needed(string_utilities_module, "gsub") local lang = require("Module:languages").getByCode("en") local langname = lang:getCanonicalName() -- Old English localization: category wordings come from [[Module:floccnaman]] -- (see that module); the English wording is kept when a translation is missing. -- Loaded lazily and optionally, so a missing module can never break a page. local floccnaman_module = "Module:floccnaman" local floccnaman local function get_floccnaman() if floccnaman == nil then local ok, mod = pcall(require, floccnaman_module) floccnaman = ok and mod or false end return floccnaman or nil end -- Old English wording for one category word, or the English wording unchanged. local function cat_word(l, text) local mod = get_floccnaman() return mod and mod.get(l, text) or text end local list_param = {list = true, disallow_holes = true} local list_allow_holes = {list = true, allow_holes = true} local boolean_param = {type = "boolean"} local function ine(val) if val == "" then return nil else return val end end local function track(page) require("Module:debug/track")("en-headword/" .. page) return true end ------------------------------------------- UTILITY FUNCTIONS ------------------------------------------ -- Parse and return an inflection not requiring additional processing. The raw arguments come from `args[field]`, which -- is parsed for inline modifiers. local function parse_inflection(args, field, is_head) local argfield = field if type(argfield) == "table" then argfield = argfield[1] end return m_headword_utilities.parse_term_list_with_modifiers { paramname = field, forms = args[argfield], splitchar = ",", is_head = is_head, } end -- Insert the parsed inflections in `terms` (as parsed by `parse_inflection`) into `data.inflections`, with label -- `label` and optional accelerator spec `accel`. local function insert_inflection(data, terms, label, accel, no_label) for _, termobj in ipairs(terms) do m_headword_utilities.remove_termobj_field_modifiers(termobj) end m_headword_utilities.insert_inflection { headdata = data, terms = terms, label = label, no_label = no_label, accel = accel and {form = accel} or nil, } end -- Insert a fixed label `label` into the inflections for `data`. If `originating_term` is supplied, copy the decorations -- from it into the fixed label. local function insert_fixed_inflection(data, label, originating_term) m_headword_utilities.insert_fixed_inflection { headdata = data, originating_term = originating_term, label = label, } end -- Parse and insert an inflection not requiring additional processing into `data.inflections`. The raw arguments come -- from `args[field]`, which is parsed for inline modifiers. `label` is the label that the inflections are given; -- `accel` is the accelerator form, or nil. local function parse_and_insert_inflection(data, args, field, label, accel) m_headword_utilities.parse_and_insert_inflection { headdata = data, forms = args[field], paramname = field, splitchar = ",", label = label, accel = accel and {form = accel} or nil, } end -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(term) local last_cons = term:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. term .. "' must end in a consonant to use ++") end return term .. last_cons end local function compute_plusplus_s_form(term, default_s_form) if term:find("[szx]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(term) .. "es" else return default_s_form end end -- On English Wiktionary, {{tl|en-head}} is the template that means "interjection"; it invokes this module without -- a part of speech. This wiki's template namespace is named "Bysen", not "Template", so the namespace id and the -- title without its namespace prefix are compared instead of a hard-coded "Template:en-head". -- Scribunto's title object exposes these as the fields `namespace`, `nsText` and `fullText`; it has no -- getNamespace()/getBaseText() methods, so those must not be used here. local function is_en_head_template() local title = mw.title.getCurrentTitle() return title.namespace == 10 and title.fullText == title.nsText .. ":en-head" end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local iparams = { [1] = true, } local iargs = require("Module:parameters").process(frame.args, iparams) local parargs = frame:getParent().args local poscat = iargs[1] local pos_in_1 = not poscat if pos_in_1 then poscat = ine(parargs[1]) or is_en_head_template() and "interjection" or error("Part of speech must be specified in 1=") poscat = require(headword_module).canonicalize_pos(poscat) end local indexing_poscat = pos_in_1 and "head" or poscat local params = { ["head"] = list_param, ["id"] = true, ["json"] = boolean_param, ["sort"] = true, ["splithyph"] = boolean_param, ["nosplithyph"] = boolean_param, ["hyphspace"] = boolean_param, ["nolink"] = boolean_param, ["nolinkhead"] = {type = "boolean_param", alias_of = "nolink"}, ["suffix"] = boolean_param, ["nosuffix"] = boolean_param, ["nomultiwordcat"] = boolean_param, ["abbr"] = list_param, ["the"] = true, ["def"] = {alias_of = "the"}, ["pagename"] = true, -- for testing } if not pos_in_1 then params[1] = {required = true} -- required but ignored as already processed above end local pos_data = pos_functions[indexing_poscat] local pos_func if pos_data then local pos_params = pos_data.params if pos_params then for key, val in pairs(pos_params) do params[key] = val end end pos_func = pos_data.func end local args = process_params(parargs, params) -- Account for unsupported titles, e.g. 'C|N>K' instead of 'Unsupported titles/C through N to K'. local pagename = args.pagename or mw.loadData("Module:headword/data").pagename local user_specified_heads = parse_inflection(args, "head", "is_head") local heads = user_specified_heads local autohead if args.nolink or not pagename:find("[ '%-]") then autohead = pagename else local en_no_split_apostrophe_words = list_to_set { "one's", "someone's", "he's", "she's", "it's", } local en_include_hyphen_prefixes = list_to_set { -- We don't include things that are also words even though they are often (perhaps mostly) prefixes, e.g. -- "be", "counter", "cross", "extra", "half", "mid", "over", "pan", "under". "acro", "acousto", "Afro", "agro", "anarcho", "angio", "Anglo", "ante", "anti", "arch", "auto", "bi", "bio", "cis", "co", "cryo", "crypto", "de", "demi", "eco", "electro", "Euro", "ex", "Greco", "hemi", "hydro", "hyper", "hypo", "infra", "Indo", "inter", "intra", "Judeo", "macro", "meta", "micro", "mini", "multi", "neo", "neuro", "non", "para", "peri", "post", "pre", "pro", "proto", "pseudo", "re", "semi", "sub", "super", "trans", "un", "vice", } local function is_english(term) local title = mw.title.new(term) if title and title.exists then local content = title:getContent() if content and content:find("==English==\n") then return true end end return false end local function en_split_hyphen_when_space(word) if not word:find("-", nil, true) then return nil end if args.hyphspace then return "[[" .. word:gsub("%-+", " ") .. "|" .. word .. "]]" end if args.nosplithyph then return "[[" .. word .. "]]" end if not args.splithyph then local space_word = word:gsub("%-+", " ") if is_english(space_word) then return "[[" .. space_word .. "|" .. word .. "]]" end if is_english(word) then return "[[" .. word .. "]]" end end return nil end local function en_split_apostrophe(word) local base = word:match("^(.*)'s$") if base then return "[[" .. base .. "]][[-'s|'s]]" end -- Only treat final apostrophe as possessive if preceded by something that looks like a plural ending in /z/. -- In particular we don't want to do it for words like [[truckin']]. base = word:match("^(.*[sxz])'$") if base then if base:find("s$") then local sg = singularize(base) if is_english(sg) then return "[[" .. sg .. "|" .. base .. "]][[-'|']]" end end return "[[" .. base .. "]][[-'|']]" end return "[[" .. word .. "]]" end autohead = add_links_to_multiword_term(pagename, { split_hyphen_when_space = en_split_hyphen_when_space, split_apostrophe = en_split_apostrophe, no_split_apostrophe_words = en_no_split_apostrophe_words, include_hyphen_prefixes = en_include_hyphen_prefixes, }) end if not heads[1] then heads = {{term = autohead}} else for _, headobj in ipairs(heads) do local head = headobj.term if head:find("^~") then head = apply_link_modifiers(autohead, head:sub(2), lang) headobj.term = head elseif head:find("^[!?]$") then -- If explicit head= just consists of ! or ?, add it to the end of the default head. headobj.term = autohead .. head end if head == autohead then track("redundant-head") end end end -- handle the=/def= if args.the == "~" then local newheads = {} for _, headobj in ipairs(heads) do local barehead = shallowCopy(headobj) insert(newheads, barehead) headobj.term = "the " .. headobj.term insert(newheads, headobj) end heads = newheads elseif args.the then local the = require(yesno_module)(args.the) if the then for _, headobj in ipairs(heads) do headobj.term = "the " .. headobj.term end end end local data = { lang = lang, pos_category = poscat, categories = {}, heads = heads, user_specified_heads = user_specified_heads, -- We use our own splitting algorithm so the redundant head cat will be inaccurate. no_redundant_head_cat = true, inflections = {}, nomultiwordcat = args.nomultiwordcat, sort_key = args.sort, pagename = pagename, id = args.id, force_cat_output = force_cat, } local function inscat(cat) insert(data.categories, langname .. " " .. cat_word(lang, cat)) end local is_suffix = false if args.suffix or not args.nosuffix and pagename:find("^%-") and not pagename:find("^%-%-") and poscat ~= "suffix forms" then is_suffix = true data.pos_category = "suffixes" local singular_poscat = singularize(poscat) inscat(singular_poscat .. "-forming suffixes") insert(data.inflections, {label = singular_poscat .. "-forming suffix"}) end if pos_func then pos_func(args, data, is_suffix) end local extra_categories = {} if pagename:find("[Qq]") then -- Check for q not followed by u. We want to exclude things like [[13q deletion syndrome]] and [[BFOQ]] that -- don't have a lowercase letter on either side, as well as things like [[& seq.]] and [[acq.]] that are -- abbreviations for words containing a following u. -- -- Approximate range of combining diacritics; we want to remove them so the checks below for -- a lowercase letter next to the q aren't tripped up by diacritics on the letter. local u300 = u(0x0300) local u36F = u(0x036F) local pagename_no_diacritics = ugsub(toNFD(pagename), "[" .. u300 .. "-" .. u36F .. "]", "") if pagename_no_diacritics:find("[Qq][a-tv-z]") or pagename_no_diacritics:find("[a-z]q[^u.]") or pagename_no_diacritics:find("[a-z]q$") then inscat("words containing Q not followed by U") end end -- toNFD performs decomposition, so letters that decompose to an ASCII -- vowel and a diacritic, such as é, are counted as vowels and do not do not -- need to be included in the pattern. if not umatch(ulower(toNFD(pagename)), "[aeiouyæœøəªºαεηιουω]") then inscat("words spelled wiþūtan vowels") end if pagename:find("yre$") then inscat('words ending in "-yre"') end if not pagename:find(" ") and ulen(pagename) >= 25 then insert(extra_categories, langname .. " " .. cat_word(lang, "Long words")) end if pagename:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then inscat("words that use all vowels in alphabetical order") end parse_and_insert_inflection(data, args, "abbr", "abbreviation") if args.json then return toJSON(data) end return full_headword(data) .. (extra_categories[1] and format_categories(extra_categories, lang, args.sort) or "") end local function make_default_comparative(word) if word == "good" or word == "well" then return {"better"} elseif word == "bad" or word == "badly" then return {"worse"} elseif word == "far" then return {"further", "farther"} else return {add_suffix(word, "r")} end end local function make_default_superlative(word) if word == "good" or word == "well" then return {"best"} elseif word == "bad" or word == "badly" then return {"worst"} elseif word == "far" then return {"furthest", "farthest"} else return {add_suffix(word, "st.superlative")} end end -- This function does the common work between adjectives and adverbs. local function process_comparative_args(data, args, plpos) local pagename = data.pagename local comps = parse_inflection(args, 1) local sups = parse_inflection(args, "sup") local outcomps, outsups if args.componly then if comps[1] then error("Can't specify comparatives of comparative-only " .. plpos) end insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) insert(data.categories, langname .. " " .. cat_word(lang, "comparative-only " .. plpos)) -- Set to empty list so we don't get any comparatives output, but process superlatives if specified. outcomps = {} if not sups[1] then -- Set to empty list so we don't get any superlatives output unless explicitly given. outsups = {} end elseif args.suponly then if comps[1] or sups[1] then error("Can't specify comparatives or superlatives of or superlative-only " .. plpos) end insert(data.inflections, {label = glossary_link("superlative") .. " form only"}) insert(data.categories, langname .. " " .. cat_word(lang, "superlative-only " .. plpos)) return end -- If the first parameter is ?, then don't show anything, just return. if comps[1] and comps[1].term == "?" then if comps[2] then error("Can't specify additional comparatives along wiþ '?'") end if sups[1] then error("Can't specify superlatives along wiþ '?' for the comparative") end return end if comps[1] and comps[1].term == "-" then local hyphencomp = remove(comps, 1) -- Remove the "-" but retain for decorations. -- Not (generally) comparable; may occasionally have a comparative if comps[1] then insert_fixed_inflection(data, "not generally <<comparable>>", hyphencomp) elseif not sups[1] then insert_fixed_inflection(data, "not <<comparable>>", hyphencomp) insert(data.categories, langname .. " " .. cat_word(lang, "uncomparable " .. plpos)) return else -- No comparative, but a superlative. insert_inflection() will correctly generate 'no comparative' if we -- pass in "-" as the value. outcomps = {hyphencomp} end elseif not comps[1] then comps = {{term = "more"}} end if not outcomps then -- not if we set `outcomps` to "-" above or processed a comparative-only term outcomps = {} -- Go over each parameter given and create a comparative and superlative form. for _, compobj in ipairs(comps) do local comp = compobj.term if comp == "-" then error("Comparative of '-' only allowed as first comparative") end if comp == "+" then comp = "+more" elseif comp == "more" and pagename ~= "many" and pagename ~= "much" then comp = "+more" elseif comp == "further" and pagename ~= "far" then comp = "+further" elseif comp == "better" and pagename ~= "good" and pagename ~= "well" then comp = "+better" elseif comp:find("~") then comp = comp:gsub("~", replacement_escape(pagename)) end compobj.origterm = comp if comp == "+more" then comp = "more [[" .. pagename .. "]]" elseif comp == "+further" then comp = {"further [[" .. pagename .. "]]", "farther [[" .. pagename .. "]]"} elseif comp == "+better" then comp = "better [[" .. pagename .. "]]" elseif comp == "er" then -- Add -er. comp = add_suffix(pagename, "r") elseif comp == "ier" then if pagename:sub(-1) ~= "y" then error("Can't specify 'ier' comparative unless the term ends wiþ 'y': " .. pagename) end comp = pagename:gsub("e?y$", "ier") elseif comp:find("^%+") then local special = m_headword_utilities.get_special_indicator(comp, "noerror") if special then comp = m_headword_utilities.handle_multiword(pagename, special, make_default_comparative) end end if type(comp) == "table" and not comp[2] then comp = comp[1] end if type(comp) == "table" then for i = 1, #comp - 1 do local outobj = shallowCopy(compobj) outobj.term = comp[i] insert(outcomps, outobj) end compobj.term = comp[#comp] insert(outcomps, compobj) else compobj.term = comp insert(outcomps, compobj) end end end if sups[1] and sups[1].term == "-" then if sups[2] then error("Can't specify '-' as superlative followed by further values") end -- No superlative. insert_inflection() will correctly generate 'no superlative' if we pass in "-" as the value. outsups = sups else if not sups[1] then sups = {{term = "+"}} end end -- `outsups` will be set if we set `outsups` to "-" above or processed a comparative-only term without superlatives. if not outsups then outsups = {} local function process_sup(sup, special, supobj, compobj) if special then sup = m_headword_utilities.handle_multiword(pagename, special, make_default_superlative) elseif sup == "-" or sup == "+" then error(("Internal error: Superlative value of '%s' should have been handled earlier"):format(sup)) elseif sup == "+most" then sup = "most [[" .. pagename .. "]]" elseif sup == "+furthest" then sup = {"furthest [[" .. pagename .. "]]", "farthest [[" .. pagename .. "]]"} elseif sup == "+best" then sup = "best [[" .. pagename .. "]]" elseif sup == "est" then -- Add -est. sup = add_suffix(pagename, "st.superlative") elseif sup == "iest" then if pagename:sub(-1) ~= "y" then error("Can't specify 'iest' superlative unless the term ends wiþ 'y': " .. pagename) end sup = pagename:gsub("e?y$", "iest") end if type(sup) == "table" and not sup[2] then sup = sup[1] end if compobj then supobj = shallowCopy(supobj) supobj = m_headword_utilities.combine_termobj_decorations(supobj, compobj) end if type(sup) == "table" then for i = 1, #sup - 1 do local outobj = shallowCopy(supobj) outobj.term = sup[i] insert(outsups, outobj) end supobj.term = sup[#sup] insert(outsups, supobj) else supobj.term = sup insert(outsups, supobj) end end for _, supobj in ipairs(sups) do local sup = supobj.term if sup == "-" then error("Superlative of '-' only allowed as first superlative") end if sup == "+" then if not comps[1] then error("Superlative of '+' can't be specified when there are no comparatives") end for _, compobj in ipairs(comps) do local comp = compobj.origterm local special if comp == "+more" then sup = "+most" elseif comp == "+further" then sup = "+furthest" elseif comp == "+better" then sup = "+best" elseif comp == "er" then sup = "est" elseif comp == "ier" then sup = "iest" else if comp:find("^%+") then special = m_headword_utilities.get_special_indicator(comp, "noerror") end if not special then -- If the full comparative was given, then derive the superlative by replacing -er with -- -est. if comp:sub(-2) == "er" then sup = comp:sub(1, -3) .. "est" else error(("The superlative cannot be derived automatically from comparative '%s' because it doesn't end in -er"):format(comp)) end end end process_sup(sup, special, supobj, compobj) end else local special = m_headword_utilities.get_special_indicator(sup, "noerror") -- Do some work here rather than in process_sup() so we don't end up double-processing a term with a '~' -- in it or a term that happens to be 'most' or similar after substitution of ~ in the comparative. if not special then if sup == "most" and pagename ~= "many" and pagename ~= "much" then sup = "+most" elseif sup == "furthest" and pagename ~= "far" then sup = "+furthest" elseif sup == "best" and pagename ~= "good" and pagename ~= "well" then sup = "+best" elseif sup:find("~") then sup = sup:gsub("~", replacement_escape(pagename)) end end process_sup(sup, special, supobj) end end end insert_inflection(data, outcomps, "<<comparative>>", "wiþmetendlic") insert_inflection(data, outsups, "<<superlative>>", "oferstīgendlīc") end pos_functions["adjectives"] = { params = { [1] = list_param, ["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the comparative value", }, ["sup"] = list_param, ["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the superlative value", }, ["componly"] = boolean_param, ["suponly"] = boolean_param, }, func = function(args, data) -- Process the comparatives and superlatives. process_comparative_args(data, args, "adjectives") end, } pos_functions["adverbs"] = { params = { [1] = list_param, ["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the comparative value", }, ["sup"] = list_param, ["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the superlative value", }, ["componly"] = boolean_param, ["suponly"] = boolean_param, }, func = function(args, data) -- Process the comparatives and superlatives. process_comparative_args(data, args, "adverbs") end, } local function escape(str) return (str:gsub("\\([:#])", "\\\\%1") :gsub("[:#]", "\\%0")) end local function canonicalize_plural(pl, pagename, pos) if pl == "+" then return escape(add_suffix(pagename, "s.plural", pos)) elseif pl == "++" then return escape(compute_plusplus_s_form(pagename, add_suffix(pagename, "s.plural", pos))) elseif pl == "*" then return escape(pagename) elseif pl == "ies" then if pagename:sub(-1) == "y" then return escape(pagename:gsub("e?y$", pl)) end error("Can't specify 'ies' plural unless the term ends wiþ 'y'.") elseif pl == "s" or pl == "es" or pl == "'s" then return escape(pagename .. pl) end end local function do_nouns(args, data, pos) local pagename = data.pagename pos = pos or "noun" local plurals = parse_inflection(args, 1) local function insert_plurale_tantum_inflections(is_plural_only, originating_label) if args.sg[1] then insert_fixed_inflection(data, "normally plural", originating_label) parse_and_insert_inflection(data, args, "sg", "singular") elseif is_plural_only then insert_fixed_inflection(data, "plural only", originating_label) end if args.attr[1] then parse_and_insert_inflection(data, args, "attr", "attributive") end end local function first_pl_term() return plurals[1] and plurals[1].term or nil end if first_pl_term() == "p" then -- plurale tantum if plurals[2] then error("Wiþ plurale tantum nama, can't specify more than one plural") end data.genders = {"p"} -- this should auto-insert the correct 'pluralia tantum' category insert_plurale_tantum_inflections("plural only", plurals[1]) return end local function inscat(cat) insert(data.categories, langname .. " " .. cat_word(lang, cat)) end local need_default_plural = pos == "noun" if first_pl_term() == "sp" then -- construed as singular or plural sp = remove(plurals, 1) -- Remove the "sp" but retain it for its decorations. inscat("naman construed as singular or plural") data.genders = {"s", "p"} -- this should auto-insert the correct 'pluralia tantum' category insert_plurale_tantum_inflections(nil, sp) need_default_plural = false elseif first_pl_term() == "-" then -- Untellendlīc noun; may occasionally have a plural local hyphpl = remove(plurals, 1) -- Remove the "-" but retain for decorations. inscat("untellendlīc naman") -- If plural forms were given explicitly, then show "oft" if plurals[1] then insert_fixed_inflection(data, "oft <<untellendlīc>>", hyphpl) else insert_fixed_inflection(data, "<<untellendlīc>>", hyphpl) end need_default_plural = false elseif first_pl_term() == "#" then -- oft tellendlīc (e.g., "grilled cheese") local hashpl = remove(plurals, 1) -- Remove the "#" but retain for decorations. insert_fixed_inflection(data, "oft <<tellendlīc>>", hashpl) inscat("untellendlīc naman") inscat("tellendlīc naman") -- If no plural was given, add a default one now if not plurals[1] then plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))} end elseif first_pl_term() == "~" then -- Mixed tellendlīc/untellendlīc noun, always has a plural local tildepl = remove(plurals, 1) -- Remove the "~" but retain for decorations. insert_fixed_inflection(data, "<<tellendlīc>> and <<untellendlīc>>", tildepl) inscat("untellendlīc naman") inscat("tellendlīc naman") -- If no plural was given, add a default one now if not plurals[1] then plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))} end end -- Plural is unknown if first_pl_term() == "?" then local questionpl = remove(plurals, 1) -- Remove the "?" but retain for decorations. -- Not desired; see [[Wiktionary:Tea_room/2021/August#"Plural unknown or uncertain"]] -- insert_fixed_inflection(data, "manigfeald unġecnāwen oþþe ungewiss", questionpl) inscat("naman wiþ unġecnāwen oþþe ungewiss manigfealde") if plurals[1] then error("Ne cann āmearcian sweotole manigfealde andlang wiþ '?' of unġecnāwen/ungewiss manigfeald") end return end -- Plural is not attested if first_pl_term() == "!" then local exclampl = remove(plurals, 1) -- Remove the "!" but retain for decorations. insert_fixed_inflection(data, "plural not attested", exclampl) inscat("naman wiþ unattested manigfealde") if plurals[1] then error("Ne cann āmearcian sweotole manigfealde andlang wiþ '!' of gecȳþed manigfeald") end return end -- If no plural was given, maybe add a default one, otherwise (when "-" was given or proper noun) return. if not plurals[1] then if not need_default_plural then inscat("untellendlīc naman") return end plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))} end -- There are plural forms to show, so show them. inscat("tellendlīc naman") local irregular, indeclinable for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl.term, pagename, pos) if canon_pl then pl.term = canon_pl end local pl_term = get_link_page(pl.term, lang) if not (pagename:find(" ") or is_regular_plural(pl_term, pagename)) then irregular = true if pl_term == pagename then indeclinable = true end end end if irregular then inscat("naman wiþ fremde manigfealde") end if indeclinable then inscat("undeclīnigendlīce naman") end insert_inflection(data, plurals, "plural", "p") end -- Return the parameters to be used for nouns and proper nouns. Currently the same. local noun_params = { [1] = list_param, ["pl\1qual"] = {list = true, allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the plural", }, -- The following four only used for pluralia tantum (1=p) ["sg"] = list_param, ["attr"] = list_param, } pos_functions["naman"] = { params = noun_params, func = do_naman, } pos_functions["agennaman"] = { params = noun_params, func = function(args, data) return do_nouns(args, data, "agennama") end, } local function base_default_verb_forms(verb) return escape(add_suffix(verb, "s.verb")), escape(add_suffix(verb, "ing")), escape(add_suffix(verb, "d")) end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest, first, rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil, nil, nil end end local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Word '" .. verb .. "' mōt hæfþ rum in sīde tō notienne **") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Fyrest word '" .. first .. "' mōt ende wiþ samod swēgend tō notienne **") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form, pagename) if form == nil then error("Word '" .. pagename .. "' mōt hæfþ rum in sīde tō notienne *, **, *l, *! or *'") end return form end local function sub_tilde(form, pagename) if not form then return nil end if form:find("~") then form = form:gsub("~", replacement_escape(pagename)) end return form end local deprecated_qual_replaced_by_inline_modifier = { list = true, allow_holes = true, replaced_by = false, instead = "use an inline modifier <q:...> or <l:...> on the value" } pos_functions["verbs"] = { params = { [1] = {list = "pres_3sg", disallow_holes = true}, ["pres_3sg\1_qual"] = deprecated_qual_replaced_by_inline_modifier, [2] = {list = "pres_ptc", disallow_holes = true}, ["pres_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier, [3] = {list = "past", disallow_holes = true}, ["past\1_qual"] = deprecated_qual_replaced_by_inline_modifier, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier, ["noautolinkverb"] = boolean_param, ["angle_bracket"] = boolean_param, }, func = function(args, data) -- Get parameters local par1s local par2s = parse_inflection(args, {2, "pres_ptc"}) local par3s = parse_inflection(args, {3, "past"}) local par4s = parse_inflection(args, {4, "past_ptc"}) local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = data.pagename ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed local lemma local function set_lemma_and_default_forms(the_lemma) lemma = the_lemma full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed, lemma_first, lemma_rest = default_verb_forms(the_lemma) end local function canonicalize_s_form(form) if form == "+" then error("Internal error: Should not see '+' here") elseif form == "^" then return full_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s, lemma) elseif form == "++" then return compute_plusplus_s_form(lemma, full_default_s) elseif form == "**" then if lemma:find("^[^ ]*[szx] ") then return compute_double_last_cons_stem_of_split_verb(lemma, "es") else return check_non_nil_star_form(split_default_s, lemma) end elseif form == "+!" then return lemma .. "s" elseif form == "*!" then return check_non_nil_star_form(lemma_first) .. "s" .. lemma_rest elseif form == "+'" then return lemma .. "'s" elseif form == "*'" then return check_non_nil_star_form(lemma_first) .. "'s" .. lemma_rest elseif form == "+l" then if lemma:find("[szx]$") then return {{term = full_default_s, l = {"US"}}, {term = compute_plusplus_s_form(lemma, full_default_s), l = {"UK"}}} else return compute_plusplus_s_form(lemma, full_default_s) end elseif form == "*l" then if lemma:find("^[^ ]*[szx] ") then return {{term = check_non_nil_star_form(split_default_s, lemma), l = {"US"}}, {term = compute_double_last_cons_stem_of_split_verb(lemma, "es"), l = {"UK"}}} else return check_non_nil_star_form(split_default_s, lemma) end else return sub_tilde(form, lemma) end end local function canonicalize_ing_form(form) if form == "+" then error("Internal error: Should not see '+' here") elseif form == "^" then return full_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing, lemma) elseif form == "++" then return compute_double_last_cons_stem(lemma) .. "ing" elseif form == "**" then return compute_double_last_cons_stem_of_split_verb(lemma, "ing") elseif form == "+!" then return lemma .. "ing" elseif form == "*!" then return check_non_nil_star_form(lemma_first) .. "ing" .. lemma_rest elseif form == "+'" then return lemma .. "'ing" elseif form == "*'" then return check_non_nil_star_form(lemma_first) .. "'ing" .. lemma_rest elseif form == "+l" then return {{term = full_default_ing, l = {"US"}}, {term = compute_double_last_cons_stem(lemma) .. "ing", l = {"UK"}}} elseif form == "*l" then return {{term = check_non_nil_star_form(split_default_ing, lemma), l = {"US"}}, {term = compute_double_last_cons_stem_of_split_verb(lemma, "ing"), l = {"UK"}}} else return sub_tilde(form, lemma) end end local function canonicalize_ed_form(form) if form == "+" then error("Internal error: Should not see '+' here") elseif form == "^" then return full_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed, lemma) elseif form == "++" then return compute_double_last_cons_stem(lemma) .. "ed" elseif form == "+!" then return lemma .. "ed" elseif form == "*!" then return check_non_nil_star_form(lemma_first) .. "ed" .. lemma_rest elseif form == "+'" then return {{term = lemma .. "'d"}, {term = lemma .. "'ed"}} elseif form == "*'" then return {{term = check_non_nil_star_form(lemma_first) .. "'d" .. lemma_rest}, {term = check_non_nil_star_form(lemma_first) .. "'ed" .. lemma_rest}} elseif form == "**" then return compute_double_last_cons_stem_of_split_verb(lemma, "ed") elseif form == "+l" then return {{term = full_default_ed, l = {"US"}}, {term = compute_double_last_cons_stem(lemma) .. "ed", l = {"UK"}}} elseif form == "*l" then return {{term = check_non_nil_star_form(split_default_ed, lemma), l = {"US"}}, {term = compute_double_last_cons_stem_of_split_verb(lemma, "ed"), l = {"UK"}}} else return sub_tilde(form, lemma) end end -- FIXME: options should be "+", "*", "++", "**", "+n", "*n", "++n" and "**n", but not "n" local function canonicalize_en_form(form) if form == "n" then track("n4") return add_suffix(lemma, "n") end return canonicalize_ed_form(form) end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local is_angle_bracket = args.angle_bracket if is_angle_bracket then if par2s[1] or par3s[1] or par4s[1] then error("Can't specify explicit values for 2=, 3= or 4= along wiþ the angle-bracket format") end elseif is_angle_bracket == nil and not par2s[1] and not par3s[1] and not par4s[1] and not args[1][2] and args[1][1] and args[1][1]:find("<") then if put.term_contains_top_level_html(args[1][1]) then -- Often, term_contains_top_level_html() returns true on the angle-bracket format, which would -- make the pcall() below succeed but leave the angle brackets as-is. Check for this and only do the -- pcall() if term_contains_top_level_html() returns false. is_angle_bracket = true else -- If it's ambiguous whether it's an angle-bracket format or separate params with an inline modifier, -- try to parse as the latter. If an error occurs, treat as the former. local ok ok, par1s = pcall(parse_inflection, args, {1, "pres_3sg"}) if not ok then par1s = nil is_angle_bracket = true end end end if is_angle_bracket then -------------------------- ANGLE-BRACKET FORMAT -------------------------- -- (0) Expand multiword term with angle brackets just on the first word. local arg11 = args[1][1] if arg11:find("^<.*>$") and pagename:find(" ") then local first, rest = pagename:match("^(.-)( .*)$") arg11 = first .. arg11 .. rest end -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = put.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = put.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec, expected at most 4: " .. angle_bracket_spec) end local function fetch_footnotes(separated_group) local footnotes for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed footnotes: '" .. concat(separated_group) .. "'") end if not footnotes then footnotes = {} end insert(footnotes, separated_group[j]) end return footnotes end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{term = "+"}} end local specs = {} local colon_separated_groups = put.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then error("*, **, *l, *! and *' not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = "+" end local termobj = { term = form } local footnotes = fetch_footnotes(colon_separated_group) if footnotes then for _, footnote in ipairs(footnotes) do m_headword_utilities.add_footnote_to_termobj(termobj, footnote) end end insert(specs, termobj) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(arg11, parse_props) -- (2) Check for user-specified brackets; remove any links from the lemma, but remember the original -- form so we can use it below in the 'lemma_linked' form. -- Check to see if there are brackets in the pre-text or post-text. If so, use the linked lemma (with the -- verb autolinked unless noautolinkverb is given). Otherwise, use the default headword algorithm. local function check_bracket(val) if val:find("%[%[") then alternant_multiword_spec.saw_bracket = true end end for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do check_bracket(alternant_or_word_spec.before_text) if alternant_or_word_spec.alternants then for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do for _, word_spec in ipairs(multiword_spec.word_specs) do check_bracket(word_spec.before_text) end check_bracket(multiword_spec.post_text) end end end check_bracket(alternant_multiword_spec.post_text) iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = remove_links(base.lemma) if args.noautolinkverb or base.orig_lemma:find("%[%[") then base.linked_lemma = base.orig_lemma else base.linked_lemma = "[[" .. base.orig_lemma .. "]]" end end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local function process_specs(slot, specs, canon_func, default_values, default_already_formobj) local function insert_termobj_into_slot(termobj) local formobj = m_headword_utilities.convert_termobj_to_formobj(termobj) -- If the form is -, don't insert any forms, which will result in there being no overall forms -- (in fact it will be nil). We check for that down below and substitute a single "-" as the -- form, which in turn gets turned into special labels like "no present participle". if formobj.form == "-" then if formobj.footnotes then error("Unable to preserve footnotes specified on missing form '-': FIXME: " .. dump(formobj.footnotes)) end else iut.insert_form(base.forms, slot, formobj) end end local function canonicalize_and_insert(arg) local canon_arg = canon_func(arg) if type(canon_arg) == "string" then arg.term = canon_arg insert_termobj_into_slot(arg) else for _, canon in ipairs(canon_arg) do m_headword_utilities.combine_termobj_decorations(canon, arg) insert_termobj_into_slot(canon) end end end for _, arg in ipairs(specs) do if arg.term == "+" then if default_values then -- will be nil if past tense specified as - and no past ptc given for _, val in ipairs(default_values) do val = shallowCopy(val) if default_already_formobj then local argformobj = m_headword_utilities.convert_termobj_to_formobj(arg) val.footnotes = iut.combine_footnotes(val.footnotes, argformobj.footnotes) iut.insert_form(base.forms, slot, val) else m_headword_utilities.combine_termobj_decorations(val, arg) canonicalize_and_insert(val) end end end else canonicalize_and_insert(arg) end end end set_lemma_and_default_forms(base.lemma) local all_part_default_specs = {} local function process_and_canonicalize_s_form(arg) local form = arg.term if form == "+" then error("Internal error: '+' should have been converted to '^' by now") end if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then error(("Internal error: '%s' should have already thrown an error"):format(form)) end if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" then insert(all_part_default_specs, shallowCopy(arg)) end return canonicalize_s_form(form) end process_specs("s_form", base.s_specs, process_and_canonicalize_s_form, {{term = "^"}}) if not all_part_default_specs[1] then all_part_default_specs[1] = {term = "^"} end process_specs("ing_form", base.ing_specs, function(arg) return canonicalize_ing_form(arg.term) end, all_part_default_specs) process_specs("ed_form", base.ed_specs, function(arg) return canonicalize_ed_form(arg.term) end, all_part_default_specs) process_specs("en_form", base.en_specs, function(arg) return canonicalize_en_form(arg.term) end, base.forms.ed_form, "default already formobj") iut.insert_form(base.forms, "lemma", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.linked_lemma:find("%[%[") then return base.linked_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_termobjs(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - for a spec. if not forms or not forms[1] then return {{term = "-"}} end local termobjs = {} for _, formobj in ipairs(forms) do insert(termobjs, m_headword_utilities.convert_formobj_to_termobj(formobj)) end return termobjs end pres_3sgs = fetch_termobjs("s_form") pres_ptcs = fetch_termobjs("ing_form") pasts = fetch_termobjs("ed_form") past_ptcs = fetch_termobjs("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given and the user specified -- brackets in one of the lemmas. Otherwise we use the default headword-linking algorithm. if not data.user_specified_heads[1] and alternant_multiword_spec.saw_bracket then data.heads = {} for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do insert(data.heads, m_headword_utilities.convert_formobj_to_termobj(lemma_obj)) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- set_lemma_and_default_forms(pagename) par1s = par1s or parse_inflection(args, {1, "pres_3sg"}) pres_3sgs = {} pres_ptcs = {} pasts = {} past_ptcs = {} if not par1s[1] then par1s = {{term = "+"}} end if not par2s[1] then par2s = {{term = "+"}} end if not par3s[1] then par3s = {{term = "+"}} end if not par4s[1] then par4s = {{term = "+"}} end local function process_argument(args, dest, canon_func, default_values, default_already_canonicalized) local function canonicalize_and_insert(arg) local canon_arg = canon_func(arg) if type(canon_arg) == "string" then arg.term = canon_arg m_headword_utilities.insert_termobj_combining_duplicates(dest, arg) else for _, canon in ipairs(canon_arg) do m_headword_utilities.combine_termobj_decorations(canon, arg) m_headword_utilities.insert_termobj_combining_duplicates(dest, canon) end end end for _, arg in ipairs(args) do if arg.term == "+" then for _, val in ipairs(default_values) do val = shallowCopy(val) m_headword_utilities.combine_termobj_decorations(val, arg) if default_already_canonicalized then m_headword_utilities.insert_termobj_combining_duplicates(dest, val) else canonicalize_and_insert(val) end end else canonicalize_and_insert(arg) end end end local all_part_default_specs = {} local function process_and_canonicalize_s_form(arg) local form = arg.term if form == "+" then error("Internal error: '+' should have been converted to '^' by now") end if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" or form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then insert(all_part_default_specs, shallowCopy(arg)) end return canonicalize_s_form(form) end process_argument(par1s, pres_3sgs, process_and_canonicalize_s_form, {{term = "^"}}) if not all_part_default_specs[1] then all_part_default_specs[1] = {term = "^"} end process_argument(par2s, pres_ptcs, function(arg) return canonicalize_ing_form(arg.term) end, all_part_default_specs) process_argument(par3s, pasts, function(arg) return canonicalize_ed_form(arg.term) end, all_part_default_specs) process_argument(par4s, past_ptcs, function(arg) return canonicalize_en_form(arg.term) end, pasts, "default already canonicalized") end ------------------------------------------- INSERT INFLECTIONS ------------------------------------------ insert_inflection(data, pres_3sgs, "þridda had anfeald ānfeald andweard", "s-verb-form") insert_inflection(data, pres_ptcs, "andweard dǣlnimend", "ing-form") if deepEquals(pasts, past_ptcs) then insert_inflection(data, pasts, "ānfeald forþgewiten and forþgewiten dǣlnimend", "ed-form", "na ānfeald forþgewiten oþþe forþgewiten dǣlnimend") else insert_inflection(data, pasts, "ānfeald forþgewiten", "spast") insert_inflection(data, past_ptcs, "forþgewiten dǣlnimend", "past|part") end if pagename:find(" ") then -- Check for placeholder "it" local words = split(pagename, " ") for _, word in ipairs(words) do if word == "it" or word == "its" or word == "it's" then insert(data.categories, langname .. ' ' .. cat_word(lang, 'terms with placeholder "it"')) break end end -- Check for phrasal verbs local phrasal_adverbs = list_to_set{ -- NOTE: This should only contain common phrasal adverbs, not random words like [[low]], -- [[adrift]], etc. "aback", "about", "above", "across", "after", "against", "ahead", "along", "apart", "around", "as", "aside", "at", "away", "back", "before", "behind", "below", "between", "beyond", "by", "down", "for", "forth", "from", "in", "into", "of", "off", "on", "onto", "out", "over", "past", "round", "through", "to", "together", "towards", "under", "up", "upon", "with", "without", } local allowed_non_adverb_words = list_to_set{ "it", "one", "oneself", "someone", } local base = pagename local seen_adverbs = {} -- Only consider a verb to be phrasal if it consists of a single base verb followed exclusively by either -- adverbs from `phrasal_adverbs` or placeholder words from `allowed_non_adverb_words`, where at -- least one following word is from `phrasal_adverbs` (hence [[can it]] is not a phrasal verb). while true do local prev, word = base:match("^(.+) (.-)$") if not prev then break end if phrasal_adverbs[word] then insert(seen_adverbs, word) elseif allowed_non_adverb_words[word] then -- do nothing else break end base = prev end if not base:find(" ") and seen_adverbs[1] then insert(data.categories, langname .. " " .. cat_word(lang, "phrasal verbs")) for i = #seen_adverbs, 1, -1 do insert(data.categories, langname .. ' ' .. cat_word(lang, "phrasal verbs formed with") .. ' "' .. seen_adverbs[i] .. '\"') end end end end, } ----------------------------------------------------------------------------------------- -- Suffix forms -- ----------------------------------------------------------------------------------------- pos_functions["suffix forms"] = { params = { [1] = {required = true, list = true, disallow_holes = true}, }, func = function(args, data, is_suffix) local suffix_type = {} for _, typ in ipairs(args[1]) do insert(suffix_type, typ .. "-forming suffix") end insert(data.inflections, {label = "non-lemma form of " .. m_table.serialCommaJoin(suffix_type, {conj = "or"})}) end, } return export 07vup55kji1lworcyay189s5fda5bka 55108 55107 2026-10-01T15:37:30Z Deadend0914 7211 55108 Scribunto text/plain local export = {} local pos_functions = {} --[==[ Author from 2020 on: mostly Benwing2, with significant contributions from Theknightwho. Based on a prior version by Rua (by now mostly rewritten), with contributions from Erutuon and others (see history for full attribution). ]==] local force_cat = false -- for testing; if true, categories appear in non-mainspace pages local require = require local require_when_needed = require("Module:require when needed") local en_utilities_module = "Module:en-utilities" local headword_utilities_module = "Module:headword utilities" local headword_module = "Module:headword" local inflection_utilities_module = "Module:inflection utilities" local parse_utilities_module = "Module:parse utilities" local JSON_module = "Module:JSON" local labels_module = "Module:labels" local links_module = "Module:links" local parameters_module = "Module:parameters" local string_utilities_module = "Module:string utilities" local table_module = "Module:table" local utilities_module = "Module:utilities" local yesno_module = "Module:yesno" local iut = require_when_needed(inflection_utilities_module) local put = require_when_needed(parse_utilities_module) local m_headword_utilities = require_when_needed(headword_utilities_module) local add_links_to_multiword_term = require_when_needed(headword_utilities_module, "add_links_to_multiword_term") local add_suffix = require_when_needed(en_utilities_module, "add_suffix") local apply_link_modifiers = require_when_needed(headword_utilities_module, "apply_link_modifiers") local concat = table.concat local deepEquals = require_when_needed(table_module, "deepEquals") local dump = mw.dumpObject local format_categories = require_when_needed(utilities_module, "format_categories") local full_headword = require_when_needed(headword_module, "full_headword") local get_label_info = require_when_needed(labels_module, "get_label_info") local get_link_page = require_when_needed(links_module, "get_link_page") local glossary_link = require_when_needed(headword_utilities_module, "glossary_link") local insert = table.insert local insertIfNot = require_when_needed(table_module, "insertIfNot") local ipairs = ipairs local is_regular_plural = require_when_needed(en_utilities_module, "is_regular_plural") local list_to_set = require_when_needed(table_module, "listToSet") local pairs = pairs local process_params = require_when_needed(parameters_module, "process") local remove = table.remove local remove_links = require_when_needed(links_module, "remove_links") local replacement_escape = require_when_needed(string_utilities_module, "replacement_escape") local shallowCopy = require_when_needed(table_module, "shallowCopy") local singularize = require_when_needed(en_utilities_module, "singularize") local split = require_when_needed(string_utilities_module, "split") local toJSON = require_when_needed(JSON_module, "toJSON") local toNFD = mw.ustring.toNFD local type = type local ulen = require_when_needed(string_utilities_module, "len") local ulower = require_when_needed(string_utilities_module, "lower") local umatch = require_when_needed(string_utilities_module, "match") local u = require_when_needed(string_utilities_module, "char") local ugsub = require_when_needed(string_utilities_module, "gsub") local lang = require("Module:languages").getByCode("en") local langname = lang:getCanonicalName() -- Old English localization: category wordings come from [[Module:floccnaman]] -- (see that module); the English wording is kept when a translation is missing. -- Loaded lazily and optionally, so a missing module can never break a page. local floccnaman_module = "Module:floccnaman" local floccnaman local function get_floccnaman() if floccnaman == nil then local ok, mod = pcall(require, floccnaman_module) floccnaman = ok and mod or false end return floccnaman or nil end -- Old English wording for one category word, or the English wording unchanged. local function cat_word(l, text) local mod = get_floccnaman() return mod and mod.get(l, text) or text end local list_param = {list = true, disallow_holes = true} local list_allow_holes = {list = true, allow_holes = true} local boolean_param = {type = "boolean"} local function ine(val) if val == "" then return nil else return val end end local function track(page) require("Module:debug/track")("en-headword/" .. page) return true end ------------------------------------------- UTILITY FUNCTIONS ------------------------------------------ -- Parse and return an inflection not requiring additional processing. The raw arguments come from `args[field]`, which -- is parsed for inline modifiers. local function parse_inflection(args, field, is_head) local argfield = field if type(argfield) == "table" then argfield = argfield[1] end return m_headword_utilities.parse_term_list_with_modifiers { paramname = field, forms = args[argfield], splitchar = ",", is_head = is_head, } end -- Insert the parsed inflections in `terms` (as parsed by `parse_inflection`) into `data.inflections`, with label -- `label` and optional accelerator spec `accel`. local function insert_inflection(data, terms, label, accel, no_label) for _, termobj in ipairs(terms) do m_headword_utilities.remove_termobj_field_modifiers(termobj) end m_headword_utilities.insert_inflection { headdata = data, terms = terms, label = label, no_label = no_label, accel = accel and {form = accel} or nil, } end -- Insert a fixed label `label` into the inflections for `data`. If `originating_term` is supplied, copy the decorations -- from it into the fixed label. local function insert_fixed_inflection(data, label, originating_term) m_headword_utilities.insert_fixed_inflection { headdata = data, originating_term = originating_term, label = label, } end -- Parse and insert an inflection not requiring additional processing into `data.inflections`. The raw arguments come -- from `args[field]`, which is parsed for inline modifiers. `label` is the label that the inflections are given; -- `accel` is the accelerator form, or nil. local function parse_and_insert_inflection(data, args, field, label, accel) m_headword_utilities.parse_and_insert_inflection { headdata = data, forms = args[field], paramname = field, splitchar = ",", label = label, accel = accel and {form = accel} or nil, } end -- These functions are used directly in the <> format as well as in the utility functions #2 below. local function compute_double_last_cons_stem(term) local last_cons = term:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Verb stem '" .. term .. "' must end in a consonant to use ++") end return term .. last_cons end local function compute_plusplus_s_form(term, default_s_form) if term:find("[szx]$") then -- regas -> regasses, derez -> derezzes return compute_double_last_cons_stem(term) .. "es" else return default_s_form end end -- On English Wiktionary, {{tl|en-head}} is the template that means "interjection"; it invokes this module without -- a part of speech. This wiki's template namespace is named "Bysen", not "Template", so the namespace id and the -- title without its namespace prefix are compared instead of a hard-coded "Template:en-head". -- Scribunto's title object exposes these as the fields `namespace`, `nsText` and `fullText`; it has no -- getNamespace()/getBaseText() methods, so those must not be used here. local function is_en_head_template() local title = mw.title.getCurrentTitle() return title.namespace == 10 and title.fullText == title.nsText .. ":en-head" end -- The main entry point. -- This is the only function that can be invoked from a template. function export.show(frame) local iparams = { [1] = true, } local iargs = require("Module:parameters").process(frame.args, iparams) local parargs = frame:getParent().args local poscat = iargs[1] local pos_in_1 = not poscat if pos_in_1 then poscat = ine(parargs[1]) or is_en_head_template() and "interjection" or error("Part of speech must be specified in 1=") poscat = require(headword_module).canonicalize_pos(poscat) end local indexing_poscat = pos_in_1 and "head" or poscat local params = { ["head"] = list_param, ["id"] = true, ["json"] = boolean_param, ["sort"] = true, ["splithyph"] = boolean_param, ["nosplithyph"] = boolean_param, ["hyphspace"] = boolean_param, ["nolink"] = boolean_param, ["nolinkhead"] = {type = "boolean_param", alias_of = "nolink"}, ["suffix"] = boolean_param, ["nosuffix"] = boolean_param, ["nomultiwordcat"] = boolean_param, ["abbr"] = list_param, ["the"] = true, ["def"] = {alias_of = "the"}, ["pagename"] = true, -- for testing } if not pos_in_1 then params[1] = {required = true} -- required but ignored as already processed above end local pos_data = pos_functions[indexing_poscat] local pos_func if pos_data then local pos_params = pos_data.params if pos_params then for key, val in pairs(pos_params) do params[key] = val end end pos_func = pos_data.func end local args = process_params(parargs, params) -- Account for unsupported titles, e.g. 'C|N>K' instead of 'Unsupported titles/C through N to K'. local pagename = args.pagename or mw.loadData("Module:headword/data").pagename local user_specified_heads = parse_inflection(args, "head", "is_head") local heads = user_specified_heads local autohead if args.nolink or not pagename:find("[ '%-]") then autohead = pagename else local en_no_split_apostrophe_words = list_to_set { "one's", "someone's", "he's", "she's", "it's", } local en_include_hyphen_prefixes = list_to_set { -- We don't include things that are also words even though they are often (perhaps mostly) prefixes, e.g. -- "be", "counter", "cross", "extra", "half", "mid", "over", "pan", "under". "acro", "acousto", "Afro", "agro", "anarcho", "angio", "Anglo", "ante", "anti", "arch", "auto", "bi", "bio", "cis", "co", "cryo", "crypto", "de", "demi", "eco", "electro", "Euro", "ex", "Greco", "hemi", "hydro", "hyper", "hypo", "infra", "Indo", "inter", "intra", "Judeo", "macro", "meta", "micro", "mini", "multi", "neo", "neuro", "non", "para", "peri", "post", "pre", "pro", "proto", "pseudo", "re", "semi", "sub", "super", "trans", "un", "vice", } local function is_english(term) local title = mw.title.new(term) if title and title.exists then local content = title:getContent() if content and content:find("==English==\n") then return true end end return false end local function en_split_hyphen_when_space(word) if not word:find("-", nil, true) then return nil end if args.hyphspace then return "[[" .. word:gsub("%-+", " ") .. "|" .. word .. "]]" end if args.nosplithyph then return "[[" .. word .. "]]" end if not args.splithyph then local space_word = word:gsub("%-+", " ") if is_english(space_word) then return "[[" .. space_word .. "|" .. word .. "]]" end if is_english(word) then return "[[" .. word .. "]]" end end return nil end local function en_split_apostrophe(word) local base = word:match("^(.*)'s$") if base then return "[[" .. base .. "]][[-'s|'s]]" end -- Only treat final apostrophe as possessive if preceded by something that looks like a plural ending in /z/. -- In particular we don't want to do it for words like [[truckin']]. base = word:match("^(.*[sxz])'$") if base then if base:find("s$") then local sg = singularize(base) if is_english(sg) then return "[[" .. sg .. "|" .. base .. "]][[-'|']]" end end return "[[" .. base .. "]][[-'|']]" end return "[[" .. word .. "]]" end autohead = add_links_to_multiword_term(pagename, { split_hyphen_when_space = en_split_hyphen_when_space, split_apostrophe = en_split_apostrophe, no_split_apostrophe_words = en_no_split_apostrophe_words, include_hyphen_prefixes = en_include_hyphen_prefixes, }) end if not heads[1] then heads = {{term = autohead}} else for _, headobj in ipairs(heads) do local head = headobj.term if head:find("^~") then head = apply_link_modifiers(autohead, head:sub(2), lang) headobj.term = head elseif head:find("^[!?]$") then -- If explicit head= just consists of ! or ?, add it to the end of the default head. headobj.term = autohead .. head end if head == autohead then track("redundant-head") end end end -- handle the=/def= if args.the == "~" then local newheads = {} for _, headobj in ipairs(heads) do local barehead = shallowCopy(headobj) insert(newheads, barehead) headobj.term = "the " .. headobj.term insert(newheads, headobj) end heads = newheads elseif args.the then local the = require(yesno_module)(args.the) if the then for _, headobj in ipairs(heads) do headobj.term = "the " .. headobj.term end end end local data = { lang = lang, pos_category = poscat, categories = {}, heads = heads, user_specified_heads = user_specified_heads, -- We use our own splitting algorithm so the redundant head cat will be inaccurate. no_redundant_head_cat = true, inflections = {}, nomultiwordcat = args.nomultiwordcat, sort_key = args.sort, pagename = pagename, id = args.id, force_cat_output = force_cat, } local function inscat(cat) insert(data.categories, langname .. " " .. cat_word(lang, cat)) end local is_suffix = false if args.suffix or not args.nosuffix and pagename:find("^%-") and not pagename:find("^%-%-") and poscat ~= "suffix forms" then is_suffix = true data.pos_category = "suffixes" local singular_poscat = singularize(poscat) inscat(singular_poscat .. "-forming suffixes") insert(data.inflections, {label = singular_poscat .. "-forming suffix"}) end if pos_func then pos_func(args, data, is_suffix) end local extra_categories = {} if pagename:find("[Qq]") then -- Check for q not followed by u. We want to exclude things like [[13q deletion syndrome]] and [[BFOQ]] that -- don't have a lowercase letter on either side, as well as things like [[& seq.]] and [[acq.]] that are -- abbreviations for words containing a following u. -- -- Approximate range of combining diacritics; we want to remove them so the checks below for -- a lowercase letter next to the q aren't tripped up by diacritics on the letter. local u300 = u(0x0300) local u36F = u(0x036F) local pagename_no_diacritics = ugsub(toNFD(pagename), "[" .. u300 .. "-" .. u36F .. "]", "") if pagename_no_diacritics:find("[Qq][a-tv-z]") or pagename_no_diacritics:find("[a-z]q[^u.]") or pagename_no_diacritics:find("[a-z]q$") then inscat("words containing Q not followed by U") end end -- toNFD performs decomposition, so letters that decompose to an ASCII -- vowel and a diacritic, such as é, are counted as vowels and do not do not -- need to be included in the pattern. if not umatch(ulower(toNFD(pagename)), "[aeiouyæœøəªºαεηιουω]") then inscat("words spelled wiþūtan vowels") end if pagename:find("yre$") then inscat('words ending in "-yre"') end if not pagename:find(" ") and ulen(pagename) >= 25 then insert(extra_categories, langname .. " " .. cat_word(lang, "Long words")) end if pagename:find("^[^aeiou ]*a[^aeiou ]*e[^aeiou ]*i[^aeiou ]*o[^aeiou ]*u[^aeiou ]*$") then inscat("words that use all vowels in alphabetical order") end parse_and_insert_inflection(data, args, "abbr", "abbreviation") if args.json then return toJSON(data) end return full_headword(data) .. (extra_categories[1] and format_categories(extra_categories, lang, args.sort) or "") end local function make_default_comparative(word) if word == "good" or word == "well" then return {"better"} elseif word == "bad" or word == "badly" then return {"worse"} elseif word == "far" then return {"further", "farther"} else return {add_suffix(word, "r")} end end local function make_default_superlative(word) if word == "good" or word == "well" then return {"best"} elseif word == "bad" or word == "badly" then return {"worst"} elseif word == "far" then return {"furthest", "farthest"} else return {add_suffix(word, "st.superlative")} end end -- This function does the common work between adjectives and adverbs. local function process_comparative_args(data, args, plpos) local pagename = data.pagename local comps = parse_inflection(args, 1) local sups = parse_inflection(args, "sup") local outcomps, outsups if args.componly then if comps[1] then error("Can't specify comparatives of comparative-only " .. plpos) end insert(data.inflections, {label = glossary_link("comparative") .. " form only"}) insert(data.categories, langname .. " " .. cat_word(lang, "comparative-only " .. plpos)) -- Set to empty list so we don't get any comparatives output, but process superlatives if specified. outcomps = {} if not sups[1] then -- Set to empty list so we don't get any superlatives output unless explicitly given. outsups = {} end elseif args.suponly then if comps[1] or sups[1] then error("Can't specify comparatives or superlatives of or superlative-only " .. plpos) end insert(data.inflections, {label = glossary_link("superlative") .. " form only"}) insert(data.categories, langname .. " " .. cat_word(lang, "superlative-only " .. plpos)) return end -- If the first parameter is ?, then don't show anything, just return. if comps[1] and comps[1].term == "?" then if comps[2] then error("Can't specify additional comparatives along wiþ '?'") end if sups[1] then error("Can't specify superlatives along wiþ '?' for the comparative") end return end if comps[1] and comps[1].term == "-" then local hyphencomp = remove(comps, 1) -- Remove the "-" but retain for decorations. -- Not (generally) comparable; may occasionally have a comparative if comps[1] then insert_fixed_inflection(data, "not generally <<comparable>>", hyphencomp) elseif not sups[1] then insert_fixed_inflection(data, "not <<comparable>>", hyphencomp) insert(data.categories, langname .. " " .. cat_word(lang, "uncomparable " .. plpos)) return else -- No comparative, but a superlative. insert_inflection() will correctly generate 'no comparative' if we -- pass in "-" as the value. outcomps = {hyphencomp} end elseif not comps[1] then comps = {{term = "more"}} end if not outcomps then -- not if we set `outcomps` to "-" above or processed a comparative-only term outcomps = {} -- Go over each parameter given and create a comparative and superlative form. for _, compobj in ipairs(comps) do local comp = compobj.term if comp == "-" then error("Comparative of '-' only allowed as first comparative") end if comp == "+" then comp = "+more" elseif comp == "more" and pagename ~= "many" and pagename ~= "much" then comp = "+more" elseif comp == "further" and pagename ~= "far" then comp = "+further" elseif comp == "better" and pagename ~= "good" and pagename ~= "well" then comp = "+better" elseif comp:find("~") then comp = comp:gsub("~", replacement_escape(pagename)) end compobj.origterm = comp if comp == "+more" then comp = "more [[" .. pagename .. "]]" elseif comp == "+further" then comp = {"further [[" .. pagename .. "]]", "farther [[" .. pagename .. "]]"} elseif comp == "+better" then comp = "better [[" .. pagename .. "]]" elseif comp == "er" then -- Add -er. comp = add_suffix(pagename, "r") elseif comp == "ier" then if pagename:sub(-1) ~= "y" then error("Can't specify 'ier' comparative unless the term ends wiþ 'y': " .. pagename) end comp = pagename:gsub("e?y$", "ier") elseif comp:find("^%+") then local special = m_headword_utilities.get_special_indicator(comp, "noerror") if special then comp = m_headword_utilities.handle_multiword(pagename, special, make_default_comparative) end end if type(comp) == "table" and not comp[2] then comp = comp[1] end if type(comp) == "table" then for i = 1, #comp - 1 do local outobj = shallowCopy(compobj) outobj.term = comp[i] insert(outcomps, outobj) end compobj.term = comp[#comp] insert(outcomps, compobj) else compobj.term = comp insert(outcomps, compobj) end end end if sups[1] and sups[1].term == "-" then if sups[2] then error("Can't specify '-' as superlative followed by further values") end -- No superlative. insert_inflection() will correctly generate 'no superlative' if we pass in "-" as the value. outsups = sups else if not sups[1] then sups = {{term = "+"}} end end -- `outsups` will be set if we set `outsups` to "-" above or processed a comparative-only term without superlatives. if not outsups then outsups = {} local function process_sup(sup, special, supobj, compobj) if special then sup = m_headword_utilities.handle_multiword(pagename, special, make_default_superlative) elseif sup == "-" or sup == "+" then error(("Internal error: Superlative value of '%s' should have been handled earlier"):format(sup)) elseif sup == "+most" then sup = "most [[" .. pagename .. "]]" elseif sup == "+furthest" then sup = {"furthest [[" .. pagename .. "]]", "farthest [[" .. pagename .. "]]"} elseif sup == "+best" then sup = "best [[" .. pagename .. "]]" elseif sup == "est" then -- Add -est. sup = add_suffix(pagename, "st.superlative") elseif sup == "iest" then if pagename:sub(-1) ~= "y" then error("Can't specify 'iest' superlative unless the term ends wiþ 'y': " .. pagename) end sup = pagename:gsub("e?y$", "iest") end if type(sup) == "table" and not sup[2] then sup = sup[1] end if compobj then supobj = shallowCopy(supobj) supobj = m_headword_utilities.combine_termobj_decorations(supobj, compobj) end if type(sup) == "table" then for i = 1, #sup - 1 do local outobj = shallowCopy(supobj) outobj.term = sup[i] insert(outsups, outobj) end supobj.term = sup[#sup] insert(outsups, supobj) else supobj.term = sup insert(outsups, supobj) end end for _, supobj in ipairs(sups) do local sup = supobj.term if sup == "-" then error("Superlative of '-' only allowed as first superlative") end if sup == "+" then if not comps[1] then error("Superlative of '+' can't be specified when there are no comparatives") end for _, compobj in ipairs(comps) do local comp = compobj.origterm local special if comp == "+more" then sup = "+most" elseif comp == "+further" then sup = "+furthest" elseif comp == "+better" then sup = "+best" elseif comp == "er" then sup = "est" elseif comp == "ier" then sup = "iest" else if comp:find("^%+") then special = m_headword_utilities.get_special_indicator(comp, "noerror") end if not special then -- If the full comparative was given, then derive the superlative by replacing -er with -- -est. if comp:sub(-2) == "er" then sup = comp:sub(1, -3) .. "est" else error(("The superlative cannot be derived automatically from comparative '%s' because it doesn't end in -er"):format(comp)) end end end process_sup(sup, special, supobj, compobj) end else local special = m_headword_utilities.get_special_indicator(sup, "noerror") -- Do some work here rather than in process_sup() so we don't end up double-processing a term with a '~' -- in it or a term that happens to be 'most' or similar after substitution of ~ in the comparative. if not special then if sup == "most" and pagename ~= "many" and pagename ~= "much" then sup = "+most" elseif sup == "furthest" and pagename ~= "far" then sup = "+furthest" elseif sup == "best" and pagename ~= "good" and pagename ~= "well" then sup = "+best" elseif sup:find("~") then sup = sup:gsub("~", replacement_escape(pagename)) end end process_sup(sup, special, supobj) end end end insert_inflection(data, outcomps, "<<wiþmetendlic>>", "wiþmetendlic") insert_inflection(data, outsups, "<<oferstīgendlīc>>", "oferstīgendlīc") end pos_functions["adjectives"] = { params = { [1] = list_param, ["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the comparative value", }, ["sup"] = list_param, ["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the superlative value", }, ["componly"] = boolean_param, ["suponly"] = boolean_param, }, func = function(args, data) -- Process the comparatives and superlatives. process_comparative_args(data, args, "adjectives") end, } pos_functions["adverbs"] = { params = { [1] = list_param, ["comp_qual"] = {list = "comp\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the comparative value", }, ["sup"] = list_param, ["sup_qual"] = {list = "sup\1_qual", allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the superlative value", }, ["componly"] = boolean_param, ["suponly"] = boolean_param, }, func = function(args, data) -- Process the comparatives and superlatives. process_comparative_args(data, args, "adverbs") end, } local function escape(str) return (str:gsub("\\([:#])", "\\\\%1") :gsub("[:#]", "\\%0")) end local function canonicalize_plural(pl, pagename, pos) if pl == "+" then return escape(add_suffix(pagename, "s.plural", pos)) elseif pl == "++" then return escape(compute_plusplus_s_form(pagename, add_suffix(pagename, "s.plural", pos))) elseif pl == "*" then return escape(pagename) elseif pl == "ies" then if pagename:sub(-1) == "y" then return escape(pagename:gsub("e?y$", pl)) end error("Can't specify 'ies' plural unless the term ends wiþ 'y'.") elseif pl == "s" or pl == "es" or pl == "'s" then return escape(pagename .. pl) end end local function do_nouns(args, data, pos) local pagename = data.pagename pos = pos or "noun" local plurals = parse_inflection(args, 1) local function insert_plurale_tantum_inflections(is_plural_only, originating_label) if args.sg[1] then insert_fixed_inflection(data, "normally plural", originating_label) parse_and_insert_inflection(data, args, "sg", "singular") elseif is_plural_only then insert_fixed_inflection(data, "plural only", originating_label) end if args.attr[1] then parse_and_insert_inflection(data, args, "attr", "attributive") end end local function first_pl_term() return plurals[1] and plurals[1].term or nil end if first_pl_term() == "p" then -- plurale tantum if plurals[2] then error("Wiþ plurale tantum nama, can't specify more than one plural") end data.genders = {"p"} -- this should auto-insert the correct 'pluralia tantum' category insert_plurale_tantum_inflections("plural only", plurals[1]) return end local function inscat(cat) insert(data.categories, langname .. " " .. cat_word(lang, cat)) end local need_default_plural = pos == "noun" if first_pl_term() == "sp" then -- construed as singular or plural sp = remove(plurals, 1) -- Remove the "sp" but retain it for its decorations. inscat("naman construed as singular or plural") data.genders = {"s", "p"} -- this should auto-insert the correct 'pluralia tantum' category insert_plurale_tantum_inflections(nil, sp) need_default_plural = false elseif first_pl_term() == "-" then -- Untellendlīc noun; may occasionally have a plural local hyphpl = remove(plurals, 1) -- Remove the "-" but retain for decorations. inscat("untellendlīc naman") -- If plural forms were given explicitly, then show "oft" if plurals[1] then insert_fixed_inflection(data, "oft <<untellendlīc>>", hyphpl) else insert_fixed_inflection(data, "<<untellendlīc>>", hyphpl) end need_default_plural = false elseif first_pl_term() == "#" then -- oft tellendlīc (e.g., "grilled cheese") local hashpl = remove(plurals, 1) -- Remove the "#" but retain for decorations. insert_fixed_inflection(data, "oft <<tellendlīc>>", hashpl) inscat("untellendlīc naman") inscat("tellendlīc naman") -- If no plural was given, add a default one now if not plurals[1] then plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))} end elseif first_pl_term() == "~" then -- Mixed tellendlīc/untellendlīc noun, always has a plural local tildepl = remove(plurals, 1) -- Remove the "~" but retain for decorations. insert_fixed_inflection(data, "<<tellendlīc>> and <<untellendlīc>>", tildepl) inscat("untellendlīc naman") inscat("tellendlīc naman") -- If no plural was given, add a default one now if not plurals[1] then plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))} end end -- Plural is unknown if first_pl_term() == "?" then local questionpl = remove(plurals, 1) -- Remove the "?" but retain for decorations. -- Not desired; see [[Wiktionary:Tea_room/2021/August#"Plural unknown or uncertain"]] -- insert_fixed_inflection(data, "manigfeald unġecnāwen oþþe ungewiss", questionpl) inscat("naman wiþ unġecnāwen oþþe ungewiss manigfealde") if plurals[1] then error("Ne cann āmearcian sweotole manigfealde andlang wiþ '?' of unġecnāwen/ungewiss manigfeald") end return end -- Plural is not attested if first_pl_term() == "!" then local exclampl = remove(plurals, 1) -- Remove the "!" but retain for decorations. insert_fixed_inflection(data, "plural not attested", exclampl) inscat("naman wiþ unattested manigfealde") if plurals[1] then error("Ne cann āmearcian sweotole manigfealde andlang wiþ '!' of gecȳþed manigfeald") end return end -- If no plural was given, maybe add a default one, otherwise (when "-" was given or proper noun) return. if not plurals[1] then if not need_default_plural then inscat("untellendlīc naman") return end plurals[1] = {term = escape(add_suffix(pagename, "s.plural", pos))} end -- There are plural forms to show, so show them. inscat("tellendlīc naman") local irregular, indeclinable for i, pl in ipairs(plurals) do local canon_pl = canonicalize_plural(pl.term, pagename, pos) if canon_pl then pl.term = canon_pl end local pl_term = get_link_page(pl.term, lang) if not (pagename:find(" ") or is_regular_plural(pl_term, pagename)) then irregular = true if pl_term == pagename then indeclinable = true end end end if irregular then inscat("naman wiþ fremde manigfealde") end if indeclinable then inscat("undeclīnigendlīce naman") end insert_inflection(data, plurals, "plural", "p") end -- Return the parameters to be used for nouns and proper nouns. Currently the same. local noun_params = { [1] = list_param, ["pl\1qual"] = {list = true, allow_holes = true, replaced_by = false, instead = "use <l:...> or <q:...> inline modifier on the plural", }, -- The following four only used for pluralia tantum (1=p) ["sg"] = list_param, ["attr"] = list_param, } pos_functions["naman"] = { params = noun_params, func = do_naman, } pos_functions["agennaman"] = { params = noun_params, func = function(args, data) return do_nouns(args, data, "agennama") end, } local function base_default_verb_forms(verb) return escape(add_suffix(verb, "s.verb")), escape(add_suffix(verb, "ing")), escape(add_suffix(verb, "d")) end local function default_verb_forms(verb) local full_s_form, full_ing_form, full_ed_form = base_default_verb_forms(verb) if verb:find(" ") then local first, rest = verb:match("^(.-)( .*)$") local first_s_form, first_ing_form, first_ed_form = base_default_verb_forms(first) return full_s_form, full_ing_form, full_ed_form, first_s_form .. rest, first_ing_form .. rest, first_ed_form .. rest, first, rest else return full_s_form, full_ing_form, full_ed_form, nil, nil, nil, nil, nil end end local function compute_double_last_cons_stem_of_split_verb(verb, ending) local first, rest = verb:match("^(.-)( .*)$") if not first then error("Word '" .. verb .. "' mōt hæfþ rum in sīde tō notienne **") end local last_cons = first:match("([bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ])$") if not last_cons then error("Fyrest word '" .. first .. "' mōt ende wiþ samod swēgend tō notienne **") end return first .. last_cons .. ending .. rest end local function check_non_nil_star_form(form, pagename) if form == nil then error("Word '" .. pagename .. "' mōt hæfþ rum in sīde tō notienne *, **, *l, *! or *'") end return form end local function sub_tilde(form, pagename) if not form then return nil end if form:find("~") then form = form:gsub("~", replacement_escape(pagename)) end return form end local deprecated_qual_replaced_by_inline_modifier = { list = true, allow_holes = true, replaced_by = false, instead = "use an inline modifier <q:...> or <l:...> on the value" } pos_functions["verbs"] = { params = { [1] = {list = "pres_3sg", disallow_holes = true}, ["pres_3sg\1_qual"] = deprecated_qual_replaced_by_inline_modifier, [2] = {list = "pres_ptc", disallow_holes = true}, ["pres_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier, [3] = {list = "past", disallow_holes = true}, ["past\1_qual"] = deprecated_qual_replaced_by_inline_modifier, [4] = {list = "past_ptc", allow_holes = true}, ["past_ptc\1_qual"] = deprecated_qual_replaced_by_inline_modifier, ["noautolinkverb"] = boolean_param, ["angle_bracket"] = boolean_param, }, func = function(args, data) -- Get parameters local par1s local par2s = parse_inflection(args, {2, "pres_ptc"}) local par3s = parse_inflection(args, {3, "past"}) local par4s = parse_inflection(args, {4, "past_ptc"}) local pres_3sgs, pres_ptcs, pasts, past_ptcs local pagename = data.pagename ------------------------------------------- UTILITY FUNCTIONS #2 ------------------------------------------ -- These functions are used in both in the separate-parameter format and in the override params such as past_ptc2=. local full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed local lemma local function set_lemma_and_default_forms(the_lemma) lemma = the_lemma full_default_s, full_default_ing, full_default_ed, split_default_s, split_default_ing, split_default_ed, lemma_first, lemma_rest = default_verb_forms(the_lemma) end local function canonicalize_s_form(form) if form == "+" then error("Internal error: Should not see '+' here") elseif form == "^" then return full_default_s elseif form == "*" then return check_non_nil_star_form(split_default_s, lemma) elseif form == "++" then return compute_plusplus_s_form(lemma, full_default_s) elseif form == "**" then if lemma:find("^[^ ]*[szx] ") then return compute_double_last_cons_stem_of_split_verb(lemma, "es") else return check_non_nil_star_form(split_default_s, lemma) end elseif form == "+!" then return lemma .. "s" elseif form == "*!" then return check_non_nil_star_form(lemma_first) .. "s" .. lemma_rest elseif form == "+'" then return lemma .. "'s" elseif form == "*'" then return check_non_nil_star_form(lemma_first) .. "'s" .. lemma_rest elseif form == "+l" then if lemma:find("[szx]$") then return {{term = full_default_s, l = {"US"}}, {term = compute_plusplus_s_form(lemma, full_default_s), l = {"UK"}}} else return compute_plusplus_s_form(lemma, full_default_s) end elseif form == "*l" then if lemma:find("^[^ ]*[szx] ") then return {{term = check_non_nil_star_form(split_default_s, lemma), l = {"US"}}, {term = compute_double_last_cons_stem_of_split_verb(lemma, "es"), l = {"UK"}}} else return check_non_nil_star_form(split_default_s, lemma) end else return sub_tilde(form, lemma) end end local function canonicalize_ing_form(form) if form == "+" then error("Internal error: Should not see '+' here") elseif form == "^" then return full_default_ing elseif form == "*" then return check_non_nil_star_form(split_default_ing, lemma) elseif form == "++" then return compute_double_last_cons_stem(lemma) .. "ing" elseif form == "**" then return compute_double_last_cons_stem_of_split_verb(lemma, "ing") elseif form == "+!" then return lemma .. "ing" elseif form == "*!" then return check_non_nil_star_form(lemma_first) .. "ing" .. lemma_rest elseif form == "+'" then return lemma .. "'ing" elseif form == "*'" then return check_non_nil_star_form(lemma_first) .. "'ing" .. lemma_rest elseif form == "+l" then return {{term = full_default_ing, l = {"US"}}, {term = compute_double_last_cons_stem(lemma) .. "ing", l = {"UK"}}} elseif form == "*l" then return {{term = check_non_nil_star_form(split_default_ing, lemma), l = {"US"}}, {term = compute_double_last_cons_stem_of_split_verb(lemma, "ing"), l = {"UK"}}} else return sub_tilde(form, lemma) end end local function canonicalize_ed_form(form) if form == "+" then error("Internal error: Should not see '+' here") elseif form == "^" then return full_default_ed elseif form == "*" then return check_non_nil_star_form(split_default_ed, lemma) elseif form == "++" then return compute_double_last_cons_stem(lemma) .. "ed" elseif form == "+!" then return lemma .. "ed" elseif form == "*!" then return check_non_nil_star_form(lemma_first) .. "ed" .. lemma_rest elseif form == "+'" then return {{term = lemma .. "'d"}, {term = lemma .. "'ed"}} elseif form == "*'" then return {{term = check_non_nil_star_form(lemma_first) .. "'d" .. lemma_rest}, {term = check_non_nil_star_form(lemma_first) .. "'ed" .. lemma_rest}} elseif form == "**" then return compute_double_last_cons_stem_of_split_verb(lemma, "ed") elseif form == "+l" then return {{term = full_default_ed, l = {"US"}}, {term = compute_double_last_cons_stem(lemma) .. "ed", l = {"UK"}}} elseif form == "*l" then return {{term = check_non_nil_star_form(split_default_ed, lemma), l = {"US"}}, {term = compute_double_last_cons_stem_of_split_verb(lemma, "ed"), l = {"UK"}}} else return sub_tilde(form, lemma) end end -- FIXME: options should be "+", "*", "++", "**", "+n", "*n", "++n" and "**n", but not "n" local function canonicalize_en_form(form) if form == "n" then track("n4") return add_suffix(lemma, "n") end return canonicalize_ed_form(form) end --------------------------------- MAIN PARSING/CONJUGATING CODE -------------------------------- local is_angle_bracket = args.angle_bracket if is_angle_bracket then if par2s[1] or par3s[1] or par4s[1] then error("Can't specify explicit values for 2=, 3= or 4= along wiþ the angle-bracket format") end elseif is_angle_bracket == nil and not par2s[1] and not par3s[1] and not par4s[1] and not args[1][2] and args[1][1] and args[1][1]:find("<") then if put.term_contains_top_level_html(args[1][1]) then -- Often, term_contains_top_level_html() returns true on the angle-bracket format, which would -- make the pcall() below succeed but leave the angle brackets as-is. Check for this and only do the -- pcall() if term_contains_top_level_html() returns false. is_angle_bracket = true else -- If it's ambiguous whether it's an angle-bracket format or separate params with an inline modifier, -- try to parse as the latter. If an error occurs, treat as the former. local ok ok, par1s = pcall(parse_inflection, args, {1, "pres_3sg"}) if not ok then par1s = nil is_angle_bracket = true end end end if is_angle_bracket then -------------------------- ANGLE-BRACKET FORMAT -------------------------- -- (0) Expand multiword term with angle brackets just on the first word. local arg11 = args[1][1] if arg11:find("^<.*>$") and pagename:find(" ") then local first, rest = pagename:match("^(.-)( .*)$") arg11 = first .. arg11 .. rest end -- (1) Parse the indicator specs inside of angle brackets. local function parse_indicator_spec(angle_bracket_spec) local inside = angle_bracket_spec:match("^<(.*)>$") assert(inside) local segments = put.parse_balanced_segment_run(inside, "[", "]") local comma_separated_groups = put.split_alternating_runs(segments, ",") if #comma_separated_groups > 4 then error("Too many comma-separated parts in indicator spec, expected at most 4: " .. angle_bracket_spec) end local function fetch_footnotes(separated_group) local footnotes for j = 2, #separated_group - 1, 2 do if separated_group[j + 1] ~= "" then error("Extraneous text after bracketed footnotes: '" .. concat(separated_group) .. "'") end if not footnotes then footnotes = {} end insert(footnotes, separated_group[j]) end return footnotes end local function fetch_specs(comma_separated_group) if not comma_separated_group then return {{term = "+"}} end local specs = {} local colon_separated_groups = put.split_alternating_runs(comma_separated_group, ":") for _, colon_separated_group in ipairs(colon_separated_groups) do local form = colon_separated_group[1] if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then error("*, **, *l, *! and *' not allowed inside of indicator specs: " .. angle_bracket_spec) end if form == "" then form = "+" end local termobj = { term = form } local footnotes = fetch_footnotes(colon_separated_group) if footnotes then for _, footnote in ipairs(footnotes) do m_headword_utilities.add_footnote_to_termobj(termobj, footnote) end end insert(specs, termobj) end return specs end local s_specs = fetch_specs(comma_separated_groups[1]) local ing_specs = fetch_specs(comma_separated_groups[2]) local ed_specs = fetch_specs(comma_separated_groups[3]) local en_specs = fetch_specs(comma_separated_groups[4]) return { forms = {}, s_specs = s_specs, ing_specs = ing_specs, ed_specs = ed_specs, en_specs = en_specs, } end local parse_props = { parse_indicator_spec = parse_indicator_spec, } local alternant_multiword_spec = iut.parse_inflected_text(arg11, parse_props) -- (2) Check for user-specified brackets; remove any links from the lemma, but remember the original -- form so we can use it below in the 'lemma_linked' form. -- Check to see if there are brackets in the pre-text or post-text. If so, use the linked lemma (with the -- verb autolinked unless noautolinkverb is given). Otherwise, use the default headword algorithm. local function check_bracket(val) if val:find("%[%[") then alternant_multiword_spec.saw_bracket = true end end for _, alternant_or_word_spec in ipairs(alternant_multiword_spec.alternant_or_word_specs) do check_bracket(alternant_or_word_spec.before_text) if alternant_or_word_spec.alternants then for _, multiword_spec in ipairs(alternant_or_word_spec.alternants) do for _, word_spec in ipairs(multiword_spec.word_specs) do check_bracket(word_spec.before_text) end check_bracket(multiword_spec.post_text) end end end check_bracket(alternant_multiword_spec.post_text) iut.map_word_specs(alternant_multiword_spec, function(base) if base.lemma == "" then base.lemma = pagename end base.orig_lemma = base.lemma base.lemma = remove_links(base.lemma) if args.noautolinkverb or base.orig_lemma:find("%[%[") then base.linked_lemma = base.orig_lemma else base.linked_lemma = "[[" .. base.orig_lemma .. "]]" end end) -- (3) Conjugate the verbs according to the indicator specs parsed above. local all_verb_slots = { lemma = "infinitive", lemma_linked = "infinitive", s_form = "3|s|pres", ing_form = "pres|ptcp", ed_form = "past", en_form = "past|ptcp", } local function conjugate_verb(base) local function process_specs(slot, specs, canon_func, default_values, default_already_formobj) local function insert_termobj_into_slot(termobj) local formobj = m_headword_utilities.convert_termobj_to_formobj(termobj) -- If the form is -, don't insert any forms, which will result in there being no overall forms -- (in fact it will be nil). We check for that down below and substitute a single "-" as the -- form, which in turn gets turned into special labels like "no present participle". if formobj.form == "-" then if formobj.footnotes then error("Unable to preserve footnotes specified on missing form '-': FIXME: " .. dump(formobj.footnotes)) end else iut.insert_form(base.forms, slot, formobj) end end local function canonicalize_and_insert(arg) local canon_arg = canon_func(arg) if type(canon_arg) == "string" then arg.term = canon_arg insert_termobj_into_slot(arg) else for _, canon in ipairs(canon_arg) do m_headword_utilities.combine_termobj_decorations(canon, arg) insert_termobj_into_slot(canon) end end end for _, arg in ipairs(specs) do if arg.term == "+" then if default_values then -- will be nil if past tense specified as - and no past ptc given for _, val in ipairs(default_values) do val = shallowCopy(val) if default_already_formobj then local argformobj = m_headword_utilities.convert_termobj_to_formobj(arg) val.footnotes = iut.combine_footnotes(val.footnotes, argformobj.footnotes) iut.insert_form(base.forms, slot, val) else m_headword_utilities.combine_termobj_decorations(val, arg) canonicalize_and_insert(val) end end end else canonicalize_and_insert(arg) end end end set_lemma_and_default_forms(base.lemma) local all_part_default_specs = {} local function process_and_canonicalize_s_form(arg) local form = arg.term if form == "+" then error("Internal error: '+' should have been converted to '^' by now") end if form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then error(("Internal error: '%s' should have already thrown an error"):format(form)) end if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" then insert(all_part_default_specs, shallowCopy(arg)) end return canonicalize_s_form(form) end process_specs("s_form", base.s_specs, process_and_canonicalize_s_form, {{term = "^"}}) if not all_part_default_specs[1] then all_part_default_specs[1] = {term = "^"} end process_specs("ing_form", base.ing_specs, function(arg) return canonicalize_ing_form(arg.term) end, all_part_default_specs) process_specs("ed_form", base.ed_specs, function(arg) return canonicalize_ed_form(arg.term) end, all_part_default_specs) process_specs("en_form", base.en_specs, function(arg) return canonicalize_en_form(arg.term) end, base.forms.ed_form, "default already formobj") iut.insert_form(base.forms, "lemma", {form = base.lemma}) -- Add linked version of lemma for use in head=. We write this in a general fashion in case -- there are multiple lemma forms (which isn't possible currently at this level, although it's -- possible overall using the ((...,...)) notation). iut.insert_forms(base.forms, "lemma_linked", iut.map_forms(base.forms.lemma, function(form) if form == base.lemma and base.linked_lemma:find("%[%[") then return base.linked_lemma else return form end end)) end local inflect_props = { slot_table = all_verb_slots, inflect_word_spec = conjugate_verb, } iut.inflect_multiword_or_alternant_multiword_spec(alternant_multiword_spec, inflect_props) -- (4) Fetch the forms and put the conjugated lemmas in data.heads if not explicitly given. local function fetch_termobjs(slot) local forms = alternant_multiword_spec.forms[slot] -- See above. This should only occur if the user explicitly used - for a spec. if not forms or not forms[1] then return {{term = "-"}} end local termobjs = {} for _, formobj in ipairs(forms) do insert(termobjs, m_headword_utilities.convert_formobj_to_termobj(formobj)) end return termobjs end pres_3sgs = fetch_termobjs("s_form") pres_ptcs = fetch_termobjs("ing_form") pasts = fetch_termobjs("ed_form") past_ptcs = fetch_termobjs("en_form") -- Use the "linked" form of the lemma as the head if no head= explicitly given and the user specified -- brackets in one of the lemmas. Otherwise we use the default headword-linking algorithm. if not data.user_specified_heads[1] and alternant_multiword_spec.saw_bracket then data.heads = {} for _, lemma_obj in ipairs(alternant_multiword_spec.forms.lemma_linked) do insert(data.heads, m_headword_utilities.convert_formobj_to_termobj(lemma_obj)) end end else -------------------------- SEPARATE-PARAM FORMAT -------------------------- set_lemma_and_default_forms(pagename) par1s = par1s or parse_inflection(args, {1, "pres_3sg"}) pres_3sgs = {} pres_ptcs = {} pasts = {} past_ptcs = {} if not par1s[1] then par1s = {{term = "+"}} end if not par2s[1] then par2s = {{term = "+"}} end if not par3s[1] then par3s = {{term = "+"}} end if not par4s[1] then par4s = {{term = "+"}} end local function process_argument(args, dest, canon_func, default_values, default_already_canonicalized) local function canonicalize_and_insert(arg) local canon_arg = canon_func(arg) if type(canon_arg) == "string" then arg.term = canon_arg m_headword_utilities.insert_termobj_combining_duplicates(dest, arg) else for _, canon in ipairs(canon_arg) do m_headword_utilities.combine_termobj_decorations(canon, arg) m_headword_utilities.insert_termobj_combining_duplicates(dest, canon) end end end for _, arg in ipairs(args) do if arg.term == "+" then for _, val in ipairs(default_values) do val = shallowCopy(val) m_headword_utilities.combine_termobj_decorations(val, arg) if default_already_canonicalized then m_headword_utilities.insert_termobj_combining_duplicates(dest, val) else canonicalize_and_insert(val) end end else canonicalize_and_insert(arg) end end end local all_part_default_specs = {} local function process_and_canonicalize_s_form(arg) local form = arg.term if form == "+" then error("Internal error: '+' should have been converted to '^' by now") end if form == "^" or form == "++" or form == "+l" or form == "+!" or form == "+'" or form == "*" or form == "**" or form == "*l" or form == "*!" or form == "*'" then insert(all_part_default_specs, shallowCopy(arg)) end return canonicalize_s_form(form) end process_argument(par1s, pres_3sgs, process_and_canonicalize_s_form, {{term = "^"}}) if not all_part_default_specs[1] then all_part_default_specs[1] = {term = "^"} end process_argument(par2s, pres_ptcs, function(arg) return canonicalize_ing_form(arg.term) end, all_part_default_specs) process_argument(par3s, pasts, function(arg) return canonicalize_ed_form(arg.term) end, all_part_default_specs) process_argument(par4s, past_ptcs, function(arg) return canonicalize_en_form(arg.term) end, pasts, "default already canonicalized") end ------------------------------------------- INSERT INFLECTIONS ------------------------------------------ insert_inflection(data, pres_3sgs, "þridda had anfeald ānfeald andweard", "s-verb-form") insert_inflection(data, pres_ptcs, "andweard dǣlnimend", "ing-form") if deepEquals(pasts, past_ptcs) then insert_inflection(data, pasts, "ānfeald forþgewiten and forþgewiten dǣlnimend", "ed-form", "na ānfeald forþgewiten oþþe forþgewiten dǣlnimend") else insert_inflection(data, pasts, "ānfeald forþgewiten", "spast") insert_inflection(data, past_ptcs, "forþgewiten dǣlnimend", "past|part") end if pagename:find(" ") then -- Check for placeholder "it" local words = split(pagename, " ") for _, word in ipairs(words) do if word == "it" or word == "its" or word == "it's" then insert(data.categories, langname .. ' ' .. cat_word(lang, 'terms with placeholder "it"')) break end end -- Check for phrasal verbs local phrasal_adverbs = list_to_set{ -- NOTE: This should only contain common phrasal adverbs, not random words like [[low]], -- [[adrift]], etc. "aback", "about", "above", "across", "after", "against", "ahead", "along", "apart", "around", "as", "aside", "at", "away", "back", "before", "behind", "below", "between", "beyond", "by", "down", "for", "forth", "from", "in", "into", "of", "off", "on", "onto", "out", "over", "past", "round", "through", "to", "together", "towards", "under", "up", "upon", "with", "without", } local allowed_non_adverb_words = list_to_set{ "it", "one", "oneself", "someone", } local base = pagename local seen_adverbs = {} -- Only consider a verb to be phrasal if it consists of a single base verb followed exclusively by either -- adverbs from `phrasal_adverbs` or placeholder words from `allowed_non_adverb_words`, where at -- least one following word is from `phrasal_adverbs` (hence [[can it]] is not a phrasal verb). while true do local prev, word = base:match("^(.+) (.-)$") if not prev then break end if phrasal_adverbs[word] then insert(seen_adverbs, word) elseif allowed_non_adverb_words[word] then -- do nothing else break end base = prev end if not base:find(" ") and seen_adverbs[1] then insert(data.categories, langname .. " " .. cat_word(lang, "phrasal verbs")) for i = #seen_adverbs, 1, -1 do insert(data.categories, langname .. ' ' .. cat_word(lang, "phrasal verbs formed with") .. ' "' .. seen_adverbs[i] .. '\"') end end end end, } ----------------------------------------------------------------------------------------- -- Suffix forms -- ----------------------------------------------------------------------------------------- pos_functions["suffix forms"] = { params = { [1] = {required = true, list = true, disallow_holes = true}, }, func = function(args, data, is_suffix) local suffix_type = {} for _, typ in ipairs(args[1]) do insert(suffix_type, typ .. "-forming suffix") end insert(data.inflections, {label = "non-lemma form of " .. m_table.serialCommaJoin(suffix_type, {conj = "or"})}) end, } return export 7f91hnzg0q3bclmvtac5j4aln7e8nne Module:floccnaman 828 8082 55115 55012 2026-10-02T03:38:07Z Deadend0914 7211 55115 Scribunto text/plain --[=[ Floccnaman (category names) for the Old English Wiktionary. Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or "<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki ("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need translating, never the word order. The modules that build such categories ([[Module:headword]], [[Module:headword utilities]], [[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]], [[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English wording first and keep the English wording if it is not here yet. Every missing wording is tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs to be added is always up to date: [[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]] Words are entered without leading or trailing spaces, in the singular for parts of speech ("nama", not "naman"), because that is what the pre-existing categories use. The plural forms used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...). Only categories a reader sees on an entry page are translated here. Maintenance and tracking categories (sortkeys, script codes, requests, pages with ...), the categories of the template namespace and the ones produced by MediaWiki itself stay English on purpose. ]=] local export = {} --[=[ English wording -> Old English wording. The words in this first group are already used by categories and template names that exist on this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender words match the existing "Eald Noren werlic nama" style. ]=] local words = { -- Parts of speech. ["nouns"] = "naman", ["verbs"] = "word", ["verb forms"] = "word gebīegednessa", ["adjectives"] = "tōgeīecendlice word", ["adverbs"] = "bīword", ["conjunctions"] = "fégunga", ["pronouns"] = "bīnaman", ["prepositions"] = "foresetnessa", ["participles"] = "dǣlnimend", ["past participles"] = "forþgewiten dǣlnimend", ["present participles"] = "andweard dǣlnimend", ["masculine"] = "werlic", ["masculine nouns"] = "werlic naman", ["masculine a-stem nouns"] = "werlic a-stefn naman", ["feminine"] = "wīflic", ["feminine nouns"] = "wīflic naman", ["neuter"] = "nāhwæðer", ["neuter nouns"] = "nāhwæðer naman", ["neuter a-stem nouns"] = "nāhwæðer a-stefn naman", ["lemmas"] = "frumcennede word", ["non-lemma forms"] = "gebīegede word", ["variant lemmas"] = "ōþre frumcennede word", ["variant non-lemma forms"] = "ōþre gebīegede word", ["proper nouns"] = "āgennama", ["numerals"] = "getælu", ["letters"] = "stafas", ["proverbs"] = "gecyndesprǣce", ["other languages"] = "ōþre sprǣce", ["terms borrowed from"] = "word borgodon of", ["terms borrowed back into"] = "word borgodon tō", ["terms inherited from"] = "word ierfde of", ["terms derived from"] = "word ofgangende fram", ["learned borrowings"] = "leornode borgiende", ["compound words"] = "manigfeald word", ["abbreviations"] = "scortnessa", ["plural"] = "manigfeald", ["phrases"] = "cwidas", ["determiners"] = "bīnama", ["symbols"] = "rūna", ["countable nouns"] = "tellendlīc naman", ["uncountable nouns"] = "untellendlīc naman", ["initialisms"] = "styrtende stæfgefēg", ["particles"] = "grot", ["pages with entries"] = "trāmetas mid word" } --[=[ Wording still to be translated. Anything listed here (or used in a module but not listed at all) falls back to its English form and shows up in [[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in. Suggestions, commented out until checked against a source: -- ["suffixes"] = "?", -- "Englisc ?" -- ["prefixes"] = "?", -- ["interjections"] = "?", -- ["Translingual"] = "?", -- ["taxonomic names"] = "?", ]=] --[=[ Wording that carries a variable part, as a leading phrase. For example the affix templates build categories such as "terms suffixed with -kas", where only the beginning is fixed; the language name is prepended by the caller. Longest phrase first, so the most specific rule wins. ]=] local prefixes = { {"terms spelled with ", "word areahton mid "} -- {"terms suffixed with ", "?"}, -- {"terms prefixed with ", "?"}, -- {"terms circumfixed with ", "?"}, -- {"terms infixed with ", "?"}, -- {"terms interfixed with ", "?"}, } local function track(text) local ok, track_module = pcall(require, "Module:debug/track") if ok then track_module("flocc/untranslated/" .. tostring(text)) end end --[==[ Return the Old English wording for one category name, or nil if it is not known yet. `lang` is accepted so that a wording can later be made language-specific if that turns out to be needed. ]==] function export.translate(lang, text) if type(text) ~= "string" or text == "" then return nil end if words[text] then return words[text] end for _, rule in ipairs(prefixes) do if text:sub(1, #rule[1]) == rule[1] then return rule[2] .. text:sub(#rule[1] + 1) end end track(text) return nil end --[==[ Return the Old English wording for one category name, or the English wording unchanged if it is not known yet. Use this in the modules that build categories: the language name is prepended by the caller, so only the wording itself is passed in. ]==] function export.get(lang, text) return export.translate(lang, text) or text end -- The table is exposed for tests and maintenance scripts; use get() elsewhere. export.words = words return export 07vql2proj1fvg1kfpecgva5cw7qznz 55116 55115 2026-10-02T03:39:20Z Deadend0914 7211 55116 Scribunto text/plain --[=[ Floccnaman (category names) for the Old English Wiktionary. Every category that a reader sees on an entry page is built as "<sprǣc> <word>" or "<sprǣc> <word> <word>", exactly like the categories that already exist by hand on this wiki ("Englisc nama", "Nīwenglisc fégung", "Eald Noren werlic nama"), so only the words need translating, never the word order. The modules that build such categories ([[Module:headword]], [[Module:headword utilities]], [[Module:form of]], [[Module:gender and number]], [[Module:affix]], [[Module:etymology]], [[Module:etymology/specialized]], [[Module:ang-headword]]) ask this module for the Old English wording first and keep the English wording if it is not here yet. Every missing wording is tracked in [[Wiktionary:Tracking/flocc/untranslated/<wording>]], so the list of what still needs to be added is always up to date: [[Special:WhatLinksHere/Wiktionary:Tracking/flocc/untranslated]] Words are entered without leading or trailing spaces, in the singular for parts of speech ("nama", not "naman"), because that is what the pre-existing categories use. The plural forms used for the lemma categories are entered separately ("lemmas", "non-lemma forms", ...). Only categories a reader sees on an entry page are translated here. Maintenance and tracking categories (sortkeys, script codes, requests, pages with ...), the categories of the template namespace and the ones produced by MediaWiki itself stay English on purpose. ]=] local export = {} --[=[ English wording -> Old English wording. The words in this first group are already used by categories and template names that exist on this wiki, so their spelling is established ("Flocc:Nama", "Flocc:Bīnaman", "Flocc:Nīwenglisc fégung", "Bysen:Tōgeīecendlic-Tabule", "Cynn 1 strang forþgewiten dǣlnimend"), and the gender words match the existing "Eald Noren werlic nama" style. ]=] local words = { -- Parts of speech. ["nouns"] = "naman", ["verbs"] = "word", ["verb forms"] = "word gebīegednessa", ["adjectives"] = "tōgeīecendlice word", ["adverbs"] = "bīword", ["conjunctions"] = "fégunga", ["pronouns"] = "bīnaman", ["prepositions"] = "foresetnessa", ["participles"] = "dǣlnimend", ["past participles"] = "forþgewiten dǣlnimend", ["present participles"] = "andweard dǣlnimend", ["masculine"] = "werlic", ["masculine nouns"] = "werlic naman", ["masculine a-stem nouns"] = "werlic a-stefn naman", ["feminine"] = "wīflic", ["feminine nouns"] = "wīflic naman", ["neuter"] = "nāhwæðer", ["neuter nouns"] = "nāhwæðer naman", ["neuter a-stem nouns"] = "nāhwæðer a-stefn naman", ["lemmas"] = "frumcennede word", ["non-lemma forms"] = "gebīegede word", ["variant lemmas"] = "ōþre frumcennede word", ["variant non-lemma forms"] = "ōþre gebīegede word", ["proper nouns"] = "āgennama", ["numerals"] = "getælu", ["letters"] = "stafas", ["proverbs"] = "gecyndesprǣce", ["other languages"] = "ōþre sprǣce", ["terms borrowed from"] = "word borgodon of", ["terms borrowed back into"] = "word borgodon tō", ["terms inherited from"] = "word ierfde of", ["terms derived from"] = "word ofgangende fram", ["learned borrowings"] = "leornode borgiende", ["compound words"] = "manigfeald word", ["abbreviations"] = "scortnessa", ["plural"] = "manigfeald", ["phrases"] = "cwidas", ["determiners"] = "bīnama", ["symbols"] = "rūna", ["countable nouns"] = "tellendlīc naman", ["uncountable nouns"] = "untellendlīc naman", ["initialisms"] = "styrtende stæfgefēg", ["particles"] = "grot", ["pages with entries"] = "trāmetas mid word", ["terms spelled with"] = "word areahton mid" } --[=[ Wording still to be translated. Anything listed here (or used in a module but not listed at all) falls back to its English form and shows up in [[Wiktionary:Tracking/flocc/untranslated]], so nothing breaks while the table is filled in. Suggestions, commented out until checked against a source: -- ["suffixes"] = "?", -- "Englisc ?" -- ["prefixes"] = "?", -- ["interjections"] = "?", -- ["Translingual"] = "?", -- ["taxonomic names"] = "?", ]=] --[=[ Wording that carries a variable part, as a leading phrase. For example the affix templates build categories such as "terms suffixed with -kas", where only the beginning is fixed; the language name is prepended by the caller. Longest phrase first, so the most specific rule wins. ]=] local prefixes = { {"terms spelled with ", "word areahton mid "} -- {"terms suffixed with ", "?"}, -- {"terms prefixed with ", "?"}, -- {"terms circumfixed with ", "?"}, -- {"terms infixed with ", "?"}, -- {"terms interfixed with ", "?"}, } local function track(text) local ok, track_module = pcall(require, "Module:debug/track") if ok then track_module("flocc/untranslated/" .. tostring(text)) end end --[==[ Return the Old English wording for one category name, or nil if it is not known yet. `lang` is accepted so that a wording can later be made language-specific if that turns out to be needed. ]==] function export.translate(lang, text) if type(text) ~= "string" or text == "" then return nil end if words[text] then return words[text] end for _, rule in ipairs(prefixes) do if text:sub(1, #rule[1]) == rule[1] then return rule[2] .. text:sub(#rule[1] + 1) end end track(text) return nil end --[==[ Return the Old English wording for one category name, or the English wording unchanged if it is not known yet. Use this in the modules that build categories: the language name is prepended by the caller, so only the wording itself is passed in. ]==] function export.get(lang, text) return export.translate(lang, text) or text end -- The table is exposed for tests and maintenance scripts; use get() elsewhere. export.words = words return export 0zdw64t8uy0kvyn9rk5z779dwp86gyo Bysen:en-adj 10 8181 55106 2026-10-01T15:31:40Z Deadend0914 7211 Gesceop tramet þe hafaþ '{{#invoke:en-headword|show|adjectives}}<!-- --><noinclude>{{documentation}}</noinclude>' 55106 wikitext text/x-wiki {{#invoke:en-headword|show|adjectives}}<!-- --><noinclude>{{documentation}}</noinclude> lvpkjlvgsuf4gngox245odrgtead9c2 Bysen:lbor 10 8182 55113 2026-10-01T15:56:23Z Deadend0914 7211 Redirected page to [[Bysen:learned borrowing]] 55113 wikitext text/x-wiki #REDIRECT [[Bysen:learned borrowing]] 5cgm6wrali5699tz83cp8j8e4ns5jxf Bysen:learned borrowing 10 8183 55114 2026-10-01T15:56:37Z Deadend0914 7211 Gesceop tramet þe hafaþ '<includeonly>{{#invoke:etymology/templates|specialized_borrowing|bortype=learned}}</includeonly><noinclude>{{lbor|mul|mul|test}}{{documentation}}</noinclude>' 55114 wikitext text/x-wiki <includeonly>{{#invoke:etymology/templates|specialized_borrowing|bortype=learned}}</includeonly><noinclude>{{lbor|mul|mul|test}}{{documentation}}</noinclude> leqvgq63dxaka2a0vaadfh9xzyifpot Bysen:gmw-infl-noun-a 10 8184 55118 2026-10-02T03:49:36Z Deadend0914 7211 Gesceop tramet þe hafaþ '{{#invoke:gmw-noun|a}}<noinclude>{{documentation}}</noinclude>' 55118 wikitext text/x-wiki {{#invoke:gmw-noun|a}}<noinclude>{{documentation}}</noinclude> aa22nqh4bwxx0gk5pq8o981crv0ahrw Module:gmw-noun 828 8185 55119 2026-10-02T03:50:02Z Deadend0914 7211 Gesceop tramet þe hafaþ 'local export = {} local lang = require("Module:languages").getByCode("gmw-pro") local insert = table.insert local ugsub = mw.ustring.gsub local ufind = mw.ustring.find local umatch = mw.ustring.match local ulen = mw.ustring.len local genders = { ["m"] = "masculine", ["f"] = "feminine", ["n"] = "neuter", } local n_param = {set = {"s", "p"}} local function inscat(data, cat) insert(data.categories, lang:getCanonicalName() .. " " .. cat) end local function...' 55119 Scribunto text/plain local export = {} local lang = require("Module:languages").getByCode("gmw-pro") local insert = table.insert local ugsub = mw.ustring.gsub local ufind = mw.ustring.find local umatch = mw.ustring.match local ulen = mw.ustring.len local genders = { ["m"] = "masculine", ["f"] = "feminine", ["n"] = "neuter", } local n_param = {set = {"s", "p"}} local function inscat(data, cat) insert(data.categories, lang:getCanonicalName() .. " " .. cat) end local function detect_j(stem) -- match long vowel or diphthong followed by consonants local rest, nucleus, coda = umatch(stem, "^(.-)([āēīōūąįųĀĒĪŌŪ]?̄?[aeiouAEIOU]*)([bdfghjklmnprʀstþwBDFGHJKLMNPRSTÞW]+)$") if not rest or nucleus == "" then error("Stem does not end in a vowel or diphthong followed by consonants") elseif ulen(coda) > 1 or ufind(nucleus, "^[āēīōūąįųĀĒĪŌŪ]̄?$") or ufind(nucleus, "^[aeiouAEIOU][aeiouAEIOU]$") then return "ij" elseif ufind(rest, "^[bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*$") then return "j" else error("Stem consists of multiple syllables or its weight cannot be otherwise be determined") end end local function geminate(stem) stem = stem:gsub("w$", "uw") stem = ugsub(stem, "([bdghklmnpstþ])$", "%1%1") return stem end -- Inflection functions function export.a(frame) local params = { [1] = {template_default = "{{{1}}}"}, g = {required = true, set = {"m", "n"}, template_default = "m"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local function insgendercat(cat) inscat(data, genders[args.g] .. " " .. cat) end local stem, suffix = umatch(lemma, "^(.-)([iīu])$") local stem_u local nom_sg if suffix == "ī" then stem = stem .. "ij" data.info = "''ja''-stem" insgendercat("ja-stem nouns") elseif suffix == "i" then stem = geminate(stem) .. "j" data.info = "''ja''-stem" insgendercat("ja-stem nouns") elseif suffix == "u" then stem_u = stem stem = stem .. "w" data.info = "''wa''-stem" insgendercat("wa-stem nouns") else stem = lemma data.info = "''a''-stem" insgendercat("a-stem nouns") end nom_sg = {lemma, stem .. "a"} stem_u = stem_u or stem data.info = genders[args.g] .. " " .. data.info data.forms["nom|s"] = nom_sg data.forms["acc|s"] = nom_sg data.forms["gen|s"] = {stem .. "as"} data.forms["dat|s"] = {stem .. "ē"} data.forms["ins|s"] = {stem_u .. "u"} data.forms["nom|p"] = args.g == "n" and {stem_u .. "u"} or {stem .. "ōs"} data.forms["acc|p"] = args.g == "n" and {stem_u .. "u"} or {stem .. "ā"} data.forms["gen|p"] = {stem .. "ō"} data.forms["dat|p"] = {stem_u .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.an(frame) local params = { [1] = {template_default = "{{{1}}}ō"}, n = n_param, wk = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local stem, suffix = umatch(lemma, "^(.-)([āō])$") local g if suffix == "ā" then g = "n" elseif suffix == "ō" then g = "m" else error("an-stems must end in -ō or -ā") end local data = { forms = {}, info = genders[g] .. " ''an''-stem", categories = {}, } inscat(data, genders[g] .. " an-stem nouns") if args.wk then stem_weak = args.wk inscat(data, "irregular nouns") else stem_weak = stem end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = g == "n" and {lemma} or {stem .. "an"} data.forms["gen|s"] = {stem_weak .. "ini", stem_weak .. "an"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = g == "n" and {stem .. "ōn"} or {stem .. "an"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_weak .. "anō"} data.forms["dat|p"] = {stem_weak .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.cons(frame) local params = { [1] = {template_default = "{{{1}}}"}, n = n_param, ns = true, wk = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "consonant stem", categories = {}, } inscat(data, "consonant stem nouns") if args.wk then stem_weak = args.wk inscat(data, "irregular nouns") else stem_weak = lemma end if args.ns then inscat(data, "irregular nouns") end data.forms["nom|s"] = {args.ns or lemma} data.forms["acc|s"] = {args.ns or lemma .. "u"} data.forms["gen|s"] = {stem_weak .. "i"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = {lemma .. "i"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_weak .. "ō"} data.forms["dat|p"] = {stem_weak .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.i(frame) local params = { [1] = {template_default = "{{{1}}}i"}, j = {template_default = "ij"}, n = n_param, wk = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local stem, suffix = umatch(lemma, "^(.-)(i)$") local stem_j, stem_weak_j if args.wk then stem_weak = args.wk inscat(data, "irregular nouns") else stem_weak = stem end if suffix == "i" then if (args.j or detect_j(stem)) == "ij" then stem_j = stem .. "ij" stem_weak_j = stem_weak .. "ij" else stem_j = geminate(stem) .. "j" stem_weak_j = geminate(stem_weak) .. "j" end else error("i-stems must end in -i") end data.info = "''i''-stem" inscat(data, "i-stem nouns") data.forms["nom|s"] = {lemma} data.forms["acc|s"] = data.forms["nom|s"] data.forms["gen|s"] = {stem_weak .. "ī"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = {stem .. "ī"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_weak_j .. "ō"} data.forms["dat|p"] = {stem_weak .. "im", stem_weak_j .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end export["in"] = function(frame) local params = { [1] = {template_default = "{{{1}}}ī"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "''īn''-stem", categories = {}, } inscat(data, "īn-stem nouns") local stem, suffix = umatch(lemma, "^(.-)(ī)$") if suffix ~= "ī" then error("īn-stems must end in -ī") end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "īn"} data.forms["gen|s"] = data.forms["acc|s"] data.forms["dat|s"] = data.forms["acc|s"] data.forms["ins|s"] = data.forms["acc|s"] postprocess(args, data) return make_table(data) end function export.o(frame) local params = { [1] = {template_default = "{{{1}}}u"}, j = true, n = n_param, w = {type = "boolean"}, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local stem, suffix = umatch(lemma, "^(.-)([iu])$") local stem_u if suffix == "i" then if (args.j or detect_j(stem)) == "ij" then stem = stem .. "ij" elseif umatch(stem, "^(.-)([bdfghjklmnprʀstþw-]+)(in)$") then stem = ugsub(stem, "in$", "unn") .. "j" else stem = geminate(stem) .. "j" end data.info = "''ī''/''jō''-stem" inscat(data, "ī/jō-stem nouns") elseif suffix == "u" then if args.w then stem_u = stem stem = stem .. "w" data.info = "''wō''-stem" inscat(data, "wō-stem nouns") else data.info = "''ō''-stem" inscat(data, "ō-stem nouns") end else error("ō-stems must end in -i or -u") end stem_u = stem_u or stem data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "ā"} data.forms["gen|s"] = data.forms["acc|s"] data.forms["dat|s"] = {stem .. "ē"} data.forms["ins|s"] = {stem_u .. "u"} data.forms["nom|p"] = {stem .. "ō"} data.forms["acc|p"] = {stem .. "ā"} data.forms["gen|p"] = {stem .. "ō"} data.forms["dat|p"] = {stem .. "ōm", stem_u .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.on(frame) local params = { [1] = {template_default = "{{{1}}}ā"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "''ōn''-stem", categories = {}, } inscat(data, "ōn-stem nouns") local stem, suffix = umatch(lemma, "^(.-)(ā)$") if suffix ~= "ā" then error("ōn-stems must end in -ā") end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "ōn"} data.forms["gen|s"] = data.forms["acc|s"] data.forms["dat|s"] = data.forms["acc|s"] data.forms["ins|s"] = data.forms["acc|s"] data.forms["nom|p"] = data.forms["acc|s"] data.forms["acc|p"] = data.forms["acc|s"] data.forms["gen|p"] = {stem .. "ōnō"} data.forms["dat|p"] = {stem .. "ōm", stem .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.r(frame) local params = { [1] = {template_default = "{{{1}}}er"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "r-stem", categories = {}, } inscat(data, "r-stem nouns") local stem, suffix = umatch(lemma, "^(.-)(er)$") if suffix ~= "er" then error("r-stems must end in -er") end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "ar"} data.forms["gen|s"] = {stem .. "ur"} data.forms["dat|s"] = {stem .. "ri"} data.forms["ins|s"] = data.forms["dat|s"] data.forms["nom|p"] = {stem .. "ar"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem .. "rō"} data.forms["dat|p"] = {stem .. "rum"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.u(frame) local params = { [1] = {template_default = "{{{1}}}u"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local stem, suffix = umatch(lemma, "^(.-)(u)$") if suffix ~= "u" then error("u-stems must end in -u") end data.info = "''u''-stem" inscat(data, "u-stem nouns") data.forms["nom|s"] = {lemma} data.forms["acc|s"] = data.forms["nom|s"] data.forms["gen|s"] = {stem .. "ō"} data.forms["dat|s"] = {stem .. "iwi", stem .. "ō"} data.forms["ins|s"] = {stem .. "u"} data.forms["nom|p"] = {stem .. "iwi", stem .. "ō"} data.forms["acc|p"] = {stem .. "ū"} data.forms["gen|p"] = {stem .. "iwō"} data.forms["dat|p"] = {stem .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.z(frame) local params = { [1] = {template_default = "{{{1}}}"}, n = n_param, ns = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "''z''-stem", categories = {}, } inscat(data, "z-stem nouns") local stem_i = ugsub(lemma, "e(u?[bdfghklmnprʀstþw]*)$", "i%1") if args.ns then inscat(data, "irregular nouns") end data.forms["nom|s"] = {args.ns or lemma} data.forms["acc|s"] = data.forms["nom|s"] data.forms["gen|s"] = {stem_i .. "iʀi"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = {stem_i .. "iʀu"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_i .. "iʀō"} data.forms["dat|p"] = {stem_i .. "iʀum"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function postprocess(args, data) data.n = args.n if args.n == "p" then inscat(data, "pluralia tantum") elseif args.n == "s" then inscat(data, "singularia tantum") elseif args.n then error("Internal error: args= must be \"s\" or \"p\".") end for key, form in pairs(data.forms) do -- Do not show singular or plural forms for nominals that don't have them if (args.n == "p" and key:find("|s$")) or (args.n == "s" and key:find("|p$")) then form = nil end data.forms[key] = form end end -- Make the table function make_table(data) local function repl(param) if param == "info" then return mw.getContentLanguage():ucfirst(data.info or "") end local forms = data.forms[param] if not forms then return "&mdash;" end local ret = {} for key, subform in ipairs(forms) do -- i-umlaut if ufind(subform, "[iīįǐj]") then subform = ugsub(subform, "([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW])e(u?)([bdfghjklmnprʀstþw]+)([iīįj])", "%1i%2%3%4") subform = ugsub(subform, "([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW])o([bdfghjklmnprʀstþw]+)([iīįj])", "%1u%2%3") end -- *u[+stress] > *o /{C,#}_C[-nasal]V[+back] if ufind(subform, "u") then subform = ugsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]+)u([bdfghklprʀstþw]+)([aoāōą])", "%1o%2%3") end -- *w > ∅ /V́_*u if ufind(subform, "[aeiouāēīōūAEIOUĀĒĪŌŪ]wu") then subform = ugsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*)uwu", "%1ū") subform = ugsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*)([aeiouāēīōūAEIOUĀĒĪŌŪ])w(u)", "%1%2%3") end -- Mahlow's Law (*ōu > *ō / _C{#,V}) if ufind(subform, "ō[uw]") then subform = ugsub(subform, "(ō)[uw]", "%1") end if ufind(subform, "ū[uw]") then subform = ugsub(subform, "(ū)[uw]", "%1") end -- C[+plosive -voice] > CC /_LV (Ringe 2014:54) if ufind(subform, "[ptkh][lr]") then subform = ugsub(subform, "([aeiouāēīōūAEIOUĀĒĪŌŪ])([ptkh])([lr][aeiouāēīōūąįų])", "%1%2%2%3") end insert(ret, require("Module:links").full_link({lang = lang, alt = "*" .. subform})) end return table.concat(ret, ", ") end local wikicode = {} insert(wikicode, [=[ {| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="border: solid 1px var(--wikt-palette-grey-4, #CCCCCC);" |- style="background: var(--wikt-palette-grey-3, #CCCCCC); text-align: left;" ! class="vsToggleElement" colspan="3" | {{{info}}} |- class="vsShow" ! style="width: 9em;" | ! style="width: 15em; background: var(--wikt-palette-grey-2, #DDDDDD);" colspan="2" | Singular |- class="vsShow" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Nominative | colspan="2" | {{{nom|s}}} |- class="vsShow" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Genitive | colspan="2" | {{{gen|s}}} |- class="vsHide" | style="width: 9em;" | ! style="width: 15em; background: var(--wikt-palette-grey-2, #DDDDDD);" | Singular ! style="width: 15em; background: var(--wikt-palette-grey-2, #DDDDDD);" | Plural |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Nominative | {{{nom|s}}} | {{{nom|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Accusative | {{{acc|s}}} | {{{acc|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Genitive | {{{gen|s}}} | {{{gen|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Dative | {{{dat|s}}} | {{{dat|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Instrumental | {{{ins|s}}} | {{{ins|p}}} |}]=]) return ugsub(table.concat(wikicode), "{{{([#!]?[a-z0-9|]+)}}}", repl) .. require("Module:utilities").format_categories(data.categories, lang) end return export ox3t3ekqz8rii33xjtigbpfy955zmfh 55125 55119 2026-10-02T04:18:06Z Deadend0914 7211 55125 Scribunto text/plain local export = {} local lang = require("Module:languages").getByCode("gmw-pro") local insert = table.insert local ugsub = mw.ustring.gsub local ufind = mw.ustring.find local umatch = mw.ustring.match local ulen = mw.ustring.len local genders = { ["m"] = "masculine", ["f"] = "feminine", ["n"] = "nāhwæðer", } local n_param = {set = {"s", "p"}} local function inscat(data, cat) insert(data.categories, lang:getCanonicalName() .. " " .. cat) end local function detect_j(stem) -- match long vowel or diphthong followed by consonants local rest, nucleus, coda = umatch(stem, "^(.-)([āēīōūąįųĀĒĪŌŪ]?̄?[aeiouAEIOU]*)([bdfghjklmnprʀstþwBDFGHJKLMNPRSTÞW]+)$") if not rest or nucleus == "" then error("Stem does not end in a vowel or diphthong followed by consonants") elseif ulen(coda) > 1 or ufind(nucleus, "^[āēīōūąįųĀĒĪŌŪ]̄?$") or ufind(nucleus, "^[aeiouAEIOU][aeiouAEIOU]$") then return "ij" elseif ufind(rest, "^[bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*$") then return "j" else error("Stem consists of multiple syllables or its weight cannot be otherwise be determined") end end local function geminate(stem) stem = stem:gsub("w$", "uw") stem = ugsub(stem, "([bdghklmnpstþ])$", "%1%1") return stem end -- Inflection functions function export.a(frame) local params = { [1] = {template_default = "{{{1}}}"}, g = {required = true, set = {"m", "n"}, template_default = "m"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local function insgendercat(cat) inscat(data, genders[args.g] .. " " .. cat) end local stem, suffix = umatch(lemma, "^(.-)([iīu])$") local stem_u local nom_sg if suffix == "ī" then stem = stem .. "ij" data.info = "''ja''-stem" insgendercat("ja-stem nouns") elseif suffix == "i" then stem = geminate(stem) .. "j" data.info = "''ja''-stem" insgendercat("ja-stem nouns") elseif suffix == "u" then stem_u = stem stem = stem .. "w" data.info = "''wa''-stem" insgendercat("wa-stem nouns") else stem = lemma data.info = "''a''-stem" insgendercat("a-stem nouns") end nom_sg = {lemma, stem .. "a"} stem_u = stem_u or stem data.info = genders[args.g] .. " " .. data.info data.forms["nom|s"] = nom_sg data.forms["acc|s"] = nom_sg data.forms["gen|s"] = {stem .. "as"} data.forms["dat|s"] = {stem .. "ē"} data.forms["ins|s"] = {stem_u .. "u"} data.forms["nom|p"] = args.g == "n" and {stem_u .. "u"} or {stem .. "ōs"} data.forms["acc|p"] = args.g == "n" and {stem_u .. "u"} or {stem .. "ā"} data.forms["gen|p"] = {stem .. "ō"} data.forms["dat|p"] = {stem_u .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.an(frame) local params = { [1] = {template_default = "{{{1}}}ō"}, n = n_param, wk = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local stem, suffix = umatch(lemma, "^(.-)([āō])$") local g if suffix == "ā" then g = "n" elseif suffix == "ō" then g = "m" else error("an-stems must end in -ō or -ā") end local data = { forms = {}, info = genders[g] .. " ''an''-stem", categories = {}, } inscat(data, genders[g] .. " an-stem nouns") if args.wk then stem_weak = args.wk inscat(data, "irregular nouns") else stem_weak = stem end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = g == "n" and {lemma} or {stem .. "an"} data.forms["gen|s"] = {stem_weak .. "ini", stem_weak .. "an"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = g == "n" and {stem .. "ōn"} or {stem .. "an"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_weak .. "anō"} data.forms["dat|p"] = {stem_weak .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.cons(frame) local params = { [1] = {template_default = "{{{1}}}"}, n = n_param, ns = true, wk = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "consonant stem", categories = {}, } inscat(data, "consonant stem nouns") if args.wk then stem_weak = args.wk inscat(data, "irregular nouns") else stem_weak = lemma end if args.ns then inscat(data, "irregular nouns") end data.forms["nom|s"] = {args.ns or lemma} data.forms["acc|s"] = {args.ns or lemma .. "u"} data.forms["gen|s"] = {stem_weak .. "i"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = {lemma .. "i"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_weak .. "ō"} data.forms["dat|p"] = {stem_weak .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.i(frame) local params = { [1] = {template_default = "{{{1}}}i"}, j = {template_default = "ij"}, n = n_param, wk = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local stem, suffix = umatch(lemma, "^(.-)(i)$") local stem_j, stem_weak_j if args.wk then stem_weak = args.wk inscat(data, "irregular nouns") else stem_weak = stem end if suffix == "i" then if (args.j or detect_j(stem)) == "ij" then stem_j = stem .. "ij" stem_weak_j = stem_weak .. "ij" else stem_j = geminate(stem) .. "j" stem_weak_j = geminate(stem_weak) .. "j" end else error("i-stems must end in -i") end data.info = "''i''-stem" inscat(data, "i-stem nouns") data.forms["nom|s"] = {lemma} data.forms["acc|s"] = data.forms["nom|s"] data.forms["gen|s"] = {stem_weak .. "ī"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = {stem .. "ī"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_weak_j .. "ō"} data.forms["dat|p"] = {stem_weak .. "im", stem_weak_j .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end export["in"] = function(frame) local params = { [1] = {template_default = "{{{1}}}ī"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "''īn''-stem", categories = {}, } inscat(data, "īn-stem nouns") local stem, suffix = umatch(lemma, "^(.-)(ī)$") if suffix ~= "ī" then error("īn-stems must end in -ī") end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "īn"} data.forms["gen|s"] = data.forms["acc|s"] data.forms["dat|s"] = data.forms["acc|s"] data.forms["ins|s"] = data.forms["acc|s"] postprocess(args, data) return make_table(data) end function export.o(frame) local params = { [1] = {template_default = "{{{1}}}u"}, j = true, n = n_param, w = {type = "boolean"}, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local stem, suffix = umatch(lemma, "^(.-)([iu])$") local stem_u if suffix == "i" then if (args.j or detect_j(stem)) == "ij" then stem = stem .. "ij" elseif umatch(stem, "^(.-)([bdfghjklmnprʀstþw-]+)(in)$") then stem = ugsub(stem, "in$", "unn") .. "j" else stem = geminate(stem) .. "j" end data.info = "''ī''/''jō''-stem" inscat(data, "ī/jō-stem nouns") elseif suffix == "u" then if args.w then stem_u = stem stem = stem .. "w" data.info = "''wō''-stem" inscat(data, "wō-stem nouns") else data.info = "''ō''-stem" inscat(data, "ō-stem nouns") end else error("ō-stems must end in -i or -u") end stem_u = stem_u or stem data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "ā"} data.forms["gen|s"] = data.forms["acc|s"] data.forms["dat|s"] = {stem .. "ē"} data.forms["ins|s"] = {stem_u .. "u"} data.forms["nom|p"] = {stem .. "ō"} data.forms["acc|p"] = {stem .. "ā"} data.forms["gen|p"] = {stem .. "ō"} data.forms["dat|p"] = {stem .. "ōm", stem_u .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.on(frame) local params = { [1] = {template_default = "{{{1}}}ā"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "''ōn''-stem", categories = {}, } inscat(data, "ōn-stem nouns") local stem, suffix = umatch(lemma, "^(.-)(ā)$") if suffix ~= "ā" then error("ōn-stems must end in -ā") end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "ōn"} data.forms["gen|s"] = data.forms["acc|s"] data.forms["dat|s"] = data.forms["acc|s"] data.forms["ins|s"] = data.forms["acc|s"] data.forms["nom|p"] = data.forms["acc|s"] data.forms["acc|p"] = data.forms["acc|s"] data.forms["gen|p"] = {stem .. "ōnō"} data.forms["dat|p"] = {stem .. "ōm", stem .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.r(frame) local params = { [1] = {template_default = "{{{1}}}er"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "r-stem", categories = {}, } inscat(data, "r-stem nouns") local stem, suffix = umatch(lemma, "^(.-)(er)$") if suffix ~= "er" then error("r-stems must end in -er") end data.forms["nom|s"] = {lemma} data.forms["acc|s"] = {stem .. "ar"} data.forms["gen|s"] = {stem .. "ur"} data.forms["dat|s"] = {stem .. "ri"} data.forms["ins|s"] = data.forms["dat|s"] data.forms["nom|p"] = {stem .. "ar"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem .. "rō"} data.forms["dat|p"] = {stem .. "rum"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.u(frame) local params = { [1] = {template_default = "{{{1}}}u"}, n = n_param, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = nil, categories = {}, } local stem, suffix = umatch(lemma, "^(.-)(u)$") if suffix ~= "u" then error("u-stems must end in -u") end data.info = "''u''-stem" inscat(data, "u-stem nouns") data.forms["nom|s"] = {lemma} data.forms["acc|s"] = data.forms["nom|s"] data.forms["gen|s"] = {stem .. "ō"} data.forms["dat|s"] = {stem .. "iwi", stem .. "ō"} data.forms["ins|s"] = {stem .. "u"} data.forms["nom|p"] = {stem .. "iwi", stem .. "ō"} data.forms["acc|p"] = {stem .. "ū"} data.forms["gen|p"] = {stem .. "iwō"} data.forms["dat|p"] = {stem .. "um"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function export.z(frame) local params = { [1] = {template_default = "{{{1}}}"}, n = n_param, ns = true, pagename = true, } local args = require("Module:parameters").process(frame:getParent().args, params) local lemma = args[1] or args.pagename or mw.loadData("Module:headword/data").pagename local data = { forms = {}, info = "''z''-stem", categories = {}, } inscat(data, "z-stem nouns") local stem_i = ugsub(lemma, "e(u?[bdfghklmnprʀstþw]*)$", "i%1") if args.ns then inscat(data, "irregular nouns") end data.forms["nom|s"] = {args.ns or lemma} data.forms["acc|s"] = data.forms["nom|s"] data.forms["gen|s"] = {stem_i .. "iʀi"} data.forms["dat|s"] = data.forms["gen|s"] data.forms["ins|s"] = data.forms["gen|s"] data.forms["nom|p"] = {stem_i .. "iʀu"} data.forms["acc|p"] = data.forms["nom|p"] data.forms["gen|p"] = {stem_i .. "iʀō"} data.forms["dat|p"] = {stem_i .. "iʀum"} data.forms["ins|p"] = data.forms["dat|p"] postprocess(args, data) return make_table(data) end function postprocess(args, data) data.n = args.n if args.n == "p" then inscat(data, "pluralia tantum") elseif args.n == "s" then inscat(data, "singularia tantum") elseif args.n then error("Internal error: args= must be \"s\" or \"p\".") end for key, form in pairs(data.forms) do -- Do not show singular or plural forms for nominals that don't have them if (args.n == "p" and key:find("|s$")) or (args.n == "s" and key:find("|p$")) then form = nil end data.forms[key] = form end end -- Make the table function make_table(data) local function repl(param) if param == "info" then return mw.getContentLanguage():ucfirst(data.info or "") end local forms = data.forms[param] if not forms then return "&mdash;" end local ret = {} for key, subform in ipairs(forms) do -- i-umlaut if ufind(subform, "[iīįǐj]") then subform = ugsub(subform, "([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW])e(u?)([bdfghjklmnprʀstþw]+)([iīįj])", "%1i%2%3%4") subform = ugsub(subform, "([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW])o([bdfghjklmnprʀstþw]+)([iīįj])", "%1u%2%3") end -- *u[+stress] > *o /{C,#}_C[-nasal]V[+back] if ufind(subform, "u") then subform = ugsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]+)u([bdfghklprʀstþw]+)([aoāōą])", "%1o%2%3") end -- *w > ∅ /V́_*u if ufind(subform, "[aeiouāēīōūAEIOUĀĒĪŌŪ]wu") then subform = ugsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*)uwu", "%1ū") subform = ugsub(subform, "^([bdfghjklmnprʀstþwBDFGHJKLMNPRƦSTÞW]*)([aeiouāēīōūAEIOUĀĒĪŌŪ])w(u)", "%1%2%3") end -- Mahlow's Law (*ōu > *ō / _C{#,V}) if ufind(subform, "ō[uw]") then subform = ugsub(subform, "(ō)[uw]", "%1") end if ufind(subform, "ū[uw]") then subform = ugsub(subform, "(ū)[uw]", "%1") end -- C[+plosive -voice] > CC /_LV (Ringe 2014:54) if ufind(subform, "[ptkh][lr]") then subform = ugsub(subform, "([aeiouāēīōūAEIOUĀĒĪŌŪ])([ptkh])([lr][aeiouāēīōūąįų])", "%1%2%2%3") end insert(ret, require("Module:links").full_link({lang = lang, alt = "*" .. subform})) end return table.concat(ret, ", ") end local wikicode = {} insert(wikicode, [=[ {| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="border: solid 1px var(--wikt-palette-grey-4, #CCCCCC);" |- style="background: var(--wikt-palette-grey-3, #CCCCCC); text-align: left;" ! class="vsToggleElement" colspan="3" | {{{info}}} |- class="vsShow" ! style="width: 9em;" | ! style="width: 15em; background: var(--wikt-palette-grey-2, #DDDDDD);" colspan="2" | Singular |- class="vsShow" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Nominative | colspan="2" | {{{nom|s}}} |- class="vsShow" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Genitive | colspan="2" | {{{gen|s}}} |- class="vsHide" | style="width: 9em;" | ! style="width: 15em; background: var(--wikt-palette-grey-2, #DDDDDD);" | Singular ! style="width: 15em; background: var(--wikt-palette-grey-2, #DDDDDD);" | Plural |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Nominative | {{{nom|s}}} | {{{nom|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Accusative | {{{acc|s}}} | {{{acc|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Genitive | {{{gen|s}}} | {{{gen|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Dative | {{{dat|s}}} | {{{dat|p}}} |- class="vsHide" ! style="background: var(--wikt-palette-grey-1, #EEEEEE)" | Instrumental | {{{ins|s}}} | {{{ins|p}}} |}]=]) return ugsub(table.concat(wikicode), "{{{([#!]?[a-z0-9|]+)}}}", repl) .. require("Module:utilities").format_categories(data.categories, lang) end return export jt3l1d7b68nnx1vbt78axa6p93p5zkm Module:gmw-pro-sortkey 828 8186 55120 2026-10-02T03:51:57Z Deadend0914 7211 Gesceop tramet þe hafaþ 'local export = {} local u = mw.ustring.char local remove_diacritics = u(0x0304) .. u(0x0328) -- macron, ogonek local oneChar = { ["ʀ"] = "r" } function export.makeSortKey(text, lang, sc) return mw.ustring.upper(mw.ustring.toNFC(mw.ustring.gsub(mw.ustring.toNFD(mw.ustring.gsub(mw.ustring.lower(text), ".", oneChar)), "[" .. remove_diacritics .. "]", ""))) -- decompose, remove appropriate diacritics, then recompose again end return export' 55120 Scribunto text/plain local export = {} local u = mw.ustring.char local remove_diacritics = u(0x0304) .. u(0x0328) -- macron, ogonek local oneChar = { ["ʀ"] = "r" } function export.makeSortKey(text, lang, sc) return mw.ustring.upper(mw.ustring.toNFC(mw.ustring.gsub(mw.ustring.toNFD(mw.ustring.gsub(mw.ustring.lower(text), ".", oneChar)), "[" .. remove_diacritics .. "]", ""))) -- decompose, remove appropriate diacritics, then recompose again end return export 7lc3wpilcm5n7sf864u24efw71z1off Module:data/namespaces 828 8187 55121 2026-10-02T03:52:27Z Deadend0914 7211 Gesceop tramet þe hafaþ 'local data = {} local gsub = string.gsub local next = next local ulower = require("Module:string utilities").lower for _, namespace in next, mw.site.namespaces do local prefix = ulower((gsub(namespace.name, "_", " "))) data[prefix] = prefix for _, alias in next, namespace.aliases do data[ulower((gsub(alias, "_", " ")))] = prefix end end return data' 55121 Scribunto text/plain local data = {} local gsub = string.gsub local next = next local ulower = require("Module:string utilities").lower for _, namespace in next, mw.site.namespaces do local prefix = ulower((gsub(namespace.name, "_", " "))) data[prefix] = prefix for _, alias in next, namespace.aliases do data[ulower((gsub(alias, "_", " ")))] = prefix end end return data qbasf1wuit8dmyo26k8ojua3okgfc5l Bysen:reconstructed/styles.css 10 8188 55122 2026-10-02T03:56:18Z Deadend0914 7211 Gesceop tramet þe hafaþ '/* palettize? the last time, people complained. these are about as close as you can get: background: var(--wikt-palette-grey-orange-2, AntiqueWhite); border-color: var(--wikt-palette-grey-orange-6, Tan); However, the background color is slightly less saturated than AntiqueWhite. In addition, there is still the filter for the icon. Using just skin-invert-image makes the asterisk white, which is distracting. Here it just remains grey. -...' 55122 sanitized-css text/css /* palettize? the last time, people complained. these are about as close as you can get: background: var(--wikt-palette-grey-orange-2, AntiqueWhite); border-color: var(--wikt-palette-grey-orange-6, Tan); However, the background color is slightly less saturated than AntiqueWhite. In addition, there is still the filter for the icon. Using just skin-invert-image makes the asterisk white, which is distracting. Here it just remains grey. -- Surjection 2025-09-27 */ .messagebox-reconstruction { background: AntiqueWhite; border-color: Tan; } /* dark mode stuff; styles need to be duplicated exactly between these two media blocks */ @media screen { html.skin-theme-clientpref-night .messagebox-reconstruction-icon { filter: contrast(0%) brightness(100%); } html.skin-theme-clientpref-night .messagebox-reconstruction { background: var(--wikt-palette-beige, #2f1f10); border-color: #c9b165; } } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os .messagebox-reconstruction-icon { filter: contrast(0%) brightness(100%); } html.skin-theme-clientpref-os .messagebox-reconstruction { background: var(--wikt-palette-beige, #2f1f10); border-color: #c9b165; } } 1sjnsvqtg9izwe6mzkkglwxo1l4a4hj Bysen:reconstructed 10 8189 55123 2026-10-02T04:11:32Z Deadend0914 7211 Gesceop tramet þe hafaþ '{| class="messagebox messagebox-reconstruction" style="margin-bottom: 0.5em; border-style: solid; border-width: 1px; border-spacing: 0.5rem" |- | [[Image:Asterisk.svg|none|45px|class=messagebox-reconstruction-icon|link=]] | Þis {{#switch:{{NAMESPACE}}|Reconstruction = {{reconstructed/sub}}}} gewrit hielt '''[[Wiktionary:Amacod word|amacod and frumcenned word]]'''. Þus, sē/þā word hēr ne biþ directly [[w:wot sprǣc|wot]], būtan biþ geþōht tō bēonne fo...' 55123 wikitext text/x-wiki {| class="messagebox messagebox-reconstruction" style="margin-bottom: 0.5em; border-style: solid; border-width: 1px; border-spacing: 0.5rem" |- | [[Image:Asterisk.svg|none|45px|class=messagebox-reconstruction-icon|link=]] | Þis {{#switch:{{NAMESPACE}}|Reconstruction = {{reconstructed/sub}}}} gewrit hielt '''[[Wiktionary:Amacod word|amacod and frumcenned word]]'''. Þus, sē/þā word hēr ne biþ directly [[w:wot sprǣc|wot]], būtan biþ geþōht tō bēonne for [[w:Wiþmetenlic cræft|wiþmetenlic]] tācnu. |}<templatestyles src="Template:reconstructed/styles.css" /><includeonly>{{#invoke:reconstruction|main}}</includeonly><noinclude>{{documentation}}</noinclude> efkaudart8gcb1rz5l3dwq0kf9piphl Module:reconstruction 828 8190 55124 2026-10-02T04:12:11Z Deadend0914 7211 Gesceop tramet þe hafaþ 'local export = {} -- from [[WT:POS]] local POS_headers = require "Module:table".listToSet { "Adjective", "Adverb", "Ambiposition", "Article", "Circumfix", "Circumposition", "Classifier", "Combining form", "Conjunction", "Contraction", "Counter", "Determiner", "Diacritical mark", "Han character", "Hanja", "Hanzi", "Ideophone", "Infix", "Interfix", "Interjection", "Kanji", "Letter", "Ligature", "Noun", "Number", "Numeral", "Participle", "Particle", "Phrase",...' 55124 Scribunto text/plain local export = {} -- from [[WT:POS]] local POS_headers = require "Module:table".listToSet { "Adjective", "Adverb", "Ambiposition", "Article", "Circumfix", "Circumposition", "Classifier", "Combining form", "Conjunction", "Contraction", "Counter", "Determiner", "Diacritical mark", "Han character", "Hanja", "Hanzi", "Ideophone", "Infix", "Interfix", "Interjection", "Kanji", "Letter", "Ligature", "Noun", "Number", "Numeral", "Participle", "Particle", "Phrase", "Postposition", "Prefix", "Preposition", "Prepositional phrase", "Pronoun", "Proper noun", "Proverb", "Punctuation mark", "Romanization", "Root", "Suffix", "Syllable", "Symbol", "Verb", } -- This isn't a perfect pattern, but should work in entries that don't have -- bad syntax. local title_pattern = "%f[^\n%z]==+%s*(.-)%s*==+" local function count_POS_headers(title) local POS_count = 0 local content = title:getContent() if content then for header in content:gmatch(title_pattern) do if POS_headers[header] then POS_count = POS_count + 1 end end end return POS_count end local function has_header(title, header_to_find) local content = title:getContent() if content then for header in content:gmatch(title_pattern) do if header == header_to_find then return true end end end return false end -- Track Proto-Indo-European entries with more than one part-of-speech header. -- Invoked by {{reconstruction}}, requested by Victar. function export.main(frame) local title = mw.title.getCurrentTitle() local cats = {} local language = title.text:match "^[^/]+" local langcode = require("Module:languages").getByCanonicalName(language) if not langcode then -- Can happen e.g. if used on a user page return end if language == "Proto-Indo-European" and count_POS_headers(title) > 1 then table.insert(cats, "Proto-Indo-European entries with more than one part of speech") end local has_references_header = has_header(title, "References") local has_further_reading_header = has_header(title, "Further reading") if not has_references_header then table.insert(cats, language .. " entries without References header") end local temp_rfref = "" if not (has_references_header or has_further_reading_header) then table.insert(cats, language .. " entries without References or Further reading header") if langcode and langcode._code=="sla-pro" then local book_search = "[https://google.com/search?tbm=bks&q="..mw.uri.encode("\""..mw.loadData("Module:headword/data").pagename.."\"","QUERY").." Google Books]" temp_rfref = frame:expandTemplate{ title = "Template:rfref", args = { langcode._code, "Check [[:Category:"..language.." reference templates]] or "..book_search } } end end return temp_rfref .. require("Module:utilities").format_categories(cats, langcode) end return export rgm7p7yxo9z98u6apakspwaghm6brtd Reconstruction:Ealdoric Westerngermanisc/barn 0 8191 55126 2026-10-02T04:20:06Z Deadend0914 7211 Gesceop tramet þe hafaþ '{{reconstructed}} =={{sprǣc|gmw-pro}}== ===Wordstǣr=== {{inh+|gmw-pro|gem-pro|*barną}}. ===Nāhwæðer Nama=== # [[cild]], [[bearn]] ====Declīnung==== {{gmw-infl-noun-a|g=n}}' 55126 wikitext text/x-wiki {{reconstructed}} =={{sprǣc|gmw-pro}}== ===Wordstǣr=== {{inh+|gmw-pro|gem-pro|*barną}}. ===Nāhwæðer Nama=== # [[cild]], [[bearn]] ====Declīnung==== {{gmw-infl-noun-a|g=n}} dex93b6dhkrajhuvwchv3037kz4euwb Babilōn 0 8192 55127 2026-10-02T04:35:49Z Deadend0914 7211 Gesceop tramet þe hafaþ '=={{sprǣc|ang}}== ===Āwendednessa=== * Babilónie * Babilónige ===Rihstefn=== * IPA: /ˈbɑ.bi.loːn/ ===Wiflic Nama=== # sēo ealde burg þǣr þā [[babilónisc|Babilónisc]] (cyningdōm of Babylonia) lifdon' 55127 wikitext text/x-wiki =={{sprǣc|ang}}== ===Āwendednessa=== * Babilónie * Babilónige ===Rihstefn=== * IPA: /ˈbɑ.bi.loːn/ ===Wiflic Nama=== # sēo ealde burg þǣr þā [[babilónisc|Babilónisc]] (cyningdōm of Babylonia) lifdon kj31tpcky0diw8heywesjl8c2v539u0 55128 55127 2026-10-02T04:36:14Z Deadend0914 7211 /* {{sprǣc|ang}} */ 55128 wikitext text/x-wiki =={{sprǣc|ang}}== ===Āwendednessa=== * Babilónie * Babilónige ===Rihstefn=== * IPA: /ˈbɑ.bi.loːn/ ===Wiflic Nama=== {{ang-noun|wif}} # sēo ealde burg þǣr þā [[babilónisc|Babilónisc]] (cyningdōm of Babylonia) lifdon mwdnowohzo9b7jh8bxz6116umww9glw