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 "—"
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 "—"
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