Wiktionary
viwiktionary
https://vi.wiktionary.org/wiki/Wiktionary:Trang_Ch%C3%ADnh
MediaWiki 1.48.0-wmf.3
case-sensitive
Phương tiện
Đặc biệt
Thảo luận
Thành viên
Thảo luận Thành viên
Wiktionary
Thảo luận Wiktionary
Tập tin
Thảo luận Tập tin
MediaWiki
Thảo luận MediaWiki
Bản mẫu
Thảo luận Bản mẫu
Trợ giúp
Thảo luận Trợ giúp
Thể loại
Thảo luận Thể loại
Phụ lục
Thảo luận Phụ lục
TimedText
TimedText talk
Mô đun
Thảo luận Mô đun
Sự kiện
Thảo luận Sự kiện
Wiktionary:Tin tức
4
644
2576444
2576362
2026-11-08T14:29:54Z
Hiyuune
50834
/* Chủ nhật, ngày 8 tháng 11 năm 2026 */
2576444
wikitext
text/x-wiki
__NOTOC__
{{Lưu trữ|
{{*ym|year=2004–2009|month=no|base=Wiktionary:Tin tức}}
{{*ym|year=2010–2020|month=no|base=Wiktionary:Tin tức}}
{{*ym|year=2021–2023|month=no|base=Wiktionary:Tin tức}}
{{*ym|year=2024|month=no|base=Wiktionary:Tin tức}}
{{*ym|year=2025|month=no|base=Wiktionary:Tin tức}}
{{*ym|year=2026|month=no|base=Wiktionary:Tin tức}}
}}
Trang này dành cho '''tin tức về dự án''' [[Wiktionary]] tiếng Việt nói riêng hay về cộng đồng Wiktionary nói chung. Bạn có biết tin tức mới không? Mời bạn ghi ra đây!
Bạn có thể chọn nút theo dõi trang để cập nhật tin tức tại [[Đặc biệt:Danh sách theo dõi|Danh sách theo dõi]].<!-- Nếu bạn đang cộng thêm một ngày nữa, và nếu đã có năm ngày ở trang này rồi, xin bạn xoá mục cuối cùng và bỏ tin tức mới trên những mục đã có rồi. Rồi, xin bạn thêm tin tức mới vào trang lưu trữ cho tháng năm phù hợp. Cám ơn. -->
== Tháng 11 năm 2026 ==
=== Thứ hai, ngày 2 tháng 11 năm 2026 ===
* {{l|pis|kaekaem}} trở thành mục từ tiếng Pijin đầu tiên của Wiktionary tiếng Việt.
=== Thứ ba, ngày 3 tháng 11 năm 2026 ===
* {{l|mnf|a̧}} trở thành mục từ tiếng Mundani đầu tiên của Wiktionary tiếng Việt.
=== Thứ sáu, ngày 6 tháng 11 năm 2026 ===
* {{l|sel-pro|*e̮ra}} trở thành mục từ tiếng Selkup nguyên thủy đầu tiên của Wiktionary tiếng Việt.
* {{l|syd-pro|*wën}} trở thành mục từ tiếng Samoyed nguyên thủy đầu tiên của Wiktionary tiếng Việt.
* {{l|ibe|íɲí}} trở thành mục từ tiếng Akpes đầu tiên của Wiktionary tiếng Việt.
* {{l|aqg|mẹn}} trở thành mục từ tiếng Arigidi đầu tiên của Wiktionary tiếng Việt.
=== Chủ nhật, ngày 8 tháng 11 năm 2026 ===
* {{l|oco|scol}} trở thành mục từ tiếng Cornwall cổ đầu tiên của Wiktionary tiếng Việt.
* {{l|aud|toru}} trở thành mục từ tiếng Anuta đầu tiên của Wiktionary tiếng Việt.
== Xem thêm ==
*[[Thành viên:WikimediaNotifier/notifications|Thời sự Wikimedia]]
*[[m:Tin tức về Wikimedia|Tin tức Wikimedia]]
[[Thể loại:Tin tức Wiktionary| ]]
[[Thể loại:Cộng đồng Wiktionary|{{PAGENAME}}]]
nrmsgzo6oxo5xq4w66bebmf9bqjepti
astéroïde
0
36321
2576465
2429991
2026-11-09T01:50:18Z
Hiyuune
50834
2576465
wikitext
text/x-wiki
{{also|asteroide|Asteroide|asteróide|asteroïde}}
=={{langname|fr}}==
[[Hình:Galileo Gaspra Mosaic.jpg|thumb|astéroïde]]
==={{section|etym}}===
Vay mượn từ {{bor|fr|en|asteroid}}, bản thân chính từ này cũng vay mượn học tập từ {{der|fr|grc|ἀστεροειδής}}.
==={{section|pron}}===
* {{fr-IPA}}
* {{audio|fr|Fr-astéroïde-1.oga}}
* {{audio|fr|LL-Q150 (fra)-GrandCelinien-astéroïde.wav|a=Paris}}
* {{audio|fr|LL-Q150 (fra)-LoquaxFR-astéroïde.wav|a=Vosges}}
* {{audio|fr|LL-Q150 (fra)-Mecanautes-astéroïde.wav|a=Pháp}}
* {{audio|fr|LL-Q150 (fra)-Poslovitch-astéroïde.wav|a=Vosges}}
* {{audio|fr|LL-Q150 (fra)-WikiLucas00-astéroïde.wav|a=Lyon}}
* {{audio|fr|LL-Q150 (fra)-Bananax47-astéroïde.wav|a=Agen}}
* {{homophones|fr|astéroïdes}}
* {{hyphenation|fr|as|té|ro|ïde}}
==={{section|n}}===
{{fr-noun|m}}
# {{lb|fr|astronomy}} [[tiểu hành tinh]].
#: {{syn|fr|planétoïde}}
===={{section|drv}}====
{{col3|fr
|ceinture d'astéroïdes
}}
==={{section|ref}}===
* {{R:FVDP|db=fv}}
==={{section|further}}===
* {{R:fr:TLFi}}
pih1fsk4dkiy9cl0l7n8671oyygmsxq
Thảo luận Wiktionary:Thảo luận
5
103987
2576495
2575237
2026-11-09T10:34:31Z
MediaWiki message delivery
19980
Mục mới: /* Bản tin Kỹ thuật: Tuần 46-2026 */
2576495
wikitext
text/x-wiki
<!-- Xin bắt đầu cuộc thảo luận mói ở CUỐI trang! Cám ơn. -->
{{Lưu trữ}}
== Bản tin Kỹ thuật: Tuần 24-2026 ==
<section begin="technews-2026-W24"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/24|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Wikimedia Enterprise đã tăng giới hạn sử dụng miễn phí cho các dịch vụ API của mình. Giới hạn yêu cầu hàng tháng dành cho API Theo yêu cầu đã tăng từ 5.000 lên 50.000 yêu cầu, trong khi giới hạn đối với API Hình chụp nhanh đã tăng từ 15 lên 30 yêu cầu mỗi tháng. Ngoài ra, Nội dung Có cấu trúc của ảnh chụp nhanh hiện đã có sẵn cho các tài khoản miễn phí. Những thay đổi này sẽ mở rộng quyền truy cập vào dữ liệu Wikimedia Enterprise cho các nhà phát triển, nhà nghiên cứu và các tổ chức sử dụng nội dụng Wikimedia. [https://enterprise.wikimedia.com/blog/enhanced-free-api]
'''Cập nhật cho biên tập viên'''
* [[mw:Special:MyLanguage/Wikimedia_Apps/Team/Explore Feed Refresh/Phase 1|Bảng tin Khám phá được làm mới]], nay với tên gọi là Bảng tin Trang chủ, đang được triển khai tới 50% người dùng ứng dụng Wikipedia dành cho Android. Bảng tin Trang chủ giúp người đọc khám phá nội dung liên quan thông qua hai tab mới: ''Cộng đồng'' và ''Dành cho Bạn''. Tab Cộng đồng cung cấp một bảng tin cuộn được chứa những nội dung được chọn lọc cùng những cập nhật từ không gian rộng lớn hơn của cộng đồng và phong trào Wikimedia, trong khi tab ''Dành cho Bạn'' cung cấp trải nghiệm toàn màn hình, có thể vuốt được để hiển thị nội dung được điều chỉnh theo sở thích của người dùng. Việc thiết kế lại này là một phần trong nỗ lực lớn hơn nhằm cải thiện khả năng tìm kiếm và nâng cao trải nghiệm học trong ứng dụng Wikipedia.
* Trò chơi giải đố hàng ngày [[mw:Special:MyLanguage/Wikimedia Apps/Team/iOS/"Which came first?" Game|Sự kiện nào diễn ra trước nhỉ?]] nay đã có sẵn trong phiên bản beta của ứng dụng Wikipedia dành cho iOS bằng tiếng Anh, tiếng Đức, tiếng Pháp, tiếng Bồ Đào Nha, tiếng Nga, tiếng Tây Ban Nha, tiếng Ả Rập, tiếng Trung và tiếng Thổ Nhĩ Kỳ. Trò chơi này sử dụng các sự kiện lịch sử từ nội dung trong mục "Ngày này năm xưa" của Wikipedia và thử thách người đọc đoán xem sự kiện nào trong hai sự kiện đã xảy ra trước. Trò chơi này đã được phát hành trên Android trước đây. Những cộng đồng quan tâm đến việc cung cấp trò chơi này bằng ngôn ngữ của mình có thể [[mw:Special:MyLanguage/Wikimedia_Apps/Team/Games#Game availability by language|đọc qua hướng dẫn và yêu cầu]].
* [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|Chú thích phụ]], một tính năng MediaWiki mới cho phép biên tập viên tái sử dụng nguồn tham khảo với nhiều chi tiết khác nhau, sẽ bắt đầu được triển khai đến các wiki của Wikimedia sau giải đoạn thí điểm thành công. Việc triển khai sẽ bắt đầu vào ngày 8 tháng 6 đối với hầu hết các [[wikitech:Deployments/Train#Wednesday|wiki Nhóm 1]] và Wikipedia tiếng Pháp, trong khi các phiên bản ngôn ngữ khác của Wikipedia sẽ nhận được tính năng này trong những tháng tới. Các cộng đồng được khuyến khích chuẩn bị bằng cách kiểm tra [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-cite&language=en&action_source=search&filter=%21translated&optional=1&action=translate các thông báo chưa được dịch của phần mở rộng Cite] bằng ngôn ngữ của họ và xem xét bất kỳ việc sử dụng [[mw:Special:MyLanguage/Reference Tooltips|Chú thích nổi]] nào, chúng có thể cần phải được [[:phab:T416304#11668731|cập nhật]] để hỗ trợ chức năng mới này. Những wiki sử dụng [[mw:Special:MyLanguage/Help:Reference Previews|Xem trước Chú thích]] không cần phải thực hiện bất kỳ hành động nào. Các cộng đồng cũng có thể mong muốn tạo [[Special:TrackingCategories|thể loại theo dõi]] ''cite-tracking-category-ref-details'' dưới dạng thể loại ẩn sử dụng <code><nowiki>__HIDDENCAT__</nowiki></code> (hoặc một bản mẫu chuyên dụng), và kết nối nó với khoản mục Wikidata [[d:Q129764848]] tương ứng. [https://phabricator.wikimedia.org/T425662]
* [[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews#Experimentation|Thử nghiệm Xem trước Trang]] trên giao diện web di động đã kết thúc. Nhóm đã quyết định không triển khai tính năng này sau khi kết quả cho thấy rằng không có tác động đáng kể nào về mặt thống kê lên tỷ lệ giữ chân người đọc, vì chỉ số thành công chính là việc cải thiện tỷ lệ giữ chân người đọc. Tính năng Xem trước Trang, vốn đã có sẵn trên máy tính để bàn và trong ứng dụng, hiển thị hình thu nhỏ, đoạn mở đầu và liên kết đến bài viết đầy đủ khi người đọc nhấn vào liên kết xanh. Thử nghiệm này đã thử trải nghiệm này trên giao diện web di động trên sáu trang Wikipedia.
* [[mw:Special:MyLanguage/Codex/Design/Icons|Thư viện biểu tượng giao diện người dùng]] sẽ được [[phab:T399175|cập nhật vào cuối tuần này hoặc đầu tuần sau]]. Hầu hết trong số ~300 biểu tượng đã được điều chỉnh một chút và ~30 biểu tượng mới đã được thêm vào. Những thay đổi này cải thiện các biểu tượng để làm cho chúng thêm nhất quán và dễ hiểu hơn, đồng thời mang lại sự cân bằng trực quan hơn khi chúng được sử dụng theo nhóm.
* Giao diện [[mw:Special:MyLanguage/Universal Language Selector|Bộ chọn Ngôn ngữ Toàn cục]] (ULS) trong MediaWiki, công cụ giúp người dùng chọn nội dung bằng các ngôn ngữ khác, đã được cập nhật. Phiên bản mới cải thiện tốc độ và khả năng truy cập, đồng thời giờ đây người dùng trên các dự án Wikimedia có thể ghim các ngôn ngữ để chuyển đổi ngôn ngữ một cách nhanh chóng hơn. Việc triển khai lên các trang web của Wikimedia sẽ diễn ra dần dần trong những tuần tới. Bạn có thể thử nghiệm tính năng này ngay bây giờ bằng cách chọn [[Special:Preferences#mw-prefsection-betafeatures|tính năng beta]] trong tùy chọn hồ sơ của mình và chia sẻ phản hồi của bạn trên [[mw:Special:MyLanguage/Universal Language Selector/New ULS|trang dự án]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:21}} {{PLURAL:21|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến bảng điều khiển Phân tích Lượt xem Trang trên pageviews.wmcloud.org ngừng cập nhật dữ liệu đồ thị vào tháng 5 năm 2026, ảnh hưởng đến tất cả người dùng, đã được giải quyết. [https://phabricator.wikimedia.org/T427171]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Chữ ký hàm cho <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink()</nowiki></code></bdi> đã được đơn giản hóa. Các nhà phát triển nay có thể truyền một đối tượng cấu hình thay vì một danh sách các tham số vị trí khi tạo liên kết portlet. Chữ ký hàm trước đây vẫn được hỗ trợ để đảm bảo khả năng tương thích ngược. Ví dụ, thay vì: <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink('p-cactions', '#', 'Stub', 'ca-stubtag', 'Add a stub tag to this page');</nowiki></code></bdi> sử dụng <bdi lang="zxx" dir="ltr"><code><nowiki>mw.util.addPortletLink('p-cactions', { href: '#', text: 'Stub', id: 'ca-stubtag', tooltip: 'Add a stub tag to this page' });</nowiki></code></bdi>. Những người bảo trì đoạn mã được khuyến khích xem chỗ nào hiện đang sử dụng <bdi lang="zxx" dir="ltr"><code><nowiki>addPortletLink()</nowiki></code></bdi> và cập nhật chúng nếu thích hợp. Thay đổi này sẽ có mặt trên tất cả các wiki từ ngày 11 tháng 6. Xin cảm ơn tình nguyện viên cộng đồng Gerges đã đóng góp cải tiến này. [https://phabricator.wikimedia.org/T427945]
* '''Thảo luận về Danh sách Mong muốn của Cộng đồng''': Nhóm Sản phẩm & Công nghệ [[m:Special:MyLanguage/Community Wishlist/Updates#May 20, 2026: Community Tech becomes a program|đã đưa ra những thay đổi]] nhằm mục đích tăng số lượng và độ phức tạp của những mong muốn được đáp ứng, bao gồm cả việc giải thể nhóm Công nghệ Cộng đồng. Họ đang [[m:Special:MyLanguage/Community Wishlist/Updates|tham gia thảo luận]] về một [[m:Talk:Community Wishlist#Proposed direction for Wishlist|đề xuất hướng đi cho danh sách mong muốn]] từ các thành viên cộng đồng. Bao gồm những cách để cấu trúc việc bỏ phiếu hàng năm, theo dõi mong muốn một cách tốt hơn, loại bỏ các lĩnh vực trọng tâm, và [[m:Special:MyLanguage/Community Wishlist/Updates|điều chỉnh việc quản lý nhân sự]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.6|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/24|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W24"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 21:30, ngày 8 tháng 6 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30650573 -->
== Bản tin Kỹ thuật: Tuần 25-2026 ==
<section begin="technews-2026-W25"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/25|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* [[mw:Special:MyLanguage/Readers/Reader Growth|Nhóm Tăng trưởng Độc giả]] đã cho ra mắt tính năng beta [[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|Duyệt Hình ảnh]] trên phiên bản web của thiết bị di động tại tất cả các phiên bản Wikipedia. Tính năng này hiển thị ở đầu bài viết một băng chuyền hình ảnh gồm 3 hình ảnh trở lên. Biên tập viên có thể cấu hình cho tính năng này với những thao tác sau: để ẩn một hình ảnh cụ thể khỏi một trang, hãy sử dụng <code>class=notpageimage</code> để loại trừ nó khỏi bản xem trước, hay dùng <code>class=noviewer</code> để loại trừ nó khỏi MediaViewer. Băng chuyền Hình ảnh còn có thể được tắt hoàn toàn ở một trang, với magic word <code><nowiki>__NOMEDIAVIEWERCAROUSEL__</nowiki></code>. Để gửi phản hồi hoặc báo cáo lỗi, hãy truy cập [[mw:Talk:Readers/Reader Growth/Image Browsing|trang dự án]].
* [[mw:Special:MyLanguage/Help:Tables#class="wikitable"|Wikitables]] nay đã có thể được [[mw:Special:MyLanguage/Help:Sortable tables#Forcing the initial sort direction|sắp xếp theo thứ tự giảm dần]] ngay lần nhấp chuột đầu tiên bằng cách thêm <code dir=ltr>data-sort-order="desc"</code> cho ô tiêu đề. Trước đây, theo mặc định, lần nhấp chuột đầu tiên vào tiêu đề cột sẽ sắp xếp cột theo thứ tự tăng dần. Sự bổ sung này cho Wikitable mang lại khả năng kiểm soát và tính linh hoạt cao hơn, trong khi hành vi mặc định cho những lần nhấp chuột tiếp theo vẫn được giữ nguyên. [https://phabricator.wikimedia.org/T398416]
'''Cập nhật cho biên tập viên'''
* Tính năng [[mw:Special:MyLanguage/Article guidance|Hướng dẫn bài viết]] hiện đang được thử nghiệm đối với một số biên tập viên tạo các bài viết mới trên các trang Wikipedia tiếng Anh đơn giản, tiếng Pháp và tiếng Thổ Nhĩ Kỳ. Thử nghiệm cũng sẽ sẽ sớm bắt đầu trên Wikipedia tiếng Ả Rập và tiếng Bengali. [[w:simple:Special:NewArticle|Tính năng này]] cung cấp cho các biên tập viên hướng dẫn do cộng đồng biên soạn để giúp họ tạo ra những bài viết tuân thủ tiêu chuẩn cộng đồng. Các biên tập viên có kinh nghiệm có thể tiếp tục tạo hoặc điều chỉnh dàn ý cho những loại bài viết cụ thể thường được tạo bởi những người đóng góp ít kinh nghiệm hơn. Những dàn ý này hướng dẫn các biên tập viên ít kinh nghiệm hơn trong việc tạo những bài viết chất lượng cao. Hướng dẫn nhanh về các ký hiệu được sử dụng trong dàn ý có thể được tìm thấy trên [[mw:Special:MyLanguage/Article guidance/Test feature guide#Markups in outlines|trang này]]. [[w:simple:Wikipedia:Article Guidance|Ví dụ về dàn ý]] có thể được điều chỉnh và hướng dẫn cách điều chỉnh chúng nằm trên [[mw:Special:MyLanguage/Article guidance#Adapting a sample outline in a Wikipedia|phần này]] của trang dự án.
* Wiki mong muốn thay thế nút "vô thời hạn" trong Đặc biệt:Cấm dành cho tài khoản tạm thời (ví dụ, wiki chỉ cấm tài khoản tạm thời đến khi tài khoản đó hết hạn) sẽ có thể thực hiện điều đó bằng cách tạo [[MediaWiki:ipb-indefinite-expiry-temporary-account]] với khoảng thời gian cấm mà họ muốn. [https://phabricator.wikimedia.org/T427125]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:41}} {{PLURAL:41|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]].
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Đến cuối tháng 6, việc sử dụng một chuỗi user-agent hợp lệ là bắt buộc để tải xuống tự động các dump từ trang web dumps.wikimedia.org. Những yêu cầu tự động cung cấp user-agent trống hoặc chung chung sẽ bị chặn. Điều này [[phab:T400119|sẽ mở rộng việc thực thi]] [[foundation:Special:MyLanguage/Policy:Wikimedia Foundation User-Agent Policy|quy định về user-agent]] đã có từ lâu. Quyền truy cập tới Dịch vụ Đám mây của Wikimedia sẽ không thay đổi.
* Quá trình triển khai [[mw:Wikimedia APIs/Rate limits|giới hạn truy cập API]] toàn cục đã hoàn tất, các giới hạn được áp dụng trên tất cả các API và ở tất cả các mức độ được ghi nhận cho tất cả các nhóm. Các bot chạy trong Toolforge/WMCS hoặc có quyền người dùng bot trên bất kỳ wiki nào vẫn được miễn trừ. Tất cả các bot nên tiếp tục theo những thực tiễn tốt nhất được ghi nhận để tránh bị vượt giới hạn truy cập.
* [https://api.wikimedia.org/wiki/Main_Page Wiki Cổng API] sẽ ở chế độ chỉ đọc kể từ tuần này (15-18 tháng 6). Vào tuần tới (22-25 tháng 6), tất cả các URL của wiki Cổng API sẽ chuyển hướng đến [[mw:Wikimedia APIs|API Wikimedia trên mediawiki.org]]. Tìm hiểu thêm trên [[wikitech:API Portal/Deprecation|trang dự án]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.7|MediaWiki]]
'''Các cuộc họp và sự kiện'''
* Vào ngày 17 tháng 6 lúc 18:00 giờ UTC WMF sẽ tổ chức một cuộc gọi Discord tập trung vào việc đánh giá code. Chúng tôi đã lắng nghe thông qua [[mw:Special:MyLanguage/Developer Satisfaction Survey/2026|Khảo sát Sự hài lòng của Nhà phát triển]] rằng các tình nguyện viên đang gặp khó khăn trong việc đánh giá code và chúng tôi muốn thảo luận về những trải nghiệm này với mục tiêu tìm ra những giải pháp khả thi. Bạn có thể tham gia cuộc gọi [https://discord.gg/wikipedia?event=1514727511102062664 thông qua máy chủ Discord Cộng đồng Wikimedia].
* [[m:Special:MyLanguage/Conferencia Wikimedia de América Latina 2026|Hội nghị Wikimedia Mỹ La-tinh]] sẽ tổ chức cuộc thi hackathon khu vực quy tụ cộng đồng kỹ thuật của phong trào Wikimedia, gồm những nhà phát triển, quản trị viên hệ thống, nhà khoa học dữ liệu và các thành viên có quyền mở rộng. Những người đóng góp kỹ thuật quan tâm có thể [https://docs.google.com/forms/d/e/1FAIpQLSf4osJzTHBJjQbYJk7TMVEJjTEQv7IgtsUDfP-o-qTgeRQQxw/viewform đăng ký học bổng] tham gia cho đến nửa đêm ngày 21 tháng 6 (giờ Bolivia, UTC-4).
* Hãy đăng ký tham gia Thử thách Nhóm của Wikimania để góp mặt tại sự kiện đặc biệt này. Thử thách nhóm sẽ diễn ra trực tuyến và trực tiếp từ ngày 21 đến 22 tháng 7, trước hội nghị Wikimania. Mọi người đều có thể tham gia, bất kể kỹ năng hay việc đăng ký Wikimania trước đó như thế nào. Các nhóm sẽ cùng nhau giải quyết 10 thử thách quan trọng trong việc hỗ trợ cộng đồng Wikimedia. Để biết thêm chi tiết, hãy truy cập [[wmania:Special:MyLanguage/2026:Team challenges|trang Thử thách Nhóm]] và [https://wikimedia.eventyay.com/wm/teamchallenges/ đăng ký tại đó]. Cổng đăng ký sẽ đóng vào ngày 20 tháng 6 lúc 23:00 UTC.
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/25|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W25"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16:48, ngày 15 tháng 6 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:UOzurumba (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30689604 -->
== Bản tin Kỹ thuật: Tuần 26-2026 ==
<section begin="technews-2026-W26"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/26|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* [[mw:Special:MyLanguage/Growth/Feature summary|Các tính năng Phát triển (Growth)]] [[phab:T418115|nay đã có mặt trên Wikidata]]. Bản cập nhật này cho phép truy cập vào chức năng Cố vấn ([[mw:Special:MyLanguage/Help:Growth/Mentorship|nếu được cấu hình]]), mô đun Tác động, Bảng Trợ giúp và Trang chủ dành cho Người mới được đơn giản hóa (không có Đề xuất sửa đổi). Các bảo quản viên Wikidata vẫn đang cấu hình các tính năng thông qua Cấu hình Cộng đồng.
'''Cập nhật cho biên tập viên'''
* Trang đặc biệt [[{{#special:RangeCalculator}}]] đã được tạo. Trang này cho phép người dùng tìm một dải IP mà không cần phải dựa vào các công cụ bên ngoài. Cho đến hiện tại, công cụ này chỉ có sẵn cho các kiểm định viên. [https://phabricator.wikimedia.org/T268429]
* [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|Chú thích phụ]] là một tính năng mới của MediaWiki cho phép biên tập viên tái sử dụng các nguồn tham khảo với những chi tiết khác nhau. Tính năng này sẽ được triển khai đến hầu hết các phiên bản ngôn ngữ Wikipedia quy mô nhỏ và trung bình vào ngày 23 tháng 6. Trang [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#deployment|Câu hỏi thường gặp]] liệt kê những hành động có thể thực hiện trên wiki của bạn để hỗ trợ việc triển khai này. Hãy kiểm tra [[:phab:T414094|kế hoạch triển khai]] để biết các bước triển khai tiếp theo. [https://phabricator.wikimedia.org/T428902]
* Bắt đầu từ tuần sau, người dùng sẽ nhận được một thông báo khi họ bị cấm sửa đổi hoặc được bỏ cấm sửa đổi, hoặc khi lệnh cấm thay đổi. [https://phabricator.wikimedia.org/T100974]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:32}} {{PLURAL:32|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]].
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Bắt đầu từ tuần tới, các bộ lọc sai phạm được đặt ở mức "yêu cầu xác minh CAPTCHA" sẽ bắt đầu ảnh hưởng đến cả những người dùng có quyền <code>skipcaptcha</code>, bao gồm hầu hết những người dùng có quyền tự động xác nhận. Các bot sẽ được miễn trừ. Thay đổi này sẽ chỉ ảnh hưởng đến những sửa đổi kích hoạt bộ lọc sai phạm. Quyền <code>skipcaptcha</code> vẫn sẽ tiếp tục giúp người dùng được miễn yêu cầu xác minh CAPTCHA trong quá trình sử dụng wiki thông thường. [https://phabricator.wikimedia.org/T402595]
* Tài liệu tham khảo cho [[wikitech:Machine_Learning/LiftWing/API|API Lift Wing]] đã được chuyển từ Cổng API sang [https://wikitech.wikimedia.org/w/index.php?api=lift-wing&title=Special%3ARestSandbox Chỗ thử REST] mang tính tương tác.
* Wiki Cổng API hiện đã đóng. Để xem tài liệu API, hãy xem [[mw:Special:MyLanguage/Wikimedia_APIs|API Wikimedia trên mediawiki.org]]. Tất cả các URL của wiki Cổng API (https://api.wikimedia.org/wiki/) sẽ đổi hướng tới trang mediawiki.org bắt đầu từ ngày 22 tháng 6. [https://phabricator.wikimedia.org/T427537]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.8|MediaWiki]]
'''Các cuộc họp và sự kiện'''
* Hãy tham gia cuộc gọi trực tuyến vào ngày 25 tháng 6 lúc 2:30 chiều giờ UTC để gặp gỡ các thực tập sinh hiện tại của Wikimedia cho [[mw:Google_Summer_of_Code/2026|Google Summer of Code]] và [[mw:Outreachy/Round_32|Outreachy]]. Các thực tập sinh sẽ giới thiệu tổng quan về các dự án của họ và demo ngắn gọn công việc mà họ đã thực hiện cho đến nay. Người tham dự được khuyến khích [[mw:event:Google_Summer_of_Code/Summer_2026_June_Internship_open_session|chia sẻ ý tưởng và kết nối trong cộng đồng của họ]].
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/26|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W26"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 13:05, ngày 23 tháng 6 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Trizek (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30722494 -->
== 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|thảo luận]])</bdi> 17:12, ngày 23 tháng 6 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Codename Noreste@metawiki gửi cho mọi người trong danh sách tại 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, ngày 25 tháng 6 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Sannita (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=30731267 -->
== Bản tin Kỹ thuật: Tuần 27-2026 ==
<section begin="technews-2026-W27"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/27|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* Là một phần của [[mw:Special:MyLanguage/Contributors/Account Creation Experiments|Thử nghiệm Tạo Tài khoản]], nhóm Phát triển đã thử nghiệm việc thêm biểu tượng tài khoản người dùng vào tiêu đề trang web trên di động dành cho người dùng chưa đăng nhập, cung cấp quyền truy cập trực tiếp vào các tác vụ "Tạo tài khoản" và "Đăng nhập". Thử nghiệm đã tăng số tài khoản được tạo lên khoảng 20% mà không ảnh hưởng tiêu cực đến chất lượng sửa đổi hoặc tỷ lệ sửa đổi mang tính xây dựng. Tính năng này giờ sẽ được triển khai đến tất cả các trang wiki của Quỹ Wikimedia trên giao diện web di động trong tuần đầu tiên của tháng 7. [https://phabricator.wikimedia.org/T428220]
* Sau một [[phab:T426248|thử nghiệm thành công]], người dùng đã đăng nhập nhưng chưa [[mw:Special:MyLanguage/Help:Email_confirmation|xác nhận địa chỉ email của mình]] khi tạo tài khoản sẽ nhìn thấy một biểu ngữ mới yêu cầu họ hoàn tất quy trình đó. Điều này giúp giảm nguy cơ người dùng bị mất quyền truy cập vào tài khoản của họ, và làm cho địa chỉ email của tài khoản nói chung trở nên đáng tin cậy hơn. Đây là một phần của dự án [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security|Bảo mật Tài khoản]]. [https://phabricator.wikimedia.org/T428292]
* Một bản cập nhật cho tính năng [[Special:Search|Tìm kiếm]] sẽ tinh chỉnh cách <bdi lang="zxx" dir="ltr"><code><nowiki>-prefix:</nowiki></code></bdi> hoạt động khi được sử dụng để loại trừ kết quả. Trước đây, việc sử dụng <bdi lang="zxx" dir="ltr"><code><nowiki>-prefix:</nowiki></code></bdi> với phủ định có thể vô tình mở rộng kết quả tìm kiếm bằng cách thêm các không gian tên nằm trong phạm vi tìm kiếm, dẫn đến hành vi gây khó hiểu đối với những người dùng mong đợi một bộ lọc loại trừ đơn giản. Với lần cập nhật này, <bdi lang="zxx" dir="ltr"><code><nowiki>-prefix:</nowiki></code></bdi> nay sẽ loại trừ chặt những tiêu đề trang trùng khớp như mong đợi và có thể hiển thị cảnh báo nếu không gian tên có liên quan không được chọn một cách rõ ràng. Mặc dù vậy, hành vi của <bdi lang="zxx" dir="ltr"><code><nowiki>prefix:</nowiki></code></bdi> khi không có phủ định vẫn sẽ không thay đổi. [https://phabricator.wikimedia.org/T427443]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:33}} {{PLURAL:33|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một sự cố khiến người đánh giá sử dụng thanh công cụ Quản lý Trang (Page Curation) không tự động được đăng ký theo dõi các cuộc thảo luận mà họ bắt đầu bình luận trên trang nay đã được giải quyết. Người đánh giá giờ sẽ nhận được thông báo khi có người nào đó trả lời những cuộc thảo luận này. [https://phabricator.wikimedia.org/T329346]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Kể từ ngày 29 tháng 6, các lượt tải xuống tự động từ trang dumps.wikimedia.org sẽ phải tuân theo [[Foundation:Special:MyLanguage/Policy:Wikimedia Foundation User-Agent Policy|quy định về user-agent]]. Các yêu cầu tự động mà cung cấp user-agent trống hoặc chung chung sẽ bị chặn. Việc truy cập vào các bản sao lưu (dump) thông qua Dịch vụ Đám mây Wikimedia sẽ không bị ảnh hưởng. Đây là thông báo tiếp theo sau thông báo được đưa ra trong [[m:Special:MyLanguage/Tech/News/2026/25|Bản tin Kỹ thuật số 25-2026]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.9|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/27|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W27"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 11:48, ngày 29 tháng 6 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30744833 -->
== <span lang="en" dir="ltr">Tech News: 2026-28</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W28"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/28|Translations]] are available.
'''Updates for editors'''
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:34}} community-submitted {{PLURAL:34|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, an issue where the search bar results on Wikidata, showed English results instead of using the correct language fallback for users of language variants, has now been fixed. Search suggestions will now follow the expected language fallback chain. [https://phabricator.wikimedia.org/T429769]
'''Updates for technical contributors'''
* In preparation for [[m:Special:MyLanguage/Event:Celebrate Women|Celebrate Women campaign]] planned for March 2027, the Wikimedia Foundation’s [[m:Special:MyLanguage/Wikimedia Foundation/Advancement/Community Growth/Content Enablement|Content Enablement team]] has launched a 22-question survey to better understand technical contributions by women+ (anyone who identifies as a woman) across Wikimedia projects. The survey takes approximately 15–20 minutes to complete and will remain open until 20 July 2026. The [[m:Special:MyLanguage/Celebrate Women/Technical contributions survey|questions]] are also available on-wiki for review in advance.
* The [[mw:Special:MyLanguage/Extension:Score|Score extension]] now supports rendering music scores as SVG images in addition to PNG, addressing a long-standing [[:phab:T49578|feature request]] and resolving historical image quality issues. Both formats are now provided to clients, with PNG in the <bdi lang="zxx" dir="ltr"><code><nowiki>src</nowiki></code></bdi> attribute and SVG in the <bdi lang="zxx" dir="ltr"><code><nowiki>srcset</nowiki></code></bdi> attribute.
* The new [[wikitech:Parsoid|Parsoid]] parser [[mw:Special:MyLanguage/Parsoid/Parser_Unification/Updates|continues to be deployed to additional wikis]], making it easier to introduce new reading and editing features. It was enabled on French Wikipedia, bringing total progress to covering 78.9% of Wikipedia page views. Rollout to English Wikipedia desktop will progress through this week.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.47/wmf.10|MediaWiki]]
'''In depth'''
* The Wikimedia Hackathon 2026 [[diffblog:2026/06/29/wikimedia-hackathon-2026-building-collaborating-and-shaping-the-future-together/|recap blog post]] is now live. It highlights the projects, sessions, and social activities from this year’s event, and shares initial plans for the 2027 Wikimedia Hackathon.
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/28|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W28"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 13:57, ngày 6 tháng 7 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30773578 -->
== Bản tin Kỹ thuật: Tuần 29-2026 ==
<section begin="technews-2026-W29"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/29|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* Tính năng [[mw:Special:MyLanguage/Growth/Revise_Tone|Xem lại Giọng văn]] giúp người mới xác định những đoạn văn trong bài viết Wikipedia mà có thể chứa ngôn ngữ không bách khoa và khuyến khích họ xem xét lại giọng văn đó. Tính năng này đã được [[w:en:A/B_testing|thử nghiệm A/B]] trên các Wikipedia tiếng Ả Rập, tiếng Anh, tiếng Pháp và tiếng Bồ Đào Nha, tại đó tỷ lệ hoàn thành nhiệm vụ của người mới [[mw:Special:MyLanguage/Growth/Revise_Tone#Experiment_Results|tăng 38.7%]] so với nhiệm vụ Hiệu đính mặc định, mà không làm giảm chất lượng sửa đổi. Cuộc thử nghiệm đã kết thúc vào ngày 9 tháng 7 và tính năng này nay đã có sẵn cho tất cả mọi người trên các wiki này, đồng thời có thể cấu hình được thông qua Cấu hình Cộng đồng. [[phab:T426364|Kế hoạch]] dự kiến là sẽ phát hành Xem lại Giọng văn đến nhiều trang wiki hơn.
* Cấu hình cộng đồng cho phép [[mw:Special:MyLanguage/Help:Growth/Mentorship#Automated mentor list cleanup|tự động loại bỏ cố vấn không hoạt động]] dựa trên các tiêu chí có thể cấu hình được sẽ được kích hoạt vào thứ 5, ngày 16, [[mw:Special:MyLanguage/Growth/Deployment|trên một số wiki]] để đảm bảo danh sách cố vấn được cập nhật. Cố vấn là những người đóng góp có kinh nghiệm, tự nguyện tham gia giúp đỡ người dùng mới trên wiki thông qua [[mw:Special:MyLanguage/Growth/Feature summary|Tính năng Phát triển (Growth)]]. Bảo quản viên nay có thể chuẩn bị các cài đặt thông qua [[w:Special:CommunityConfiguration/Mentorship|Đặc biệt:Cấu hình Cộng đồng/Cố vấn]]; những cài đặt này sẽ có hiệu lực kể từ thứ 5.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:38}} {{PLURAL:38|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một sự cố khiến một số người dùng ứng dụng Wikipedia trên thiết bị Android bị đăng xuất ngay sau khi đăng nhập, khiến họ không thể duy trì trạng thái đăng nhập và sửa đổi trang, nay đã được giải quyết. [https://phabricator.wikimedia.org/T316916]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Việc sửa đổi trang thông qua đoạn mã người dùng hoặc tiện ích khiến cho nhãn danh sách theo dõi mà người dùng gán cho trang đó bị đặt lại. Vấn đề này nay đã được giải quyết. [https://phabricator.wikimedia.org/T423778]
* Để khắc phục lỗi Safari (xem [[phab:T425211]]), trên các wiki đã kích hoạt Parsoid, các liên kết wiki href nay sử dụng urls tuyệt đối thay vì url tương đối theo giao thức. Đầu ra API REST vẫn sẽ không thay đổi và sẽ tiếp tục sử dụng url tương đối theo giao thức. Các tiện ích, đoạn mã người dùng, bot và CSS có thể cần được điều chỉnh nếu chúng dựa vào sự hiện diện của url tương đối theo giao thức trong các liên kết wiki href. [https://phabricator.wikimedia.org/T431358]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.11|MediaWiki]]
'''Chuyên sâu'''
* Nhóm Nền tảng Thử nghiệm của Quỹ Wikimedia đã đăng bài viết trên blog phản ánh về năm đầu tiên thực hiện thử nghiệm có cấu trúc của họ. Bài viết nêu bật những thử nghiệm thành công như Kiểm tra Chép dán, Kiểm tra Nguồn tham khảo và Kiểm tra Giọng văn, những thử nghiệm đã cải thiện kết quả sửa đổi và được triển khai cho nhiều người dùng hơn, cũng như những thử nghiệm không dẫn đến việc thay đổi sản phẩm. [[diffblog:2026/07/07/moving-the-needle-how-we-test-new-ideas-across-wikimedia-projects|Đọc thêm]].
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/29|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W29"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16:11, ngày 13 tháng 7 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30804401 -->
== Bản tin Kỹ thuật: Tuần 30-2026 ==
<section begin="technews-2026-W30"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/30|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* [[mw:Special:MyLanguage/Reader/Reader Experience|Nhóm Trải nghiệm Người đọc]] đã kết hợp phản hồi của cộng đồng xoay quanh vị trí của các nút sao theo dõi và nút danh sách theo dõi đối với [[mw:Special:MyLanguage/Readers/Reader Experience/WE3.3.4 Reading lists|tính năng beta Danh sách Đọc]], nhằm cho phép lưu lại các bài viết để đọc sau – một [[m:Special:MyLanguage/Community Wishlist/W102|mục danh sách mong muốn]] để đưa chức năng này lên web. Các biên tập viên được mời kích hoạt tính năng beta để thử nghiệm tính năng này và [[phab:T426453|chia sẻ suy nghĩ của mình]].
* [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Chế độ Đề xuất]] cung cấp những đề xuất sửa đổi trong Trình Soạn thảo Trực quan để cải thiện các bài viết trên Wikipedia. [[Special:EditChecks|Mọi đề xuất]] đều [[mw:Special:MyLanguage/Help:Suggestion mode#For administrators – local customization|có thể được cộng đồng cấu hình]]. Tính năng [[mw:Special:MyLanguage/Edit check/TextMatch|Văn bản Khớp chính xác]] (TextMatch) là một cách giúp cho các tình nguyện viên có thể tạo đề xuất tùy chỉnh cục bộ. Tính năng này tìm kiếm các chuỗi văn bản trong bài viết, và nay cũng bao gồm việc hỗ trợ cho các biểu thức chính quy. Điều này mang lại cho các tình nguyện viên độ chính xác và tính linh hoạt cao hơn đối với những loại đề xuất mà họ có thể tạo ra cục bộ. Lưu ý: Đề xuất [[mw:Special:MyLanguage/Edit check/Configuration#:~:text=maximumEditcount|có thể được nhắm tới]] dựa trên số lần sửa đổi của người thực hiện sửa đổi cũng như các khía cạnh khác của trang. Bạn có thể [[mw:Special:MyLanguage/Help:Suggestion mode#Create custom local types of Suggestions|tìm ví dụ từ các cộng đồng khác]] để lấy cảm hứng, kể cả việc sử dụng Văn bản Khớp chính xác nhằm phát hiện: lỗi chính tả, lỗi ngữ pháp, có khả năng quảng cáo, lời sáo rỗng, cách sử dụng dấu gạch ngang hoặc dấu gạch nối không chính xác, từ khóa thời gian không cụ thể, tên lỗi thời, v.v. Bất kỳ [[mw:Special:MyLanguage/Talk:VisualEditor/Suggestion Mode|phản hồi]] nào đều được chúng tôi hoan nghênh.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:27}} {{PLURAL:27|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, sự cố về công cụ SVG Translate khiến cho nó có thể sử dụng phiên bản tập tin lỗi thời, khiến các bản dịch hiện có bị ghi đè khi các bản dịch mới được tải lên, nay đã được [[phab:T430577|giải quyết]]. Nhìn chung, trong quý cuối cùng từ tháng 4 đến tháng 6 năm 2026, Quỹ Wikimedia đã giải quyết khoảng 337 tác vụ cộng đồng.
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Trên các wiki có hỗ trợ Parsoid, Parsoid nay hiển thị tối đa 1.250 hình ảnh mỗi trang. Một danh mục theo dõi mới, "media-limit-reached", sẽ sớm được cung cấp để xác định các trang đã đạt đến giới hạn này, giúp dễ dàng tìm thấy nội dung có thể bị hạn chế đầu ra phương tiện trong quá trình hiển thị. Xem [[phab:T430854]] để biết thêm thông tin và cung cấp phản hồi.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.12|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/30|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W30"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 05:46, ngày 21 tháng 7 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30836091 -->
== 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, ngày 24 tháng 7 năm 2026 (UTC)
</bdi>
<!-- Tin nhắn của Thành viên:DreamRimmer@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 -->
== Bản tin Kỹ thuật: Tuần 31-2026 ==
<section begin="technews-2026-W31"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/31|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Wishlist item]] Công cụ [[mw:Special:MyLanguage/ContentTranslation|Dịch Nội dung]] nay hỗ trợ chế độ tối, nhằm đáp ứng [[m:Community Wishlist/W544|yêu cầu từ Mong muốn Cộng đồng]]. Điều này giúp công cụ tương thích với các tính năng hỗ trợ khả năng tiếp cận có sẵn trong các giao diện Vector 2022 và Minerva, giúp giảm việc gây mỏi mắt cho người dùng khi dịch nội dung. [https://phabricator.wikimedia.org/T367077]
* Chế độ soạn thảo mã nguồn của Công cụ Thảo luận (DiscussionTools) và Trình soạn thảo mã nguồn 2017 nay sẽ cung cấp tính năng tự động điền cho các liên kết (<bdi lang="zxx" dir="ltr"><code><nowiki>[[</nowiki></code></bdi>), bản mẫu (<bdi lang="zxx" dir="ltr"><code><nowiki>{{</nowiki></code></bdi>), thẻ HTML và phân tích cú pháp (<bdi lang="zxx" dir="ltr"><code><nowiki><</nowiki></code></bdi>), cũng như các từ ma thuật (<bdi lang="zxx" dir="ltr"><code><nowiki>__</nowiki></code></bdi>), giúp việc chèn các liên kết, bản mẫu và mã đánh dấu wiki khác trong quá trình sửa đổi trở nên nhanh chóng và dễ dàng hơn. [https://phabricator.wikimedia.org/T432400]
* [[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews|Nhóm Phát triển Người đọc]] đã kết thúc việc thử nghiệm với tính năng xem trước trang trên thiết bị di động và sẽ không triển khai tính năng này nữa. Tính năng Xem trước Trang là một cửa sổ bật lên ở cuối trang xuất hiện khi người đọc nhấn vào liên kết xanh, hiển thị hình thu nhỏ, đoạn mở đầu và tùy chọn mở bài viết. Thử ngiệm cho thấy tỷ lệ giữ chân người dùng không thay đổi nhưng các chỉ số khác đều mang tính tiêu cực, điều này có nghĩa là người đọc trên trang web dành cho thiết bị di động thích truy cập trực tiếp vào các bài viết được liên kết hơn là sử dụng tính năng xem trước trang.
* Nhóm Trải nghiệm Người đọc đã bước đầu ghi nhận những kết quả khả quan từ [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|tính năng Danh sách Đọc]], trong đó 93% người dùng tham gia báo cáo rằng tính năng này hữu ích. Danh sách Đọc giúp người đọc hoạt động tích cực lưu lại các bài viết để đọc sau này và hỗ trợ mục tiêu học tập của họ trên các dự án Wikimedia. Nhóm dự định sẽ tiếp tục cải tiến trước khi mở rộng tính năng này cho nhiều người dùng hơn.
* Sáng kiến [[mw:Special:MyLanguage/Wikimedia Apps/Team/Explore Feed Refresh|Làm mới Nguồn cấp dữ liệu Khám phá]] đã được thử nghiệm với những người đọc mới và không thường xuyên sử dụng ứng dụng Wikipedia. Nguồn cấp dữ liệu được làm mới giúp người đọc khám phá những nội dung mới và phù hợp với mình. Với kết quả mức độ tương tác với nguồn cấp dữ liệu tăng 10,5%, nhóm Ứng dụng Wikimedia đã quyết định mở rộng việc thiết kế lại Nguồn cấp dữ liệu Trang chủ sang iOS, áp dụng những kinh nghiệm thu được từ phiên bản dành cho Android.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:23}} {{PLURAL:23|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một sự cố khiến cho tên chủ đề trong tính năng Hướng dẫn Bài viết hiển thị sai cách viết hoa trên Wikipedia tiếng Pháp nay đã được giải quyết. Tên chủ đề nay sẽ tuân theo đúng quy tắc viết hoa của ngôn ngữ đó. [https://phabricator.wikimedia.org/T427201]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Sau khi thực hiện một số [[mw:Special:MyLanguage/Contributors/Account Creation Experiments|Thử nghiệm Tạo Tài khoản]] để cải thiện tỷ lệ hoàn tất việc đăng ký, một phiên bản mới của trường tên người dùng trên trang [[Special:CreateAccount|Tạo Tài khoản]] đã được triển khai. Phiên bản này bao gồm [[:c:File:Create account - July 2026 updates.png|một cửa sổ bật lên nhằm tóm tắt quy định về tên người dùng]] để cung cấp hướng dẫn rõ ràng hơn trong quá trình tạo tài khoản. Là một phần của thay đổi này, các thông báo <bdi lang="zxx" dir="ltr"><code><nowiki>createacct-helpusername</nowiki></code></bdi> và <bdi lang="zxx" dir="ltr"><code><nowiki>createacct-username-help</nowiki></code></bdi> mà một số cộng đồng đã cấu hình sẽ không còn được sử dụng nữa. Nếu cộng đồng muốn tùy chỉnh hướng dẫn hiển thị trong cửa sổ bật lên mới, cộng đồng có thể sửa đổi các thông báo sau: <bdi lang="zxx" dir="ltr"><code><nowiki>createacct-username-policy-popover-bullet1</nowiki></code></bdi>, <bdi lang="zxx" dir="ltr"><code><nowiki>createacct-username-policy-popover-bullet2</nowiki></code></bdi> và <bdi lang="zxx" dir="ltr"><code><nowiki>createacct-username-policy-popover-bullet3</nowiki></code></bdi>. [https://phabricator.wikimedia.org/T430604]
* Cuối tuần này, [[mw:Special:MyLanguage/Help:Extension:CodeMirror|trình làm nổi bật cú pháp CodeMirror]] sẽ cung cấp [[w:en:Theme (computing)|các chủ đề]]. Các chủ đề có thể được chọn từ menu thả xuống trong hộp thoại [[mw:Special:MyLanguage/Help:Extension:CodeMirror#CodeMirror preferences|tùy chọn CodeMirror]] hoàn chỉnh. Đối với mã wiki, các chủ đề có sẵn là mặc định, thân thiện với người mù màu (trước đây là tùy chọn dễ phân biệt cho người mù màu trong [[Special:Preferences#mw-prefsection-editing]]) và không làm nổi bật. Đối với các ngôn ngữ lập trình (ví dụ: CSS/JavaScript/JSON/Vue/Lua), hiện có sẵn một vài chủ đề. Các chủ đề tương tự này sau này cũng sẽ có sẵn cho mã wiki. [https://phabricator.wikimedia.org/T163533]
* Kể từ giờ trở đi, các wiki có thể giới hạn sửa đổi trong không gian tên "Thành viên" chỉ cho chính thành viên đó và một số nhóm người dùng nhất định. [[mw:Special:MyLanguage/Manual:$wgRestrictUserPageEditing|Đọc tài liệu hướng dẫn cấu hình]] để tìm hiểu thêm.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.14|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/31|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W31"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 18:49, ngày 27 tháng 7 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30856308 -->
== Bản tin Kỹ thuật: Tuần 32-2026 ==
<section begin="technews-2026-W32"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/32|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* [[mw:Special:MyLanguage/Readers/Reader Experience|Nhóm Trải nghiệm Người đọc]] đã phát triển một [https://82db7c8d4b.catalyst.wmcloud.org/w/index.php?title=Regent%27s_Park&uselang=de bản vá demo] nhằm bọc thanh công cụ trang thành hai dòng nếu không có đủ không gian bề ngang cho tất cả các nút. Điều này nhằm mục đích giảm tình trạng quá tải trên thanh công cụ trong giao diện Vector 2022, có thể xảy ra trên một số trang ngôn ngữ Wikipedia trên một số độ rộng màn hình nhất định. [https://phabricator.wikimedia.org/T429518]
* Nhóm Trải nghiệm Người đọc dự kiến sẽ phát hành [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|Danh sách Đọc]], một [[m:Special:MyLanguage/Community Wishlist Survey 2021/Mobile and apps/Have Apps reading lists available on Destop/Mobile|mục trong Danh sách Mong muốn Cộng đồng]], hiện đang có sẵn để dùng thử dưới dạng tính năng beta, dưới dạng tính năng đầy đủ vào tháng 9. Trước thời điểm đó, chúng tôi cần các tình nguyện viên biên dịch giúp [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-readinglists&filter=&action=translate dịch các chuỗi này] sang những ngôn ngữ khác. Tính năng này giúp hỗ trợ các mục tiêu đọc và học tập trên Wikipedia.
* Vào tuần tới, mục lục trên các trang tập tin Wikimedia Commons sẽ được cải thiện bằng cách hợp nhất mục lục trang tập tin với mục lục của trang. Điều này sẽ giúp việc hiểu cấu trúc trang tập tin, điều hướng đến những đề mục cụ thể, và chia sẻ liên kết đến các đề mục riêng biệt trở nên dễ dàng hơn. [https://phabricator.wikimedia.org/T332644]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:24}} {{PLURAL:24|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một lỗi khiến cho một số hình [[w:TIFF|TIFF]] không thể tải được sau khi nhấn vào hình thu nhỏ của nó, khiến cho hình bị hỏng được hiển thị thay vì hình có kích thước đầy đủ, nay đã được giải quyết. [https://phabricator.wikimedia.org/T429326]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Bộ chọn biến và hàm trong Bộ lọc Sai phạm (AbuseFilter) đã được cập nhật để hỗ trợ tìm kiếm và tự động điền. Điều này sẽ giúp những người quản lý bộ lọc tìm kiếm biến hoặc hàm mong muốn nhanh hơn. [https://phabricator.wikimedia.org/T323698]
* Các định dạng MJPEG và VP8 đã bị loại bỏ khỏi trình phát video. Thay vào đó, định dạng MP4 (MPEG-4 Phần 2) được thêm vào, nhằm cung cấp video chất lượng cao hơn cho các thiết bị iPhone đời cũ. Việc cập nhật lại tất cả các video hiện có sẽ có thể mất vài tuần. Định dạng mặc định cho các thiết bị hiện đại vẫn sẽ được giữ nguyên (VP9/WebM). [https://phabricator.wikimedia.org/T358266]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.15|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/32|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W32"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 19:46, ngày 3 tháng 8 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30872536 -->
== Bản tin Kỹ thuật: Tuần 33-2026 ==
<section begin="technews-2026-W33"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/33|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Mục Mong muốn cộng đồng]] Công cụ mới Trình tạo Biểu đồ (ChartWizard) [[c:Special:ChartWizard/Data:Example.Pie.chart|nay đã có mặt trên Wikimedia Commons]] dành cho các thành viên có mong muốn tạo các biểu đồ từ dữ liệu của riêng mình. Trình hướng dẫn này giúp [[mw:Special:MyLanguage/Extension:Chart|phần mở rộng Chart]] trở nên thân thiện hơn với người mới bắt đầu bằng cách cho phép các biên tập viên tạo biểu đồ, chẳng hạn như biểu đồ cột và biểu đồ tròn, mà không cần phải sử dụng JSON. Các thành viên vẫn có thể chuyển sang trình soạn thảo mã JSON nếu họ muốn. Mọi ý kiến đóng góp về công cụ mới này đều được hoan nghênh trên [[m:Talk:Community Wishlist/W414|trang thảo luận của mong muốn này]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:19}} {{PLURAL:19|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho tiện ích Hình ảnh của Ngày của ứng dụng Wikipedia dành cho iOS hiển thị cùng một hình ảnh mỗi ngày thay vì cập nhật hàng ngày, nay đã được giải quyết. [https://phabricator.wikimedia.org/T430692]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Hình ảnh SVG cho [[mw:Special:MyLanguage/Extension:Math|công thức toán học]] sẽ sớm được tạo trong trình duyệt thay vì trên máy chủ. MathML vẫn sẽ tiếp tục được tạo trên máy chủ và hiển thị trong trình duyệt mà không cần JavaScript. Wikibooks sẽ áp dụng thay đổi này vào ngày 12 tháng 8, Wikisource vào ngày 19 tháng 8 và Wikipedia từ ngày 20-27 tháng 8. Bạn có thể thử thay đổi này bằng cách chọn "{{int:Mw-math-mathjax}}" trong phần tùy chọn của bạn. Thay đổi này là một phần trong lộ trình [[mw:Special:MyLanguage/RESTBase/deprecation|ngừng sử dụng RESTBase]] và [[phab:T431372|ngừng sử dụng Mathoid]]. [https://phabricator.wikimedia.org/T271001]
* <span class="mw-translate-fuzzy">Các trang thể loại sẽ sớm hỗ trợ việc sắp xếp các mục theo thời gian chúng được thêm vào thể loại. Điều này sẽ giúp việc tìm kiếm các trang được xếp thể loại gần đây hoặc đã xếp từ lâu trở nên dễ dàng hơn. Tính năng này cũng sẽ cải thiện quy trình làm việc đối với các thể loại bảo trì chẳng hạn như danh sách trang chờ xóa và các tác vụ rà soát theo thời gian khác. Bạn có thể sử dụng tham số URL <bdi lang="zxx" dir="ltr"><code><nowiki>cldsort=timestamp</nowiki></code></bdi> trong chế độ xem thể loại để sắp xếp các mục này.</span> [https://phabricator.wikimedia.org/T433768]
* Các [[mw:Special:MyLanguage/Extension:Gadgets|tiện ích]] và đoạn mã người dùng trên các wiki của Wikimedia nay có thể sử dụng [[phab:T395347|các tính năng theo chuẩn ES2018]] và [[phab:T419142|các tính năng theo chuẩn ES2019]] trong đoạn mã JavaScript. Trước đây, nền tảng chỉ cho phép sử dụng tối đa đến chuẩn ES2017. MediaWiki kiểm tra mã nguồn để bảo vệ chức năng khỏi các lỗi cú pháp và đảm bảo các đoạn mã đều hợp lệ trên tất cả [[mw:Special:MyLanguage/Compatibility#Browser_support_matrix|các trình duyệt được hỗ trợ]]. [https://phabricator.wikimedia.org/T419142]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.16|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/33|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W33"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 20:45, ngày 10 tháng 8 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30901051 -->
== Bản tin Kỹ thuật: Tuần 34-2026 ==
<section begin="technews-2026-W34"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/34|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* [[mw:Special:MyLanguage/Help:Extension:CampaignEvents/Registration/Worklist|Tính năng Danh sách Công việc (Worklist)]] dành cho công cụ Đăng ký Sự kiện nay đã có mặt trên tất cả các dự án wiki của Wikimedia. Với Danh sách Công việc, ban tổ chức sự kiện có thể thêm trực tiếp các bài viết mà sẽ là trọng tâm của sự kiện vào trang sự kiện. Danh sách Công việc cũng hỗ trợ tính năng [[mw:Special:MyLanguage/Help:Extension:CampaignEvents/Registration/Worklist#How Event Pathways uses the worklist|Lộ trình Sự kiện (Event Pathways)]] giúp thông báo cho các biên tập viên khác về sự kiện sắp hoặc đang diễn ra khi họ sửa đổi một bài viết có trong Danh sách Công việc của sự kiện đó. Đây là phiên bản khả thi tối thiểu (MVP), và chúng tôi hoan nghênh mọi ý kiến đóng góp. Các ban tổ chức được khuyến khích thử tính năng này. Buổi [[m:Special:MyLanguage/Event:Worklist Setup Workshop: Get Your Event Ready|Hội thảo Thực hành Danh sách Công việc]] sẽ diễn ra vào ngày 18 tháng 6 lúc 16:00 UTC và ngày 19 tháng 6 lúc 11:00 UTC.
'''Cập nhật cho biên tập viên'''
* [[Special:ShortPages]] hiển thị các trang ngắn dựa trên kích thước của chúng, nhưng trong nhiều trường hợp danh sách này bị lấp đầy bởi các trang định hướng và đổi hướng mềm, khiến việc tìm kiếm chính các bài viết ngắn đó trở nên khó khăn hơn. Kể từ cuối tuần này, bạn sẽ có thể loại bỏ một bài viết khỏi trang đặc biệt này bằng cách thêm từ ma thuật <bdi lang="zxx" dir="ltr"><code><nowiki>__EXPECTSHORTPAGE__</nowiki></code></bdi>. [https://phabricator.wikimedia.org/T433203]
* Một wiki mới đã được tạo ra: {{int:project-localized-name-group-wikipedia/vi}} tiếng [[d:Q3436680|Bole]] ([[w:bol:|<bdi lang="zxx" dir="ltr"><code><nowiki>w:bol:</nowiki></code></bdi>]]) [https://phabricator.wikimedia.org/T429921]
* Kể từ tuần ngày 17 tháng 8, thanh công cụ trang sẽ tự động xuống thành hai hàng khi không còn đủ không gian theo chiều ngang để hiển thị tất cả các nút. Đây là một [[phab:T429518|bản vá đã được hợp nhất hoàn toàn từ nhóm Trải nghiệm Người đọc]] nhằm giảm bớt tình trạng chật không gian trên thanh công cụ của giao diện Vector 2022, một vấn đề mà có thể xảy ra trên một số phiên bản ngôn ngữ Wikipedia ở một số độ rộng màn hình nhất định.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:16}} {{PLURAL:16|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, việc tải các tập tin có dung lượng lớn lên Wikimedia Commons đã trở nên ổn định hơn và ít gặp lỗi hơn sau một số bản sửa lỗi liên quan đến lỗi tải lên "Không thể lấy khóa". [https://phabricator.wikimedia.org/T386640]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Debian Bullseye sẽ kết thúc Hỗ trợ Dài hạn vào ngày 31 tháng 8 năm 2026. [[phab:T434103|Một số dự án Cloud VPS]] vẫn còn instance đang chạy Debian Bullseye. Bảo trì viên của những dự án này được khuyến khích chuyển sang Debian Bookworm hoặc Debian Trixie. Hiện đã có trang [[wikitech:Help:Cloud VPS instance operating system migration|hướng dẫn di chuyển]] nhằm giúp thực hiện quy trình này, đồng thời các thành viên cũng có thể muốn xem xem liệu khối lượng công việc của họ có phù hợp hơn với Toolforge hay không. Nếu bạn cần trợ giúp hoặc không thể hoàn tất quá trình chuyển đổi trước ngày 31 tháng 8, vui lòng liên hệ với quản trị viên Cloud VPS càng sớm càng tốt. [[listarchive:list/cloud-announce@lists.wikimedia.org/thread/RVIPQSYLKMSL5M46JP6NEJVGVE6I2RXQ/|Đọc thêm]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.16|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/34|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W34"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 21:03, ngày 17 tháng 8 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30922806 -->
== Bản tin Kỹ thuật: Tuần 35-2026 ==
<section begin="technews-2026-W35"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/35|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* Trang [[Special:CreateAccount|Đặc biệt:Tạo tài khoản]] đã được đơn giản hóa như là một phần của nỗ lực nhằm hiện đại hóa trải nghiệm tạo tài khoản. Khung hiển thị số liệu thống kê về dự án sẽ không còn xuất hiện bên cạnh biểu mẫu trên giao diện trang web máy tính và di động. Nhiều thử nghiệm tạo tài khoản cho thấy việc sử dụng biểu mẫu đơn giản hơn giúp người dùng mới hoàn tất quy trình đăng ký dễ dàng hơn. [https://phabricator.wikimedia.org/T433783]
* Để cải thiện hiệu suất trang, các hình ảnh nay sẽ chỉ được tải khi người dùng xem chúng. Điều này có nghĩa là những hình ảnh nằm ở phần dưới của bài viết sẽ không được tải nếu người đọc không bao giờ cuộn trang xuống phần đó của bài viết, điều này có thể ảnh hưởng đến một vài số liệu liên quan đến hình ảnh. [https://phabricator.wikimedia.org/T148047]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:42}} {{PLURAL:42|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho các hình thu nhỏ trên Abstract Wikipedia có thể không hiển thị được sau khi tập tin tương ứng được di chuyển trên Wikimedia Commons, nay đã được giải quyết. Các hình thu nhỏ nay sẽ được cập nhật chính xác khi tập tin được di chuyển. [https://phabricator.wikimedia.org/T433448]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Thẻ Thông tin Thành viên là một tính năng giúp các tuần tra viên xem thông tin về các tài khoản người dùng. Trước đây, tính năng này chỉ xuất hiện ở những nơi chẳng hạn như lịch sử trang, nhật trình và thay đổi gần đây. Giờ đây, các thành viên cũng có thể [[mw:Special:MyLanguage/Help:Extension:CheckUser#User_Info_card_in_page_content|đặt thẻ này vào nội dung trang]], bằng cách sử dụng hàm phân tích cú pháp <bdi lang="zxx" dir="ltr"><code><nowiki>{{#uic:}}</nowiki></code></bdi>. Điều này đặc biệt hữu ích trong các bản mẫu như [[:en:Template:Userlinks|<bdi lang="zxx" dir="ltr"><code><nowiki>{{Userlinks}}</nowiki></code></bdi>]] (hoặc các biến thể chuyên biệt của chúng), vì nó sẽ giúp việc xem thông tin về thành viên trên nhiều trang bảng tin nhắn trở nên dễ dàng hơn. Thẻ này sẽ chỉ được hiển thị với những người dùng đã kích hoạt tính năng này trong phần [[Special:Preferences#mw-input-wpcheckuser-userinfocard-enable|tùy chọn]] của mình. [https://phabricator.wikimedia.org/T424466]
* Do những rủi ro về bảo mật và quyền riêng tư của người dùng, chúng tôi đã vô hiệu hóa quyền truy cập vào các URL dẫn đến trang <bdi lang="zxx" dir="ltr"><code><nowiki>Special:MyPage</nowiki></code></bdi> khi sử dụng <bdi lang="zxx" dir="ltr"><code><nowiki>action=raw</nowiki></code></bdi>. Nếu điều này ảnh hưởng tới bạn, hãy cân nhắc xem bạn có thể sử dụng một phương thức nào đó thay thế hay không. Các URL dẫn đến trang <bdi lang="zxx" dir="ltr"><code><nowiki>Special:MyPage</nowiki></code></bdi> vẫn có thể truy cập và sử dụng được mà không cần sử dụng <bdi lang="zxx" dir="ltr"><code><nowiki>action=raw</nowiki></code></bdi>. Các URL cụ thể cho trang thành viên (v.d. <bdi lang="zxx" dir="ltr"><code><nowiki>User:Myusername</nowiki></code></bdi>) vẫn có thể được sử dụng với <bdi lang="zxx" dir="ltr"><code><nowiki>action=raw</nowiki></code></bdi>. [https://phabricator.wikimedia.org/T120386]
* Nhờ một bản cập nhật, phần mềm tạo hình thu nhỏ đã được cải tiến. Nó bao gồm việc nâng cấp <bdi lang="zxx" dir="ltr"><code><nowiki>librsvg</nowiki></code></bdi> lên phiên bản 2.60 và <bdi lang="zxx" dir="ltr"><code><nowiki>ImageMagick</nowiki></code></bdi> lên 7, cũng như việc khắc phục một số lỗi tạo hình thu nhỏ đã tồn tại từ lâu chẳng hạn như lỗi hiển thị. [https://phabricator.wikimedia.org/T419815#12222841]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.17|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/35|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W35"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 20:45, ngày 24 tháng 8 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30961208 -->
== Bản tin Kỹ thuật: Tuần 36-2026 ==
<section begin="technews-2026-W36"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/36|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Một hình thức mới cho Danh sách Mong muốn Cộng đồng hiện đang được lấy ý kiến đóng góp. Bạn có thể [[m:Special:MyLanguage/Community Wishlist/Community Wishlist 2027|đọc các ý tưởng đề xuất trên Meta]]. Quy trình mới này nhằm nâng cao hiệu quả sàng lọc, bỏ phiếu và ưu tiên cho các mong muốn nhằm đảm bảo tính minh bạch và sự cân bằng giữa các nhóm dự án và phiên bản ngôn ngữ. Đợt tham vấn này sẽ kéo dài trong vòng hai tuần.
'''Cập nhật cho biên tập viên'''
* Bản phát hành mới nhất của ứng dụng Wikipedia dành cho Android bao gồm các cập nhật đối với tính năng Đã lưu (Saved), giúp trải nghiệm lưu bài viết trên ứng dụng trở nên đồng bộ hơn với phiên bản iOS và Web. Bản cập nhật này thiết kế lại tab Đã lưu với giao diện “Tất cả bài viết”, xóa bỏ danh sách đọc mặc định “Đã lưu”, đổi tên các danh sách đọc thành “Bộ sưu tập” (Collections) và hiện đại hóa trải nghiệm lưu bài viết. [https://phabricator.wikimedia.org/T420788]
* Tính năng [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|Danh sách Đọc]] đã được kích hoạt cho tất cả người dùng đã đăng nhập trên Wikipedia tiếng Bengali, tiếng Trung, tiếng Séc và tiếng Việt vào ngày 25 tháng 8, sau vài tháng hoạt động dưới dạng tính năng thử nghiệm (beta). Danh sách Đọc sẽ được triển khai đến tất cả người dùng đã đăng nhập trên Wikipedia tiếng Ả Rập, tiếng Pháp và tiếng Indonesia vào ngày 1 tháng 9, sau đó là Wikipedia tiếng Anh vào ngày 14 tháng 9, và trên tất cả các wiki Wikipedia còn lại vào ngày 28 tháng 9.
* Vào cuối tháng này, một số độc giả chưa đăng nhập trên Wikipedia tiếng Bengali, tiếng Séc, tiếng Ba Tư, tiếng Anh và tiếng Ba Lan sử dụng giao diện Minerva trên thiết bị di động sẽ nhìn thấy một [[mw:Special:MyLanguage/Readers/Reader_Growth/Minimal_Minerva|thanh điều hướng được cập nhật]] trong [[:w:vi:Thử nghiệm A/B|thử nghiệm A/B]]. Thử nghiệm này sẽ so sánh thanh điều hướng hiện tại với phiên bản mới được thiết kế nhằm giúp người dùng tìm kiếm thông tin một cách nhanh chóng và dễ dàng hơn. Mục tiêu là xác định xem những thay đổi này có khuyến khích độc giả quay lại thường xuyên hơn hay không. Thử nghiệm này sẽ không làm thay đổi trải nghiệm của người dùng và/hoặc biên tập viên đã đăng nhập.
* Các biên tập viên chuyên bảo trì các trang đổi hướng, bản mẫu và thể loại được sử dụng trên các trang đổi hướng nay có thêm các phương thức cải tiến để tìm kiếm và quản lý trang đổi hướng. Trước đây, các trang đổi hướng không thể tìm kiếm được. Hai từ khóa tìm kiếm mới, <bdi lang="zxx" dir="ltr"><code><nowiki>onlyredirects:</nowiki></code></bdi> và <bdi lang="zxx" dir="ltr"><code><nowiki>withredirects:</nowiki></code></bdi>, giờ đây cho phép tìm kiếm trực tiếp các trang đổi hướng và có thể kết hợp với các từ khóa hiện có như <bdi lang="zxx" dir="ltr"><code><nowiki>incategory:</nowiki></code></bdi>, <bdi lang="zxx" dir="ltr"><code><nowiki>intitle:</nowiki></code></bdi> và <bdi lang="zxx" dir="ltr"><code><nowiki>insource:</nowiki></code></bdi>. [https://phabricator.wikimedia.org/T204089]
* Các công cụ tìm kiếm ISBN để tạo các nguồn trích dẫn gần đây đã không hoạt động do các vấn đề liên quan đến dịch vụ bên ngoài. Các nhà phát triển đang nỗ lực để tìm giải pháp khắc phục. [https://phabricator.wikimedia.org/T435179]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:30}} {{PLURAL:30|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho việc tìm kiếm trang theo thể loại sử dụng <bdi lang="zxx" dir="ltr"><code><nowiki>deepcat</nowiki></code></bdi> có thể không trả về kết quả hoặc trả về kết quả không liên quan nay đã được giải quyết. [https://phabricator.wikimedia.org/T414859]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Tên miền của URL cho hình thu nhỏ đang được thay đổi từ $1 sang thumb.wikimedia.org. Các URL cũ sẽ tiếp tục hoạt động trong tương lai gần, nhưng MediaWiki sẽ chuyển sang sử dụng tên miền mới. Các URL trỏ đến các loại tập tin đa phương tiện khác như tập tin gốc, video và tập tin chuyển mã vẫn sẽ được phục vụ từ upload.wikimedia.org. [https://phabricator.wikimedia.org/T427465]
* [https://www.mediawiki.org/w/index.php?api=wmf-math%2Fv1&title=Special%3ARestSandbox API Toán học (Math API)] của Wikimedia hiện đã lỗi thời và không còn được hỗ trợ. Các điểm cuối (endpoints) này sẽ chính thức ngừng hoạt động hoàn toàn vào cuối tháng 9 năm 2026. Các nhà phát triển gọi các điểm cuối này nên chuyển sang các giải pháp hiển thị toán học thay thế, chẳng hạn như [https://developer.mozilla.org/en-US/docs/Web/MathML MathML] tích hợp sẵn hoặc [https://www.mathjax.org/ MathJax]. Các hệ thống MediaWiki được cài đặt bởi bên thứ ba sử dụng phần mở rộng Math để hiển thị công thức bắt buộc phải nâng cấp lên phiên bản v1.43 trở lên để tránh gián đoạn dịch vụ.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.18|MediaWiki]]
'''Chuyên sâu'''
* Đọc thêm về [[mw:Special:MyLanguage/Edit_check/TextMatch|TextMatch]] trong một bài viết trên Diff có tiêu đề: [[diffblog:2026/08/28/custom-edit-suggestions-for-every-wiki-how-communities-are-shaping-suggestion-mode-with-textmatch/|Đề xuất sửa đổi tùy chỉnh cho mọi wiki: Cộng đồng đang định hình Chế độ Gợi ý với TextMatch như thế nào]].
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/36|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W36"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 20:53, ngày 31 tháng 8 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30990659 -->
== Bản tin Kỹ thuật: Tuần 37-2026 ==
<section begin="technews-2026-W37"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/37|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* Tính năng [[mw:Special:MyLanguage/Help:Growth/Tools/Add_a_link|Thêm Liên kết]] đã được nâng cấp cho người dùng trên Wikipedia tiếng Anh với khả năng phát hiện tốt hơn các liên kết có sự khác biệt về cách viết hoa. Cải tiến này sẽ giúp giảm bớt những gợi ý mơ hồ gây ra do sự khác biệt về cách viết viết hoa trong tiêu đề bài viết, bao gồm cả những bài viết về các sản phẩm văn hóa. Hiện kế hoạch cải tiến giai đoạn 2 đã được lên lịch, kế hoạch cũng sẽ nhằm mục đích chuẩn bị phát hành tính năng này ở các ngôn ngữ khác. [https://phabricator.wikimedia.org/T435526#12240876] [https://phabricator.wikimedia.org/T434259]
* Tính năng [[mw:Special:MyLanguage/Article_guidance|Chỉ dẫn bài viết]] sẽ được bật theo mặc định cho các biên tập viên mới trên Wikipedia tiếng Anh Đơn giản và Wikipedia tiếng Thổ Nhĩ Kỳ kể từ ngày 10 tháng 9 năm 2026 sau khi đã trải qua [[mw:Special:MyLanguage/Article_guidance/Updates#Summary_of_experiment_result|một cuộc thử nghiệm]]. Các biên tập viên mới có từ 0 đến 99 sửa đổi sẽ tự động nhìn thấy tính năng này khi họ nhấn vào liên kết đỏ hoặc sử dụng tùy chọn "[[tr:Vikipedi:Madde_sihirbazı|Madde oluşturto]]" (tạo bài viết) trên Wikipedia tiếng Thổ Nhĩ Kỳ để tạo bài viết mới. Thay đổi này nhằm mục đích giúp các biên tập viên mới tạo các bài viết có chất lượng cao hơn và đáp ứng các tiêu chuẩn của từng dự án Wikipedia. [[phab:maniphest/query/z3tcTjmLMxk5/#R|Các cải tiến bổ sung]] sẽ tiếp tục được thực hiện dựa trên kết quả thử nghiệm và phản hồi từ cộng đồng.
* Công cụ [https://pageviews.wmcloud.org Phân tích Lượt xem Trang] nhằm cho phép người dùng so sánh lượt xem giữa nhiều trang, năm nay đã tròn 10 tuổi và được bổ sung thêm một số tính năng mới. Chúng bao gồm [[toolforge:wikinav|WikiNav]] nhằm cung cấp thông tin chuyên sâu vào cách độc giả Wikipedia khám phá nội dung, thống kê sửa đổi trong mục [https://pageviews.wmcloud.org/siteviews?range=latest-30&sites=en.wikipedia.org Siteviews], khả năng [https://pageviews.wmcloud.org/massviews?source=wikiproject&project=en.wikipedia.org tra cứu bài viết thuộc Dự án Wiki], cũng như hỗ trợ chế độ tối. [https://phabricator.wikimedia.org/T378549]
* Một thanh điều hướng [[mw:Special:MyLanguage/Readers/Reader_Growth/Minimal_Minerva|Minerva được đơn giản hóa về mặt trực quan]] đang được thử nghiệm dành cho các độc giả chưa đăng nhập sử dụng giao diện web di động trên các dự án Wikipedia tiếng Bengal, tiếng Séc, tiếng Anh, tiếng Ba Tư và tiếng Ba Lan. Thử nghiệm này nhằm xác định xem việc đơn giản hóa thanh điều hướng có cải thiện việc giữ chân độc giả hay không. Thử nghiệm sẽ diễn ra từ ngày 31 tháng 8 đến ngày 28 tháng 9, và người dùng không cần phải thực hiện bất kỳ thao tác nào.
* [[m:Special:MyLanguage/WMDE Technical Wishes|Nhóm Mong muốn Kỹ thuật của WMDE]] đang thực hiện việc cải tiến [[en:Wikipedia:VisualEditor/Named references|tên nguồn tham khảo được tạo tự động trong Trình Soạn thảo Trực quan]]. Các biên tập viên sẽ chỉ nhận thấy một thay đổi nhỏ kể từ tuần này. Khi thêm tên nguồn tham khảo tự động việc đánh số sẽ bắt đầu tại <bdi lang="zxx" dir="ltr"><code><nowiki>:1</nowiki></code></bdi> thay vì <bdi lang="zxx" dir="ltr"><code><nowiki>:0</nowiki></code></bdi>. Đọc thêm trên [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names|trang dự án]]. [https://gerrit.wikimedia.org/r/c/VisualEditor/VisualEditor/+/1332704]
* Tất cả các wiki sẽ [[m:Special:MyLanguage/Tech/Server switch|chuyển sang chế độ chỉ đọc trong vài phút]] vào ngày 23 tháng 9. Kế hoạch dự kiến diễn ra lúc 14:00 UTC. Thông tin thêm về kế hoạch này sẽ được xuất bản trong Bản tin Kỹ thuật và cũng sẽ được đăng lên trên từng wiki trong các tuần tiếp theo. [https://phabricator.wikimedia.org/T433363]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:25}} {{PLURAL:25|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho [[mw:Special:MyLanguage/Parsoid|Parsoid]] có thể xử lý sai các thẻ nowiki được lồng nhau, khiến nội dung bị mất và hiển thị nội dung không mong muốn nay đã được giải quyết. [https://phabricator.wikimedia.org/T435116]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Bảo quản viên giao diện có thể cấu hình các tiện ích từ [[MediaWiki:Gadgets-definition]]. Định dạng của định nghĩa tiện ích đã được cập nhật và không còn yêu cầu tùy chọn <bdi lang="zxx" dir="ltr"><code><nowiki>ResourceLoader</nowiki></code></bdi> nữa, vì các tiện ích luôn được tải thông qua <bdi lang="zxx" dir="ltr"><code><nowiki>ResourceLoader</nowiki></code></bdi>. Điều này giúp đơn giản hóa cấu hình tiện ích bằng cách loại bỏ một tùy chọn không còn cần thiết nữa, giúp việc định nghĩa tiện ích trở nên dễ dàng hơn cho các bảo quản viên. [https://phabricator.wikimedia.org/T298199]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.19|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/37|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W37"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 18:44, ngày 7 tháng 9 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31008437 -->
== Bản tin Kỹ thuật: Tuần 38-2026 ==
<section begin="technews-2026-W38"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/38|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Nhóm Future Audiences đã mở một [[en:Special:MyLanguage/Wikipedia:Village pump (proposals)#New proposed experiment to let readers know about “Google preferred sources”|cuộc thảo luận trên Wikipedia tiếng Anh]] về một đề xuất thử nghiệm mới nhằm hiển thị thông báo tạm thời về tính năng mới [https://blog.google/products-and-platforms/products/search/original-high-quality-content-search/ Nguồn Ưu tiên của Google] dành cho độc giả Wikipedia truy cập từ Google. Thử nghiệm này nhằm kiểm tra xem liệu thông báo này có giúp thu hút khách truy cập quay lại Wikipedia thường xuyên hơn hay không. Tính năng Nguồn Ưu tiên cho phép người dùng chọn các trang web mà họ tin tưởng nhằm giúp Google có thể hiển thị nội dung từ các nguồn này một cách nổi bật hơn trong trải nghiệm trên Tìm kiếm và AI. Chúng tôi mong muốn triển khai thử nghiệm này trên các ngôn ngữ khác mà Google hỗ trợ và rất hoan nghênh sự hỗ trợ trong việc khởi xướng thảo luận trên các dự án wiki khác. Nếu bạn quan tâm, vui lòng liên hệ nhóm Future Audiences trên [[m:Special:MyLanguage/Future Audiences/Preferred sources|trang thảo luận]].
'''Cập nhật cho biên tập viên'''
* Nền tảng trò chuyện Discord ra mắt cơ chế (framework) tự thiết lập mới nhằm cho phép các trang web có thể sử dụng để tùy chỉnh cách hiển thị những liên kết đó khi được chia sẻ trên Discord. Nhóm Future Audiences dự định sẽ bắt đầu sử dụng cơ chế này để cải thiện cách hiển thị các liên kết Wikipedia khi được chia sẻ trên Discord, nhằm ghi công sửa đổi của các tình nguyện viên một cách tốt hơn. Hình thức và cách thức hoạt động của liên kết sẽ không thay đổi trong giai đoạn đầu của dự án này vì chúng tôi muốn thu thập một số dữ liệu cơ sở trước để đánh giá tác động của những thay đổi này trong tương lai. Dù vậy, nếu các thành viên cộng đồng đang hoạt động trên Discord có phát hiện ra bất kỳ vấn đề nào, họ có thể liên hệ qua [[phab:tag/future-audiences/|Phabricator]] hoặc [[m:Special:MyLanguage/Future Audiences|Metawiki]].
* Nhóm Phát triển Độc giả sẽ tiến hành một thử nghiệm xem liệu [[mw:Special:MyLanguage/Readers/Reader_Growth/Compact Lead|việc rút gọn phần mở đầu của bài viết]] kèm theo nút "đọc thêm" có giúp cải thiện việc giữ chân người đọc hay không. Thử nghiệm này sẽ bắt đầu vào ngày 17 tháng 9 trên các phiên bản Wikipedia tiếng Ả Rập, tiếng Tây Ban Nha, tiếng Pháp, tiếng Indonesia, tiếng Ý, tiếng Nhật, tiếng Bồ Đào Nha, tiếng Việt và tiếng Trung và sẽ kéo dài trong bốn tuần.
* Tất cả các wiki sẽ [[m:Special:MyLanguage/Tech/Server switch|chuyển sang chế độ chỉ đọc trong vòng vài phút]] vào ngày 23 tháng 9. Kế hoạch được lên lịch lúc 14:00 UTC. Thông tin chi tiết sẽ được đăng tải lên Bản tin Kỹ thuật và cũng sẽ được đăng lên từng wiki riêng lẻ trong tuần tới. [https://phabricator.wikimedia.org/T433363]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:28}} {{PLURAL:28|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến [https://wikistats.wmcloud.org/ Wikistats] dành cho Wikipedia trả về lỗi HTTP 500 và không thể truy cập được, nay đã được giải quyết. [https://phabricator.wikimedia.org/T435959]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Các nhà phát triển đang bảo trì công cụ truy vấn các bảng liên kết của Wikimedia Commons cần cập nhật mã nguồn của mình để kết nối với cụm cơ sở dữ liệu (database cluster) x4 mới. Các bảng liên kết đã được chuyển từ cụm s4 sang x4, và sẽ không còn nhận được cập nhật trên cụm s4 nữa. Các bảng trang và đổi hướng vẫn sẽ tiếp tục khả dụng trên cả hai cụm này. Một bản sao dữ liệu wiki (wiki replica) cho cụm x4 sẽ được thiết lập sau này. Thay đổi này được thực hiện do cụm s4 đã trở nên quá lớn gây ảnh hưởng đến hiệu quả vận hành của bảng liên kết. Bạn có thể [[wikitech:Special:MyLanguage/News/2026 Commons links tables database split|đọc thêm]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.20|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/38|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W38"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 15:31, ngày 14 tháng 9 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31039826 -->
== Chuyển đổi máy chủ - Wiki của bạn sẽ sớm chuyển sang chế độ chỉ đọc trong một khoảng thời gian ngắn ==
<section begin="server-switch"/><div class="plainlinks">
[[:m:Special:MyLanguage/Tech/Server switch|Đọc thông báo này bằng ngôn ngữ khác]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}]
[[foundation:|Quỹ Wikimedia]] sẽ chuyển đổi lưu lượng qua lại giữa các trung tâm dữ liệu. Điều này sẽ giúp đảm bảo rằng Wikipedia và các wiki khác của Wikimedia vẫn có thể duy trì trực tuyến ngay cả sau tình huống thiên tai.
Mọi lưu lượng sẽ chuyển đổi vào ngày '''{{#time:j xg|2026-09-23|vi}}'''. Việc chuyển đổi này sẽ bắt đầu vào lúc '''[https://zonestamp.toolforge.org/{{#time:U|2026-09-23T14:00|en}} {{#time:H:i e|2026-09-23T14:00}}]'''.
Dù vậy, vì một số hạn chế của phần mềm [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], mọi sửa đổi đều phải bị ngưng lại khi việc chuyển đổi được thực hiện. Chúng tôi chân thành xin lỗi vì sự gián đoạn này, và chúng tôi đang tìm cách giảm thiểu những tình huống như vậy trong tương lai.
Một biểu ngữ sẽ được hiển thị trên tất cả các wiki 30 phút trước khi quá trình này diễn ra. Biểu ngữ sẽ tiếp tục được hiển thị cho tới khi kết thúc quá trình này.
Bạn có thể đóng góp bằng cách [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate biên dịch và hiệu đính] dòng biểu ngữ này.
'''Bạn sẽ có thể đọc, nhưng không thể sửa đổi, tất cả wiki trong một khoảng thời gian ngắn.'''
* Bạn sẽ không thể sửa đổi trong vòng tối đa một giờ vào {{#time:l j xg Y|2026-09-23|vi}}.
* Nếu bạn cố gắng sửa đổi hay lưu trang trong khoảng thời gian này, bạn sẽ nhìn thấy một thông báo lỗi. Chúng tôi hy vọng sẽ không có sửa đổi nào bị mất trong khoảng thời gian đó, nhưng chúng tôi không thể đảm bảo được điều đó. Nếu bạn nhìn thấy thông báo lỗi, vui lòng chờ đợi cho đến khi mọi thứ trở lại bình thường. Sau đó bạn sẽ có thể lưu lại sửa đổi của mình. Tuy nhiên, chúng tôi khuyên bạn trước hết nên tạo một bản sao những thay đổi của bạn, nhằm mục đích đề phòng.
''Những ảnh hưởng khác'':
* Tác vụ xử lý nền sẽ bị chậm hơn và một số có thể bị ngừng hẳn. Các liên kết đỏ có thể sẽ không được cập nhật nhanh chóng như thường lệ. Nếu bạn tạo một bài viết đã được liên kết ở một nơi khác, liên kết đó vẫn sẽ có màu đỏ lâu hơn bình thường. Một số đoạn mã tốn nhiều thời gian chạy sẽ phải dừng lại.
* Chúng tôi hy vọng việc triển khai mã nguồn vẫn sẽ diễn ra như bất kỳ tuần nào khác. Tuy vậy, một vài trường hợp đóng băng mã nguồn có thể xảy ra nếu quá trình yêu cầu chúng sau đó.
* [[mw:Special:MyLanguage/GitLab|GitLab]] sẽ không khả dụng trong khoảng 90 phút.
Dự án này có thể bị hoãn lại nếu cần thiết. Bạn có thể [[wikitech:Switch_Datacenter|đọc lịch trình tại wikitech.wikimedia.org]]. Bất kỳ thay đổi nào đều sẽ được thông báo trong lịch trình này.
'''Xin hãy chia sẻ thông tin này với cộng đồng của bạn.'''</div><section end="server-switch"/>
[[m:user:Trizek (WMF)|Trizek (WMF)]] 12:58, ngày 15 tháng 9 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Trizek (WMF)@metawiki gửi cho mọi người trong danh sách tại 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, ngày 25 tháng 9 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Danny Benjafield (WMDE)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31081007 -->
== Bản tin Kỹ thuật: Tuần 39-2026 ==
<section begin="technews-2026-W39"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/39|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* [[m:Special:MyLanguage/Tech/Server switch|Tất cả các wiki sẽ chuyển sang chế độ chỉ đọc]] trong vòng vài phút vào thứ 4, ngày 23 tháng 9 năm 2026 lúc [https://zonestamp.toolforge.org/1790172000 14:00 UTC]. Điều này là nhằm phục vụ cho việc thử nghiệm chuyển đổi máy chủ cơ sở dữ liệu dự phòng, [[wikitech:Special:MyLanguage/Deployments/Yearly calendar|diễn ra hai lần trong một năm]]. Trong quá trình chuyển đổi này, toàn bộ lưu lượng trên các trang web của Wikimedia được chuyển từ trung tâm dữ liệu chính sang trung tâm dữ liệu dự phòng nhằm kiểm tra tính khả dụng và ngăn ngừa việc gián đoạn dịch vụ ngay cả trong những trường hợp khẩn cấp. [https://phabricator.wikimedia.org/T433363]
'''Cập nhật cho biên tập viên'''
* Nhóm Tăng trưởng đã thử nghiệm một thông báo sau khi sửa đổi mới được thiết kế nhằm [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#4. Encourage Temporary Accounts to Register|khuyến khích những người đang có Tài khoản Tạm thời đăng ký tài khoản vĩnh viễn]]. Thông báo mới này thay thế cho nhiều hộp thoại kèm thông báo chào mừng xuất hiện cùng lúc bằng một thông báo duy nhất nhằm nêu bật những lợi ích của việc tạo một tài khoản. Thử nghiệm này đã giúp tăng tỷ lệ tạo tài khoản vĩnh viễn từ 1.94% lên 3.66%, tương đương với mức tăng khoảng 87%. Thay đổi này giờ đây sẽ được triển khai đến tất cả các dự án wiki. [https://phabricator.wikimedia.org/T433551]
* Đối với các biên tập viên Wikipedia sử dụng [[Special:Preferences#mw-prefsection-betafeatures|Tính năng Beta "Chế độ gợi ý"]], hiện có một [[Special:Preferences#mw-input-wpvisualeditor-editcheck-experimental|tùy chọn mới trong phần tùy chọn của người dùng]] nhằm hiển thị các gợi ý và kiểm tra sửa đổi mang tính "thử nghiệm". Những loại này được liệt kê tại [[Special:EditChecks#experimental-checks|Đặc biệt:EditChecks]], và nhằm mục đích để lập trình viên thử nghiệm sớm cũng như để thu thập phản hồi từ những người dùng có kinh nghiệm. Các bảo quản viên có thể thay đổi [[mw:Special:MyLanguage/Edit check/Configuration|chi tiết cấu hình]] cho từng gợi ý như thường lệ. Bảo quản viên cũng có thể [[mw:Special:MyLanguage/Help:Suggestion mode#Experimental Suggestions|sử dụng tính năng này]] để giúp thử nghiệm những ý tưởng của cộng đồng về những quy tắc kiểm tra và gợi ý do cộng đồng tạo. Những loại tính năng thử nghiệm này sẽ có giao diện trực quan khác biệt hơn vào cuối tuần này. [[mw:Talk:VisualEditor/Suggestion Mode|Mọi phản hồi đều được hoan nghênh]].
* [[m:CEE Technical Village Pump|Phòng Thảo luận Kỹ thuật CEE]] (CEE Technical Village Pump) đã được mở để đóng vai trò như một không gian thảo luận và hợp tác kỹ thuật của các cộng đồng Wikimedia tại khu vực Trung và Đông Âu.
* Một công cụ mới, [[mw:Special:MyLanguage/Language Onboarding and Development/Starter kit|Bộ Công cụ Khởi đầu]] (Starter Kit), nay đã có sẵn dành cho các cộng đồng Wikipedia ngôn ngữ mới và quy mô nhỏ. Công cụ này tập hợp những nhiệm vụ có hướng dẫn, công cụ và tài nguyên nhằm giúp cộng đồng có thể bắt đầu, theo dõi tiến độ, cũng như hợp tác cùng với cộng đồng Wikimedia rộng lớn hơn. Bộ Công cụ Khởi đầu được vận hành trên nền tảng Wikimedia Toolforge và được thiết kế dành cho các dự án Wikipedia có ít hơn 50.000 bài viết. Tìm hiểu thêm cách Bộ Công cụ Khởi đầu hoạt động và cách cộng đồng đang sử dụng công cụ này trong [[diffblog:2026/09/18/introducing-starter-kit-for-new-and-small-language-wikipedias/|bài viết này trên blog Diff]].
* Nhóm Phát triển Người đọc sẽ mở một đợt tái thử nghiệm của [[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|thử nghiệm băng chuyền hình ảnh]]. Đợt tái thử nghiệm này sẽ sử dụng ba phiên bản thiết kế mới, được cập nhật dựa trên phản hồi của cộng đồng. Nhóm sẽ đánh giá kết quả và cùng cộng đồng quyết định xem có tiếp tục triển khai tính năng này hay không. Thử nghiệm này sẽ bắt đầu vào tuần ngày 28 tháng 9 và sẽ được thực hiện trên Wikipedia tiếng Ả Rập, tiếng Bengal, tiếng Trung, tiếng Séc, tiếng Anh, tiếng Ba Tư, tiếng Pháp, tiếng Đức, tiếng Indonesia, tiếng Nhật, tiếng Ba Lan, tiếng Bồ Đào Nha, tiếng Tây Ban Nha, tiếng Thụy Điển và tiếng Việt.
* Sau khi triển khai thành công trên Wikipedia tiếng Ả Rập, tiếng Bengal, tiếng Trung, tiếng Séc, tiếng Anh, tiếng Pháp, tiếng Indonesia và tiếng Việt, [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|tính năng Danh sách Đọc]] do nhóm Trải nghiệm Người đọc phát triển sẽ có mặt cho tất cả người dùng đã đăng nhập trên tất cả các dự án Wikipedia kể từ ngày 28 tháng 9.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:28}} {{PLURAL:28|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho đoạn mã trạng thái cố vấn liên tục cập nhật trạng thái của cố vấn ngay cả khi không có gì thay đổi, tạo ra những mục không cần thiết trên Thay đổi Gần đây, nay đã được giải quyết. [https://phabricator.wikimedia.org/T436659]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* API truy vấn danh sách <bdi lang="zxx" dir="ltr"><code><nowiki>abusefilters</nowiki></code></bdi>, vốn được sử dụng để lấy thông tin chi tiết về các bộ lọc sai phạm đang hoạt động hoặc đã tắt được thiết lập trên wiki, đã được cập nhật để hỗ trợ tham số cấu hình <bdi lang="zxx" dir="ltr"><code><nowiki>formatversion=2</nowiki></code></bdi>, điều này dẫn đến những thay đổi gây ra lỗi (breaking changes) đến phản hồi của API. Tất cả người dùng đang bảo trì các đoạn mã người dùng hoặc đoạn mã khác cần kiểm tra xem họ có đang sử dụng API truy vấn danh sách <bdi lang="zxx" dir="ltr"><code><nowiki>abusefilters</nowiki></code></bdi> hay không, đồng thời điều chỉnh để giải quyết những thay đổi gây ra lỗi này. [https://phabricator.wikimedia.org/T435828]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.21|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/39|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W39"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 11:56, ngày 27 tháng 9 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31085309 -->
== Bản tin Kỹ thuật: Tuần 40-2026 ==
<section begin="technews-2026-W40"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/40|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* Người dùng sử dụng giao diện mặc định trên trang web dành cho máy tính và thiết bị di động (lần lượt là Vector 2022 và Minerva) nay sẽ được thông báo nếu gợi ý tìm kiếm được hiển thị khi họ nhập vào hộp Tìm kiếm đến từ các trang đổi hướng. Trước đây, người dùng có thể bị bối rối khi gợi ý kết quả tìm kiếm hàng đầu không khớp chính xác với những gì họ nhập vào. Thông báo trang đổi hướng mới này giúp làm rõ rằng những gợi ý này không phải ngẫu nhiên mà có liên quan đến nội dung tìm kiếm. Các trang được gợi ý có thể là các trang đổi hướng đến những bài viết đích phù hợp nhất với nội dung được tìm kiếm. [https://phabricator.wikimedia.org/T303013]
* Người dùng Wikipedia chưa đăng nhập trên giao diện web di dộng sẽ bắt đầu nhìn thấy nút đánh dấu (bookmark) để lưu các bài viết vào [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|danh sách đọc]] của họ thay vì nút Sao theo dõi (Watchstar) hiện tại. Khi được nhấn vào, nút đánh dấu sẽ yêu cầu người dùng đăng nhập hoặc tạo tài khoản để lưu bài viết và đọc lại sau. Một thử nghiệm trước đó cho thấy biểu tượng đánh dấu có khả năng khuyến khích người dùng chưa đăng nhập tạo tài khoản cao gấp bốn lần so với nút Sao theo dõi. Thay đổi này là một phần trong nỗ lực nhằm khuyến khích nhiều độc giả trở thành chủ tài khoản hơn và sử dụng các tính năng giúp họ lưu lại và quay lại để đọc nội dung. [https://phabricator.wikimedia.org/T438769]
* Một thử nghiệm sẽ bắt đầu vào ngày 29 tháng 9 trên các phiên bản Wikipedia tiếng Tây Ban Nha, tiếng Ả Rập, tiếng Anh và tiếng Pháp nhằm đơn giản hóa trải nghiệm mà người dùng gặp ngay sau khi tạo tài khoản. Thử nghiệm này sẽ khám phá xem việc loại bỏ trở ngại từ Khảo sát Chào mừng người mới hiện tại có giúp người dùng mới dễ dàng hiểu được rằng cần phải làm những gì tiếp theo hơn hay không. Cuộc thử nghiệm này sẽ kéo dài đến hết tháng 10. [https://phabricator.wikimedia.org/T430058]
* [[m:Special:MyLanguage/Product and Technology Advisory Council|Hội đồng Cố vấn về Sản phẩm và Công nghệ]] đã kêu gọi cộng đồng đề xuất các chủ đề mà hội đồng nên xem xét và thảo luận với Quỹ Wikimedia. Các biên tập viên và tình nguyện viên kỹ thuật được mời đóng góp chủ đề tại [[m:Talk:Product and Technology Advisory Council|trang thảo luận của hội đồng]].
* Cuối tuần này, các cộng đồng sẽ có thể cấu hình tính năng [[mw:Special:MyLanguage/Help:Edit check|Kiểm tra và Gợi ý Sửa đổi]] để chúng được [[mw:Special:MyLanguage/Edit check/Configuration#extraNamespaces|hiển thị trong các không gian tên bổ sung]], chẳng hạn như không gian tên <bdi lang="zxx" dir="ltr"><code><nowiki>Draft:</nowiki></code></bdi>. [[mw:Talk:VisualEditor/Suggestion Mode|Mọi ý kiến đóng góp đều được hoan nghênh]].
* Một lỗi trong [[m:Special:GlobalWatchlist|Danh sách Theo dõi Toàn cục]] đang khiến cho trang không thể tải được đối với người dùng có những thay đổi chưa được xem trên Wikimedia Commons. Các lập trình viên đang tiến hành khắc phục lỗi này. Trong thời gian đó, những người dùng bị ảnh hưởng có thể làm theo các giải pháp thay thế được nêu trong mục trợ giúp [[mw:Special:MyLanguage/Extension:GlobalWatchlist#GlobalWatchlist temporarily broken for users with Wikimedia Commons|có liên quan]].
* Các từ ma thuật mới <bdi lang="zxx" dir="ltr"><code><nowiki>{{CATEGORYSORT:TIMESTAMP}}</nowiki></code></bdi> và <bdi lang="zxx" dir="ltr"><code><nowiki>{{CATEGORYSORT:RTIMESTAMP}}</nowiki></code></bdi> hiện đã có sẵn để sử dụng. Chúng có khả năng thay đổi cách sắp xếp mặc định của các thể loại dựa trên dấu thời gian xếp thể loại. [https://phabricator.wikimedia.org/T433768]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:20}} {{PLURAL:20|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, sự cố không thể truy cập được [https://wikistats.wmcloud.org/ Wikistats] cho các trang Wikipedia nay đã được giải quyết. [https://phabricator.wikimedia.org/T435959]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Việc chuyển đổi trung tâm dữ liệu, vốn dự kiến được diễn ra vào ngày 23 tháng 9, đã bị hoãn lại. [[diffblog:2025/03/12/hear-that-the-wikis-go-silent-twice-a-year/|Cuộc diễn tập Equinox]] đã bộc lộ các vấn đề về năng lực hệ thống, khiến việc chuyển đổi toàn bộ dịch vụ sang trung tâm dữ liệu khác không thể thực hiện được. Quy trình này đã được tạm dừng để ưu tiên điều tra vấn đề nêu trên, nhằm đảm bảo rằng chúng tôi vẫn có thể phục vụ người dùng một cách ổn định và tin cậy. Một cuộc diễn tập mới sẽ được lên kế hoạch sau. Trong thời gian này, mọi lưu lượng truy cập và hoạt động sửa đổi vẫn sẽ diễn ra như bình thường.
* Vào ngày 23 tháng 9, một sự cố mất điện đã ảnh hưởng đến tất cả các dự án wiki trong một khoảng thời gian ngắn, gây ra vấn đề gián đoạn cho cả chế độ đọc và sửa đổi. Sự cố này cũng ảnh hưởng đến Gerrit. Điều này không liên quan gì đến việc hoãn chuyển đổi trung tâm dữ liệu. [https://www.wikimediastatus.net/incidents/9fm19t8qykk8]
* [[mw:Special:MyLanguage/Help:Extension:Produnto|Produnto]] đã được triển khai trên mediawiki.org và [[phab:T421436|một số wiki sử dụng ngôn ngữ Ấn Độ]]. Chúng tôi mong nhận được phản hồi của bạn về sản phẩm thử nghiệm này. Produnto cho phép người dùng sử dụng các mô đun Lua được lưu trữ trên [[gitlab:repos/lua|GitLab của Wikimedia]]. Nó giúp đơn giản hóa việc chia sẻ mã nguồn Lua giữa các wiki. Thay vì phải sao chép từng mô đun Lua riêng lẻ từ wiki này sang wiki khác, người dùng có thể dễ dàng chia sẻ các gói mã nguồn trên tất cả các wiki.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.22|MediaWiki]]
'''Các cuộc họp và sự kiện'''
* [[m:Event:Cross-wiki Code Collaboration Workshop|Hội thảo cộng tác mã nguồn giữa các wiki]] sẽ được tổ chức trực tuyến vào ngày 2 tháng 10 lúc 12:30 UTC, quy tụ những cộng tác viên kỹ thuật Nam Á nhằm tìm hiểu về Produnto và bắt đầu thử nghiệm nó trên các phiên bản Wikipedia tiếng Hindi, tiếng Punjabi, tiếng Odia, tiếng Telugu và tiếng Malayalam. Produnto là một trình quản lý gói để triển khai các mô đun Lua được lưu trữ trên GitLab đến các wiki của Wikimedia và gần đây đã được triển khai trên một số wiki thí điểm.
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/40|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W40"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 10:49, ngày 28 tháng 9 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31092225 -->
== 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 [[Thành viên:MediaWiki message delivery|MediaWiki message delivery]] ([[Thảo luận Thành viên:MediaWiki message delivery|thảo luận]]) 12:43, ngày 1 tháng 10 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Danny Benjafield (WMDE)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31106967 -->
== Bản tin Kỹ thuật: Tuần 41-2026 ==
<section begin="technews-2026-W41"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/41|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Quy trình cho [[m:Special:MyLanguage/Community Wishlist/Community Wishlist 2027#Updated Community Wishlist Process 2027/2028|Danh sách mong muốn của cộng đồng]] năm nay [[m:Special:MyLanguage/Community Wishlist/Community Wishlist 2027#Updated Community Wishlist Process 2027/2028|đã được công bố]], có tính đến phản hồi từ cộng đồng. Quy trình gửi mong muốn sẽ [[m:Special:MyLanguage/Community Wishlist/FAQ#What is the deadline for submitting wishes?|kết thúc vào ngày 8 tháng 11]]. Năm nay, [[m:Special:MyLanguage/Community Wishlist/Community Wishlist 2027/Working group|một nhóm công tác (mở cho tình nguyện viên tham gia)]] gồm các thành viên cộng đồng am hiểu về khía cạnh kỹ thuật của các wiki cùng với nhân viên của Wikimedia Foundation sẽ phụ trách [[m:Special:MyLanguage/Community Wishlist/FAQ#What is triage?|quá trình phân loại]]. Dự kiến quá trình phân loại sẽ hoàn tất vào cuối tháng 11. Việc bỏ phiếu cho các mong muốn sẽ bắt đầu vào tháng 1.
'''Cập nhật cho biên tập viên'''
* Các biên tập viên sử dụng [[mw:Special:MyLanguage/VisualEditor|trình soạn thảo trực quan]] nay sẽ nhìn thấy cảnh báo khi họ dán đoạn văn bản có khả năng đã được sao chép từ nội dung ban đầu được tạo bởi một trong năm chatbot AI tạo sinh bên ngoài vào Wikipedia. Tính năng này được gọi là [[mw:Special:MyLanguage/Edit check/LLM Paste Check|Kiểm tra Dán nội dung từ LLM]]. Đây là một dạng [[mw:Special:MyLanguage/Edit check|Kiểm tra Sửa đổi]] mà cộng đồng có thể tùy chỉnh được. Hệ thống kiểm tra này tìm kiếm các mã đánh dấu (marker) trong đoạn mã HTML được sao chép và không sử dụng phương pháp phát hiện hình mờ (watermark) trong nội dung. Các sửa đổi cũng sẽ [[mw:Special:MyLanguage/Edit check/LLM Paste Check#Edit tags|được gắn thẻ]] để các tuần tra viên có thể xem xét kỹ lưỡng hơn. Tính năng này giúp người mới đóng góp nội dung tuân thủ các chính sách của Wikipedia, đồng thời giúp các biên tập viên có kinh nghiệm dễ dàng nhận diện những sửa đổi có vấn đề. Các cộng đồng có quy định riêng về việc sử dụng LLM có thể [[mw:Special:MyLanguage/Edit check/LLM Paste Check#Configuration|điều chỉnh câu từ và quy định được liên kết]]. Nhóm phát triển [[listarchive:list/translators-l@lists.wikimedia.org/message/EVHKWJ4IERZELMPIWNH3XUVUSQV5KOO4/|chân thành xin lỗi]] vì đã triển khai tính năng này mà không dành thời gian chờ cho việc dịch thuật.
* Các biên tập viên nay có thể dễ dàng [[mw:Special:MyLanguage/Wikimedia Apps/Team/Future of Editing on the Mobile Apps|truy cập trình soạn thảo trực quan bản web trực tiếp từ ứng dụng dành cho iOS và Android]]. Khi mở trình soạn thảo, người dùng sẽ được lựa chọn giữa chế độ soạn thảo trực quan và chế độ soạn thảo mã nguồn. Nếu họ chọn chế độ soạn thảo trực quan, họ sẽ được đưa tới cửa sổ giao diện web di động trong trình duyệt trên điện thoại của họ. Sau khi hoàn thành sửa đổi của mình, một biểu ngữ sẽ xuất hiện để cung cấp cho họ lựa chọn trở về ứng dụng. Điều này cho phép độc giả đóng góp nội dung một cách nhanh chóng trong khi đang đọc một cách thoải mái.
* Người dùng ứng dụng Wikipedia dành cho Android và iOS nay sẽ nhìn thấy thông báo một lần mời tạo tài khoản sau khi họ đã sử dụng ứng dụng được hai tuần liên tiếp. Thông báo này giải thích những lợi ích của việc sở hữu một tài khoản. Điều này nhằm mục đích giúp nhiều đọc giả thông thường trở thành những người dùng đã đăng nhập quay lại ứng dụng thường xuyên hơn. [https://phabricator.wikimedia.org/T434847]
* Các biên tập viên trên [[wmnoc:conf/dblists/group1.dblist|các wiki thuộc group1]], bao gồm Wikiquote, Wikibooks, Wikiversity, Wikivoyage, và Wikisource, sẽ không còn nhìn thấy thông báo trên [[mw:Special:MyLanguage/Help:Recent changes|Thay đổi Gần đây]] và [[mw:Special:MyLanguage/Help: Watching pages|Danh sách Theo dõi]] khi một liên kết đến phiên bản ngôn ngữ khác của một trang được thêm, xóa hoặc thay đổi trong khoản mục Wikidata của nó. Thay đổi này sẽ bắt đầu vào ngày 5 tháng 10 lúc 07:00 UTC dưới dạng thử nghiệm kéo dài hai tuần nhằm giảm bớt các thông báo xuất hiện với số lượng lớn nhưng ít giá trị và giúp những thay đổi quan trọng có thể được nhận diện một cách dễ dàng hơn. Các biên tập viên thường dựa vào những thông báo này có thể đọc thêm trên [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|trang dự án]] và chia sẻ ý kiến hoặc thắc mắc trên [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|trang thảo luận]]. [https://phabricator.wikimedia.org/T439415]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:36}} {{PLURAL:36|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho các cố vấn tự rút khỏi chương trình cố vấn vẫn có thể có những người được cố vấn gán vào họ và tiếp nhận các câu hỏi, nay đã được giải quyết. Những người được cố vấn sẽ được gán lại khi một cố vấn rời khỏi chương trình. [https://phabricator.wikimedia.org/T418194]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Wikimedia Brasil đã xuất bản [[m:Special:MyLanguage/Wikimedia Brasil/Arcabouço de Boas Práticas de Desenvolvimento|Khung Thực tiễn Tốt nhất về Phát triển]] (ABPD). Đây là tài liệu hướng dẫn dành cho nhân viên, nhà thầu và tình nguyện viên tham gia xây dựng các công cụ và dự án kỹ thuật. Tài liệu này bao gồm các nội dung về vòng đời dự án, bảo mật, khả năng tiếp cận, bảo vệ dữ liệu cá nhân và sử dụng AI có trách nhiệm, đồng thời giải thích cách những hướng dẫn chung của phong trào được điều chỉnh sao cho phù hợp với bối cảnh cục bộ. Họ khuyến khích các tổ chức thành viên khác sử dụng lại và tùy chỉnh tài liệu này. Đọc thêm tại [[wmfblog:2026/09/26/wikimedia-brasils-development-best-practices-framework-technical-sustainability-as-an-organizational-responsibility|bài đăng trên Diff]].
* Một URL cơ sở chuẩn (canonical base) mới dành cho các API của Wikimedia sẽ sớm được giới thiệu. Đường dẫn chuẩn mới này theo mẫu dạng <bdi lang="zxx" dir="ltr"><code><nowiki>{projectName}/api/</nowiki></code></bdi> và sẽ đóng vai trò là đường dẫn thay thế cho các API REST hiện tại (ví dụ: <bdi lang="zxx" dir="ltr"><code><nowiki>{projectName}/w/rest.php/</nowiki></code></bdi>). Cả hai phiên bản đều có thể gọi được đối với tất cả các API hiện có, nhưng cấu trúc mới sẽ là lựa chọn ưu tiên cho các mô đun API được tạo mới. Thay đổi này sẽ không gây gián đoạn cho hầu hết người dùng. Những đường dẫn hiện tại vẫn sẽ có sẵn cho mọi yêu cầu đến điểm cuối (endpoint) hiện có. Tuy nhiên, một số điểm cuối có thể trả về các URL tuân theo mẫu mới trong phần nội dung phản hồi (response body). Các thay đổi sẽ có sẵn trên wiki thử nghiệm trước, và việc triển khai dự kiến sẽ được thực hiện trên toàn bộ các dự án wiki vào cuối tháng 10. [https://phabricator.wikimedia.org/T433535]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.23|MediaWiki]].
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/41|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W41"/>
18:52, ngày 5 tháng 10 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Trizek (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31098825 -->
== Bản tin Kỹ thuật: Tuần 42-2026 ==
<section begin="technews-2026-W42"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/42|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Kể từ ngày 13 tháng 10, các wiki có thể thay đổi quy tắc (pattern) mặc định cho [[:en:Wikipedia:VisualEditor/Named references|tên nguồn tham khảo được tạo tự động trong Trình Soạn thảo Trực quan]] (hiện tại là <syntaxhighlight lang="wikitext" inline><ref name=":1" /></syntaxhighlight>). Họ sẽ có thể sử dụng tên nguồn tham khảo dễ hiểu và dựa trên nội dung mà sẽ giúp ích nhiều hơn cho các cộng tác viên sử dụng trình soạn thảo mã nguồn (v.d. <syntaxhighlight lang="wikitext" inline><ref name="Miller2026-1" /></syntaxhighlight>). Các quy tắc đặt tên nguồn tham khảo cho Trình Soạn thảo trực quan có thể được thiết lập thông qua các thông điệp hệ thống MediaWiki, JSON, bản mẫu và mô đun ([[:mw:Special:MyLanguage/Help:Cite/VisualEditor reference names|thông tin thêm]]). Bảo quản viên có thể kích hoạt những thay đổi này thông qua [[Special:CommunityConfiguration/Cite-VisualEditor-Autonames|cấu hình cộng đồng]]. Đây là một [[:m:Special:MyLanguage/Community_Wishlist/W17|mong muốn của cộng đồng]] được triển khai bởi [[:m:Special:MyLanguage/WMDE Technical Wishes|WMDE Technical Wishes]]. [https://phabricator.wikimedia.org/T436255]
* [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|Chú thích phụ]] là một tính năng MediaWiki mới cho phép các biên tập viên tái sử dụng nguồn tham khảo với thông tin khác nhau. Công cụ sẽ được triển khai tới Wikipedia tiếng Anh vào ngày 14 tháng 10 và đến các dự án wiki còn lại của Quỹ Wikimedia vào cuối tháng 10 (khoảng ngày 21 tháng 10). Trang [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#deployment|FAQ]] liệt kê các hành động có thể thực hiện trên wiki của bạn để hỗ trợ việc triển khai này. Đây là một [[:m:WMDE Technical Wishes/Sub-referencing/History|mong muốn lâu nay của cộng đồng]] được triển khai bởi [[:m:Special:MyLanguage/WMDE Technical Wishes|WMDE Technical Wishes]]. [https://phabricator.wikimedia.org/T440243][https://phabricator.wikimedia.org/T440304]
'''Cập nhật cho biên tập viên'''
* [[mw:Special:MyLanguage/Moderator Tools|Công cụ Kiểm tra]] sẽ loại bỏ chế độ xem dạng danh sách của Danh sách Theo dõi và chuyển mặc định tất cả người dùng sang chế độ xem dạng nhật ký thay đổi. Trước đây, có hai cách mà Danh sách Theo dõi được hiển thị cho người dùng phiên bản web trên di động: chế độ xem dạng danh sách, nơi mà các biên tập viên có thể xem các bài viết đã theo dõi dưới dạng danh sách, và chế độ xem dạng nhật ký thay đổi, nơi mà các biên tập viên có thể xem các thay đổi được thực hiện với các bài viết đã theo dõi dưới dạng nhật ký, được kiểm soát bởi tùy chọn Điều khiển Di động Nâng cao của người dùng. Điều này đã gây ra vấn đề cho việc bảo trì mã nguồn: hai kiểu hiển thị nghĩa là cần phải quản lý hai bộ mã nguồn khác nhau. Bằng việc chuyển mặc định sang chế độ xem nhật ký theo dõi, chúng tôi sẽ đơn giản hóa được mã nguồn và giảm thiểu nguy cơ bỏ sót lỗi.
* Ứng dụng Wikipedia dành cho Android đang thử nghiệm một cách để nghe phần giới thiệu của bài viết trong mục tin “Dành cho bạn”. Một mô hình chuyển đổi văn bản thành giọng nói (text-to-speech) sẽ đọc nội dung hiện có của bài viết mà không cần viết lại hay bổ sung thêm bất kỳ nội dung nào. Chương trình thử nghiệm 30 ngày này sẽ bắt đầu trong ứng dụng Wikipedia Beta vào tuần thứ ba của tháng 9, sau đó mở rộng sang ứng dụng Wikipedia dành cho Android bản chính thức trong tháng 10 dành cho một nhóm nhỏ người dùng đủ điều kiện. Một bộ phận nhỏ người dùng ứng dụng (những người có mục tin tiếng Anh và có quan tâm đến ít nhất một chủ đề) sẽ có quyền truy cập trải nghiệm tính năng này. Thử nghiệm này là một phần trong nỗ lực rộng lớn hơn nhằm mang lại cho độc giả nhiều lựa chọn tiếp nhận nội dung và qua đó tăng cường mức độ tương tác và khả năng giữ chân người dùng. [[mw:Special:MyLanguage/Readers/Listening to Wikipedia/Phase 1|Tìm hiểu thêm]] và [[mw:Talk:Readers/Listening to Wikipedia|chia sẻ ý kiến phản hồi]].
* Tính năng [[mw:Special:MyLanguage/Help:Extension:CodeMirror|nổi bật cú pháp bằng CodeMirror]] đã được [[phab:T288161|kích hoạt]] theo mặc định cho tất cả người dùng chưa đăng nhập và mới đăng ký trên Wikipedia tiếng Anh vào ngày 14 tháng 9. Do không ghi nhận tác động tiêu cực nào, thay đổi tương tự này đang được đề xuất áp dụng toàn cục cho tất cả các dự án wiki trong vài tuần tới. Nếu bạn có thắc mắc hay ý kiến phản hồi nào, hoặc nếu wiki của bạn muốn từ chối áp dụng thay đổi này, [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror#Enabling CodeMirror by default on all WMF wikis for newbies|vui lòng xem trang trợ giúp]]. [https://phabricator.wikimedia.org/T440077]
* Tính năng [[d:Wikidata:Usability_and_usefulness/Item_editing_experience/Mobile_editing_of_statements|sửa đổi lời phát biểu trên giao diện di dộng của Wikidata]] cho mọi kiểu dữ liệu sẽ chính thức ra mắt vào ngày 13 tháng 10, khi đó nó sẽ được loại bỏ khỏi danh sách [[d:Special:Preferences#mw-prefsection-betafeatures|tính năng thử nghiệm beta]] của Wikidata và có sẵn cho tất cả các biên tập viên. Người dùng có thể [[d:Wikidata_talk:Usability_and_usefulness/Item_editing_experience/Mobile_editing_of_statements|báo cáo lỗi và chia sẻ ý kiến phản hồi]].
* Tuần trước, những thay đổi về liên kết ngôn ngữ đã bị loại bỏ khỏi nguồn cấp dữ liệu của [[Special:RecentChanges|Thay đổi Gần đây]] và [[Special:Watchlist|Danh sách Theo dõi]] trên Wikivoyage, Wikisource, Wikiversity, Wikiquote và Wiktionary. Do không ghi nhận tác động tiêu cực nào, [[m:Wikidata_For_Wikimedia_Projects|Wikidata cho các Dự án Wikimedia]] có kế hoạch triển khai thay đổi này trên toàn cục cho tất cả các phiên bản Wikipedia. Việc triển khai dự kiến diễn ra vào ngày 13 tháng 10 lúc 07:00 UTC, sau thời điểm này các biên tập viên sẽ không còn nhìn thấy những thay đổi khi một liên kết đến phiên bản ngôn ngữ ''khác'' của trang được thêm, xóa hoặc thay đổi trong khoản mục Wikidata tương ứng. Những biên tập viên thường theo dõi các thông báo này có thể tìm hiểu thêm tại [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|trang dự án]] cũng như chia sẻ ý kiến hoặc yêu cầu không áp dụng thay đổi cho wiki của mình tại [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|trang thảo luận]]. [https://phabricator.wikimedia.org/T440698]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:28}} {{PLURAL:28|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho việc vô tình chạm vào biểu đồ trong khi cuộn trên công cụ Lượt xem trang (Pageviews) trên thiết bị di động có thể vô tình phóng to biểu đồ nay đã được khắc phục. Tính năng thu phóng bằng cách nhấn và kéo nay đã bị vô hiệu hóa trên các thiết bị có màn hình cảm ứng. [https://phabricator.wikimedia.org/T440075]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Sẽ có ba thay đổi lớn đối với các tập tin dữ liệu xuất (dump): các tập tin dữ liệu xuất nội dung kiểu cũ [https://lists.wikimedia.org/hyperkitty/list/xmldatadumps-l@lists.wikimedia.org/thread/E6D5EU4PMSTSOI2J7A46HJ3YW2W554CS/ đã ngừng hỗ trợ vào tháng 1 năm 2026] sẽ bị loại bỏ, giải pháp thay thế [https://wikitech.wikimedia.org/wiki/MediaWiki_Content_File_Exports Xuất Tập tin Nội dung MediaWiki] (MediaWiki Content File Exports) sẽ được hoãn triển khai để thiết lập một “khoảng đệm an toàn”, và chúng nay cũng có sẵn dưới dạng tập tin nén 7zip. Người dùng sẽ cần phải thay đổi URL dùng để tải xuống các tập tin dữ liệu xuất này. Để biết thêm thông tin, lộ trình thực hiện và hướng dẫn chuyển đổi, vui lòng xem trang [https://wikitech.wikimedia.org/wiki/Legacy_content_dumps_sunset Ngừng hỗ trợ tập tin dữ liệu xuất nội dung kiểu cũ].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.47/wmf.24|MediaWiki]]
'''Chuyên sâu'''
* Quỹ Wikimedia đã phát hiện các hoạt động trái phép từ các tác nhân của OpenAI trên các dự án Wikimedia, bao gồm việc sửa đổi các trang wiki, nỗ lực khai thác một công cụ ghi chú công khai, cũng như lưu lượng truy cập tự động với cường độ cao. [[diffblog:2026/10/05/openai-rogue-agent-activities-found-on-wikimedia-projects/|Đọc bài blog trên Diff]] để biết thêm thông tin chi tiết về hoạt động này cũng như phản hồi của Quỹ.
'''Các cuộc họp và sự kiện'''
* Hãy ghi lại lịch trình cho sự kiện Wikimedia Hackathon tiếp theo! Chúng tôi sẽ gặp gỡ nhau tại thành phố Tirana xinh đẹp của Albania để tham dự [https://www.mediawiki.org/wiki/Wikimedia%20Hackathon%202027 Wikimedia Hackathon 2027] diễn ra từ ngày 9–11 tháng 4 năm 2027. Hồ sơ đăng ký nhận học bổng và tài trợ cho nhân viên hiện đang được [https://pretix.eu/wikimedia/Hackathon-2027/ tiếp nhận qua nền tảng Pretix] và sẽ đóng vào ngày 30 tháng 10 năm 2026. Cổng đăng ký tham dự dành cho công chúng sẽ được mở vào tháng 1 năm 2027.
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/42|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W42"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 07:40, ngày 13 tháng 10 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31142468 -->
== Bản tin Kỹ thuật: Tuần 43-2026 ==
<section begin="technews-2026-W43"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/43|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Cập nhật cho biên tập viên'''
* Để đo lường tác động từ việc bổ sung một số [[mw:Special:MyLanguage/Readers/Reader_Growth/Image_Browsing#November 2025: Ideas and feedback|tính năng do cộng đồng yêu cầu]] đến tỷ lệ giữ chân độc giả chưa đăng nhập, một thử nghiệm về tính năng [[mw:Special:MyLanguage/Readers/Reader_Growth/Image_Browsing|Băng chuyền Hình ảnh]] (Image Carousel) sẽ được triển khai đến độc giả chưa đăng nhập. Với tính năng Băng chuyền Hình ảnh, độc giả có thể xem các hình ảnh do cộng đồng tải lên, được chọn lọc bởi các biên tập viên vì có liên quan đến bài viết cụ thể. Thử nghiệm sẽ bắt đầu vào ngày 20 tháng 11.
* Một thông báo thử nghiệm sẽ được hiển thị tới 0,5% số độc giả chưa đăng nhập sử dụng thiết bị di động khi họ truy cập Wikipedia tiếng Anh từ Google, nhằm mời họ thêm Wikipedia vào danh sách [https://blog.google/products-and-platforms/products/search/preferred-sources/ Nguồn Ưu tiên trên Google]. Thử nghiệm nhằm mục đích đánh giá liệu thông báo này có giúp tăng tỷ lệ giữ chân độc giả và khuyến khích người dùng sử dụng Google Tìm kiếm ghé thăm Wikipedia thường xuyên hơn hay không. Thử nghiệm sẽ diễn ra từ ngày 15–29 tháng 10, sau đó kết quả sẽ được phân tích nhằm xác định tác động của nó đối với tỷ lệ giữ chân và lưu lượng truy cập từ các nguồn giới thiệu.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:26}} {{PLURAL:26|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một sự cố khiến cho [[quarry:|Quarry]] trả về lỗi “Truy cập bị từ chối” khi người dùng cố gắng chạy các truy vấn SQL, làm cho các truy vấn không thể chạy được một cách bình thường, nay đã được khắc phục. [https://phabricator.wikimedia.org/T440966]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* [[File:Cog-icon-grey.svg|12px|link=|class=skin-invert|Đề mục nâng cao]] Do một lỗi đã tồn tại từ lâu, các ứng dụng sử dụng quy trình xác thực "client credentials" của [[mw:Special:MyLanguage/OAuth/For_Developers|OAuth 2]] để thay mặt chủ sở hữu thực hiện thao tác hiện đang bị hệ thống coi như là người dùng chưa đăng nhập. Vấn đề này sẽ được khắc phục đối với các ứng dụng mới đăng ký kể từ thứ Hai, ngày 19 tháng 10 trở đi. Một số ứng dụng bị ảnh hưởng sẽ cần phải thực hiện đăng ký lại. [https://phabricator.wikimedia.org/T420297]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.48/wmf.1|MediaWiki]]
'''Các cuộc họp và sự kiện'''
* Một đề xuất tổ chức sự kiện Wikimedia Hackathon ba năm một lần, xen kẽ với các sự kiện hackathon khu vực, [[mw:Wikimedia Hackathon/Community Proposal 2026|đã được chia sẻ]]. Đề xuất này hướng tới việc giúp các cộng đồng kỹ thuật tại nhiều khu vực khác nhau có thể tiếp cận sự kiện này dễ dàng hơn. Hãy chia sẻ ý kiến của bạn tại [[mw:Talk:Wikimedia Hackathon/Community Proposal 2026|trang thảo luận]] của đề xuất này trước ngày 6 tháng 11.
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/43|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W43"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 14:38, ngày 19 tháng 10 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31178499 -->
== Chuyển đổi máy chủ - Wiki của bạn sẽ sớm chuyển sang chế độ chỉ đọc trong một khoảng thời gian ngắn ==
<section begin="server-switch"/><div class="plainlinks">
[[:m:Special:MyLanguage/Tech/Server switch|Đọc thông báo này bằng ngôn ngữ khác]] • [https://meta.wikimedia.org/w/index.php?title=Special:Translate&group=page-Tech%2FServer+switch&language=&action=page&filter= {{int:please-translate}}]
[[foundation:|Quỹ Wikimedia]] sẽ chuyển đổi lưu lượng qua lại giữa các trung tâm dữ liệu. Điều này sẽ giúp đảm bảo rằng Wikipedia và các wiki khác của Wikimedia vẫn có thể duy trì trực tuyến ngay cả sau tình huống thiên tai.
Mọi lưu lượng sẽ chuyển đổi vào ngày '''{{#time:j xg|2026-10-28|vi}}'''. Việc chuyển đổi này sẽ bắt đầu vào lúc '''[https://zonestamp.toolforge.org/{{#time:U|2026-10-28T15:00|en}} {{#time:H:i e|2026-10-28T15:00}}]'''.
Dù vậy, vì một số hạn chế của phần mềm [[mw:Special:MyLanguage/Manual:What is MediaWiki?|MediaWiki]], mọi sửa đổi đều phải bị ngưng lại khi việc chuyển đổi được thực hiện. Chúng tôi chân thành xin lỗi vì sự gián đoạn này, và chúng tôi đang tìm cách giảm thiểu những tình huống như vậy trong tương lai.
Một biểu ngữ sẽ được hiển thị trên tất cả các wiki 30 phút trước khi quá trình này diễn ra. Biểu ngữ sẽ tiếp tục được hiển thị cho tới khi kết thúc quá trình này.
Bạn có thể đóng góp bằng cách [https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=Centralnotice-tgroup-read_only_banner&task=view&language=&filter=&action=translate biên dịch và hiệu đính] dòng biểu ngữ này.
'''Bạn sẽ có thể đọc, nhưng không thể sửa đổi, tất cả wiki trong một khoảng thời gian ngắn.'''
* Bạn sẽ không thể sửa đổi trong vòng tối đa một giờ vào {{#time:l j xg Y|2026-10-28|vi}}.
* Nếu bạn cố gắng sửa đổi hay lưu trang trong khoảng thời gian này, bạn sẽ nhìn thấy một thông báo lỗi. Chúng tôi hy vọng sẽ không có sửa đổi nào bị mất trong khoảng thời gian đó, nhưng chúng tôi không thể đảm bảo được điều đó. Nếu bạn nhìn thấy thông báo lỗi, vui lòng chờ đợi cho đến khi mọi thứ trở lại bình thường. Sau đó bạn sẽ có thể lưu lại sửa đổi của mình. Tuy nhiên, chúng tôi khuyên bạn trước hết nên tạo một bản sao những thay đổi của bạn, nhằm mục đích đề phòng.
''Những ảnh hưởng khác'':
* Tác vụ xử lý nền sẽ bị chậm hơn và một số có thể bị ngừng hẳn. Các liên kết đỏ có thể sẽ không được cập nhật nhanh chóng như thường lệ. Nếu bạn tạo một bài viết đã được liên kết ở một nơi khác, liên kết đó vẫn sẽ có màu đỏ lâu hơn bình thường. Một số đoạn mã tốn nhiều thời gian chạy sẽ phải dừng lại.
* Chúng tôi hy vọng việc triển khai mã nguồn vẫn sẽ diễn ra như bất kỳ tuần nào khác. Tuy vậy, một vài trường hợp đóng băng mã nguồn có thể xảy ra nếu quá trình yêu cầu chúng sau đó.
* [[mw:Special:MyLanguage/GitLab|GitLab]] sẽ không khả dụng trong khoảng 90 phút.
Dự án này có thể bị hoãn lại nếu cần thiết. Bạn có thể [[wikitech:Switch_Datacenter|đọc lịch trình tại wikitech.wikimedia.org]]. Bất kỳ thay đổi nào đều sẽ được thông báo trong lịch trình này.
'''Xin hãy chia sẻ thông tin này với cộng đồng của bạn.'''</div><section end="server-switch"/>
[[user:Trizek_(WMF)|Trizek_(WMF)]] 14:01, ngày 26 tháng 10 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Trizek (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=30513874 -->
== Bản tin Kỹ thuật: Tuần 44-2026 ==
<section begin="technews-2026-W44"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/44|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Một thử nghiệm bắt đầu từ ngày 29 tháng 9 đang kiểm tra tính năng [[mw:Special:MyLanguage/Readers/Reader_Experience/Reading_recommendations|gợi ý bài viết]] dành cho những người dùng mới tạo tài khoản mà cũng tự xác định mình là độc giả. Bằng cách đề xuất các bài viết để đọc, tương tự như những gợi ý trong ứng dụng Wikipedia dành cho độc giả đã đăng nhập, thử nghiệm này hướng tới việc khuyến khích người dùng mới tạo tài khoản đọc nội dung và quay lại trang web thường xuyên hơn, với mục tiêu tăng tỷ lệ điều hướng nội bộ (internal referrals) thêm 1%. Xem thêm đề xuất có liên quan trong [[m:Community Wishlist/W505|Danh sách Mong muốn Cộng đồng]].
* Một số dịch vụ của Wikimedia đã bị ngừng hoạt động vào tuần trước do một [https://www.php.net/archive/2026.php#2026-10-20-1 lỗ hổng bảo mật trong PHP]. Điều này là do chúng cần được cập nhật trước khi có thể an toàn để đưa trở lại trực tuyến. Đây không phải là vấn đề chỉ của phong trào Wikimedia mà còn ảnh hưởng đến rất nhiều trang web. Bạn có thể theo dõi thông tin cập nhật trên [[wikitech:Incidents/2026-10-21 PHP security update/Community|Wikitech]]. Cloud VPS và Toolforge sẽ mất nhiều thời gian hơn để đưa trở lại trực tuyến. Điều này nhằm đảm bảo rằng các ứng dụng chạy trên Cloud VPS hoặc Toolforge không bị ảnh hưởng. Những nhà phát triển công cụ có thể xem các cập nhật và thông tin chi tiết trên [https://lists.wikimedia.org/postorius/lists/cloud-announce.lists.wikimedia.org/ danh sách gửi thư thông báo trên Cloud]. [https://diff.wikimedia.org/2026/10/21/impact-of-php-vulnerabilities-on-wikimedia-tools-and-services/][https://diff.wikimedia.org/2026/10/21/impact-of-php-vulnerabilities-on-wikimedia-cloud-services/]
* [[m:Special:MyLanguage/Tech/News/2026/43|Tuần trước, chúng tôi đã chia sẻ]] rằng để đo lường tác động của việc bổ sung một số tính năng được cộng đồng yêu cầu đối với tỷ lệ giữ chân độc giả chưa đăng nhập, một thử nghiệm cho tính năng [[mw:Special:MyLanguage/Readers/Reader Growth/Image Browsing|Băng chuyền Hình ảnh]] (Image Carousel) sẽ được triển khai tới nhóm độc giả chưa đăng nhập. Do có một vấn đề phát sinh, chúng tôi sẽ khởi chạy lại thử nghiệm này, dù vậy tính năng này sẽ bắt đầu hoạt động vào ngày 26 tháng 10, thay vì ngày 20 tháng 11 như thông báo ban đầu.
'''Cập nhật cho biên tập viên'''
* Một [[wikitech:KAPOW|hệ thống phát hiện bot]] mới được thiết kế để nhận diện tốt hơn các lưu lượng truy cập tự động vốn ngụy trang thành người dùng thật, sắp được triển khai trên các dự án wiki của Wikimedia. Thay đổi này có thể dẫn đến những biến động đột ngột trong số liệu thống kê khách truy cập kể từ ngày 26 tháng 10, áp dụng cho dữ liệu từ ngày 20 tháng 6 năm 2026 trở về trước.
* Phần mở rộng [[mw:Special:MyLanguage/Extension:Score|Score]] dùng để hiển thị ký hiệu âm nhạc trong các trang wiki, đã tạm thời bị vô hiệu hóa trên tất cả các trang wiki do một vấn đề bảo mật. Các trang bị ảnh hưởng sẽ hiển thị thông báo thay vì các bản nhạc, nhưng mã nguồn gốc vẫn sẽ được giữ nguyên. Các biên tập viên không cần thực hiện bất kỳ thao tác nào, một bản sửa lỗi hiện đang được triển khai. Một thông báo khác sẽ được đưa ra khi phần mở rộng này được kích hoạt trở lại. Đọc thêm tại [[phab:T441579|Phabricator]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:18}} {{PLURAL:18|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, vấn đề khiến cho trình làm nổi bật cú pháp của CodeMirror có vẻ như đã vô tình được bật cho các biên tập viên hiện có nay đã được khắc phục. [https://phabricator.wikimedia.org/T441308]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* [[m:Special:MyLanguage/Tech/Server switch|Tất cả các wiki sẽ chuyển sang chế độ chỉ đọc trong vòng vài phút]] vào thứ 4, ngày 28 tháng 10 năm 2026 lúc [https://zonestamp.toolforge.org/1793199600 15:00 UTC]. Điều này là nhằm phục vụ cho việc thử nghiệm chuyển đổi máy chủ cơ sở dữ liệu dự phòng, [[wikitech:Deployments/Yearly calendar|diễn ra hai lần trong một năm]]. Trong quá trình chuyển đổi này, toàn bộ lưu lượng trên các trang web của Wikimedia được chuyển từ trung tâm dữ liệu chính sang trung tâm dữ liệu dự phòng nhằm kiểm tra tính khả dụng và ngăn ngừa việc gián đoạn dịch vụ ngay cả trong những trường hợp khẩn cấp. [https://phabricator.wikimedia.org/T439703]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.48/wmf.2|MediaWiki]]
'''Các cuộc họp và sự kiện'''
* Cổng nộp đơn xin học bổng và tài trợ cho [https://www.mediawiki.org/wiki/Wikimedia%20Hackathon%202027 Wikimedia Hackathon 2027] sẽ đóng lại vào thứ Sáu, ngày 30 tháng 10. Hãy gửi đơn đăng ký của bạn [https://pretix.eu/wikimedia/Hackathon-2027/ thông qua Pretix] trước thời hạn này!
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/44|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W44"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 18:56, ngày 26 tháng 10 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31199592 -->
== Bản tin Kỹ thuật: Tuần 45-2026 ==
<section begin="technews-2026-W45"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/45|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Nhiều công cụ Wikimedia đã phải tạm ngừng hoạt động vào tuần trước vì một [[:w:vi:PHP2Shell|lỗ hổng bảo mật trong PHP]]. Sự cố này đã ảnh hưởng đến rất nhiều trang web trên toàn cầu. [[m:Special:MyLanguage/Toolforge|Toolforge]] và [[m:Special:MyLanguage/Wikimedia Cloud Services|Cloud VPS]] đã hoạt động trở lại kể từ ngày 22 tháng 10. Nhiều công cụ quan trọng đã được dần khôi phục trở lại. Một số công cụ cần các tình nguyện viên bảo trì công cụ tương ứng khởi động lại chúng. Số khác vẫn cần phải được cập nhật lên phiên bản PHP được vá. Một số công cụ đang sử dụng các phiên bản cũ hơn của PHP không còn được các bản vá bảo mật gần đây hỗ trợ. Chúng cần phải được bảo trì viên nâng cấp lên phiên bản mới hơn. Việc này có thể cần đòi hỏi thêm nỗ lực. Bạn có thể theo dõi công việc [[:wikitech:Talk:Incidents/2026-10-21 PHP security update/Community#Exceptions|trên Wikitech]].
'''Cập nhật cho biên tập viên'''
* Một thử nghiệm tìm kiếm tùy chọn mới đang được triển khai trên ứng dụng dành cho Android và iOS đối với các phiên bản Wikipedia tiếng Ả Rập, tiếng Pháp và tiếng Nhật. Các độc giả tham gia có thể tìm kiếm trong các bài viết và mở trực tiếp các đoạn trích dẫn trong bài viết gốc của họ, mà không tạo ra bất kỳ câu trả lời hay bản tóm tắt nào. Đây là thử nghiệm đầu tiên trong số bốn thử nghiệm thuộc [[mw:Special:MyLanguage/Readers/Information%20Retrieval/Phase%202|Giai đoạn 2 của Tìm kiếm theo Ngữ nghĩa]] (Semantic Search). Thử nghiệm đã bắt đầu vào ngày 22 tháng 10 và sẽ kéo dài trong 20 ngày. Mọi phản hồi đều được hoan nghênh trên [[mw:Special:MyLanguage/Talk:Readers/Information%20Retrieval/Phase%202|trang thảo luận]] của dự án.
* Nhóm [[m:Special:MyLanguage/Future_Audiences|Future Audiences]] đang lên kế hoạch đưa [[m:Special:MyLanguage/Future_Audiences/Share_card|Thẻ Chia sẻ]] (Share Cards) lên Wikipedia phiên bản di động. Tính năng này cho phép người dùng chia sẻ với bạn bè một chiếc thẻ có thiết kế bắt mắt, dựa trên bài viết mà họ đang đọc. Thẻ bao gồm tiêu đề bài viết, hình ảnh, đoạn mở đầu, thông tin ghi công có liên quan, cùng một đường dẫn quay lại bài viết để đọc toàn bộ nội dung. Mời các biên tập viên trải nghiệm tính năng này bằng cách thêm <code dir="ltr">?useformat=mobile&sharecard=1</code> vào URL của bất kỳ bài viết nào trong khoảng thời gian từ ngày 29 tháng 10 đến ngày 8 tháng 11. Chia sẻ bất kỳ suy nghĩ nào trên [[m:Talk:Future_Audiences/Share_card| trang thảo luận của dự án]], và báo cáo bất kỳ lỗi nào trên trên [[phab:T439161|Phabricator]].
* Trình kết xuất mặc định cho các công thức toán học sẽ thay đổi vào ngày 2 tháng 11. Sau thay đổi này, máy chủ sẽ gửi công thức dưới dạng MathML và trình duyệt của bạn sẽ sử dụng MathJax để hiển thị công thức đó. Đây là bước cuối cùng trong quá trình loại bỏ Mathoid/RESTBase, nhằm đảm bảo tính bền vững và bảo mật. Bạn có thể [[w:en:Wikipedia:WikiProject Mathematics/MathFormattingBugs|đặt câu hỏi hoặc báo cáo vấn đề]]. [https://phabricator.wikimedia.org/T375238]
* Bạn có ý tưởng về tính năng mới, hay một lỗi cần được giải quyết? [[m:Special:MyLanguage/Community Wishlist|Hãy gửi đề xuất của bạn cho danh sách mong muốn cộng đồng trước ngày 8 tháng 11!]]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:41}} {{PLURAL:41|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]].
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.48/wmf.3|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/45|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W45"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 14:23, ngày 3 tháng 11 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:Trizek (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31236748 -->
== Bản tin Kỹ thuật: Tuần 46-2026 ==
<section begin="technews-2026-W46"/><div class="plainlinks">
'''[[m:Special:MyLanguage/Tech/News|Tin tức kỹ thuật]]''' mới nhất từ cộng đồng kỹ thuật Wikimedia. Vui lòng chia sẻ với các thành viên khác về những thay đổi này. Không phải mọi thay đổi đều sẽ ảnh hưởng đến bạn. [[m:Special:MyLanguage/Tech/News/2026/46|Các bản dịch]] của bản tin này cũng có sẵn cho bạn.
'''Nổi bật trong tuần'''
* Nhóm Ứng dụng Wikipedia đang chuẩn bị ra mắt tính năng Tổng kết Năm vào đầu tháng 12. Tổng kết Năm mang đến cho người dùng một bản tóm tắt được cá nhân hóa về cách họ đã đọc và tương tác với Wikipedia trong suốt một năm qua. Nhóm đang tìm kiếm các tình nguyện viên nhằm giúp cho tính năng này có mặt trên nhiều ngôn ngữ nhất có thể. Các biên tập viên có thể đóng góp thông qua [https://translatewiki.net/ translatewiki.net]. Với [https://translatewiki.net/w/i.php?title=Special:Translate&action=translate&group=out-wikimedia-mobile-wikipedia-android-strings&filter=%21translated Android], tìm kiếm <bdi lang="zxx" dir="ltr"><code><nowiki>yir</nowiki></code></bdi> dưới tab "Chưa dịch", và với [https://translatewiki.net/w/i.php?title=Special:Translate&action=translate&group=out-wikimedia-mobile-wikipedia-ios&filter=%21translated&optional=1 iOS], tìm kiếm <bdi lang="zxx" dir="ltr"><code><nowiki>year-in-review</nowiki></code></bdi> dưới tab "Chưa dịch".
* Tính năng [[mw:Special:MyLanguage/Article guidance|Chỉ dẫn bài viết]] nhằm giúp các biên tập viên tạo các bài viết tuân thủ các quy định của Wikipedia, nay đã có mặt trên tất cả các dự án Wikipedia. Các bảo quản viên và bảo quản viên giao diện có thể thiết lập và hiển thị tính năng này để các biên tập viên sử dụng thông qua [[Special:CommunityConfiguration/ArticleGuidance]]. Hiện [[mw:Special:MyLanguage/Article guidance/Community Configuration|đã có hướng dẫn thiết lập]]. Truy cập [[mw:Talk:Article guidance|trang thảo luận của dự án]] để đặt bất kỳ câu hỏi nào.
'''Cập nhật cho biên tập viên'''
* Tiếp nối việc phát hành tính năng [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists|Danh sách Đọc]] đến tất cả các dự án Wikipedia vào tháng 9, những người dùng đã đăng nhập sẽ sớm có thể [[mw:Special:MyLanguage/Readers/Reader Experience/Reading lists#October/November 2026: Custom collections and call to action|sắp xếp các bài viết được lưu trong danh sách của họ vào các thể loại có thể tùy chỉnh được]]. Điều này sẽ cho phép các độc giả tạo các bộ sưu tập và truy cập lại vào các bài viết đã lưu dựa trên mối quan tâm của họ, từ đó có thể khuyến khích việc truy cập thường xuyên vào Wikipedia hơn. Bản cập nhật này sẽ được phát hành đến tất cả người dùng Wikipedia trong khoảng thời gian từ ngày 9 đến ngày 16 tháng 11.
* Nhóm Ứng dụng Wikipedia đang chuẩn bị khởi động thử nghiệm đầu tiên trong số hai thử nghiệm về thông báo dành cho các độc giả Wikipedia tiếng Anh trên Android mà đã chọn tham gia nhận thông báo. Thử nghiệm kéo dài 3 tuần này sẽ gửi các thông báo gợi ý danh sách đọc Khám phá (Discover) được cá nhân hóa là bộ sưu tập các bài viết Wikipedia được đề xuất dựa trên các bài viết mà độc giả đã từng xem trước đó. Mục tiêu là nhằm tìm hiểu xem những gợi ý này có giúp độc giả khám phá những nội dung có liên quan và khuyến khích họ quay trở lại ứng dụng hay không. Người dùng không cần phải thực hiện bất kỳ thao tác nào, và có thể quản lý tùy chọn thông báo của mình trong phần cài đặt ứng dụng. [[mw:Wikimedia Apps/Team/Notifications|Tìm hiểu thêm và chia sẻ phản hồi]].
* Một lỗi trong [[m:Special:GlobalWatchlist|Danh sách Theo dõi Toàn cục]] khiến cho trang này không thể tải được với những người dùng có những thay đổi chưa được xem trên Wikimedia Commons. Lỗi này nay đã được khắc phục. Nếu bạn đã tạm thời loại bỏ <bdi lang="zxx" dir="ltr"><code><nowiki>commons.wikimedia.org</nowiki></code></bdi> khỏi [[m:Special:GlobalWatchlistSettings|cài đặt Danh sách Theo dõi Toàn cục]] cá nhân của bạn do lỗi này, bạn có thể khôi phục nó tại đó. [https://phabricator.wikimedia.org/T439203]
* Một tính năng Beta mới với tên gọi là "Nhà" (Home) sẽ được [[mw:Special:MyLanguage/Home/Deployment|triển khai đến 10 dự án Wikipedia]] dưới dạng thử nghiệm giới hạn thời gian. Tính năng này nhằm mục đích thay thế <bdi lang="zxx" dir="ltr"><code><nowiki>Special:Homepage</nowiki></code></bdi> dành cho những người mới, đồng thời dự kiến sẽ có thêm nhiều mô đun nữa trong tương lai nhằm cải thiện trải nghiệm hiện tại. Nếu bạn muốn tham gia thử nghiệm này, vui lòng [[mw:Talk:Home|đăng ký]]. "Nhà" sẽ được phát hành đến toàn bộ người dùng vào cuối tháng này.
* Trên Wikipedia tiếng Anh và tiếng Nga, [[m:User:Alaexis/Source Verifier|Xác minh Nguồn]] (Source Verification) nay đã có mặt dưới dạng Đề xuất thử nghiệm dành cho những biên tập viên có kinh nghiệm trong [[mw:Special:MyLanguage/VisualEditor/Suggestion_Mode|Chế độ Đề xuất]] (Suggestion Mode). Nó sử dụng mô hình LLM được vận hành trên [[wikitech:Machine_Learning/LiftWing|LiftWing]] để tìm cách kiểm tra xem một nguồn được trích dẫn có kiểm chứng được cho lời khẳng định đi kèm với nó hay không. Để thử nghiệm tính năng này, vui lòng [[phab:T426359|xem hướng dẫn thử nghiệm này]]. Nếu bạn ở dự án Wikipedia ngôn ngữ khác và cộng đồng tại đó quan tâm đến việc thử tính năng này, vui lòng [[m:User talk:Alaexis/Source Verifier|bày tỏ sự quan tâm của bạn]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Xem tất cả {{formatnum:35}} {{PLURAL:35|tác vụ}} được tạo bởi cộng đồng đã được [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|giải quyết vào tuần trước]]. Ví dụ, một vấn đề khiến cho ngày được truyền vào dưới dạng tham số trống đến các hàm trong mã wiki được hiểu sai là sử dụng định dạng tháng-ngày-năm thay vì định dạng ngày-tháng-năm, nay đã được khắc phục. [https://phabricator.wikimedia.org/T403884]
'''Cập nhật cho những người đóng góp vào mảng kỹ thuật'''
* Kể từ ngày 1 tháng 12 năm 2026, hCaptcha sẽ là yêu cầu bắt buộc đối với các sửa đổi được thực hiện thông qua API bởi những người dùng chưa phải là thành viên tự xác nhận. Nếu công cụ, tiện ích, hoặc đoạn mã người dùng của bạn thực hiện sửa đổi thay mặt cho người dùng mới, [[mw:Special:MyLanguage/Product Safety and Integrity/hCaptcha#November 2026: Completing hCaptcha rollout|hãy xem cách để cập nhật nó]].
* [[wikitech:Help talk:Toolforge/Toolforge standards committee#November 2026 committee nominations|Wikitech đang mở đề cử]] để chọn các thành viên mới của [[wikitech:Help:Toolforge/Toolforge standards committee|Ủy ban tiêu chuẩn của Toolforge]]. Ủy ban này giám sát [[wikitech:Help:Toolforge/Right to fork policy|Quy định quyền sử dụng bản sao]] và [[wikitech:Help:Toolforge/Abandoned tool policy|Quy định về công cụ bị bỏ rơi]] của Toolforge cùng nhiều nhiệm vụ khác. Cổng đề cử sẽ đóng vào ngày 22 tháng 11 năm 2026
* Toolforge vừa giới thiệu hai tính năng beta mới. "Cảnh báo Toolforge" (Toolforge alerts) gửi thông báo qua email khi một công cụ không thể truy cập, trả về lỗi, hoặc khởi động lại thường xuyên. "Nhật ký mở rộng" (Extended logging) giúp việc điều tra các sự cố trở nên dễ dàng hơn bằng cách cung cấp nhật ký cho các sự kiện như tạo hoặc xóa tác vụ (job), cũng như các lỗi trong quá trình triển khai tác vụ thông qua lệnh <bdi lang="zxx" dir="ltr"><code><nowiki>toolforge logs</nowiki></code></bdi>. Cả hai tính năng này đều là tính năng tùy chọn (opt-in) và giúp các bảo trì viên công cụ phát hiện và giải quyết các vấn đề nhanh chóng hơn. Các bảo trì viên có thể [[wikitech:Help:Toolforge/Alerts|bật cảnh báo]] và tìm hiểu cách [[wikitech:Help:Toolforge/Running_jobs#Toolforge_logs|truy cập nhật ký mở rộng]]. Họ cũng được khuyến khích trải nghiệm các tính năng này và [[wikitech:Help:Cloud_Services_communication|gửi phản hồi]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Đề mục định kỳ]] Chi tiết cập nhật mã nguồn sắp tới trong tuần này: [[mw:MediaWiki 1.48/wmf.4|MediaWiki]]
'''Các cuộc họp và sự kiện'''
* Một đề xuất nhằm thay đổi cách chúng tôi tổ chức sự kiện Wikimedia Hackathon hiện nay [[mw:Special:MyLanguage/Wikimedia Hackathon/Community Proposal 2026|đã được chia sẻ]]. Nó hướng tới việc giúp cho sự kiện này dễ dàng tiếp cận các cộng đồng kỹ thuật ở những khu vực khác nhau hơn. Hãy chia sẻ ý kiến của bạn tại [[mw:Special:MyLanguage/Talk:Wikimedia Hackathon/Community Proposal 2026|trang thảo luận]] của đề xuất này; hạn chót đã được kéo dài đến ngày 13 tháng 11.
'''''[[m:Special:MyLanguage/Tech/News|Tin tức Kỹ thuật]]''' do [[m:Special:MyLanguage/Tech/News/Writers|các biên tập viên Bản tin Kỹ thuật]] chuẩn bị và được đăng bởi [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Đóng góp]] • [[m:Special:MyLanguage/Tech/News/2026/46|Biên dịch]] • [[m:Tech|Nhờ giúp đỡ]] • [[m:Talk:Tech/News|Phản hồi]] • [[m:Global message delivery/Targets/Tech ambassadors|Đăng ký hoặc huỷ đăng ký]].''
</div><section end="technews-2026-W46"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 10:34, ngày 9 tháng 11 năm 2026 (UTC)
<!-- Tin nhắn của Thành viên:STei (WMF)@metawiki gửi cho mọi người trong danh sách tại https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=31249348 -->
jhven8o70j6qan4bm4dylqclr8m537i
Bản mẫu:alt of
10
233139
2576408
776866
2026-11-08T12:56:11Z
TheHighFighter2
42988
/* */
2576408
wikitext
text/x-wiki
#redirect [[Bản mẫu:alternative form of]]
bwyyjysqh1n6z4bp50kxlb1h9c3hpn0
rima tekau
0
259628
2576433
2057248
2026-11-08T14:16:38Z
Hiyuune
50834
2576433
wikitext
text/x-wiki
=={{langname|mi}}==
{{number box|mi}}
==={{section|num}}===
{{mi-num}}
# {{cln|mi|Số đếm}} [[năm mươi|Năm mươi]] (50).
fizh2gmrj7r5i0h1o33gudo8k9be9es
toru
0
259660
2576443
2563620
2026-11-08T14:29:15Z
Hiyuune
50834
2576443
wikitext
text/x-wiki
{{also|tõru|tōru|Tōru}}
=={{langname|aud}}==
==={{ĐM|num}}===
{{head|aud|Số từ}}
# {{cln|aud|Số đếm}} [[ba]].
=={{langname|ycr}}==
==={{ĐM|etym}}===
Từ {{derived|ycr|ja|取る|tr=toru}}.
==={{ĐM|verb}}===
{{head|ycr|Động từ}}
# [[lấy]].
==={{ĐM|ref}}===
* {{R:ycr:sound substitution}}
=={{langname|mi}}==
{{numberbox|mi}}
==={{ĐM|etym}}===
Từ {{inh|mi|poz-pol-pro|*tolu}}, từ {{inh|mi|poz-oce-pro|*tolu}}, từ {{inh|mi|pqe-pro|*təlu}}, từ {{inh|mi|poz-cet-pro|*təlu}}, từ {{inh|mi|poz-pro|*təlu}}, từ {{inh|mi|map-pro|*təlu}}.
==={{ĐM|pron}}===
* {{mi-IPA|toru|stress='-}}
==={{ĐM|num}}===
{{mi-num}}
# {{cln|mi|Số đếm}} [[ba]].
===={{ĐM|drv}}====
{{col|mi
|takitoru
}}
==={{ĐM|ref}}===
* {{R:mi:Te Aka 3}}
=={{langname|ja}}==
==={{ĐM|rom}}===
{{ja-romaji}}
# {{ja-romanization of|とる}}
=={{langname|rar}}==
==={{ĐM|pron}}===
* {{IPA|rar|/toru/}}
==={{ĐM|num}}===
{{head|rar|Số từ}}
# [[ba]].
=={{langname|sh}}==
==={{ĐM|n}}===
{{sh-noun form}}
# {{inflection of|sh|tor||dat//voc//loc|s}}
=={{langname|tr}}==
==={{ĐM|n}}===
{{head|tr|nf}}
# {{inflection of|tr|tor||acc|def|s}}
7i4cfiv8izft41a0ggwvjgai3ubcvqq
tekau mā iwa
0
259661
2576439
2057249
2026-11-08T14:19:14Z
Hiyuune
50834
2576439
wikitext
text/x-wiki
=={{langname|mi}}==
{{number box|mi}}
==={{section|num}}===
{{mi-num}}
# {{cln|mi|Số đếm}} [[mười chín|Mười chín]] (19).
nfx91w223g9oegt2pxf2vi8oftwvaex
iwa
0
259667
2576430
2258339
2026-11-08T14:14:20Z
Hiyuune
50834
2576430
wikitext
text/x-wiki
{{also|iwą|Iwa|Iwą}}
=={{langname|ang}}==
==={{section|pron}}===
* {{ang-IPA|īwa}}
==={{section|n}}===
{{head|ang|nf|head=īwa}}
# {{infl of|ang|īw||gen|p}}
=={{langname|ibh}}==
==={{section|n}}===
{{head|ibh|Danh từ}}
# [[hơi thở]].
==={{section|ref}}===
* Tam Thi Minh Nguyen, ''A grammar of Bih ''(2013)
=={{langname|ilo}}==
==={{section|n}}===
{{ilo-noun}}
# [[miếng|Miếng]] [[mỏng]], [[lát]] [[mỏng]].
=={{langname|mt}}==
==={{section|pron}}===
* {{IPA|mt|/ˈiː.wa/}}
* {{rhymes|mt|iːwa|s=2}}
==={{section|interj}}===
{{mt-head|Thán từ}}
# {{lb|mt|colloquial}} {{alt form of|mt|iva}}
=={{langname|mi}}==
==={{section|etym}}===
Từ {{inh|mi|poz-pol-pro|*hiwa}},<ref>{{R:Pollex|HIWA.1|hiwa1}}</ref> từ tiếng Trung Thái Bình Dương nguyên thủy {m|und||*ciwa}}, từ {{inh|mi|poz-oce-pro|*siwa}},<ref>{{R:poz-oce:LPO|6|page=466–7}}</ref> từ {{inh|mi|pqe-pro|*siwa}}, từ {{inh|mi|poz-cet-pro|*siwa}}, từ {{inh|mi|poz-pro|*siwa}}, từ {{inh|mi|map-pro|*Siwa}}. Các từ cùng gốc bao gồm {{cog|haw|iwa}}, {{cog|sm|iva}} và {{cog|to|hiva}}.
==={{section|pron}}===
* {{mi-IPA|iwa|stress='-}}
==={{section|num}}===
{{mi-num}}
# {{cln|mi|Số đếm}} [[chín|Chín]] (9).
==={{section|ref}}===
{{reflist}}
=={{langname|ja}}==
==={{section|rom}}===
{{ja-romaji}}
# {{ja-romanization of|いわ}}
=={{langname|pyu}}==
==={{section|pron}}===
* {{IPA|pyu|/iwa/}}
==={{section|num}}===
{{head|pyu|Số từ}}
# [[chín]].
==={{section|ref}}===
* Teng, Stacy Fang-ching (2008). [https://openresearch-repository.anu.edu.au/server/api/core/bitstreams/330e492f-583d-4a58-9036-dd22ad190c85/content ''A Reference Grammar of Puyuma, an Austronesian Language of Taiwan''] (PDF). Pacific Linguistics 595. Canberra: Pacific Linguistics, Research School of Pacific and Asian Studies, Australian National University. hdl:1885/28526. {{ISBN|9780858835870}}.
mqjl6eiqfb8j96l2xacdtdyvjq5ymzk
2576431
2576430
2026-11-08T14:14:34Z
Hiyuune
50834
2576431
wikitext
text/x-wiki
{{also|iwą|Iwa|Iwą}}
=={{langname|ang}}==
==={{section|pron}}===
* {{ang-IPA|īwa}}
==={{section|n}}===
{{head|ang|nf|head=īwa}}
# {{infl of|ang|īw||gen|p}}
=={{langname|ibh}}==
==={{section|n}}===
{{head|ibh|Danh từ}}
# [[hơi thở]].
==={{section|ref}}===
* Tam Thi Minh Nguyen, ''A grammar of Bih ''(2013)
=={{langname|ilo}}==
==={{section|n}}===
{{ilo-noun}}
# [[miếng|Miếng]] [[mỏng]], [[lát]] [[mỏng]].
=={{langname|mt}}==
==={{section|pron}}===
* {{IPA|mt|/ˈiː.wa/}}
* {{rhymes|mt|iːwa|s=2}}
==={{section|interj}}===
{{mt-head|Thán từ}}
# {{lb|mt|colloquial}} {{alt form of|mt|iva}}
=={{langname|mi}}==
==={{section|etym}}===
Từ {{inh|mi|poz-pol-pro|*hiwa}},<ref>{{R:Pollex|HIWA.1|hiwa1}}</ref> từ tiếng Trung Thái Bình Dương nguyên thủy {{m|und||*ciwa}}, từ {{inh|mi|poz-oce-pro|*siwa}},<ref>{{R:poz-oce:LPO|6|page=466–7}}</ref> từ {{inh|mi|pqe-pro|*siwa}}, từ {{inh|mi|poz-cet-pro|*siwa}}, từ {{inh|mi|poz-pro|*siwa}}, từ {{inh|mi|map-pro|*Siwa}}. Các từ cùng gốc bao gồm {{cog|haw|iwa}}, {{cog|sm|iva}} và {{cog|to|hiva}}.
==={{section|pron}}===
* {{mi-IPA|iwa|stress='-}}
==={{section|num}}===
{{mi-num}}
# {{cln|mi|Số đếm}} [[chín|Chín]] (9).
==={{section|ref}}===
{{reflist}}
=={{langname|ja}}==
==={{section|rom}}===
{{ja-romaji}}
# {{ja-romanization of|いわ}}
=={{langname|pyu}}==
==={{section|pron}}===
* {{IPA|pyu|/iwa/}}
==={{section|num}}===
{{head|pyu|Số từ}}
# [[chín]].
==={{section|ref}}===
* Teng, Stacy Fang-ching (2008). [https://openresearch-repository.anu.edu.au/server/api/core/bitstreams/330e492f-583d-4a58-9036-dd22ad190c85/content ''A Reference Grammar of Puyuma, an Austronesian Language of Taiwan''] (PDF). Pacific Linguistics 595. Canberra: Pacific Linguistics, Research School of Pacific and Asian Studies, Australian National University. hdl:1885/28526. {{ISBN|9780858835870}}.
gdu211we7mp5i9wuzs3iz43hq88o7bg
2576432
2576431
2026-11-08T14:14:49Z
Hiyuune
50834
2576432
wikitext
text/x-wiki
{{also|iwą|Iwa|Iwą}}
=={{langname|ang}}==
==={{section|pron}}===
* {{ang-IPA|īwa}}
==={{section|n}}===
{{head|ang|nf|head=īwa}}
# {{infl of|ang|īw||gen|p}}
=={{langname|ibh}}==
==={{section|n}}===
{{head|ibh|Danh từ}}
# [[hơi thở]].
==={{section|ref}}===
* Tam Thi Minh Nguyen, ''A grammar of Bih ''(2013)
=={{langname|ilo}}==
==={{section|n}}===
{{ilo-noun}}
# [[miếng|Miếng]] [[mỏng]], [[lát]] [[mỏng]].
=={{langname|mt}}==
==={{section|pron}}===
* {{IPA|mt|/ˈiː.wa/}}
* {{rhymes|mt|iːwa|s=2}}
==={{section|interj}}===
{{mt-head|Thán từ}}
# {{lb|mt|colloquial}} {{alt form of|mt|iva}}
=={{langname|mi}}==
{{number box|mi}}
==={{section|etym}}===
Từ {{inh|mi|poz-pol-pro|*hiwa}},<ref>{{R:Pollex|HIWA.1|hiwa1}}</ref> từ tiếng Trung Thái Bình Dương nguyên thủy {{m|und||*ciwa}}, từ {{inh|mi|poz-oce-pro|*siwa}},<ref>{{R:poz-oce:LPO|6|page=466–7}}</ref> từ {{inh|mi|pqe-pro|*siwa}}, từ {{inh|mi|poz-cet-pro|*siwa}}, từ {{inh|mi|poz-pro|*siwa}}, từ {{inh|mi|map-pro|*Siwa}}. Các từ cùng gốc bao gồm {{cog|haw|iwa}}, {{cog|sm|iva}} và {{cog|to|hiva}}.
==={{section|pron}}===
* {{mi-IPA|iwa|stress='-}}
==={{section|num}}===
{{mi-num}}
# {{cln|mi|Số đếm}} [[chín|Chín]] (9).
==={{section|ref}}===
{{reflist}}
=={{langname|ja}}==
==={{section|rom}}===
{{ja-romaji}}
# {{ja-romanization of|いわ}}
=={{langname|pyu}}==
==={{section|pron}}===
* {{IPA|pyu|/iwa/}}
==={{section|num}}===
{{head|pyu|Số từ}}
# [[chín]].
==={{section|ref}}===
* Teng, Stacy Fang-ching (2008). [https://openresearch-repository.anu.edu.au/server/api/core/bitstreams/330e492f-583d-4a58-9036-dd22ad190c85/content ''A Reference Grammar of Puyuma, an Austronesian Language of Taiwan''] (PDF). Pacific Linguistics 595. Canberra: Pacific Linguistics, Research School of Pacific and Asian Studies, Australian National University. hdl:1885/28526. {{ISBN|9780858835870}}.
7sqn45wrj0bqitra9l7ppnphhdil6cd
Thể loại:Số từ tiếng Maori
14
259668
2576434
2057255
2026-11-08T14:17:06Z
Hiyuune
50834
Hiyuune đã đổi [[Thể loại:Số tiếng Maori]] thành [[Thể loại:Số từ tiếng Maori]]
2031770
wikitext
text/x-wiki
[[Thể loại:Mục từ tiếng Maori]]
6m6sjpkokmbgywjkrlf904nic8o5eun
Mô đun:quote
828
259961
2576484
2573521
2026-11-09T05:39:50Z
TheHighFighter2
42988
2576484
Scribunto
text/plain
--[=[
This module contains functions to implement quote-* templates.
Author: Benwing2; conversion into Lua of {{quote-meta/source}} template,
written by Sgconlaw with some help from Erutuon and Benwing2.
The main interface is quote_t(). Note that the source display is handled by source(), which reads both the
arguments passed to it *and* the arguments passed to the parent template, with the former overriding the latter.
]=]
local export = {}
-- Named constants for all modules used, to make it easier to swap out sandbox versions.
local check_isxn_module = "Module:check isxn"
local debug_track_module = "Module:debug/track"
local en_utilities_module = "Module:en-utilities"
local italics_module = "Module:italics"
local labels_module = "Module:labels"
local languages_module = "Module:languages"
local languages_error_module = "Module:languages/error"
local links_module = "Module:links"
local number_utilities_module = "Module:number utilities"
local parameters_module = "Module:parameters"
local parse_utilities_module = "Module:parse utilities"
local qualifier_module = "Module:qualifier"
local roman_numerals_module = "Module:roman numerals"
local scribunto_module = "Module:Scribunto"
local script_utilities_module = "Module:script utilities"
local scripts_module = "Module:scripts"
local string_pattern_escape_module = "Module:string/patternEscape"
local string_replacement_escape_module = "Module:string/replacementEscape"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local template_parser_module = "Module:template parser"
local usex_module = "Module:usex"
local usex_templates_module = "Module:usex/templates"
local utilities_module = "Module:utilities"
local yesno_module = "Module:yesno"
local concat = table.concat
local insert = table.insert
local new_title = mw.title.new
local remove = table.remove
local require = require
local sort = table.sort
local u = mw.ustring.char
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
-- Use HTML entities here to avoid parsing issues (esp. with brackets)
local SEMICOLON_SPACE = "; "
local SPACE_LBRAC = " ["
local RBRAC = "]"
local TEMP_LT = u(0xFFF1)
local TEMP_GT = u(0xFFF2)
local TEMP_LBRAC = u(0xFFF3)
local TEMP_RBRAC = u(0xFFF4)
local TEMP_SEMICOLON = u(0xFFF5)
local function apply_subst(...)
apply_subst = require(usex_module).apply_subst
return apply_subst(...)
end
local function check_isbn(...)
check_isbn = require(check_isxn_module).check_isbn
return check_isbn(...)
end
local function check_issn(...)
check_issn = require(check_isxn_module).check_issn
return check_issn(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function embedded_language_links(...)
embedded_language_links = require(links_module).embedded_language_links
return embedded_language_links(...)
end
local function escape_wikicode(...)
escape_wikicode = require(parse_utilities_module).escape_wikicode
return escape_wikicode(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function find_parameters(...)
find_parameters = require(template_parser_module).find_parameters
return find_parameters(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_processed_labels(...)
format_processed_labels = require(labels_module).format_processed_labels
return format_processed_labels(...)
end
local function format_qualifier(...)
format_qualifier = require(qualifier_module).format_qualifier
return format_qualifier(...)
end
local function format_usex(...)
format_usex = require(usex_module).format_usex
return format_usex(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function get_number(...)
get_number = require(number_utilities_module).get_number
return get_number(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function gsplit(...)
gsplit = require(string_utilities_module).gsplit
return gsplit(...)
end
local function page_should_be_ignored(...)
page_should_be_ignored = require(usex_templates_module).page_should_be_ignored
return page_should_be_ignored(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_utilities_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function parse_inline_modifiers_from_segments(...)
parse_inline_modifiers_from_segments = require(parse_utilities_module).parse_inline_modifiers_from_segments
return parse_inline_modifiers_from_segments(...)
end
local function parse_multi_delimiter_balanced_segment_run(...)
parse_multi_delimiter_balanced_segment_run = require(parse_utilities_module).parse_multi_delimiter_balanced_segment_run
return parse_multi_delimiter_balanced_segment_run(...)
end
local function parse_term_with_lang(...)
parse_term_with_lang = require(parse_utilities_module).parse_term_with_lang
return parse_term_with_lang(...)
end
local function pattern_escape(...)
pattern_escape = require(string_pattern_escape_module)
return pattern_escape(...)
end
local function pluralize(...)
pluralize = require(en_utilities_module).pluralize
return pluralize(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function remove_links(...)
remove_links = require(links_module).remove_links
return remove_links(...)
end
local function roman_to_arabic(...)
roman_to_arabic = require(roman_numerals_module).roman_to_arabic
return roman_to_arabic(...)
end
local function replacement_escape(...)
replacement_escape = require(string_replacement_escape_module)
return replacement_escape(...)
end
local function scribunto_parameter_key(...)
scribunto_parameter_key = require(scribunto_module).scribunto_parameter_key
return scribunto_parameter_key(...)
end
local function serial_comma_join(...)
serial_comma_join = require(table_module).serialCommaJoin
return serial_comma_join(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_alternating_runs(...)
split_alternating_runs = require(parse_utilities_module).split_alternating_runs
return split_alternating_runs(...)
end
local function split_and_process_raw_labels(...)
split_and_process_raw_labels = require(labels_module).split_and_process_raw_labels
return split_and_process_raw_labels(...)
end
local function split_on_comma(...)
split_on_comma = require(parse_utilities_module).split_on_comma
return split_on_comma(...)
end
local function tag_text(...)
tag_text = require(script_utilities_module).tag_text
return tag_text(...)
end
local function tag_transcription(...)
tag_transcription = require(script_utilities_module).tag_transcription
return tag_transcription(...)
end
local function tag_translit(...)
tag_translit = require(script_utilities_module).tag_translit
return tag_translit(...)
end
local function ulen(...)
ulen = require(string_utilities_module).len
return ulen(...)
end
local function unitalicize_brackets(...)
unitalicize_brackets = require(italics_module).unitalicize_brackets
return unitalicize_brackets(...)
end
local function upper(...)
upper = require(string_utilities_module).upper
return upper(...)
end
local function usub(...)
usub = require(string_utilities_module).sub
return usub(...)
end
local function yesno(...)
yesno = require(yesno_module)
return yesno(...)
end
local function track(page)
debug_track("quote/" .. page)
end
local function maintenance_line(text)
return '<span class="maintenance-line">(' .. text .. ")</span>"
end
local function isbn(text)
return "[[Special:BookSources/"
.. text
.. "|→ISBN]]"
.. check_isbn(
text,
' <span class="error" style="font-size:88%">Invalid ISBN</span>[[Category:Pages with ISBN errors]]'
)
end
local function issn(text)
return "[https://www.worldcat.org/issn/"
.. text
.. " →ISSN]"
.. check_issn(
text,
' <span class="error" style="font-size:88%">Invalid ISSN</span>[[Category:Pages with ISSN errors]]'
)
end
local function lccn(text)
text = text:gsub(" ", "")
if text:find("-") then
-- old-style LCCN; reformat per request by [[User:The Editor's Apprentice]]
local prefix, part1, part2 = text:match("^(.-)(%d+)%-(%d+)$")
if prefix then
if ulen(part2) < 6 then
part2 = ("0"):rep(6 - ulen(part2)) .. part2
end
text = prefix .. part1 .. part2
end
end
return "[https://lccn.loc.gov/" .. mw.uri.encode(text) .. " →LCCN]"
end
local function format_date(text)
return mw.getCurrentFrame():callParserFunction("#formatdate", text, "dmy")
end
-- Parse a raw lb= param (or nil) to individual label info objects and then concatenate them appropriately into a
-- qualifier input, respecting flags like `omit_preComma` and `omit_postSpace` in the label specs.
local function parse_and_format_labels(raw_lb, lang)
if not raw_lb then
return nil
end
local labels = split_and_process_raw_labels{labels = raw_lb, lang = lang, nocat = true}
labels = format_processed_labels{labels = labels, lang = lang, no_ib_content = true}
if labels ~= "" then -- not sure labels can be an empty string but it seems possible in some circumstances
return {labels}
end
end
-- Convert a comma-separated list of language codes to a comma-separated list of language names. `fullname` is the
-- name of the parameter from which the list of language codes was fetched.
local function format_langs(langs)
local names = {}
for i, lang in ipairs(langs) do
names[i] = lang:getCanonicalName()
end
if #names == 1 then
return names[1]
end
return serial_comma_join(names)
end
local function get_first_lang(langs)
return langs[1] or get_lang("und")
end
--[=[
Normally we parse off inline modifiers and language code prefixes in various places, e.g. he:מרים<tr:Miryem>. But we
exclude HTML entries with <span ...>, <i ...>, <br/> or similar in it, caused by wrapping an argument in {{l|...}},
{{lang|...}} or similar. Basically, all tags of the sort we parse here should consist of a less-than sign, plus letters,
plus a colon, e.g. <tr:...>, so if we see a tag on the outer level that isn't in this format, we don't try to parse it.
The restriction to the outer level is to allow generated HTML inside of e.g. qualifier modifiers, such as
foo<q:similar to {{m|fr|bar}}> (if we end up supporting such modifiers).
Also exclude things that look like URL's from being parsed as having language code prefixes.
]=]
local function val_should_not_be_parsed_for_annotations(val)
return val:find("^[^<]*<%l*[^%l:]") or val:find("^%l+://")
end
local param_mods = {
t = {
-- <t:...> and <gloss:...> are aliases.
item_dest = "gloss",
},
gloss = {},
alt = {},
tr = {},
ts = {},
subst = {},
sc = {type = "script"},
f = {
convert = function(arg, parse_err)
local prefix, val = arg:match("^(.-):([^ ].*)$")
if not prefix then
prefix = ""
val = arg
end
local tags, sc_code, sc = prefix:match("^(.*)/(.-)$")
if sc_code then
sc = get_script(sc_code) or
require(languages_error_module)(sc_code, parse_err, "script code", nil, "not real lang")
else
tags = prefix
end
local quals
if tags ~= "" then
quals = split_on_comma(tags)
for i, qual in ipairs(quals) do
local obj = get_lang(qual, nil, "allow etym") or get_script(qual)
quals[i] = obj or qual
end
end
return {
quals = quals,
sc = sc,
val = val,
}
end,
store = "insert",
},
q = {},
qq = {},
}
local function generate_obj_annotated_text(text, parse_err, paramname)
local obj = {}
if text:find(":[^ ]") or text:find("%[%[") then
local display, is_wikipedia_wikisource
obj.text, obj.lang, obj.link, display, is_wikipedia_wikisource =
parse_term_with_lang {
term = text,
parse_err = parse_err,
paramname = paramname
}
-- HACK: If object is a Wikipedia or Wikisource link, we need to convert it to a two-part link
-- to avoid the w: or s: prefix showing. We should probably avoid this by calling
-- language_link() (in [[Module:links]]) in format_annotated_text() instead of the hacky stuff
-- that we currently do; but we need to test that carefully to make sure it doesn't do things like
-- munge % signs.
if is_wikipedia_wikisource and not obj.text:find("%[%[") and not obj.text:find("%]%]") then
-- Don't directly set .alt, because then if the user specifies <alt:...>, it will cause an error in
-- parse_inline_modifiers().
obj.display = display
end
else
obj.text = text
obj.link = text
end
return obj
end
--[=[
Parse a textual property that may be in a foreign language or script and may be annotated with a language prefix and/or
inline modifiers. `val` is the value of the parameter and `fullname` is the name of the parameter from which the value
was retrieved. `explicit_gloss`, if specified and non-nil, overrides any gloss specified using the <t:...> or
<gloss:...> inline modifier.
If `val` is nil, the return value of this function is nil. Otherwise it is parsed for a language prefix (e.g.
'ar:مُؤَلِّف') and inline modifiers (e.g. 'ar:مُؤَلِّف<t:Author>'), and the return value is an object with the following
fields:
`lang`: The language object corresponding to the language prefix, if specified, or nil if no language prefix is
given.
`text`: The text after stripping off any language prefix and inline modifiers.
`link`: The link part of the text if it consists of a two-part link; otherwise, same as `text`.
`alt`: Display text specified using the <alt:...> modifier, if given; otherwise, nil.
`subst`: Substitutions used to generate the transliteration, in the same format as the subst= parameter.
`sc`: The script object corresponding to the <sc:...> modifier, if given; otherwise nil.
`tr`: The transliteration corresponding to the <tr:...> modifier, if given; otherwise nil.
`ts`: The transcription corresponding to the <ts:...> modifier, if given; otherwise nil.
`gloss`: The gloss/translation corresponding to the `explicit_gloss` parameter (if given and non-nil), otherwise
the <t:...> or <gloss:...> modifiers if given, otherwise nil.
`f`: Foreign versions of the text.
`q`: Left qualifiers.
`qq`: Right qualifiers.
Note that as a special case, if `val` contains HTML tags at the top level (e.g. '<span class="Arab">...</span>', as
might be generated by specifying {{lang|ar|مُؤَلِّف}}), no language prefix or inline modifiers are parsed, and the return
value has the `noscript` field set to true, which tells format_annotated_text() not to try to identify the script of
the text and CSS-tag the text accordingly, but to leave the text untagged.
This object can be passed to format_annotated_text() to format a string displaying the text (appropriately
script-tagged, unless `noscript` is set, as described above) and modifiers.
]=]
local function parse_annotated_text(val, fullname, explicit_gloss)
if not val then
return nil
end
-- When checking for inline modifiers, exclude HTML entry with <span ...>, <i ...>, <br/> or similar in it, caused
-- by wrapping an argument in {{l|...}}, {{lang|...}} or similar. Also exclude URL's from being parsed as having
-- language code prefixes. See val_should_not_be_parsed_for_annotations() for more information. If we find a
-- parameter value with top-level HTML in it, add 'noscript = true' to indicate that we should not try to do script
-- inference and tagging. (Otherwise, e.g. if you specify {{lang|ar|مُؤَلِّف}} as the author, you'll get an extra big
-- font coming from the fact that {{lang|...}} wraps the Arabic text in CSS that increases the size from the
-- default, and then we do script detection and again wrap the text in the same CSS, which increases the size even
-- more.)
if val_should_not_be_parsed_for_annotations(val) then
return {text = val, link = val, noscript = true, gloss = explicit_gloss}
end
local obj
if val:find("<") then
-- Check for inline modifier.
obj = parse_inline_modifiers(val, {
paramname = fullname,
param_mods = param_mods,
generate_obj = generate_obj_annotated_text,
})
else
obj = generate_obj_annotated_text(val, nil, fullname)
end
if explicit_gloss then
obj.gloss = explicit_gloss
end
return obj
end
local html_entity_char_to_replacement = {
["<"] = TEMP_LT,
[">"] = TEMP_GT,
["["] = TEMP_LBRAC,
["]"] = TEMP_RBRAC,
}
local function html_entity_replacement(entity, code_without_semicolon, hash, xcode, x, code)
-- Try to decode the entity. If successful, Replace certain special HTML entities (those that are bracket-like)
-- with single Unicode characters; otherwise, replace the semicolon with a special character so it won't get
-- interpreted as a delimiter.
local ch = decode_entities(entity)
if ch ~= entity then
return html_entity_char_to_replacement[ch] or code_without_semicolon .. TEMP_SEMICOLON
end
-- If the entity doesn't decode, escape it anyway iff it follows a valid format.
if hash == "" then
-- Any nonstandard MediaWiki-only entities have now been filtered off, so treat any non-ASCII characters as
-- invalid.
return xcode:match("^[^\128-\255]+$") and code_without_semicolon .. TEMP_SEMICOLON or entity
elseif x == "" then
return xcode:match("^%d+$") and code_without_semicolon .. TEMP_SEMICOLON or entity
end
return code:match("^%x+$") and code_without_semicolon .. TEMP_SEMICOLON or entity
end
local html_entity_replacement_to_char = {
[TEMP_LT] = "<",
[TEMP_GT] = ">",
[TEMP_LBRAC] = "[",
[TEMP_RBRAC] = "]",
[TEMP_SEMICOLON] = ";",
}
local function undo_html_entity_replacement(txt)
-- Pattern covers everything in html_entity_replacement_to_char.
return (txt:gsub("\239\191[\177-\181]", html_entity_replacement_to_char))
end
-- NOTE: We try hard to optimize this function for the common cases and avoid loading [[Module:parse utilities]]
-- in such cases. The cases we can handle without loading [[Module:parse utilities]] are single values (no
-- semicolons present) without inline modifiers or language prefixes, and multi-entity values (semicolons present)
-- without (a) brackets of any kind (including parens, braces and angle brackets; angle brackets typically indicate
-- inline modifiers and other brackets may protect a semicolon from being interpreted as a delimiter);
-- (b) ampersands (which may indicate HTML entities, which protect a semicolon from being interpreted as a
-- delimiter); and (c) colons not followed by a space (which may indicate a language prefix).
local function generate_obj_multivalued_annotated_text(text, parse_err, paramname, no_undo_html_entity_replacement)
local obj = generate_obj_annotated_text(text, parse_err, paramname)
if not no_undo_html_entity_replacement then
obj.text = undo_html_entity_replacement(obj.text)
obj.link = undo_html_entity_replacement(obj.link)
end
return obj
end
--[=[
Similar to parse_annotated_text() but the parameter value may contain multiple semicolon-separated entities, each with
their own inline modifiers. Some examples:
* mainauthor=Paula Pattengale; Terea Sonsthagen
* author=Katie Brick; J. Cody Nielsen; Greg Jao; Eric Paul Rogers; John A. Monson
* author=Suzanne Brockmann; Patrick G. Lawlor (Patrick Girard); Melanie Ewbank
* author=G Ristori; et al.
* author=Jason Scott; zh:王晰宁<t:Wang Xining>
* editors=zh:包文俊; zh:金心雯
* quotee=zh:張福運<t:Chang Fu-yun>; zh:張景文<t:Chang Ching-wen>
There may be embedded semicolons within brackets, braces or parens that should not be treated as delimiters, e.g.:
* author=Oliver Optic [pseudonym; {{w|William Taylor Adams}}]
* author=author=Shannon Drake (pen name; {{w|Heather Graham Pozzessere}})
* author=James (the Elder;) Humphrys
There may also be HTML entities with semicolons in them:
* author=[{{w|Gilbert Clerke}}]
* 2ndauthor=Martin Biddle & Sally Badham
* author=Peter Christen Asbjørnsen
There may be both embedded semicolons and HTML entities with semicolons in them:
* author=[{{w|Voltaire}} [pseudonym; François-Marie Arouet]]
In general we want to treat [ like an opening bracket and ] like a closing bracket. Beware that they may be
mismatched:
* author=Anonymous [{{w|Karl Maria Kertbeny}}]
Here, `val` is the value of the parameter and `fullname` is the name of the parameter from which the value was
retrieved. `explicit_gloss`, if specified and non-nil, overrides any gloss specified using the <t:...> or <gloss:...>
inline modifier, and `explicit_gloss_fullname` is the name of the parameter from which this value was retrieved. (If
`explicit_gloss` is specified and multiple values were seen, an error results.)
Return value is a list of objects of the same sort as returned by parse_annotated_text().
]=]
local function parse_multivalued_annotated_text(val, fullname, explicit_gloss, explicit_gloss_fullname)
if not val then
return nil
end
-- NOTE: In the code that follows, we use `entity` most of the time to refer to one of the semicolon-separated
-- values in the multivalued param. Entities are most commonly people (typically authors, editors, translators or
-- the like), but may be the names of publishers, locations, or other entities. "Entity" can also refer to HTML
-- entities; in the places where this occurs, the variable name contains 'html' in it.
local splitchar, english_delim
if val:find("^,") then
splitchar = ","
english_delim = "comma"
val = val:gsub("^,", "")
else
splitchar = ";"
english_delim = "semicolon"
end
-- Optimization #1: No semicolons/commas or angle brackets (indicating inline modifiers).
if not val:find("[<" .. splitchar .. "]") then
if val_should_not_be_parsed_for_annotations(val) then
return {{text = val, link = val, noscript = true}}
else
return {generate_obj_multivalued_annotated_text(val, nil, fullname, "no undo html entity replacement")}
end
end
-- Optimization #2: Semicolons/commas but no angle brackets (indicating inline modifiers), braces, brackets, or
-- parens (any of which would protect the semicolon/comma from interpretation as a delimiter), and no ampersand
-- (which might indicate an HTML entity with a terminating semicolon, which should not be interpreted as a
-- delimiter).
if not val:find("[<>%[%](){}&]") then
local entity_objs = {}
for entity in gsplit(val, "%s*" .. splitchar .. "%s*") do
if val_should_not_be_parsed_for_annotations(entity) then
insert(entity_objs, {
text = entity,
link = entity,
noscript = true
})
else
insert(entity_objs, generate_obj_multivalued_annotated_text(entity, nil, fullname, "no undo html entity replacement"))
end
end
return entity_objs
end
-- Escape HTML entities, and get rid of directionality markers.
local amp = val:find("&", nil, true)
if amp then
-- The pattern is more permissive than the usual entity pattern, as MediaWiki has some nonstandard entities
-- that have non-ASCII characters in their codes.
val = val:gsub("((&(#?)(([xX]?)([%w\128-\255]+)));)", html_entity_replacement)
end
-- Pattern covers left-to-right (U+200E) and right-to-left (U+200F).
val = val:gsub("\226\128[\142\143]", "")
-- Parse balanced segment runs, treating HTML entities for left and right bracket and left and right angle bracket
-- as matching literal versions of the same characters.
local entity_runs = parse_multi_delimiter_balanced_segment_run(
val,
{{"[" .. TEMP_LBRAC, "]" .. TEMP_RBRAC}, {"(", ")"}, {"{", "}"}, {"<" .. TEMP_LT, ">" .. TEMP_GT}},
true
)
if type(entity_runs) == "string" then
local undo_val = undo_html_entity_replacement(val)
-- Parse error due to unbalanced delimiters. Don't throw an error here; instead, don't attempt to parse off
-- any annotations, but return the value directly, maybe allowing script tagging (not allowing it if it appears
-- the text is already script-tagged).
return {{text = undo_val, link = undo_val, noscript = not not val_should_not_be_parsed_for_annotations(val)}}
end
-- Split on semicolon (or comma), possibly surrounded by whitespace.
local separated_groups = split_alternating_runs(entity_runs, "%s*" .. splitchar .. "%s*")
-- Process each value.
local entity_objs = {}
for _, entity_group in ipairs(separated_groups) do
-- Rejoin runs that don't involve <...>.
local j = 2
while j <= #entity_group do
if not entity_group[j]:find("^<.*>$") then
entity_group[j - 1] = entity_group[j - 1] .. entity_group[j] .. entity_group[j + 1]
remove(entity_group, j)
remove(entity_group, j)
else
j = j + 2
end
end
local oneval = undo_html_entity_replacement(concat(entity_group))
-- When checking for inline modifiers, exclude HTML entry with <span ...>, <i ...>, <br/> or similar in it,
-- caused by wrapping an argument in {{l|...}}, {{lang|...}} or similar. Also exclude URL's from being parsed
-- as having language code prefixes. This works analogously to parse_annotated_text(); see there for more.
if val_should_not_be_parsed_for_annotations(oneval) then
insert(entity_objs, {
text = oneval,
link = oneval,
noscript = true
})
else
local obj
if #entity_group > 1 then
-- Check for inline modifier.
obj = parse_inline_modifiers_from_segments({
group = entity_group,
arg = oneval,
props = {
paramname = fullname,
param_mods = param_mods,
generate_obj = generate_obj_multivalued_annotated_text,
},
})
else
obj = generate_obj_multivalued_annotated_text(entity_group[1], nil, fullname)
end
insert(entity_objs, obj)
end
end
if explicit_gloss then
if #entity_objs > 1 then
error(
(
"Can't specify |%s= along with multiple %s-separated entities in |%s=; use the <t:...> "
.. "inline modifier attached to the individual entities"
):format(explicit_gloss_fullname, english_delim, fullname)
)
end
entity_objs[1].gloss = explicit_gloss
end
return entity_objs
end
--[=[
Format a text property that may be in a foreign language or script, along with annotations. This is conceptually
similar to the full_link() function in [[Module:links]], but displays the annotations in a different format that is
more appropriate for bibliographic entries. The output looks like this:
TEXT [TRANSLIT /TRANSCRIPTION/, GLOSS]
`textobj` is as returned by parse_annotated_text(). `tag_text_func`, if supplied, is a function of one argument to further
wrap the text after it has been processed and CSS-tagged appropriately, directly before insertion. `tag_gloss_func` is a
similar function for the gloss.
]=]
local function format_annotated_text(textobj, tag_text_func, tag_gloss_func)
if not textobj then
return nil
end
local text, link = textobj.text, textobj.link
local subst, tr, ts, f, gloss = textobj.subst, textobj.tr, textobj.ts, textobj.f, textobj.gloss
-- Retrieve the display text, either specified by the user (.alt) or by parse_annotated_text() (.display) when a
-- Wikipedia link is given.
local alt = textobj.alt or textobj.display
if alt then
if link:find("%[%[") or link:find("%]%]") then
local errmsg = ("Can't currently handle embedded links in '%s', with <alt:...> text '%s'"):format(link, alt)
error(escape_wikicode(errmsg))
end
text = ("[[%s|%s]]"):format(link, alt)
end
-- See above for `noscript`, meaning HTML was found in the text value, probably generated using {{lang|...}}.
-- {{lang}} already script-tags the text and processes embedded language links, so we don't want to do it again (in
-- fact, the code below within the if-clause is similar to what {{lang}} does). In such a case, an explicit language
-- won't be available and find_best_script_without_lang() may not be accurate, so we can't do automatic transliteration.
if not textobj.noscript then
local lang = textobj.lang
-- As an optimization, don't do script detection on an argument that contains only ASCII.
local sc = textobj.sc
or lang and lang:findBestScript(text)
or not text:find("^[ -~]$") and find_best_script_without_lang(text)
or nil
-- As an optimization, don't do any of the following if there's no language, script, translit or transcription,
-- as will be the case with simple ASCII values.
if lang or sc or tr or ts then
if not lang then
lang = get_lang("und")
end
if tr == "-" then
tr = nil
elseif not tr and sc and not sc:getCode():find("Lat") then -- Latn, Latf, Latg, pjt-Latn
-- might return nil
local text_for_tr = text
if subst then
text_for_tr = apply_subst(text_for_tr, subst)
else
text_for_tr = remove_links(text)
end
tr = (lang:transliterate(text_for_tr, sc))
end
if text:find("%[%[") then
-- FIXME: embedded_language_links() replaces % signs with their URL-encoded equivalents,
-- which messes up URL's that may be present (e.g. if chapterurl= is given). IMO this
-- should not happen, and embedded_language_links() should do nothing if no embedded links
-- are present. To work around this, only call embedded_language_links() when there are
-- embedded links present.
text = embedded_language_links({
term = text,
lang = lang,
sc = sc,
})
end
if lang:getCode() ~= "und" or sc:getCode() ~= "Latn" then
text = tag_text(text, lang, sc)
end
if tr then
-- Should we link to the transliteration of languages with lang:link_tr()? Probably not because `text` is not
-- likely to be a term that has an entry.
tr = tag_translit(tr, lang, "usex")
end
if ts then
ts = tag_transcription(ts, lang, "usex")
end
end
end
text = unitalicize_brackets(text)
if tag_text_func then
text = tag_text_func(text)
end
local parts = {}
if textobj.q then
insert(parts, format_qualifier(textobj.q) .. " ")
end
insert(parts, text)
if tr or ts or f or gloss then
insert(parts, SPACE_LBRAC)
local subparts = {}
if tr or ts then
local tr_ts
if ts then
ts = "/" .. ts .. "/"
end
if tr and ts then
tr_ts = tr .. " " .. ts
else
tr_ts = tr or ts
end
insert(subparts, tr_ts)
end
if f then
for _, ff in ipairs(f) do
local sc = ff.sc
local lang
if not sc and ff.quals then
local qual = ff.quals[1]
if type(qual) == "string" then
-- do nothing; we'll do script detection farther down
elseif qual:hasType("script") then
sc = qual
else -- language
sc = qual:findBestScript(ff.val)
lang = qual
end
end
if not lang then
lang = get_lang("und")
end
sc = sc or find_best_script_without_lang(ff.val)
local val = embedded_language_links({
term = ff.val,
lang = lang,
sc = sc,
})
if lang:getCode() ~= "und" or sc:getCode() ~= "Latn" then
val = tag_text(val, lang, sc)
end
local qual_prefix
if ff.quals then
for i, qual in ipairs(ff.quals) do
if type(qual) ~= "string" and (qual:hasType("script") or qual:hasType("language")) then
ff.quals[i] = qual:getCanonicalName()
end
end
qual_prefix = concat(ff.quals, "/") .. ": "
else
qual_prefix = ""
end
insert(subparts, qual_prefix .. val)
end
end
if gloss then
gloss = '<span class="e-translation">' .. gloss .. "</span>"
gloss = unitalicize_brackets(gloss)
if tag_gloss_func then
gloss = tag_gloss_func(gloss)
end
insert(subparts, gloss)
end
insert(parts, concat(subparts, ", "))
insert(parts, RBRAC)
end
if textobj.qq then
insert(parts, " " .. format_qualifier(textobj.qq))
end
return concat(parts)
end
--[=[
Format a multivalued text property that may be in a foreign language or script, along with annotations. This is the
multivalued analog to format_annotated_text(), and formats each individual entity using format_annotated_text(),
joining the results with `delimiter`, which defaults to ", ". It `delimiter` is "and" or "or", join the results using
serial_comma_join() with the specified conjunction.
`textobjs` is as returned by parse_multivalued_annotated_text(). `tag_text_func` and `tag_gloss_func` are as in
format_annotated_text().
]=]
local function format_multivalued_annotated_text(textobjs, delimiter, tag_text_func, tag_gloss_func)
if not textobjs then
return nil
end
if #textobjs == 1 then
return format_annotated_text(textobjs[1], tag_text_func, tag_gloss_func)
end
local parts = {}
for _, textobj in ipairs(textobjs) do
insert(parts, format_annotated_text(textobj, tag_text_func, tag_gloss_func))
end
-- Change delimiter to semicolon if the items themselves contain commas (e.g., in ", Jr.")
local use_semicolon = false
for _, obj in ipairs(textobjs) do
-- Use remove_links to ignore commas in links
if obj.text and remove_links(obj.text):find(", ") then
use_semicolon = true
break
end
end
local n = #parts
if n > 0 and parts[n]:match("^'*et al[.']*$") then
-- Special handling for 'et al.'
parts[n] = "''và đồng nghiệp''"
if n == 2 then
-- author et al.
return concat(parts, " ")
else
-- author 1, author 2, et al.
return concat(parts, (use_semicolon and "; ") or ", ")
end
if delimiter == "và" or delimiter == "hoặc" then
delimiter = ", "
end
return concat(parts, delimiter)
end
if delimiter == "và" or delimiter == "hoặc" then
return serial_comma_join(parts, {conj = delimiter})
end
return concat(parts, delimiter or ((use_semicolon and "; ") or ", "))
end
-- Fancy version of ine() (if-not-empty). Converts empty string to nil, but also strips leading/trailing space.
local function ine(arg)
if not arg then
return nil
elseif type(arg) ~= "string" then
return arg
end
arg = mw.text.trim(arg)
if arg == "" then
return nil
end
return arg
end
local abbrs = {
["a."] = {anchor = "a.", full = "trước"},
["c."] = {anchor = "kh.", full = "khoảng"},
["kh."] = {anchor = "kh.", full = "khoảng"},
["p."] = {anchor = "p.", full = "sau"},
}
-- Process prefixes 'a.' (ante), 'c.' (circa) and 'p.' (post) at the beginning of an arbitrary date or year spec.
-- Returns two values, the formatted version of the prefix and the date spec minus the prefix. If no prefix is found,
-- returns an empty string and the full date.
local function process_ante_circa_post(date)
local prefix = usub(date, 1, 2)
local abbr = abbrs[prefix]
local abbr_prefix = ""
if abbr then
abbr_prefix = "''[[Phụ lục:Từ điển thuật ngữ#"
.. abbr.anchor
.. '|<abbr title="'
.. abbr.full
.. '">'
.. abbr.anchor
.. "</abbr>]]'' "
-- Remove lowercase letter, period, and space from beginning of date parameter.
date = ugsub(date, "^%l%.%s*", "")
end
return abbr_prefix, date
end
-- Format the arguments that specify the date of the quotation. These include the following:
-- |date=: The date. If |start_date= is given, this is the end date.
-- |year=, |month=: Year and month of quotation date or end of range, if |date= isn't given.
-- |start_date=: The start date, to specify a range.
-- |start_year=, |start_month=: Year and month of start of range, if |start_date= isn't given.
-- |accessdate=: Date a website was accessed; processed if no other date was given.
-- |nodate=: Indicate that no date is present; otherwise a maintenance line will be displayed if there is no date.
--
-- If `parampref` and/or `paramsuf` are given, this modifies all the date arguments accordingly. For example, if
-- `parampref` == "orig" and `paramsuf` is omitted, the date is specified using |origdate= or |origyear=/|origmonth=,
-- and the start of the range is |origstart_date=, etc. Similarly, if `parampref` is omitted and `paramsuf` is
-- "_published", the date is specified using |date_published= or |year_published=/|month_published=, and the start of
-- the range is |start_date_published=, etc.
--
-- `a` and `get_full_paramname` are functions with the same interpretation as the local functions of the same name in
-- source(). These are used to fetch parameters and get their full names. Note that this may cause all arguments to
-- have an index added to them (|date2=, |year2=, |month2=, etc.).
--
-- `alias_map` is as in source() and is used to map canonical arguments to their aliases when aliases were used.
--
-- If `bold_year` is given, displayed years are boldfaced unless boldface is present in the parameter value.
--
-- If `maintenance_line_no_date` is specified, it should be a string that will be returned if no date is found (i.e.
-- neither |date= nor |year=, or their appropriate equivalents per `parampref` and `paramsuf`, are specified, and
-- neither |nodate= is given to indicate that there is no date, or |accessdate= is given).
--
-- Returns two values: the formatted date and a boolean indicating whether to add a maintenance category
-- [[:Category:Requests for date in LANG entries]]. The first return value will be nil if nothing is to be added
-- (in which case the scond return value will always be nil).
local function format_date_args(
a,
get_full_paramname,
alias_map,
parampref,
paramsuf,
bold_year,
maintenance_line_no_date,
year_last
)
local output = {}
parampref = parampref or ""
paramsuf = paramsuf or ""
local function getp(param)
return a(parampref .. param .. paramsuf)
end
local function pname(param)
local fullname = get_full_paramname(parampref .. param .. paramsuf)
return alias_map[fullname] or fullname
end
-- Format `timestamp` (a timestamp referencing a date) according to the spec in `code`. `param` is the base name of
-- the parameter from which the timestamp was fetched, for error messages.
local function format_date_with_code(code, timestamp, param)
local language = mw.getContentLanguage()
local ok, date = pcall(language.formatDate, language, code, timestamp)
if ok then
return date
else
-- All the formats used in format_date_args() are fine, so the timestamp must be at fault.
error(
(
"Timestamp |%s=%s (possibly canonicalized from its original format) could not be parsed; see the "
.. "[[mw:Help:Extension:ParserFunctions##time|documentation for the #time parser function]]"
):format(pname(param), tostring(timestamp))
)
end
end
-- Try to figure out if the given timestamp has the day of the month explicitly given. We use the following
-- algorithm:
-- 1. Format as year-month-day; if the day is not 1, the day was explicitly given, since if only the year/month are
-- given, the day shows up as 1.
-- 2. If the day shows up as 1 and there isn't a 1 or 01 in the timestamp, the day wasn't explicitly given.
-- 3. Otherwise, if there are three separate numbers (e.g. 2022-07-01), or two separate numbers plus a capitalized
-- letter (taken as an English month, e.g. 2022 July 1), the day was explicitly given, otherwise not.
--
-- `param` is the base name of the parameter from which the timestamp was fetched.
local function date_has_day_specified(timestamp, param)
local day = format_date_with_code("j", timestamp, param)
if day ~= "1" then
return true
end
local english_month = timestamp:find("%u")
local canon_timestamp = mw.text.trim((timestamp:gsub("%D+", " ")))
local seen_nums = split(canon_timestamp, " ", true)
local saw_one = false
for _, num in ipairs(seen_nums) do
if num == "1" or num == "01" then
saw_one = true
break
end
end
if not saw_one then
return false
end
return #seen_nums >= 3 or english_month and #seen_nums >= 2
end
-- Format a date with boldfaced year, as e.g. '''2023''' August 3. `explicit_day_given` indicates whether to include
-- the day; if false, the return value will be e.g. '''2023''' August. `date_param` is the base name of the param
-- from which the date was fetched, for error messages.
local function format_bold_date(date, explicit_day_given, date_param)
local day_month_code = explicit_day_given and "j F" or "F"
local month_day_code = explicit_day_given and "d/m/" or "F"
if year_last then
if bold_year then
-- This formats like "3 August '''2023'''" (or "August '''2023'''" if day not explicitly given).
return format_date_with_code(day_month_code .. " '''Y'''", date, date_param)
else
-- This formats like "3 August 2023" (or "August 2023" if day not explicitly given).
return format_date_with_code(day_month_code .. " Y", date, date_param)
end
else
if bold_year then
-- This formats like "'''2023''' August 3" (or "'''2023''' August" if day not explicitly given).
return format_date_with_code("'''" .. month_day_code .. "Y'''", date, date_param)
else
-- This formats like "2023 August 3" (or "2023 August" if day not explicitly given).
return format_date_with_code(month_day_code .. "Y", date, date_param)
end
end
end
-- The formatDate method of the mw.language object behaves like the {{#time:}} parser function, which doesn't
-- accept the formats "monthday monthname, year" or "year monthname monthday", but outputs garbage when it receives
-- them, behavior inherited from PHP. {{#formatdate:}} magic word is more forgiving. Fix dates so that, for
-- instance, the |date= parameter of {{quote-journal}} (which uses this code) and the |accessdate= parameter (which
-- uses {{#formatdate:}}) accept similar date formats. See:
-- * [[mw:Extension:Scribunto/Lua_reference_manual#mw.language:formatDate]]
-- * [[mw:Help:Extension:ParserFunctions##time]]
-- * [[mw:Help:Magic_words#Formatting]]
-- `date` is the date spec from the user, which is assumed to come from a parameter whose base name ends in "date";
-- `parampref` is the prefix added to "date" to get the parameter name.
local function fix_date(date, param_pref)
if tonumber(date) ~= nil then
error(
("|%s= should contain a full date (year, month, day of month); use |%s= for year"):format(
pname(param_pref .. "date"),
pname(param_pref .. "year")
)
)
elseif date and date:find("%s*%a+,%s*%d+%s*$") then
error(
("|%s= should contain a full date (year, month, day of month); use |%s=, |%s= for month and year"):format(
pname(param_pref .. "date"),
pname(param_pref .. "month"),
pname(param_pref .. "year")
)
)
end
if date then
-- Commas are replaced with spaces to prevent parsing issues
local fixed_date = ugsub(date, ", *", " ")
return (ugsub(ugsub(fixed_date or date, "(%d+ %a+),", "%1"), "^(%d%d%d%d) (%a+ %d%d?)$", "%2 %1"))
end
end
local start_date, date = fix_date(getp("start_date"), "start_"), fix_date(getp("date"), "")
local year = getp("year")
local month = getp("month")
local start_year = getp("start_year")
local start_month = getp("start_month")
if date and year then
error(("Only one of |%s= or |%s= should be specified"):format(pname("date"), pname("year")))
end
if date and month then
error(
("|%s= should only be specified in conjunction with |%s=, not with |%s="):format(
pname("month"),
pname("year"),
pname("date")
)
)
end
if start_date and start_year then
error(("Only one of |%s= or |%s= should be specified"):format(pname("start_date"), pname("start_year")))
end
if start_date and start_month then
error(
("|%s= should only be specified in conjunction with |%s=, not with |%s="):format(
pname("start_month"),
pname("start_year"),
pname("start_date")
)
)
end
if (start_date or start_year) and not (date or year) then
error(
("|%s= or |%s=/|%s= cannot be specified without specifying |%s= or |%s=/|%s="):format(
pname("start_date"),
pname("start_year"),
pname("start_month"),
pname("date"),
pname("year"),
pname("month")
)
)
end
local dash = " – "
local day_explicitly_given = date and date_has_day_specified(date, "date")
local start_day_explicitly_given = start_date and date_has_day_specified(start_date, "start_date")
-- Format a date with boldfaced year, as e.g. '''2023''' August 3 (if `explicit_day_given` specified) or
-- '''2023''' August (if `explicit_day_given` not specified). If no date specified, fall back to formatting based
-- on the year and (optionally) month params given in `yearobj` and `monthobj`, boldfacing the year if not already.
-- `date_param` is the base name of the param from which the date was fetched, for error messages.
local function format_date_or_year_month(date, yearobj, monthobj, explicit_day_given, date_param)
if date then
return format_bold_date(date, explicit_day_given, date_param)
else
-- Boldface a year spec if it's not already boldface.
if bold_year and not yearobj.text:find("'''") then
-- Clone the year object before modifying it because we may use it later to check against the current
-- year (if we're dealing with start_year).
yearobj = shallow_copy(yearobj)
yearobj.text = "'''" .. yearobj.text .. "'''"
if yearobj.alt then
yearobj.alt = "'''" .. yearobj.alt .. "'''"
end
end
if year_last then
return (monthobj and format_annotated_text(monthobj) .. " " or "") .. format_annotated_text(yearobj)
else
return format_annotated_text(yearobj) .. (monthobj and " " .. format_annotated_text(monthobj) or "")
end
end
end
local yearobj = parse_annotated_text(year, pname("year"))
local monthobj = parse_annotated_text(month, pname("month"))
local start_yearobj = parse_annotated_text(start_year, pname("start_year"))
local start_monthobj = parse_annotated_text(start_month, pname("start_month"))
if start_yearobj then
local abbr_prefix
abbr_prefix, start_yearobj.text = process_ante_circa_post(start_yearobj.text)
start_yearobj.link = select(2, process_ante_circa_post(start_yearobj.link))
insert(output, abbr_prefix)
elseif yearobj then
local abbr_prefix
abbr_prefix, yearobj.text = process_ante_circa_post(yearobj.text)
yearobj.link = select(2, process_ante_circa_post(yearobj.link))
insert(output, abbr_prefix)
end
if start_date or start_year then
local cur_year = yearobj and yearobj.text or format_date_with_code("Y", date, "date")
local cur_month = monthobj and monthobj.text or date and format_date_with_code("F", date, "date") or nil
local cur_day = date and day_explicitly_given and format_date_with_code("j", date, "date") or nil
local beg_year = start_yearobj and start_yearobj.text or format_date_with_code("Y", start_date, "start_date")
local beg_month = start_monthobj and start_monthobj.text
or start_date and format_date_with_code("F", start_date, "start_date")
or nil
local beg_day = start_date
and start_day_explicitly_given
and format_date_with_code("j", start_date, "start_date")
or nil
if year_last then
if beg_day then
insert(output, beg_day .. " " .. beg_month)
else
insert(output, beg_month)
end
if beg_year ~= cur_year then
insert(output, " " .. beg_year)
end
else
insert(output, format_date_or_year_month(
start_date,
start_yearobj,
start_monthobj,
start_day_explicitly_given,
"start_date"
))
end
if cur_year ~= beg_year then
-- Different years; insert current date in full.
if beg_month or cur_month then
insert(output, dash)
else
insert(output, "–")
end
insert(output, format_date_or_year_month(date, yearobj, monthobj, day_explicitly_given, "date"))
elseif cur_month and cur_month ~= beg_month then
local month_ins = monthobj and format_annotated_text(monthobj) or cur_month
-- Same year but different months; insert current month and (if available) current day.
if cur_day then
insert(output, dash)
if year_last then
insert(output, cur_day .. " " .. month_ins)
else
insert(output, month_ins .. " " .. cur_day)
end
else
if beg_day then
insert(output, dash)
else
insert(output, "–")
end
insert(output, month_ins)
end
elseif cur_day and cur_day ~= beg_day then
-- Same year and month but different days; insert current day.
insert(output, "–")
insert(output, cur_day)
else
-- Same year, month and day; or same year and month, and day not available; or same year, and month and
-- day not available. Do nothing. FIXME: Should we throw an error?
end
if year_last and beg_year == cur_year then
if cur_month then
insert(output, " " .. cur_year)
else
insert(output, " " .. cur_year)
end
end
elseif date or yearobj then
insert(output, format_date_or_year_month(date, yearobj, monthobj, day_explicitly_given, "date"))
elseif not maintenance_line_no_date then
-- Not main quote date. Return nil, caller will handle.
return nil, nil
elseif not getp("nodate") then
local accessdate = getp("accessdate")
if accessdate then
local explicit_day_given = date_has_day_specified(accessdate, "accessdate")
insert(output, format_bold_date(accessdate, explicit_day_given, "accessdate") .. " (truy cập lần cuối)")
else
if mw.title.getCurrentTitle().namespace ~= 10 then
return maintenance_line(maintenance_line_no_date), true
end
return nil, nil
end
end
return ine(concat(output)), nil
end
local function tag_with_cite(txt)
return "<cite>" .. txt .. "</cite>"
end
-- Display the source line of the quote, above the actual quote text. This contains the majority of the logic of this
-- module (formerly contained in {{quote-meta/source}}).
function export.source(args, alias_map, format_as_cite, other_controls)
local tracking_categories = {}
local argslang = args[1] or args.lang
if not argslang then
-- For the moment, only trigger an error on mainspace pages and
-- other pages that are not user pages or pages containing discussions.
-- These are the same pages that appear in the appropriate tracking
-- categories. User and discussion pages have not generally been
-- fixed up to include a language code and so it's more helpful
-- to use a maintenance line than signal an error.
local current_title = mw.title.getCurrentTitle()
if not (current_title.namespace == 10 or page_should_be_ignored(current_title.fullText)) then
require(languages_error_module)(nil, 1)
end
end
-- Given a canonical param, convert it to the original parameter specified by the user (which may have been an
-- alias).
local function alias(param)
return alias_map[param] or param
end
local output, sep = {}
local overrides = other_controls and other_controls.overrides or {}
-- Add text to the output. The text goes into a list, and we concatenate all the list components together at the
-- end. To make it easier to handle comma-separated items, we keep track (in `sep`) of the separator (if any) that
-- needs to be inserted before the next item added. For example, if we're in the "newversion" code (ind ~= ""), and
-- there's no title and no URL, then the first time we add anything after the title, we don't want to add a
-- separating comma because the preceding text will say "republished " or "republished as " or "translated as " or
-- similar. In all- other cases, we do want to add a separating comma. The bare add() function reset the separator
-- to be nothing, while the add_with_sep() function resets the separator to be the value of `next_sep` (defaulting
-- to ", "), so the next time around we do add a comma to separate `text` from the preceding piece of text.
local function add(text)
if sep then
insert(output, sep)
end
insert(output, text)
sep = nil
end
local function add_with_sep(text, next_sep)
add(text)
sep = next_sep or ", "
end
-- FIXME: This is all very over-engineered, which makes it slow and memory-inefficient.
-- Return a function that generates the actual parameter name associated with a base param (e.g. "author", "last").
-- The actual parameter name may have an index added (an empty string for the first set of params, e.g. author=,
-- last=, or a numeric index for further sets of params, e.g. author2=, last2=, etc.).
local function make_get_full_paramname(ind)
return function(param)
return param .. ind
end
end
-- Function to fetch the actual parameter name associated with a base param (see make_get_full_paramname() above).
-- Assigned at various times below by calling make_get_full_paramname(). We do it this way so that we can have
-- wrapper functions that access params and define them only once.
local get_full_paramname
-- Return two values: the value of a parameter given the base param name (which may have a numeric index added),
-- and the parameter name from which the value was fetched (which may be an alias, i.e. you can't necessarily fetch
-- the parameter value from args[] given this name). The base parameter can be a list of such base params, which
-- are checked in turn, or nil, in which case nil is returned.
local function a_with_name(param)
if not param then
return nil
elseif type(param) ~= "table" then
local fullname = get_full_paramname(param)
return args[fullname], alias(fullname)
end
for _, par in ipairs(param) do
local val, fullname = a_with_name(par)
if val then
return val, alias(fullname)
end
end
return nil
end
-- Fetch the value of a parameter given the base param name (which may have a numeric index added). The base
-- parameter can be a list of such base params, which are checked in turn, or nil, in which case nil is returned.
local function a(param)
return (a_with_name(param))
end
-- Identical to a_with_name(param) except that it verifies that no space is present. Should be used for URL's.
local function aurl_with_name(param)
local value, fullname = a_with_name(param)
if value and value:find(" ") and not value:find("%[") then
error(("URL not allowed to contain a space, but saw |%s=%s"):format(fullname, value))
end
return value, fullname
end
-- Identical to a(param) except that it verifies that no space is present. Should be used for URL's.
local function aurl(param)
return (aurl_with_name(param))
end
-- Convenience function to fetch a parameter that may be in a foreign language or text (and may consequently have
-- a language prefix and/or inline modifiers), parse the annotations and convert the result into a formatted string.
-- This is the same as parse_and_format_annotated_text() below but also returns the full param name as the second
-- return value.
local function parse_and_format_annotated_text_with_name(param, tag_text_func, tag_gloss_func)
local val, fullname = a_with_name(param)
local obj = parse_annotated_text(val, fullname)
return format_annotated_text(obj, tag_text_func, tag_gloss_func), fullname
end
-- Convenience function to fetch a parameter that may be in a foreign language or text (and may consequently have
-- a language prefix and/or inline modifiers), parse the modifiers and convert the result into a formatted string.
-- This is a wrapper around parse_annotated_text() and format_annotated_text(). `param` is the base parameter name (see
-- a_with_name()), `tag_text_func` is an optional function to tag the parameter text after all other processing (e.g.
-- wrap in <cite>...</cite> tags), and `tag_gloss_func` is a similar function for the parameter translation/gloss.
local function parse_and_format_annotated_text(param, tag_text_func, tag_gloss_func)
return (parse_and_format_annotated_text_with_name(param, tag_text_func, tag_gloss_func))
end
-- Convenience function to fetch a multivalued parameter that may be in a foreign language or text (and may
-- consequently have a language prefix and/or inline modifiers), parse the modifiers and convert the result into a
-- formatted string. This is the multivalued analog to parse_and_format_annotated_text_with_name() and returns two
-- values, the formatted string and the full name of the parameter fetched. `delimiter` is as in
-- format_multivalued_annotated_text().
local function parse_and_format_multivalued_annotated_text_with_name(param, delimiter, tag_text_func, tag_gloss_func)
local val, fullname = a_with_name(param)
local objs = parse_multivalued_annotated_text(val, fullname)
local num_objs = objs and #objs or 0
return format_multivalued_annotated_text(objs, delimiter, tag_text_func, tag_gloss_func), fullname, num_objs
end
-- Convenience function to fetch a multivalued parameter that may be in a foreign language or text (and may
-- consequently have a language prefix and/or inline modifiers), parse the modifiers and convert the result into a
-- formatted string. This is the multivalued analog to parse_and_format_annotated_text(). `delimiter` is as in
-- format_multivalued_annotated_text().
local function parse_and_format_multivalued_annotated_text(param, delimiter, tag_text_func, tag_gloss_func)
return (parse_and_format_multivalued_annotated_text_with_name(param, delimiter, tag_text_func, tag_gloss_func))
end
-- This determines whether to display "Mary Bloggs, transl." (if there's no author preceding) or "translated by
-- Mary Bloggs" (if there's an author preceding).
local author_outputted = false
-- When formatting as a citation, the priority is to display a name and a date before the book/chapter title
-- this tracks whether or not the author/date has been displayed
local date_outputted, formatted_date, formatted_origdate = false
local function add_date(no_paren)
if not date_outputted then
if no_paren then
sep = ", "
else
sep = " "
end
if formatted_date then
if no_paren then
add(formatted_date)
else
add("(" .. formatted_date .. ")")
end
end
if formatted_origdate then
add(SPACE_LBRAC .. formatted_origdate .. RBRAC)
end
sep = ", "
date_outputted = true
end
end
local function is_anonymous(val)
return val:match("^[Aa]nonymous$") or val:match("^[Aa]non%.?$")
end
-- Add a formatted author (whose values may be specified using `author` or, for compatibility purposes, split
-- among various parameters):
-- * `author` is the value of the author param (e.g. "author", "author2" or "2ndauthor"), and `author_fullname` is
-- the full parameter name holding that value;
-- * `trans_author` is the optional value of the param holding the gloss/translation of the author, and
-- `trans_author_fullname` is the full parameter name holding that value (or nil for no such parameter);
-- * `authorlink` is the value of the authorlink param, which holds the Wikipedia link of the author(s) in `author`,
-- and `authorlink_fullname` is the full parameter name holding that value;
-- * `trans_authorlink` is the optional value of the param holding the Wikipedia link of the gloss/translation of
-- the author, and `trans_authorlink_fullname` is the full parameter name holding that value (or nil for no such
-- parameter);
-- * `first` is the value of the parameter holding the first name of the author, and `first_fullname` is the full
-- parameter name holding that value;
-- * `trans_first` is the value of the corresponding parameter holding the gloss/translation of the first name
-- (e.g. "trans-first"), and `trans_first_fullname` is the full parameter name holding that value (or nil for
-- no such parameter);
-- * `last` is the value of the parameter holding the last name of the author, and `last_fullname` is the full
-- parameter name holding that value;
-- * `trans_last` is the value of the corresponding parameter holding the gloss/translation of the last name
-- (e.g. "trans-last"), and `trans_last_fullname` is the full parameter name holding that value (or nil for
-- no such parameter).
-- * `last_first` if set, when parameters `first` and `last` are used, display the author name as "last, first"
local function add_author(
author,
author_fullname,
trans_author,
trans_author_fullname,
authorlink,
authorlink_fullname,
trans_authorlink,
trans_authorlink_fullname,
first,
first_fullname,
trans_first,
trans_first_fullname,
last,
last_fullname,
trans_last,
trans_last_fullname,
last_first
)
local function make_author_with_url(txt, txtparam, authorlink, authorlink_param)
if authorlink then
if authorlink:find("%[%[") then
error(("Can't specify links in |%s=%s"):format(authorlink_param, authorlink))
end
if txt:find("%[%[") then
error(("Can't specify links in %s=%s"):format(txtparam, txt))
end
return "[[w:" .. authorlink .. "|" .. txt .. "]]"
else
return txt
end
end
local num_authorobjs
if author then
local authorobjs =
parse_multivalued_annotated_text(author, author_fullname, trans_author, trans_author_fullname)
num_authorobjs = #authorobjs
if num_authorobjs == 1 then
if is_anonymous(authorobjs[1].text) then
authorobjs[1].text = "Tác giả khuyết danh"
authorobjs[1].link = "Tác giả khuyết danh"
end
if authorlink then
authorobjs[1].text = make_author_with_url(
authorobjs[1].text,
"|" .. author_fullname,
authorlink,
"|" .. authorlink_fullname
)
authorobjs[1].link = make_author_with_url(
authorobjs[1].link,
"|" .. author_fullname,
authorlink,
"|" .. authorlink_fullname
)
end
if authorobjs[1].gloss and trans_authorlink then
authorobjs[1].gloss = make_author_with_url(
authorobjs[1].gloss,
("<t:...> in |%s"):format(author_fullname),
trans_authorlink,
"|" .. trans_author_fullname
)
end
add(format_multivalued_annotated_text(authorobjs))
elseif trans_authorlink then
error(
(
"Can't specify |%s= along with multiple semicolon-separated entities in |%s=; use the "
.. "<t:...> inline modifier attached to the individual entities and put the link directly "
.. "in the value of the inline modifier"
):format(trans_authorlink_fullname, author_fullname)
)
else
-- Allow an authorlink with multiple authors, e.g. for use with |author=Max Mills; Harvey Mills
-- with |authorlink=Max and Harvey. For this we have to generate the entire text and link it
-- all.
local formatted_text = format_multivalued_annotated_text(authorobjs)
if authorlink then
formatted_text = make_author_with_url(
formatted_text,
"|" .. author_fullname,
authorlink,
"|" .. authorlink_fullname
)
end
add(formatted_text)
end
else
num_authorobjs = 1
-- Author separated into first name + last name. We don't currently support non-Latin-script
-- authors separated this way and probably never will.
if first then
if last_first then
author = last .. ", " .. first
else
author = first .. " " .. last
end
else
author = last
end
if authorlink then
local authorparam = first and ("|%s |%s"):format(first_fullname, last_fullname) or "|" .. last_fullname
author = make_author_with_url(author, authorparam, authorlink, authorlink_fullname)
end
local trans_author
if trans_last then
if trans_first then
trans_author = trans_first .. " " .. trans_last
else
trans_author = trans_last
end
if trans_authorlink then
local trans_authorparam = trans_first
and ("|%s |%s"):format(trans_first_fullname, trans_last_fullname)
or "|" .. trans_last_fullname
trans_author = make_author_with_url(
trans_author,
trans_authorparam,
trans_authorlink,
trans_authorlink_fullname
)
end
end
add(author)
if trans_author then
add(SPACE_LBRAC)
add(trans_author)
add(RBRAC)
end
end
author_outputted = true
return num_authorobjs
end
local function add_authorlike(
param,
prefix_with_preceding_authors,
suffix_without_preceding_authors,
suffix_if_multiple,
anonymous_suffix
)
local delimiter = author_outputted and "và" or ", "
local entities, _, num_entities = parse_and_format_multivalued_annotated_text_with_name(param, delimiter)
if not entities then
return
end
if is_anonymous(entities) then
-- If tlr=anonymous or similar given, display as "anonymous translator" or similar. If a specific
-- anonymous suffix not given, try to derive the anonymous suffix from the non-preceding-author suffix.
if not anonymous_suffix then
local cleaned_suffix = suffix_without_preceding_authors
:gsub(" ", " ")
:gsub(" ", " ")
:gsub(" ", " ")
:gsub("[", "[")
:gsub("]", "]")
cleaned_suffix = mw.text.trim(cleaned_suffix)
if not anonymous_suffix then
anonymous_suffix = " " .. cleaned_suffix:match("^, (.*)$")
end
if not anonymous_suffix then
anonymous_suffix = " " .. cleaned_suffix:match("^%((.*)%)$")
end
if not anonymous_suffix then
anonymous_suffix = " " .. cleaned_suffix:match("^%[(.*)%]$")
end
if not anonymous_suffix then
anonymous_suffix = suffix_without_preceding_authors
end
end
add_with_sep("anonymous" .. anonymous_suffix)
elseif prefix_with_preceding_authors and (author_outputted or not suffix_without_preceding_authors) then
add_with_sep(entities .. prefix_with_preceding_authors)
elseif suffix_if_multiple and num_entities > 1 then
add_with_sep(entities .. suffix_if_multiple)
else
add_with_sep(entities .. suffix_without_preceding_authors)
end
author_outputted = true
end
local function add_authorlabel()
local default_authorlabel = a("default-authorlabel")
if default_authorlabel and yesno(a("authorlabel"), true) then
sep = nil
add_with_sep(" " .. default_authorlabel)
end
end
local function has_new_title_or_author()
return args["2ndauthor"]
or args["2ndlast"]
or args.chapter2
or args.title2
or args.tlr2
or args.mainauthor2
or args.editor2
or args.editors2
or args.compiler2
or args.compilers2
or args.director2
or args.directors2
end
local function has_newversion()
return args.newversion or args.location2 or has_new_title_or_author()
end
-- Handle chapter=, section=, etc. `param` is the base name of the parameter in question, e.g. "chapter" or
-- "section". If numeric (either Arabic or Roman), add `numeric_prefix`; otherwise, parse as textual (allowing for
-- language prefixes, inline modifiers, etc.), prefix with `textual_prefix` (if given) and suffix with
-- `textual_suffix` (if given). Also checks for and handles the following (assuming param == "chapter"):
-- * chapterurl=: URL of the chapter.
-- * trans-chapter=: Chapter translation (can be given using an inline modifier <t:...>).
-- * chapter_number=: Chapter number, when chapter= is also given (otherwise put the chapter number in chapter=).
-- * chapter_plain=: Plain version of the chapter number; the "chapter " prefix isn't added.
-- * chapter_series=: Series that the chapter is within (used e.g. for journal articles part of a series).
-- * chapter_seriesvolume=: Volume of the series (compare seriesvolume=).
--
-- Returns nil if no value specified for the main parameter, otherwise the formatted value.
local function format_chapterlike(param, numeric_prefix, textual_prefix, textual_suffix)
local chap, chap_fullname = a_with_name(param)
local chap_num, chap_num_fullname = a_with_name(param .. "_number")
local chap_plain, chap_plain_fullname = parse_and_format_annotated_text_with_name(param .. "_plain")
if chap_num and chap_plain then
error(("Specify only one of |%s= or %s="):format(chap_num_fullname, chap_plain_fullname))
end
local chap_series, chap_series_fullname =
parse_and_format_annotated_text_with_name(param .. "_series", tag_with_cite, tag_with_cite)
local chap_seriesvolume, chap_seriesvolume_fullname =
parse_and_format_annotated_text_with_name(param .. "_seriesvolume")
if chap_series then
chap_series = ", " .. chap_series
end
if chap_seriesvolume then
if not chap_series then
error(("Cannot specify |%s= without %s="):format(chap_series_fullname, chap_seriesvolume_fullname))
end
chap_series = chap_series .. " (" .. chap_seriesvolume .. ")"
end
local chapterurl
local function make_chapter_with_url(chap)
if chapterurl then
return "[" .. chapterurl .. " " .. chap .. "]"
else
return chap
end
end
if not chap then
if chap_num then
error(
("Cannot specify |%s= without |%s=; put the numeric value in |%s= directly"):format(
chap_num_fullname,
chap_fullname,
chap_fullname
)
)
end
if chap_plain then
chapterurl = aurl(param .. "url")
return make_chapter_with_url(chap_plain .. (chap_series or ""))
end
return nil
end
local cleaned_chap = chap:gsub("<sup>[^<>]*</sup>", ""):gsub("[*+#]", "")
chapterurl = aurl(param .. "url")
local formatted
if numeric_prefix and get_number(cleaned_chap) then
-- Arabic chapter number
formatted = numeric_prefix .. make_chapter_with_url(chap)
elseif
numeric_prefix
and cleaned_chap:match("^[mdclxviMDCLXVI]+$")
and roman_to_arabic(cleaned_chap, true)
and (not overrides[param] or not overrides[param].noroman)
then
-- Roman chapter number
formatted = numeric_prefix .. make_chapter_with_url(upper(chap))
else
-- strip leading ! (used to force text-mode for titles that look like Roman numerals like "mil" and "dill")
if chap:find("^!") then
chap = chap:gsub("^!", "")
end
-- Must be a chapter name
local chapterobj = parse_annotated_text(chap, chap_fullname, a("trans-" .. param))
chapterobj.text = make_chapter_with_url(chapterobj.text)
chapterobj.link = make_chapter_with_url(chapterobj.link)
formatted = (textual_prefix or "") .. format_annotated_text(chapterobj) .. (textual_suffix or "")
end
if chap_num or chap_plain then
-- NOTE: Up above we throw an error if both chap_num and chap_plain are specified.
formatted = formatted .. " (" .. (chap_plain or numeric_prefix .. chap_num) .. ")"
end
if chap_series then
formatted = formatted .. chap_series
end
return formatted
end
-- This handles everything after displaying the author, starting with the chapter and ending with page, column,
-- line and then other=. It is currently called twice: Once to handle the main portion of the citation, and once to
-- handle a "newversion" citation. `ind` is either "" for the main portion or a number (currently only 2) for a
-- "newversion" citation. In a few places we conditionalize on `ind` to take actions depending on its value.
local function postauthor(ind, num_authors, format_as_cite)
get_full_paramname = make_get_full_paramname(ind)
if author_outputted then
add_authorlabel()
end
local coauthors = parse_and_format_multivalued_annotated_text("coauthors", "và")
if coauthors then
local with_prefix = ""
if author_outputted then
with_prefix = "; "
if num_authors == 1 then
sep = ""
end
end
add_with_sep(with_prefix .. coauthors)
author_outputted = true
end
add_authorlike("quotee", " (trích dẫn gốc) ", ", quotee", ", quotees")
if format_as_cite and author_outputted and not date_outputted then
add_date()
sep = ", "
end
add_authorlike("chapter_tlr", " (dịch)", " (dịch)", nil, " translator")
local function add_sg_and_pl_authorlike(noun, verbed)
local sgparam = noun
local plparam = noun .. "s"
local sgval, sgval_fullname = a_with_name(sgparam)
local plval, plval_fullname = a_with_name(plparam)
if sgval and plval then
error(("Can't specify both |%s= and |%s="):format(sgval_fullname, plval_fullname))
end
if sgval or plval then
local verbed_by = " (" .. verbed .. ")"
local comma_sgnoun = " (" .. noun .. ")"
local comma_plnoun = " (" .. noun .. ")"
add_authorlike(sgparam, verbed_by, comma_sgnoun, comma_plnoun)
add_authorlike(plparam, verbed_by, comma_plnoun)
end
end
local formatted_entry = format_chapterlike("entry", nil, "“", "”")
local formatted_chapter = format_chapterlike("chapter", "chương ", "“", "”")
local function add_entry()
if formatted_entry then
add_with_sep(formatted_entry)
if not a("notitle") then
add("trong ")
author_outputted = false
else
author_outputted = true
end
formatted_entry = nil
end
end
local function add_chapter()
add_entry()
if formatted_chapter then
add_with_sep(formatted_chapter)
if not a("notitle") then
add("trong ")
author_outputted = false
end
formatted_chapter = nil
end
end
local function add_actor_role(format_as_cite)
local role = parse_and_format_multivalued_annotated_text("role", "và")
local actor_val, actor_fullname = a_with_name("actor")
local actor_objs = parse_multivalued_annotated_text(actor_val, actor_fullname)
local actor = format_multivalued_annotated_text(actor_objs, "và")
if format_as_cite then
if role then
if actor then
add_with_sep(actor)
end
sep = nil
add_with_sep(" as " .. role)
elseif actor then
add_with_sep(actor .. " (" .. (#actor_objs > 1 and "actors" or "actor") .. ")")
end
else
if role then
add_with_sep("spoken by " .. role)
if actor then
sep = nil
add_with_sep(" (" .. actor .. ")")
end
elseif actor then
add_with_sep(actor .. " (" .. (#actor_objs > 1 and "actors" or "actor") .. ")")
end
end
end
if format_as_cite then
if date_outputted then
add_chapter()
end
local output_len = #output
local mainauthor = parse_and_format_multivalued_annotated_text("mainauthor")
if mainauthor then
add_with_sep(mainauthor)
end
-- quote-* templates display "jobbed by name" after the author, controlled by the author_outputted flag
author_outputted = false
add_authorlike("tlr", " (dịch)", " (dịch)", nil, " translator")
author_outputted = false
add_authorlike("editor", " (biên tập)")
add_authorlike("editors", " (biên tập)")
add_authorlike("compiler", " (biên soạn)")
add_authorlike("compilers", " (biên soạn)")
add_sg_and_pl_authorlike("director", "directed")
add_authorlike("lyricist", nil, " (lời)", nil, " lyricist")
add_authorlike("lyrics-translator", nil, " (translation)", nil, " lyrics translator")
add_authorlike("composer", nil, " (nhạc)", nil, " composer")
add_actor_role("format_as_cite")
-- if the output length has changed, a credit name has been printed
-- and we can print the date
if output_len ~= #output then
author_outputted = true
add_date()
end
add_chapter()
else
add_chapter()
local mainauthor = parse_and_format_multivalued_annotated_text("mainauthor")
if mainauthor then
add_with_sep(mainauthor)
author_outputted = true
end
add_authorlike("tlr", " (dịch)", " (dịch)", nil, " translator")
add_authorlike("editor", " (biên tập)")
add_authorlike("editors", " (biên tập)")
add_sg_and_pl_authorlike("compiler", "compiled")
add_sg_and_pl_authorlike("director", "directed")
add_authorlike("lyricist", nil, " (lời)", nil, " lyricist")
add_authorlike("lyrics-translator", nil, " (translation)", nil, " lyrics translator")
add_authorlike("composer", nil, " (nhạc)", nil, " composer")
end
local title, title_fullname = a_with_name("title")
local need_comma = false
if title then
local titleobj = parse_annotated_text(title, title_fullname, a("trans-title"))
add(format_annotated_text(titleobj, tag_with_cite, tag_with_cite))
local series = parse_and_format_annotated_text("series")
if series then
add(" (" .. series)
local seriesvolume = parse_and_format_annotated_text("seriesvolume")
if seriesvolume then
add(SEMICOLON_SPACE .. seriesvolume)
end
add(")")
end
need_comma = true
elseif ind == "" then
if not a("notitle") then
add(maintenance_line("Vui lòng cung cấp tên cuốn sách hoặc tên tạp chí"))
need_comma = true
end
end
local archiveurl, archiveurl_fullname = aurl_with_name("archiveurl")
local url, url_fullname = aurl_with_name("url")
local urls, urls_fullname = aurl_with_name("urls")
if url and urls then
error(("Supply only one of |%s= and |%s="):format(url_fullname, urls_fullname))
end
local function verify_title_supplied(url_name)
-- There are too many cases of this to throw an error at this time.
-- if not title then
-- error(("If |%s= is given, |%s= must also be supplied"):format(url_name, title_fullname))
-- end
end
if archiveurl or url then
verify_title_supplied(archiveurl and archiveurl_fullname or url_fullname)
sep = nil
add("‎<sup>[" .. (archiveurl or url) .. "]</sup>")
elseif urls then
verify_title_supplied(urls_fullname)
sep = nil
add("‎<sup>" .. urls .. "</sup>")
end
-- display (in Language) if language is provided and is not English and not overriden by termlang or worklang
if format_as_cite and ind == "" and not (args.termlang or args.worklang) and (args[1] or args.lang) then
local lang = get_first_lang(args[1] or args.lang)
if lang then
local langcode = lang:getCode()
if not (langcode == "und" or langcode == "vi") then
local langs = format_langs(args[1] or args.lang)
if langs then
add(" (bằng " .. langs .. ")")
end
end
end
end
if need_comma then
sep = ", "
end
local edition, edition_fullname = parse_and_format_annotated_text_with_name("edition")
local edition_plain, edition_plain_fullname = parse_and_format_annotated_text_with_name("edition_plain")
if edition and edition_plain then
error(("Supply only one of |%s= and |%s="):format(edition_fullname, edition_plain_fullname))
end
if edition then
add_with_sep("ấn bản " .. edition)
end
if edition_plain then
add_with_sep(edition_plain)
end
-- Display a numeric param such as page=, volume=, column=. For each `paramname`, four params are actually
-- recognized, e.g. for paramname == "page", the params page=, pages=, page_plain= and pageurl= are recognized
-- and checked (or the same with an index, e.g. page2=, pages2=, page_plain2= and pageurl2= respectively if
-- ind == "2"). Only one of the first three can be specified; an error results if more than one are given.
-- If none are given, the return value is nil; otherwise it is a string. The numeric spec is taken directly
-- from e.g. page_plain= if given; otherwise if e.g. pages= is given, or if page= is given and looks like a
-- combination of numbers (i.e. it has a hyphen or dash in it, a comma, or the word " and "), it is prefixed
-- by `singular_desc` + "s" (e.g. "pages "), otherwise it is prefixed by just `singular_desc` (e.g. "page ").
-- (As a special case, if either e.g. page=unnumbered or pages=unnumbered is given, the numeric spec is
-- "unnumbered page".) The resulting spec is returned directly unless e.g. pageurl= is given, in which case
-- it is linked to the specified URL. Note that any of the specs can be foreign text, e.g. foreign numbers
-- (including with optional inline modifiers), and such text is handled appropriately.
local function format_numeric_param(paramname, singular_desc)
local sgval = a_with_name(paramname)
local sgobj = parse_annotated_text(sgval, paramname)
local plparamname = paramname .. "s"
local plval = a_with_name(plparamname)
local plobj = parse_annotated_text(plval, plparamname)
local plainval, plain_fullname = parse_and_format_annotated_text_with_name(paramname .. "_plain")
local numspec
if not sgval and not plval and not plainval then
return
elseif plainval and (sgval or plval) then
error(("Can't specify " .. plain_fullname .. " with " .. paramname .. " or " .. plparamname))
elseif sgval and plval then
-- if both singular and plural, display "page 1 of 1-10"
numspec = singular_desc .. " " .. sgval .. " của " .. plval
else
-- Merge page= and pages= and treat alike because people often mix them up in both directions.
if plainval then
numspec = plainval
else
local val = sgobj and sgobj.text or plobj.text
if val == "unnumbered" then
numspec = "unnumbered " .. singular_desc
else
local desc
if val:find("^!") then
val = val:gsub("^!", "")
desc = sgval and singular_desc or pluralize(singular_desc)
else
local check_val = val
if check_val:find("%[") then
check_val = remove_links(check_val)
-- convert URL's of the form [URL DISPLAY] to the displayed value
check_val = check_val:gsub("%[[^ %[%]]* ([^%[%]]*)%]", "%1")
end
-- in case of negative page numbers (do they exist?), don't treat as multiple pages
check_val = check_val:gsub("^%-", "")
-- replace HTML entity en-dashes and em-dashes with their literal codes
check_val = check_val:gsub("–", "–")
check_val = check_val:gsub("–", "–")
check_val = check_val:gsub("—", "—")
check_val = check_val:gsub("—", "—")
-- Check for en-dash or em-dash, or two numbers (possibly with stuff after like 12a-15b)
-- separated by a hyphen or by comma a followed by a space (to avoid firing on thousands separators).
if
umatch(check_val, "[–—]")
or check_val:find(" and ")
or check_val:match("%d+[^ ]* *%- *%d+")
or check_val:match("%d+[^ ]* *, +%d+")
then
desc = singular_desc
else
desc = singular_desc
end
end
local obj = sgobj or plobj
obj.text = val
if obj.link:find("^!") then
obj.link = obj.link:gsub("^!", "")
end
val = format_annotated_text(obj)
numspec = desc .. " " .. val
end
end
end
local url = a(paramname .. "url")
if url then
return "[" .. url .. " " .. numspec .. "]"
else
return numspec
end
end
local volume = format_numeric_param("volume", a("volume_prefix") or "tập")
if volume then
add_with_sep(volume)
end
local issue = format_numeric_param("issue", a("issue_prefix") or "số")
if issue then
add_with_sep(issue)
end
-- number= is an alias for issue= (except in {{quote-av}}, where it is the episode number)
local number = format_numeric_param("number", a("number_prefix") or "số")
if number then
add_with_sep(number)
end
local annotations = {}
local genre = a("genre")
if genre then
insert(annotations, genre)
end
local format = a("format")
if format then
insert(annotations, format)
end
local medium = a("medium")
if medium then
insert(annotations, medium)
end
-- Now handle the display of language annotations like "(in French)" or
-- "(quotation in Nauruan; overall work in German)".
local quotelang = args[1] or args.lang
if not quotelang then
if ind == "" then
-- This can only happen for certain non-mainspace pages, e.g. Talk pages; otherwise an error is thrown
-- above.
insert(annotations, maintenance_line("Please specify the language of the quote using |1="))
else
-- do nothing in newversion= portion
end
elseif ind == "" then
local worklang = a("worklang")
local termlang = a("termlang")
worklang = worklang or quotelang
termlang = termlang or quotelang
if worklang == quotelang then
if worklang == termlang then
-- do nothing
else
insert(annotations, "bằng " .. format_langs(quotelang))
end
else
if quotelang ~= termlang then
insert(annotations, "quotation in " .. format_langs(quotelang))
end
insert(annotations, "toàn bộ nội dung viết bằng " .. format_langs(worklang))
end
else
local lang2 = a("lang2")
if lang2 then
insert(annotations, "bằng " .. format_langs(lang2))
end
end
if #annotations > 0 then
sep = nil
add_with_sep(" (" .. concat(annotations, SEMICOLON_SPACE) .. ")")
end
local artist = parse_and_format_multivalued_annotated_text("artist", "và")
if artist then
add_with_sep(artist .. " biểu diễn")
end
local feat = parse_and_format_multivalued_annotated_text("feat", "và")
if feat then
sep = " "
add_with_sep("ft. " .. feat)
end
if not format_as_cite then
add_actor_role()
end
local others = parse_and_format_annotated_text("others")
if others then
add_with_sep(others)
end
local quoted_in = parse_and_format_annotated_text("quoted_in", tag_with_cite, tag_with_cite)
if quoted_in then
add_with_sep("dẫn trong " .. quoted_in)
insert(tracking_categories, "Quotations using quoted-in parameter")
end
local location = parse_and_format_multivalued_annotated_text("location", "; ")
local publisher = parse_and_format_multivalued_annotated_text("publisher", "; ")
if publisher then
if location then
add_with_sep(location) -- colon
sep = ": " -- colon
end
add_with_sep(publisher)
elseif location then
add_with_sep(location)
end
if not date_outputted then
add_date("no_paren")
end
local source = parse_and_format_multivalued_annotated_text("source", "và")
if source then
add_with_sep("sourced from " .. source)
end
local original = parse_and_format_annotated_text("original", tag_with_cite, tag_with_cite)
local by = parse_and_format_multivalued_annotated_text("by", "và")
local origtype = a("deriv") or "bản dịch"
if original or by then
add_with_sep(origtype .. " cho " .. (original or "bản gốc") .. (by and " của " .. by or ""))
end
-- Handle origlang=, origworklang=. How we handle them depends on whether the original title or author are explicitly
-- given.
local origlang = a("origlang")
local origworklang = a("origworklang")
local origlangtext, origworklangtext
if origlang then
origlangtext = "từ " .. format_langs(origlang)
end
if origworklang then
origworklangtext = "toàn bộ nội dung viết bằng " .. format_langs(origworklang)
end
if origlang or origworklang then
if original or by then
local orig_annotations = {}
if origlangtext then
insert(orig_annotations, origlangtext)
end
if origworklangtext then
insert(orig_annotations, origworklangtext)
end
sep = nil
add_with_sep(" (" .. concat(orig_annotations, SEMICOLON_SPACE) .. ")")
else
add_with_sep(origtype .. " có nguồn gốc" .. (origlangtext and " " .. origlangtext or ""))
if origworklangtext then
sep = nil
add_with_sep(" (" .. origworklangtext .. ")")
end
end
end
if ind ~= "" and has_newversion() then
local formatted_new_date = format_date_args(a, get_full_paramname, alias_map, "", "", nil, "Please provide a date or year", true)
if formatted_new_date then
add_with_sep(formatted_new_date)
end
end
-- Fetch date_published=/year_published=/month_published= and format appropriately.
local formatted_date_published = format_date_args(a, get_full_paramname, alias_map, "", "_published", nil, nil, true)
local platform = parse_and_format_multivalued_annotated_text("platform", "và")
if formatted_date_published then
add_with_sep("xuất bản " .. formatted_date_published .. (platform and " thông qua " .. platform or ""))
elseif platform then
add_with_sep("thông qua " .. platform)
end
-- From here on out, there should always be a preceding item, so we
-- can dispense with add_with_sep() and always insert the comma.
sep = nil
local function small(txt)
add(", <small>")
add(txt)
add("</small>")
end
-- Add an identifier to a book or article database such as DOI, ISBN, JSTOR, etc. `param_or_params`
-- is a string identifying the base param, or a list of such strings to check in turn. If found, the value
-- of the parameter is processed using `process` (a function of one argument, defaulting to mw.uri.encode()),
-- and then the actual URL to insert is generated by preceding with `pretext`, following with `posttext`,
-- and running the resulting string through small(), which first adds a comma and then the URL in small font.
local function add_identifier(param_or_params, pretext, posttext, process)
local val = a(param_or_params)
if val then
val = (process or mw.uri.encode)(val)
small(pretext .. val .. posttext)
end
end
add_identifier("bibcode", "[https://adsabs.harvard.edu/abs/", " →Bibcode]")
add_identifier("doi", '<span class="neverexpand">[https://doi.org/', " →DOI]</span>")
add_identifier("isbn", "", "", isbn)
add_identifier("issn", "", "", issn)
add_identifier("jstor", "[https://www.jstor.org/stable/", " →JSTOR]")
add_identifier("lccn", "", "", lccn)
add_identifier("oclc", "[https://search.worldcat.org/title/", " →OCLC]")
add_identifier("ol", "[https://openlibrary.org/works/OL", "/ →OL]")
add_identifier("pmid", "[https://www.ncbi.nlm.nih.gov/pubmed/", " →PMID]")
add_identifier("pmcid", "[https://www.ncbi.nlm.nih.gov/pmc/articles/", "/ →PMCID]")
add_identifier("ssrn", "[https://ssrn.com/abstract=", " →SSRN]")
-- add_identifier("urn", "", "", urn)
local id = a("id")
if id then
small(id)
end
archiveurl, archiveurl_fullname = aurl_with_name("archiveurl")
if archiveurl then
add(", [" .. url .. " bản gốc]")
local url, url_fullname = aurl_with_name("url")
if not url then
-- attempt to infer original URL from archive URL; this works at
-- least for Wayback Machine (web.archive.org) URL's
url = archiveurl:match("/(https?:.*)$")
if not url then
error(
("When |%s= is specified, |%s= must also be included"):format(archiveurl_fullname, url_fullname)
)
end
end
add(" lưu trữ ")
local archivedate, archivedate_fullname = a_with_name("archivedate")
if archivedate then
add(format_date(archivedate))
elseif string.sub(archiveurl, 1, 28) == "https://web.archive.org/web/" then
-- If the archive is from the Wayback Machine, then it already contains the date
-- Get the date and format it
local wayback_date = string.sub(archiveurl, 29, 29 + 7)
wayback_date = string.sub(wayback_date, 1, 4)
.. "-"
.. string.sub(wayback_date, 5, 6)
.. "-"
.. string.sub(wayback_date, 7, 8)
add(format_date(wayback_date))
else
error(
("When |%s= is specified, |%s= must also be included"):format(
archiveurl_fullname,
archivedate_fullname
)
)
end
end
if a("accessdate") then
--Otherwise do not display here, as already used as a fallback for missing date= or year= earlier.
if (a("date") or a("nodate") or a("year")) and not a("archivedate") then
add(", truy cập " .. format_date(a("accessdate")))
end
end
local formatted_section = format_chapterlike("section", "mục ")
if formatted_section then
add(", ")
add(formatted_section)
end
-- video game stuff
local system = parse_and_format_annotated_text("system")
if system then
add(", " .. system)
end
local scene = parse_and_format_annotated_text("scene")
if scene then
add(", scene: " .. scene)
end
local level = parse_and_format_annotated_text("level")
if level then
add(", level/area: " .. level)
end
local note = parse_and_format_annotated_text("note")
if note then
add(", " .. note)
end
local note_plain = parse_and_format_annotated_text("note_plain")
if note_plain then
add(" " .. note_plain)
end
-- Wrapper around format_numeric_param that inserts the formatted text with optional preceding text.
local function handle_numeric_param(paramname, singular_desc, pretext)
local numspec = format_numeric_param(paramname, singular_desc)
if numspec then
add((pretext or "") .. numspec)
end
end
handle_numeric_param("page", a("page_prefix") or "tr.", ", ")
handle_numeric_param("column", a("column_prefix") or "cột", ", ")
handle_numeric_param("line", a("line_prefix") or "dòng", ", ")
-- FIXME: Does this make sense? What is other=?
local other = parse_and_format_annotated_text("other")
if other then
add(", " .. other)
end
end
local function add_authors(args, last_first)
-- Find maximum indexed author or last name.
local maxind = math.max(args.author.maxindex, args.last.maxindex)
-- Include max index of ancillary params so we get an error message about their use without the primary params.
local ancillary_params =
{"trans-author", "authorlink", "trans-authorlink", "first", "trans-first", "trans-last"}
for _, ancillary in ipairs(ancillary_params) do
maxind = math.max(maxind, args[ancillary].maxindex)
end
local num_authors = 0
for i = 1, maxind do
local ind = i == 1 and "" or i
local author, last = args.author[i], args.last[i]
if author or last then
local this_num_authors = add_author(
author,
"author" .. ind,
args["trans-author"][i],
"trans-author" .. ind,
args.authorlink[i],
"authorlink" .. ind,
args["trans-authorlink"][i],
"trans-authorlink" .. ind,
args.first[i],
"first" .. ind,
args["trans-first"][i],
"trans-first" .. ind,
last,
"last" .. ind,
args["trans-last"][i],
"trans-last" .. ind,
last_first
)
num_authors = num_authors + this_num_authors
sep = last_first and "; " or ", "
else
for _, cant_have in ipairs(ancillary_params) do
if args[cant_have][i] then
error(("Can't have |%s%s= without |author%s= or |last%s="):format(cant_have, ind, ind, ind))
end
end
end
end
return num_authors
end
local function add_newversion()
-- If there's a "newversion" section, add the new-version text.
if has_newversion() then
sep = nil
--Test for new version of work.
add(SEMICOLON_SPACE)
if args.newversion then -- newversion= is intended for English text, e.g. "quoted in" or "republished as".
add(args.newversion)
elseif not args.edition2 then
if has_new_title_or_author() then
add("tái bản: ")
else
add("republished")
end
end
add(" ")
return ""
else
return ", "
end
end
------------------- Now we start outputting text ----------------------
local need_comma = false
-- Set this now so a() works just below.
get_full_paramname = make_get_full_paramname("")
if args.brackets then
add("[")
end
bold_year = not format_as_cite
year_last = format_as_cite
formatted_date, need_date = format_date_args(
a,
get_full_paramname,
alias_map,
nil,
nil,
bold_year,
"Vui lòng thêm [[:Thể loại:Yêu cầu ngày tháng|ngày tháng]] cho trích dẫn",
year_last
)
-- Fetch origdate=/origyear=/origmonth= and format appropriately.
formatted_origdate = format_date_args(a, get_full_paramname, alias_map, "orig", nil, nil, nil, year_last)
local num_authors, need_date
if format_as_cite then
num_authors = add_authors(args, "last_first")
if author_outputted then
sep = " "
end
-- Display all the text that comes after the author, for the main portion.
postauthor("", num_authors, "format_as_cite")
author_outputted = false
sep = add_newversion()
-- Add the newversion author(s).
if args["2ndauthor"] or args["2ndlast"] then
num_authors = add_author(
args["2ndauthor"],
"2ndauthor",
nil,
nil,
args["2ndauthorlink"],
"2ndauthorlink",
nil,
nil,
args["2ndfirst"],
"2ndfirst",
nil,
nil,
args["2ndlast"],
"2ndlast",
nil,
nil,
"last_first"
)
sep = ", "
else
for _, cant_have in ipairs{"2ndauthorlink", "2ndfirst"} do
if args[cant_have] then
error(("Can't have |%s= without |2ndauthor= or |2ndlast="):format(cant_have))
end
end
end
-- Display all the text that comes after the author, for the "newversion" section.
postauthor(2, num_authors, "format_as_cite")
else
if formatted_date then
need_comma = true
add(formatted_date)
end
if formatted_origdate then
need_comma = true
add(SPACE_LBRAC .. formatted_origdate .. RBRAC)
end
if need_comma then
sep = ", "
end
date_outputted = true
num_authors = add_authors(args)
-- Display all the text that comes after the author, for the main portion.
postauthor("", num_authors)
author_outputted = false
sep = add_newversion()
-- Add the newversion author(s).
if args["2ndauthor"] or args["2ndlast"] then
num_authors = add_author(
args["2ndauthor"],
"2ndauthor",
nil,
nil,
args["2ndauthorlink"],
"2ndauthorlink",
nil,
nil,
args["2ndfirst"],
"2ndfirst",
nil,
nil,
args["2ndlast"],
"2ndlast",
nil,
nil
)
sep = ", "
else
for _, cant_have in ipairs{"2ndauthorlink", "2ndfirst"} do
if args[cant_have] then
error(("Can't have |%s= without |2ndauthor= or |2ndlast="):format(cant_have))
end
end
end
-- Display all the text that comes after the author, for the "newversion" section.
postauthor(2, num_authors)
end
if not args.nocolon then
sep = nil
add(":")
elseif args.usenodot and not args.nodot then
add(".")
end
-- Concatenate output portions to form output text.
local output_text = concat(output)
-- Remainder of code handles adding categories. We add one or more of the following categories:
--
-- 1. [[Category:LANG terms with quotations]], based on the first language code in termlang= or 1=. Added to
-- mainspace, Reconstruction: and Appendix: pages as well as Citations: pages if the corresponding mainspace
-- page exists. Not added if nocat= is given. Note that [[Module:usex]] adds the same category using the same
-- logic, but we do it here too because we may not have a quotation to format. (We add in those circumstances
-- because typically when there's no quotation to format, it's because it's formatted manually underneath the
-- citation, or using {{ja-x}}, {{th-x}} or similar.)
-- 2. [[Category:Requests for date in LANG entries]], based on the first language code in 1=. Added to mainspace,
-- Reconstruction:, Appendix: and Citations: pages unless nocat= is given.
-- 3. [[Category:Quotations using nocat parameter]], if nocat= is given. Added to mainspace, Reconstruction:,
-- Appendix: and Citations: pages.
local categories = {}
local termlang = get_first_lang(args.termlang or argslang)
if args.nocat then
if format_as_cite then
insert(tracking_categories, "Citations using nocat parameter")
else
insert(tracking_categories, "Quotations using nocat parameter")
end
else
-- don't create language tracking categories for citations
if not format_as_cite then
local title
if args.pagename then -- for testing, doc pages, etc.
title = mw.title.new(args.pagename)
if not title then
error(("Bad value for `args.pagename`: '%s'"):format(args.pagename))
end
else
title = mw.title.getCurrentTitle()
end
-- Only add [[Citations:foo]] to [[:Category:LANG terms with quotations]] if [[foo]] exists.
local ok_to_add_cat
if title.nsText ~= "Citations" then
ok_to_add_cat = true
else
local mainspace_title = mw.title.new(title.text)
if mainspace_title and mainspace_title.exists then
ok_to_add_cat = true
end
end
if ok_to_add_cat then
insert(categories, termlang:getFullName() .. " terms with quotations")
end
end
if need_date then
local argslangobj = get_first_lang(argslang)
insert(categories, "Requests for date in " .. argslangobj:getCanonicalName() .. " entries")
end
end
return output_text .. (
not lang and "" or
(#categories > 0 and format_categories(categories, lang, args.sort) or "") .. (
#tracking_categories > 0
and format_categories(
tracking_categories,
lang,
args.sort,
nil,
not page_should_be_ignored(mw.title.getCurrentTitle().fullText)
)
or ""
)
)
end
-- Alias specs for type= and type2=. Each spec is `{canon, aliases, with_newversion}` where `canon` is the canonical
-- parameter (with "2" added if type2= is being handled), `aliases` is a comma-separated string of aliases (with "2"
-- added if type2= is being handled, except for numeric params), and `with_newversion` indicates whether we should
-- process this spec if type2= is being handled.
local type_alias_specs = {
av = {
{"author", "writer,writers", true},
{"chapter", "episode", true},
{"chapterurl", "episodeurl", true},
{"trans-chapter", "trans-episode", true},
{"chapter_tlr", "episode_tlr,episode_tlrs,episode_translator,episode_translators", true},
{"chapter_series", "episode_series", true},
{"chapter_seriesvolume", "episode_seriesvolume", true},
{"chapter_number", "episode_number", true},
{"chapter_plain", "episode_plain", true},
{"volume", "season", true},
{"volumes", "seasons", true},
{"volume_plain", "season_plain", true},
{"volumeurl", "seasonurl", true},
{"platform", "network", true},
},
book = {
{"author", "3"},
{"title", "4"},
{"url", "5"},
{"year", "2"},
{"page", "6"},
{"text", "7"},
{"t", "8"},
},
journal = {
{"year", "2"},
{"author", "3"},
{"chapter", "title,article,4", true},
{"chapterurl", "titleurl,articleurl", true},
{"trans-chapter", "trans-title,trans-article", true},
{"chapter_tlr", "title_tlr,title_tlrs,title_translator,title_translators,article_tlr,article_tlrs,article_translator,article_translators", true},
{"chapter_series", "title_series,article_series", true},
{"chapter_seriesvolume", "title_seriesvolume,article_seriesvolume", true},
{"chapter_number", "title_number,article_number", true},
{"chapter_plain", "title_plain,article_plain", true},
{"title", "journal,magazine,newspaper,work,5", true},
{"trans-title", "trans-journal,trans-magazine,trans-newspaper,trans-work", true},
{"tlr", "journal_tlr,journal_tlrs,journal_translator,journal_translators,magazine_tlr,magazine_tlrs,magazine_translator,magazine_translators,newspaper_tlr,newspaper_tlrs,newspaper_translator,newspaper_translators,work_tlr,work_tlrs,work_translator,work_translators", true},
{"url", "6,journalurl,magazineurl,newspaperurl,workurl", true},
{"page", "7"},
{"source", "newsagency,news_agency", true},
{"text", "8"},
{"t", "9"},
},
}
-- Process interally-handled aliases related to type= or type2=. `args` is a table of arguments; `typ` is the value of
-- type= or type2=; newversion=true if we're dealing with type2=; alias_map is used to keep track of alias mappings
-- seen.
local function process_type_aliases(args, typ, newversion, alias_map)
local ind = newversion and "2" or ""
local deprecated = ine(args.lang)
if not type_alias_specs[typ] then
local possible_values = {}
for possible, _ in pairs(type_alias_specs) do
insert(possible_values, possible)
end
sort(possible_values)
error(
("Unrecognized value '%s' for type%s=; possible values are %s"):format(
typ,
ind,
concat(possible_values, ",")
)
)
end
for _, alias_spec in ipairs(type_alias_specs[typ]) do
local canon, aliases, with_newversion = unpack(alias_spec)
if with_newversion or not newversion then
canon = canon .. ind
aliases = split(aliases, ",", true)
local saw_alias = nil
for _, alias in ipairs(aliases) do
if alias:match("^%d+$") then
alias = tonumber(alias)
if deprecated then
alias = alias - 1
end
else
alias = alias .. ind
end
if args[alias] then
if saw_alias == nil then
saw_alias = alias
else
error(("|%s= and |%s= are aliases; cannot specify a value for both"):format(saw_alias, alias))
end
end
end
if saw_alias and (not newversion or type(saw_alias) == "string") then
if args[canon] then
error(("|%s= is an alias of |%s=; cannot specify a value for both"):format(saw_alias, canon))
end
args[canon] = args[saw_alias]
-- Wipe out the original after copying. This is important in case of a param that has general significance
-- but has been redefined (e.g. {{quote-av}} redefines number= for the episode number, and
-- {{quote-journal}} redefines title= for the chapter= (article). It's also important due to unhandled
-- parameter checking.
args[saw_alias] = nil
alias_map[canon] = saw_alias
end
end
end
end
-- Clone and combine frame's and parent's args while also assigning nil to empty strings. Handle aliases and ignores.
local function clone_args(direct_args, parent_args)
local args = {}
-- Processing parent args must come first so that direct args override parent args. Note that if a direct arg is
-- specified but is blank, it will still override the parent arg (with nil).
for pname, param in pairs(parent_args) do
-- [[Special:WhatLinksHere/Wiktionary:Tracking/quote/param/PARAM]]
track("param/" .. pname)
args[pname] = ine(param)
end
-- Process ignores. The value of `ignore` is a comma-separated list of parameter names to ignore (erase). We need to
-- do this before aliases due to {{quote-song}}, which sets chapter= to the value of title= in the direct params and
-- sets title= to the value of album= using an alias. If we do the ignores after aliases, we get an error during alias
-- processing, saying that title= and its alias album= are both present.
local ignores = ine(direct_args.ignore)
if ignores then
for ignore in gsplit(ignores, "%s*,%s*") do
args[ignore] = nil
end
end
local alias_map = {}
local other_controls = {}
-- noroman
local noroman = ine(direct_args.noroman)
if noroman then
other_controls.overrides = other_controls.overrides or {}
for param in gsplit(noroman, "%s*,%s*") do
other_controls.overrides[param] = (other_controls.overrides[param] or {})
other_controls.overrides[param].noroman = true
end
end
-- Process internally-specified aliases using type= or type2=.
local typ = args.type or direct_args.type
if typ then
process_type_aliases(args, typ, false, alias_map)
end
local typ2 = args.type2 or direct_args.type2
if typ2 then
process_type_aliases(args, typ2, true, alias_map)
end
-- Process externally-specified aliases. The value of `alias` is a list of semicolon-separated specs, each of which
-- is of the form DEST:SOURCE,SOURCE,... where DEST is the canonical name of a parameter and SOURCE refers to an
-- alias. Whitespace is allowed between all delimiters. The order of aliases may be important. For example, for
-- {{quote-journal}}, title= contains the article name and is an alias of underlying chapter=, while journal= or
-- work= contains the journal name and is an alias of underlying title=. As a result, the title -> chapter alias
-- must be specified before the journal/work -> title alias.
--
-- Whenever we copy a value from argument SOURCE to argument DEST, we record an entry for the pair in alias_map, so
-- that when we would display an error message about DEST, we display SOURCE instead.
--
-- Do alias processing (and ignore and error_if processing) before processing direct_args so that e.g. we can set up
-- an alias of title -> chapter and then set title= to something else in the direct args ({{quote-hansard}} does
-- this).
--
-- FIXME: Delete this once we've converted all alias processing to internal.
local aliases = ine(direct_args.alias)
if aliases then
-- Allow and discard a trailing semicolon, to make managing multiple aliases easier.
aliases = ugsub(aliases, "%s*;$", "")
for alias_spec in gsplit(aliases, "%s*;%s*") do
local alias_spec_parts = split(alias_spec, "%s*:%s*")
if #alias_spec_parts ~= 2 then
error(("Alias spec '%s' should have one colon in it"):format(alias_spec))
end
local dest, sources = unpack(alias_spec_parts)
sources = split(sources, "%s*,%s*")
local saw_source = nil
for _, source in ipairs(sources) do
if source:match("^%d+$") then
source = tonumber(source)
end
if args[source] then
if saw_source == nil then
saw_source = source
else
error(("|%s= and |%s= are aliases; cannot specify a value for both"):format(saw_source, source))
end
end
end
if saw_source then
if args[dest] then
error(("|%s= is an alias of |%s=; cannot specify a value for both"):format(saw_source, dest))
end
args[dest] = args[saw_source]
-- Wipe out the original after copying. This important in case of a param that has general significance
-- but has been redefined (e.g. {{quote-av}} redefines number= for the episode number, and
-- {{quote-journal}} redefines title= for the chapter= (article). It's also important due to unhandled
-- parameter checking.
args[saw_source] = nil
alias_map[dest] = saw_source
end
end
end
-- Process error_if. The value of `error_if` is a comma-separated list of parameter names to throw an error if seen
-- in parent_args (they are params we overwrite in the direct args).
local error_ifs = ine(direct_args.error_if)
if error_ifs then
for error_if in gsplit(error_ifs, "%s*,%s*") do
if ine(parent_args[error_if]) then
error(
("Cannot specify a value |%s=%s as it would be overwritten or ignored"):format(
error_if,
ine(parent_args[error_if])
)
)
end
end
end
for pname, param in pairs(direct_args) do
-- ignore control params
if pname ~= "ignore" and pname ~= "alias" and pname ~= "error_if" and pname ~= "noroman" then
args[pname] = ine(param)
end
end
return args, alias_map, other_controls
end
local function get_args(frame_args, parent_args, require_lang)
-- FIXME: We are processing arguments twice, once in clone_args() and then again in [[Module:parameters]]. This is
-- wasteful of memory.
local cloned_args, alias_map, other_controls = clone_args(frame_args, parent_args)
local deprecated = ine(parent_args.lang)
local alias_of_t = {alias_of = "t"}
local boolean = {type = "boolean"}
local language_sublist = {type = "language", sublist = true}
local list_allow_holes = {list = true, allow_holes = true}
local script = {type = "script"}
-- First, the "single" params that don't have FOO2 or FOOn versions.
local params = {
[deprecated and "lang" or 1] = {required = require_lang, type = "language", sublist = true, default = "und"},
["lang2"] = language_sublist,
["newversion"] = true,
["author"] = list_allow_holes,
["2ndauthor"] = true,
["trans-author"] = list_allow_holes,
["authorlink"] = list_allow_holes,
["2ndauthorlink"] = true,
["trans-authorlink"] = list_allow_holes,
["first"] = list_allow_holes,
["2ndfirst"] = true,
["trans-first"] = list_allow_holes,
["last"] = list_allow_holes,
["2ndlast"] = true,
["trans-last"] = list_allow_holes,
["nocat"] = boolean,
["nocolon"] = boolean,
-- quote params
text = true,
passage = {alias_of = "text"},
tr = true,
transliteration = {alias_of = "tr"},
ts = true,
transcription = {alias_of = "ts"},
norm = true,
normalization = {alias_of = "norm"},
sc = script,
normsc = script,
sort = true,
subst = true,
footer = true,
lit = true,
t = true,
translation = alias_of_t,
gloss = alias_of_t,
lb = true,
brackets = boolean,
-- original quote params
origtext = true,
origtr = true,
origts = true,
orignorm = true,
origsc = script,
orignormsc = script,
origsubst = true,
origlb = true,
usenodot = boolean,
nodot = boolean,
inline = boolean,
asquote = boolean,
ascite = boolean,
}
-- Most params have PARAM2 variants for use with `newversion`. FIXME: We should generalize this to
-- allow PARAMN variants for any N.
local function add_with_2(param, value)
params[param] = value
params[param .. "2"] = value
end
local function alias_with_2(alias, canon)
params[alias] = {alias_of = canon}
params[alias .. "2"] = {alias_of = canon .. "2"}
end
for _, param12 in ipairs{
"worklang",
"termlang",
"origlang",
"origworklang"
} do
add_with_2(param12, language_sublist)
end
-- Then the newversion params (which have FOO2 versions).
for _, param12 in ipairs{
-- author-like params; author params themselves are either list params (author=, last=, etc.) or single params
-- (2ndauthor=, 2ndlast=, etc.)
"coauthors",
"quotee",
"tlr",
"editor",
"editors",
"mainauthor",
"compiler",
"compilers",
"director",
"directors",
"lyricist",
"lyrics-translator",
"composer",
"role",
"actor",
"artist",
"feat",
-- author control params
"default-authorlabel",
"authorlabel",
-- title
"title",
"trans-title",
"series",
"seriesvolume",
"notitle",
-- entry
"entry",
"entryurl",
"trans-entry",
-- chapter
"chapter",
"chapterurl",
"chapter_number",
"chapter_plain",
"chapter_series",
"chapter_seriesvolume",
"trans-chapter",
"chapter_tlr",
-- section
"section",
"sectionurl",
"section_number",
"section_plain",
"section_series",
"section_seriesvolume",
"trans-section",
-- other video-game params
"system",
"scene",
"level",
-- URL
"url",
"urls",
"archiveurl",
-- edition
"edition",
"edition_plain",
-- ID params
"bibcode",
"doi",
"isbn",
"issn",
"jstor",
"lccn",
"oclc",
"ol",
"pmid",
"pmcid",
"ssrn",
"urn",
"id",
-- misc date params; most date params handled below
"archivedate",
"accessdate",
"nodate",
-- numeric params handled below
-- other params
"type",
"genre",
"format",
"medium",
"others",
"quoted_in",
"location",
"publisher",
"original",
"by",
"deriv",
"note",
"note_plain",
"other",
"source",
"platform",
} do
add_with_2(param12, true)
end
-- Then the aliases of newversion params (which have FOO2 versions).
for _, param12_aliased in ipairs{
{"role", "roles"},
{"role", "speaker"},
{"tlr", "tlrs"},
{"tlr", "translator"},
{"tlr", "translators"},
{"chapter_tlr", "chapter_tlrs"},
{"chapter_tlr", "chapter_translator"},
{"chapter_tlr", "chapter_translators"},
{"doi", "DOI"},
{"isbn", "ISBN"},
{"issn", "ISSN"},
{"jstor", "JSTOR"},
{"lccn", "LCCN"},
{"oclc", "OCLC"},
{"ol", "OL"},
{"pmid", "PMID"},
{"pmcid", "PMCID"},
{"ssrn", "SSRN"},
{"urn", "URN"},
} do
local canon, alias = unpack(param12_aliased)
alias_with_2(alias, canon)
end
-- Then the date params.
for _, datelike in ipairs{{"", ""}, {"orig", ""}, {"", "_published"}} do
local pref, suf = unpack(datelike)
for _, arg in ipairs{"date", "year", "month", "start_date", "start_year", "start_month"} do
add_with_2(pref .. arg .. suf, true)
end
end
local numeric_param_suffixes = {"", "s", "_plain", "url", "_prefix"}
-- Then the numeric params.
for _, numeric in ipairs{"volume", "issue", "number", "line", "page", "column"} do
for _, suf in ipairs(numeric_param_suffixes) do
add_with_2(numeric .. suf, true)
end
end
-- And the aliases of numeric params.
for _, numeric_aliased in ipairs{{"volume", "vol"}} do
local canon, alias = unpack(numeric_aliased)
for _, suf in ipairs(numeric_param_suffixes) do
alias_with_2(alias .. suf, canon .. suf)
end
end
return process_params(cloned_args, params), alias_map, other_controls
end
local function get_origtext_params(args)
local origtext, origtextlang, origsc, orignormsc
if args.origtext then
-- Wiktionary language codes have at least two lowercase letters followed possibly by lowercase letters and/or
-- hyphens (there are more restrictions but this is close enough). Also check for nonstandard Latin etymology
-- language codes (e.g. VL. or LL.). (There used to be more nonstandard codes but they have all been
-- eliminated.)
origtextlang, origtext = args.origtext:match("^(%l%l[%l-]*):([^ ].*)$")
if not origtextlang then
-- Special hack for Latin variants, which can have nonstandard etym codes, e.g. VL., LL.
origtextlang, origtext = args.origtext:match("^(%uL%.):([^ ].*)$")
end
if not origtextlang then
error("origtext= should begin with a language code prefix")
end
origtextlang = get_lang(origtextlang, nil, "allow etym") or
error("origtext= should begin with a language code prefix")
origsc = args.origsc
orignormsc = args.orignormsc
else
for _, noparam in ipairs{"origtr", "origts", "origsc", "orignorm", "orignormsc", "origsubst", "origlb"} do
if args[noparam] then
error(("Cannot specify %s= without origtext="):format(noparam))
end
end
end
return origtext, origtextlang, origsc, orignormsc
end
local function get_quote(args, is_cite)
local text = args.text
local gloss = args.t
local tr = args.tr
local ts = args.ts
local norm = args.norm
local sc = args.sc
local normsc = args.normsc
-- Fetch original-text parameters.
local origtext, origtextlang, origsc, orignormsc = get_origtext_params(args)
-- If any quote-related args are present, display the actual quote; otherwise, display nothing.
if text or gloss or tr or ts or norm or args.origtext then
-- Pass "und" here rather than cause an error; there will be an error on mainspace, Citations, etc. pages
-- in any case in source() if the language is omitted.
local lang = get_first_lang(args[1] or args.lang)
local termlang = args.termlang and get_first_lang(args.termlang) or lang
local usex_data = {
lang = lang,
termlang = termlang,
usex = text,
sc = sc,
translation = gloss,
normalization = norm,
normsc = normsc,
transliteration = tr,
transcription = ts,
brackets = args.brackets,
subst = args.subst,
lit = args.lit,
footer = args.footer,
qq = parse_and_format_labels(args.lb, lang),
quote = "quote-meta",
orig = origtext,
origlang = origtextlang,
origsc = origsc,
orignorm = args.orignorm,
orignormsc = orignormsc,
origtr = args.origtr,
origts = args.origts,
origsubst = args.origsubst,
origqq = parse_and_format_labels(args.origlb, lang),
noreq = args.noreq,
nocat = is_cite or args.nocat,
}
if args.inline then
-- don't let usex format the footer, otherwise it gets inlined with the rest of the quoted text
usex_data.footer = nil
usex_data.inline = 1
text = format_usex(usex_data)
if text then
text = " “" .. text .. "”"
else
text = ""
end
if args.footer then
text = text .. "<dl><dd>" .. args.footer .. "</dd></dl>"
end
else
text = "<dl><dd>" .. format_usex(usex_data) .. "</dd></dl>"
end
elseif args.footer then
text = "<dl><dd>" .. args.footer .. "</dd></dl>"
end
return text
end
-- External interface, meant to be called from a template. Replaces {{quote-meta}} and meant to be the primary
-- interface for {{quote-*}} templates.
function export.quote_t(frame)
local args, alias_map, other_controls = get_args(frame.args, frame:getParent().args, "require_lang")
if args.ascite then
return export.cite_t(frame)
end
return show_quote(args, alias_map, other_controls)
end
function show_quote(args, alias_map, other_controls)
local parts = {}
insert(parts, '<div class="citation-whole"><span class="cited-source">')
insert(parts, export.source(args, alias_map, nil, other_controls))
insert(parts, "</span>")
insert(parts, get_quote(args))
insert(parts, "</div>")
local retval = concat(parts)
return deprecated and frame:expandTemplate({
title = "check deprecated lang param usage",
args = {retval, lang = args.lang},
}) or retval
end
-- External interface, meant to be called from a template. Replaces {{cite-meta}} and meant to be the primary
-- interface for {{cite-*}} templates.
function export.cite_t(frame)
local parent_args = {}
for k, v in pairs(frame:getParent().args) do
parent_args[k] = v
end
-- use "und" as lang if none provided
if parent_args[1] == nil then
parent_args[1] = "und"
end
local args, alias_map, other_controls = get_args(frame.args, parent_args)
if args.asquote then
return show_quote(args, alias_map, other_controls)
end
return show_cite(args, alias_map, other_controls)
end
function show_cite(args, alias_map, other_controls)
local parts = {}
-- don't nag for translations
if args.text and not args.t then
args.noreq = 1
end
local len_visible = args.text and ulen((args.text:gsub("<[^<>]+>", ""))) or 0
if len_visible == 0 then
if not args.t or args.t == "-" then
args.nocolon = true
end
elseif args.inline == nil then
args.inline = not (
args.block_text
or len_visible > 300
or (args.t and not args.t == "-" and len_visible < 80)
or string.match(args.text, "<br>")
)
end
insert(parts, '<span class="citation-whole"><span class="cited-source">')
insert(parts, export.source(args, alias_map, "format_as_cite", other_controls))
insert(parts, "</span>")
insert(parts, get_quote(args, "is_cite"))
insert(parts, "</span>")
local retval = concat(parts)
return deprecated
and frame:expandTemplate({
title = "check deprecated lang param usage",
args = {retval, lang = args.lang},
})
or retval
end
-- External interface, meant to be called from a template.
function export.call_quote_template(frame)
return export.call_template(frame)
end
-- External interface, for calling a template with overloaded parameters.
function export.overload(frame)
local iargs, overloaded_args = process_params(frame.args, {
[1] = {required = true}
}, true)
local parent_args = frame:getParent().args
for k, v in pairs(parent_args) do
overloaded_args[k] = v
end
return frame:expandTemplate{title = iargs[1], args = overloaded_args}
end
-- External interface, meant to be called from a template.
function export.call_template(frame)
local parameter_sublist = {type = "parameter", sublist = true}
local iargs, other_direct_args = process_params(frame.args, {
["template"] = true,
["textparam"] = parameter_sublist,
["pageparam"] = parameter_sublist,
["propagateparams"] = parameter_sublist,
["allowparams"] = {sublist = true}, -- Doesn't use type = "parameter", because any that end in :list get processed differently.
}, true)
local function fetch_param(source, params)
for _, param in ipairs(params) do
if source[param] then
return source[param]
end
end
return nil
end
local params = {
["text"] = true,
["passage"] = true,
["footer"] = true, -- always propagates, but gets special formatting
}
-- paramaters that can be used during template declaration or included in template calls
-- if the template is called with param=- it will set any declared value to nil
local always_propagate = {
["brackets"] = true,
["usenodot"] = true,
["nodot"] = true,
["ascite"] = true,
["asquote"] = true,
}
for k,v in pairs(always_propagate) do
params[k] = v
end
local textparam = iargs.textparam or {}
for _, param in ipairs(textparam) do
params[param] = true
end
local pageparam = iargs.pageparam or {}
local pageparam1 = pageparam[1]
if pageparam1 ~= nil then
params["page"], params["pages"] = true, true
for _, param in ipairs(pageparam) do
params[param] = true
end
end
local allowparams, allow_all, list = iargs.allowparams, false
if allowparams ~= nil then
for _, allow in ipairs(allowparams) do
local param = allow:match("^(.*):list$")
if param then
if list == nil then
list = {list = true}
end
params[scribunto_parameter_key(param)] = list
elseif allow == "*" then
track("no parameter checking")
allow_all = true
else
params[scribunto_parameter_key(allow)] = true
end
end
else
local parent = frame:getParent()
local template_name = parent:getTitle()
local template_title = new_title(template_name)
local content = template_title:getContent()
local allowed_params, seen = {}, {}
-- Detect all params used by the parent template. param:get_name() takes the
-- parent frame arg table as an argument so that preprocessing will take
-- them into account, since it will matter if the name contains another
-- parameter (e.g. the outer param in "{{{foo{{{bar}}}baz}}}" will change
-- depending on the value for bar=). `seen` memoizes results based on the
-- raw parameter text (which is stored as a string in the parameter object),
-- which avoids unnecessary param:get_name() calls, which are non-trivial.
for param in find_parameters(content) do
local raw = param.raw
if not seen[raw] then
allow = param:get_name(template_args)
params[scribunto_parameter_key(allow)] = true
seen[raw] = true
end
end
end
local propagateparams = iargs.propagateparams or {}
for _, param in ipairs(propagateparams) do
params[param] = true
end
local parent_args = frame:getParent().args
local args = process_params(parent_args, params, allow_all)
parent_args = shallow_copy(parent_args)
if textparam[1] ~= "-" then
other_direct_args.passage = args.text or args.passage or fetch_param(args, textparam)
end
if not (pageparam1 == nil or pageparam1 == "-") then
other_direct_args.page = fetch_param(args, pageparam) or args.page or other_direct_args.page or nil
other_direct_args.pages = args.pages or other_direct_args.pages or nil
if other_direct_args.page == "-" then
other_direct_args.page = nil
end
if other_direct_args.pages == "-" then
other_direct_args.pages = nil
end
end
if args.footer then
other_direct_args.footer = frame:expandTemplate{title = "small", args = {args.footer}}
end
for param, _ in pairs(always_propagate) do
if args[param] == "-" then
other_direct_args[param] = nil
else
other_direct_args[param] = args[param] or other_direct_args[param] or nil
end
end
-- authorlink=- can be used to prevent copying of author= to authorlink= but we don't want to propagate this to
-- the actual {{quote-*}} code.
if other_direct_args.authorlink == "-" then
other_direct_args.authorlink = nil
end
for _, param in ipairs(propagateparams) do
if args[param] then
other_direct_args[param] = args[param]
end
end
return frame:expandTemplate{title = iargs.template or "quote-book", args = other_direct_args}
end
local paramdoc_param_replacements = {
passage = {
param_with_synonym = "<<synonym>>, {{para|text}}, or {{para|passage}}",
param_no_synonym = "{{para|text}} or {{para|passage}}",
text = [=[
* <<params>> – the passage to be quoted.]=],
},
page = {
param_with_synonym = "<<synonym>> or {{para|page}}, or {{para|pages}}",
param_no_synonym = "{{para|page}} or {{para|pages}}",
text = [=[
* <<params>> – '''mandatory in some cases''': the page number(s) quoted from. When quoting a range of pages, note the following:
** Separate the first and last pages of the range with an [[en dash]], like this: {{para|pages|10–11}}.
** You must also use {{para|pageref}} to indicate the page to be linked to (usually the page on which the Wiktionary entry appears).
: This parameter must be specified to have the template link to the online version of the work.]=],
},
page_with_roman_preface = {
param_with_synonym = {"inherit", "page"},
param_no_synonym = {"inherit", "page"},
text = [=[
* <<params>> – '''mandatory in some cases''': the page number(s) quoted from. If quoting from the preface, specify the page number(s) in lowercase Roman numerals. When quoting a range of pages, note the following:
** Separate the first and last page number of the range with an [[en dash]], like this: {{para|pages|10–11}} or {{para|pages|iii–iv}}.
** You must also use {{para|pageref}} to indicate the page to be linked to (usually the page on which the Wiktionary entry appears).
: This parameter must be specified to have the template link to the online version of the work.]=],
},
chapter = {
param_with_synonym = "<<synonym>> or {{para|chapter}}",
param_no_synonym = "{{para|chapter}}",
text = [=[
* <<params>> – the name of the chapter quoted from.]=],
},
roman_chapter = {
param_with_synonym = {"inherit", "chapter"},
param_no_synonym = {"inherit", "chapter"},
text = [=[
* <<params>> – the chapter number quoted from in uppercase Roman numerals.]=],
},
arabic_chapter = {
param_with_synonym = {"inherit", "chapter"},
param_no_synonym = {"inherit", "chapter"},
text = [=[
* <<params>> – the chapter number quoted from in Arabic numerals.]=],
},
trailing_params = {
text = [=[
* {{para|footer}} – a comment on the passage quoted.
* {{para|brackets}} – use {{para|brackets|on}} to surround a quotation with [[bracket#Noun|brackets]]. This indicates that the quotation either contains a mere mention of a term (for example, “some people find the word '''''manoeuvre''''' hard to spell”) rather than an actual use of it (for example, “we need to '''manoeuvre''' carefully to avoid causing upset”), or does not provide an actual instance of a term but provides information about related terms.]=],
},
}
function export.paramdoc(frame)
local parargs = frame:getParent().args
local args = process_params(parargs, {
[1] = true,
})
local text = args[1]
local function do_param_with_optional_synonym(param, text_to_sub, paramtext_synonym, paramtext_no_synonym)
local function sub_param(synonym)
local subbed_paramtext
if synonym then
subbed_paramtext = paramtext_synonym:gsub("<<synonym>>", "{{para|" .. replacement_escape(synonym) .. "}}")
else
subbed_paramtext = paramtext_no_synonym
end
return frame:preprocess((text_to_sub:gsub("<<params>>", replacement_escape(subbed_paramtext))))
end
text = text:gsub("<<" .. pattern_escape(param) .. ">>", function()
return sub_param()
end)
text = text:gsub("<<" .. pattern_escape(param) .. ":(.-)>>", sub_param)
end
local function fetch_text(param_to_replace, key)
local spec = paramdoc_param_replacements[param_to_replace]
local val = spec[key]
if type(val) == "string" then
return val
end
if type(val) == "table" and val[1] == "inherit" then
return fetch_text(val[2], key)
end
error(
"Internal error: Unrecognized value for param '"
.. param_to_replace
.. "', key '"
.. key
.. "': "
.. mw.dumpObject(val)
)
end
for param_to_replace, spec in pairs(paramdoc_param_replacements) do
if not spec.param_no_synonym then
-- Text to substitute directly.
text = text:gsub("<<" .. pattern_escape(param_to_replace) .. ">>", function()
return frame:preprocess(fetch_text(param_to_replace, "text"))
end)
else
do_param_with_optional_synonym(
param_to_replace,
fetch_text(param_to_replace, "text"),
fetch_text(param_to_replace, "param_with_synonym"),
fetch_text(param_to_replace, "param_no_synonym")
)
end
end
-- Remove final newline so template code can add a newline after invocation
text = text:gsub("\n$", "")
return text
end
return export
ebfg5f6t13ie4m6ytr40c34nsxmmbdk
Mô đun:headword
828
261391
2576440
2575768
2026-11-08T14:23:18Z
Hiyuune
50834
2576440
Scribunto
text/plain
local export = {}
-- Named constants for all modules used, to make it easier to swap out sandbox versions.
local debug_track_module = "Module:debug/track"
local decorations_module = "Module:decorations"
local gender_and_number_module = "Module:gender and number"
local headword_data_module = "Module:headword/data"
local headword_page_module = "Module:headword/page"
local links_module = "Module:links"
local load_module = "Module:load"
local pages_module = "Module:pages"
local palindromes_module = "Module:palindromes"
local scripts_module = "Module:scripts"
local scripts_data_module = "Module:scripts/data"
local script_utilities_module = "Module:script utilities"
local script_utilities_data_module = "Module:script utilities/data"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local ucfirst = require("Module:string utilities").ucfirst
local lcfirst = require("Module:string utilities").lcfirst
local concat = table.concat
local dump = mw.dumpObject
local insert = table.insert
local ipairs = ipairs
local max = math.max
local new_title = mw.title.new
local pairs = pairs
local require = require
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local type = type
local ufind = mw.ustring.find
local ugmatch = mw.ustring.gmatch
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
--[==[
Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==]
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function contains(...)
contains = require(table_module).contains
return contains(...)
end
local function encode_entities(...)
encode_entities = require(string_utilities_module).encode_entities
return encode_entities(...)
end
local function extend(...)
extend = require(table_module).extend
return extend(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_genders(...)
format_genders = require(gender_and_number_module).format_genders
return format_genders(...)
end
local function format_decorations(...)
format_decorations = require(decorations_module).format_decorations
return format_decorations(...)
end
local function full_link(...)
full_link = require(links_module).full_link
return full_link(...)
end
local function get_current_L2(...)
get_current_L2 = require(pages_module).get_current_L2
return get_current_L2(...)
end
local function get_link_page(...)
get_link_page = require(links_module).get_link_page
return get_link_page(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function is_palindrome(...)
is_palindrome = require(palindromes_module).is_palindrome
return is_palindrome(...)
end
local function language_link(...)
language_link = require(links_module).language_link
return language_link(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities_module).pattern_escape
return pattern_escape(...)
end
local function process_page(...)
process_page = require(headword_page_module).process_page
return process_page(...)
end
local function remove_links(...)
remove_links = require(links_module).remove_links
return remove_links(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function tag_text(...)
tag_text = require(script_utilities_module).tag_text
return tag_text(...)
end
local function tag_transcription(...)
tag_transcription = require(script_utilities_module).tag_transcription
return tag_transcription(...)
end
local function tag_translit(...)
tag_translit = require(script_utilities_module).tag_translit
return tag_translit(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function ulen(...)
ulen = require(string_utilities_module).len
return ulen(...)
end
--[==[
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==]
local m_data
local function get_data()
m_data = load_data(headword_data_module)
return m_data
end
local script_data
local function get_script_data()
script_data = load_data(scripts_data_module)
return script_data
end
local script_utilities_data
local function get_script_utilities_data()
script_utilities_data = load_data(script_utilities_data_module)
return script_utilities_data
end
-- If set to true, categories always appear, even in non-mainspace pages
local test_force_categories = false
-- Add a tracking category to track entries with certain (unusually undesirable) properties. `track_id` is an identifier
-- for the particular property being tracked and goes into the tracking page. Specifically, this adds a link in the
-- page text to [[Wiktionary:Tracking/headword/TRACK_ID]], meaning you can find all entries with the `track_id` property
-- by visiting [[Special:WhatLinksHere/Wiktionary:Tracking/headword/TRACK_ID]].
--
-- If `lang` (a language object) is given, an additional tracking page [[Wiktionary:Tracking/headword/TRACK_ID/CODE]] is
-- linked to where CODE is the language code of `lang`, and you can find all entries in the combination of `track_id`
-- and `lang` by visiting [[Special:WhatLinksHere/Wiktionary:Tracking/headword/TRACK_ID/CODE]]. This makes it possible to
-- isolate only the entries with a specific tracking property that are in a given language. Note that if `lang`
-- references at etymology-only language, both that language's code and its full parent's code are tracked.
local function track(track_id, lang)
local tracking_page = "headword/" .. track_id
if lang and lang:hasType("etymology-only") then
debug_track{tracking_page, tracking_page .. "/" .. lang:getCode(),
tracking_page .. "/" .. lang:getFullCode()}
elseif lang then
debug_track{tracking_page, tracking_page .. "/" .. lang:getCode()}
else
debug_track(tracking_page)
end
return true
end
local function text_in_script(text, script_code)
local sc = get_script(script_code)
if not sc then
error("Internal error: Bad script code " .. script_code)
end
local characters = sc.characters
local out
if characters then
text = ugsub(text, "%W", "")
out = ufind(text, "[" .. characters .. "]")
end
if out then
return true
else
return false
end
end
local spacingPunctuation = "[%s%p]+"
--[[ List of punctuation or spacing characters that are found inside of words.
Used to exclude characters from the regex above. ]]
local wordPunc = "-#%%&@־׳״'.·*’་•:᠊"
local notWordPunc = "[^" .. wordPunc .. "]+"
--[=[
Format a term (either a head term or an inflection term) along with any decorations (left or right qualifiers, labels,
references or customized separator). `part` is the object specifying the term (and `lang` the language of the term),
which should optionally contain:
* left qualifiers in `q`, an array of strings;
* right qualifiers in `qq`, an array of strings;
* left labels in `l`, an array of strings;
* right labels in `ll`, an array of strings;
* references in `refs`, an array either of strings (formatted reference text) or objects containing fields `text`
(formatted reference text) and optionally `name` and/or `group`;
* a separator in `separator`, defaulting to " <i>or</i> " if this is not the first term (j > 1), otherwise "".
`formatted` is the formatted version of the term itself, and `j` is the index of the term.
]=]
local function format_term_with_decorations(lang, part, formatted, j)
local function part_non_empty(field)
local list = part[field]
if not list then
return nil
end
if type(list) ~= "table" then
error(("Internal error: Wrong type for `part.%s`=%s, should be \"table\""):format(field, dump(list)))
end
return list[1]
end
if part_non_empty("q") or part_non_empty("qq") or part_non_empty("l") or
part_non_empty("ll") or part_non_empty("refs") then
formatted = format_decorations {
lang = lang,
text = formatted,
q = part.q,
qq = part.qq,
l = part.l,
ll = part.ll,
refs = part.refs,
}
end
local separator = part.separator or j > 1 and " <i>hoặc</i> " -- use "" to request no separator
if separator then
formatted = separator .. formatted
end
return formatted
end
--[==[Return true if the given head is multiword according to the algorithm used in full_headword().]==]
function export.head_is_multiword(head)
for possibleWordBreak in ugmatch(head, spacingPunctuation) do
if umatch(possibleWordBreak, notWordPunc) then
return true
end
end
return false
end
do
local function workaround_to_exclude_chars(s)
return (ugsub(s, notWordPunc, "\2%1\1"))
end
--[==[
Add appropriate links to `head`, correctly handling multiword terms. This is intended for multiword terms but can
be used for any term if you want links added to single-word terms as well. If you want to only add
links to multiword terms, first check that the term is multiword using `head_is_multiword`.
If `default` is specified, this will escape colons so that they don't get interpreted as interwiki links. This
should generally only be used when `head` is an actual pagename or is taken from a {{para|pagename}} parameter, not
when taken from a {{para|head}} parameter.
]==]
function export.add_multiword_links(head, default)
head = "\1" .. ugsub(head, spacingPunctuation, workaround_to_exclude_chars) .. "\2"
if default then
head = head
:gsub("(\1[^\2]*)\\([:#][^\2]*\2)", "%1\\\\%2")
:gsub("(\1[^\2]*)([:#][^\2]*\2)", "%1\\%2")
end
--Escape any remaining square brackets to stop them breaking links (e.g. "[citation needed]").
head = encode_entities(head, "[]", true, true)
--[=[
use this when workaround is no longer needed:
head = "[[" .. ugsub(head, WORDBREAKCHARS, "]]%1[[") .. "]]"
Remove any empty links, which could have been created above
at the beginning or end of the string.
]=]
return (head
:gsub("\1\2", "")
:gsub("[\1\2]", {["\1"] = "[[", ["\2"] = "]]"}))
end
end
local function non_categorizable(full_raw_pagename)
return full_raw_pagename:find("^Appendix:Gestures/") or
-- Unsupported titles with descriptive names.
(full_raw_pagename:find("^Unsupported titles/") and not full_raw_pagename:find("`"))
end
local function tag_text_and_add_decorations(data, head, formatted, j)
-- Add language and script wrapper.
formatted = tag_text(formatted, data.lang, head.sc, "head", nil, j == 1 and data.id or nil)
-- Add decorations (qualifiers, labels, references and separator).
return format_term_with_decorations(data.lang, head, formatted, j)
end
-- Format a headword with transliterations.
local function format_headword(data)
-- Are there non-empty transliterations?
local has_translits = false
local has_manual_translits = false
------ Format the headwords. ------
local head_parts = {}
local unique_head_parts = {}
local has_multiple_heads = not not data.heads[2]
for j, head in ipairs(data.heads) do
if head.tr or head.ts then
has_translits = true
end
if head.tr and head.tr_manual or head.ts then
has_manual_translits = true
end
local formatted
-- Apply processing to the headword, for formatting links and such.
if head.term:find("[[", nil, true) and head.sc:getCode() ~= "Image" then
formatted = language_link{term = head.term, lang = data.lang}
else
formatted = data.lang:makeDisplayText(head.term, head.sc, true)
end
local head_part = tag_text_and_add_decorations(data, head, formatted, j)
insert(head_parts, head_part)
-- If multiple heads, try to determine whether all heads display the same. To do this we need to effectively
-- rerun the text tagging and addition of decorations, using 1 for all indices.
if has_multiple_heads then
local unique_head_part
if j == 1 then
unique_head_part = head_part
else
unique_head_part = tag_text_and_add_decorations(data, head, formatted, 1)
end
unique_head_parts[unique_head_part] = true
end
end
local set_size = 0
if has_multiple_heads then
for _ in pairs(unique_head_parts) do
set_size = set_size + 1
end
end
if set_size == 1 then
head_parts = head_parts[1]
else
head_parts = concat(head_parts)
end
if has_manual_translits then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/manual-tr]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/manual-tr/LANGCODE]]
track("manual-tr", data.lang)
end
------ Format the transliterations and transcriptions. ------
local translits_formatted
if has_translits then
local translit_parts = {}
for _, head in ipairs(data.heads) do
if head.tr or head.ts then
local this_parts = {}
if head.tr then
insert(this_parts, tag_translit(head.tr, data.lang:getCode(), "head", nil, head.tr_manual))
if head.ts then
insert(this_parts, " ")
end
end
if head.ts then
insert(this_parts, "/" .. tag_transcription(head.ts, data.lang:getCode(), "head") .. "/")
end
insert(translit_parts, concat(this_parts))
end
end
translits_formatted = " (" .. concat(translit_parts, " <i>or</i> ") .. ")"
local function format_transliteration_page_link(langname)
local transliteration_pagename = "Chuyển tự " .. langname
local transliteration_page = new_title(transliteration_pagename, "Wiktionary")
if transliteration_page and transliteration_page:getContent() then
return ("[[Wiktionary:Chuyển tự %s|•]]"):format(transliteration_pagename)
end
return nil
end
local translit_page_link = format_transliteration_page_link(data.lang:getCanonicalName())
-- If data.lang is an etymology-only language and we didn't find a translation page for it, fall back to the
-- full parent.
if not translit_page_link and data.lang:hasType("etymology-only") then
translit_page_link = format_transliteration_page_link(data.lang:getFullName())
end
if translit_page_link then
translits_formatted = " " .. translit_page_link .. translits_formatted
end
else
translits_formatted = ""
end
------ Paste heads and transliterations/transcriptions. ------
local lemma_gloss
if data.gloss then
lemma_gloss = ' <span class="ib-content qualifier-content">' .. data.gloss .. '</span>'
else
lemma_gloss = ""
end
return head_parts .. translits_formatted .. lemma_gloss
end
local function format_headword_genders(data, is_varform_only)
local retval = ""
if data.genders and data.genders[1] then
if data.gloss then
retval = ","
end
local pos_for_cat
if not data.nogendercat and not is_varform_only then
local no_gender_cat = (m_data or get_data()).no_gender_cat
if not (no_gender_cat[data.lang:getCode()] or no_gender_cat[data.lang:getFullCode()]) then
pos_for_cat = (m_data or get_data()).pos_for_gender_number_cat[data.pos_category:gsub("^reconstructed ", "")]
end
end
local text, cats = format_genders(data.genders, data.lang, pos_for_cat)
if cats then
extend(data.categories, cats)
end
retval = retval .. " " .. text
end
return retval
end
-- Forward reference
local format_inflections
local function format_inflection_parts(data, parts)
for j, part in ipairs(parts) do
if type(part) ~= "table" then
part = {term = part}
end
local partaccel = part.accel
local face = part.face or "bold"
if face ~= "bold" and face ~= "plain" and face ~= "hypothetical" then
error("The face `" .. face .. "` " .. (
(script_utilities_data or get_script_utilities_data()).faces[face] and
"should not be used for non-headword terms on the headword line." or
"is invalid."
))
end
-- Here the final part 'or data.nolinkinfl' allows to have 'nolinkinfl=true'
-- right into the 'data' table to disable inflection links of the entire headword
-- when inflected forms aren't entry-worthy, e.g.: in Vulgar Latin
local nolinkinfl = part.face == "hypothetical" or (part.nolink and track("nolink") or part.nolinkinfl) or (
data.nolink and track("nolink") or data.nolinkinfl)
local formatted
if part.label then
-- FIXME: There should be a better way of italicizing a label. As is, this isn't customizable.
formatted = "<i>" .. part.label .. "</i>"
else
-- Convert the term into a full link. Don't show a transliteration here unless enable_auto_translit is
-- requested, either at the `parts` level (i.e. per inflection) or at the `data.inflections` level (i.e.
-- specified for all inflections). This is controllable in {{head}} using autotrinfl=1 for all inflections,
-- or fNautotr=1 for an individual inflection (remember that a single inflection may be associated with
-- multiple terms). The reason for doing this is to avoid clutter in headword lines by default in languages
-- where the script is relatively straightforward to read by learners (e.g. Greek, Russian), but allow it
-- to be enabled in languages with more complex scripts (e.g. Arabic).
--
-- FIXME: With nested inflections, should we also respect `enable_auto_translit` at the top level of the
-- nested inflections structure?
local tr = part.tr or not (parts.enable_auto_translit or data.inflections.enable_auto_translit) and "-" or nil
local postprocess_annotations
if part.inflections then
postprocess_annotations = function(infldata)
insert(infldata.annotations, {text = format_inflections(data, part.inflections)})
end
end
formatted = full_link(
{
term = not nolinkinfl and part.term or nil,
alt = part.alt or (nolinkinfl and part.term or nil),
lang = part.lang or data.lang,
sc = part.sc or parts.sc or nil,
gloss = part.gloss,
pos = part.pos,
lit = part.lit,
id = part.id,
genders = part.genders,
tr = tr,
ts = part.ts,
accel = partaccel or parts.accel,
postprocess_annotations = postprocess_annotations,
},
face
)
end
parts[j] = format_term_with_decorations(part.lang or data.lang, part,
formatted, j)
end
local parts_output
if parts[1] then
parts_output = (parts.label and " " or "") .. concat(parts)
elseif parts.request then
parts_output = " <small>[vui lòng chỉ định]</small>"
insert(data.categories, "Yêu cầu biến tố mục từ " .. data.lang:getFullName())
else
parts_output = ""
end
local parts_label = parts.label and ("<i>" .. parts.label .. "</i>") or ""
return format_term_with_decorations(data.lang, parts, parts_label .. parts_output, 1)
end
-- Format the inflections following the headword or nested after a given inflection. Declared local above.
function format_inflections(data, inflections)
if inflections and inflections[1] then
-- Format each inflection individually.
for key, infl in ipairs(inflections) do
inflections[key] = format_inflection_parts(data, infl)
end
return concat(inflections, ", ")
else
return ""
end
end
-- Format the top-level inflections following the headword. Currently this just adds parens around the
-- formatted comma-separated inflections in `data.inflections`.
local function format_top_level_inflections(data)
local result = format_inflections(data, data.inflections)
if result ~= "" then
return " (" .. result .. ")"
else
return result
end
end
-- Forward reference
local check_red_link_inflections
-- Check a single inflection (which consists of a label and zero or more terms, each possibly with nested inflections)
-- for red links. If so, insert a red-link category based on `plpos` (the plural part of speech to insert in the
-- category), stop further processing, and return true. If no red links found, return false.
local function check_red_link_inflection_parts(data, parts, plpos)
for _, part in ipairs(parts) do
if type(part) ~= "table" then
part = {term = part}
end
local term = part.term
if term and not term:find("%[%[") then
local stripped_physical_term = get_link_page(term, data.lang, part.sc or parts.sc or nil)
if stripped_physical_term then
local title = mw.title.new(stripped_physical_term)
if title and not title:getContent() then
insert(data.categories, plpos .. " có liên kết đỏ trong dòng tên mục từ " .. data.lang:getFullName())
return true
end
end
end
if part.inflections then
if check_red_link_inflections(data, part.inflections, plpos) then
return true
end
end
end
return false
end
-- Check a set of inflections (each of which describes a single inflection of the term, such as feminine or plural, and
-- consists of a label and zero or more terms, each possibly with nested inflections) for red links. If so, insert a
-- red-link category based on `plpos` (the plural part of speech to insert in the category), stop further processing,
-- and return true. If no red links found, return false.
function check_red_link_inflections(data, inflections, plpos)
if inflections and inflections[1] then
-- Check each inflection individually.
for key, infl in ipairs(inflections) do
if check_red_link_inflection_parts(data, infl, plpos) then
return true
end
end
end
return false
end
-- Check the top-level inflections in `data.inflections`, along with any nested inflections, for red links. If so,
-- insert a red-link category based on `plpos` (the plural part of speech to insert in the category), stop further
-- processing, and return true. If no red links found, return false.
local function check_red_link_inflections_top_level(data, plpos)
return check_red_link_inflections(data, data.inflections, plpos)
end
--[==[
Returns the plural form of `pos`, a raw part of speech input, which could be singular or
plural. Irregular plural POS are taken into account (e.g. "kanji" pluralizes to
"kanji").
]==]
function export.pluralize_pos(pos)
-- Make the plural form of the part of speech
return (m_data or get_data()).irregular_plurals[pos] or
pos:sub(-1) == "" and pos or
pos
end
--[==[
Return "lemma" if the given POS is a lemma, "non-lemma form" if a non-lemma form, or nil
if unknown. The POS passed in must be in its plural form ("nouns", "prefixes", etc.).
If you have a POS in its singular form, call {export.pluralize_pos()} above to pluralize it
in a smart fashion that knows when to add "-s" and when to add "-es", and also takes
into account any irregular plurals.
If `best_guess` is given and the POS is in neither the lemma nor non-lemma list, guess
based on whether it ends in " forms"; otherwise, return nil.
]==]
function export.pos_lemma_or_nonlemma(plpos, best_guess)
local m_headword_data = m_data or get_data()
local isLemma = m_headword_data.lemmas
-- Is it a lemma category?
if isLemma[plpos] then
return ucfirst("mục từ")
end
local plpos_no_recon = plpos:gsub("^reconstructed ", "")
if isLemma[plpos_no_recon] then
return ucfirst("mục từ")
end
-- Is it a nonlemma category?
local isNonLemma = m_headword_data.nonlemmas
if isNonLemma[plpos] or isNonLemma[plpos_no_recon] then
return ucfirst("mục từ biến thể hình thái")
end
local plpos_no_mut = plpos:gsub("^mutated ", "")
if isLemma[plpos_no_mut] or isNonLemma[plpos_no_mut] then
return ucfirst("mục từ biến thể hình thái")
elseif best_guess then
return plpos:find(" forms$") and ucfirst("mục từ biến thể hình thái") or ucfirst("mục từ")
else
return nil
end
end
--[==[
Canonicalize a part of speech as specified in 2= in {{tl|head}}. This checks for POS aliases and non-lemma form
aliases ending in 'f', and then pluralizes if the POS term does not have an invariable plural.
]==]
function export.canonicalize_pos(pos)
-- FIXME: Temporary code to throw an error for alias 'pre' (= preposition) that will go away.
if pos == "pre" then
-- Don't throw error on 'pref' as it's an alias for "prefix".
error("POS 'pre' for 'preposition' no longer allowed as it's too ambiguous; use 'prep'")
end
-- Likewise for pro = pronoun.
if pos == "pro" or pos == "prof" then
error("POS 'pro' for 'pronoun' no longer allowed as it's too ambiguous; use 'pron'")
end
local m_headword_data = m_data or get_data()
if m_headword_data.pos_aliases[pos] then
pos = m_headword_data.pos_aliases[pos]
elseif pos:sub(-1) == "f" then
pos = pos:sub(1, -2)
pos = "Biến thể hình thái " .. lcfirst((m_headword_data.pos_aliases[pos] or pos))
end
return ucfirst(pos)
end
-- Find and return the maximum index in the array `data[element]` (which may have gaps in it), and initialize it to a
-- zero-length array if unspecified. Check to make sure all keys are numeric (other than "maxindex", which is set by
-- [[Module:parameters]] for list parameters), all values are strings, and unless `allow_blank_string` is given,
-- no blank (zero-length) strings are present.
local function init_and_find_maximum_index(data, element, allow_blank_string)
local maxind = 0
if not data[element] then
data[element] = {}
end
local typ = type(data[element])
if typ ~= "table" then
error(("Internal error: In full_headword(), `data.%s` must be an array but is a %s"):format(element, typ))
end
for k, v in pairs(data[element]) do
if k ~= "maxindex" then
if type(k) ~= "number" then
error(("Internal error: Unrecognized non-numeric key '%s' in `data.%s`"):format(k, element))
end
if k > maxind then
maxind = k
end
if v then
if type(v) ~= "string" then
error(("Internal error: For key '%s' in `data.%s`, value should be a string but is a %s"):format(k, element, type(v)))
end
if not allow_blank_string and v == "" then
error(("Internal error: For key '%s' in `data.%s`, blank string not allowed; use 'false' for the default"):format(k, element))
end
end
end
end
return maxind
end
--[==[
-- Add the page to various maintenance categories for the language and the
-- whole page. These are placed in the headword somewhat arbitrarily, but
-- mainly because headword templates are mandatory for entries (meaning that
-- in theory it provides full coverage).
--
-- This is provided as an external entry point so that modules which transclude
-- information from other entries (such as {{tl|ja-see}}) can take advantage
-- of this feature as well, because they are used in place of a conventional
-- headword template.]==]
do
-- Handle any manual sortkeys that have been specified in raw categories
-- by tracking if they are the same or different from the automatically-
-- generated sortkey, so that we can track them in maintenance
-- categories.
local function handle_raw_sortkeys(tbl, sortkey, page, lang, lang_cats)
sortkey = sortkey or lang:makeSortKey(page.pagename)
-- If there are raw categories with no sortkey, then they will be
-- sorted based on the default MediaWiki sortkey, so we check against
-- that.
if tbl == true then
if page.raw_defaultsort ~= sortkey then
insert(lang_cats, "Mục từ có mã sắp xếp thủ công không thừa " .. lang:getFullName())
end
return
end
local redundant, different
for k in pairs(tbl) do
if k == sortkey then
redundant = true
else
different = true
end
end
if redundant then
insert(lang_cats, "Mục từ có mã sắp xếp thừa " .. lang:getFullName())
end
if different then
insert(lang_cats, "Mục từ có mã sắp xếp thủ công không thừa " .. lang:getFullName())
end
return sortkey
end
function export.maintenance_cats(page, lang, lang_cats, page_cats)
extend(page_cats, page.cats)
lang = lang:getFull() -- since we are just generating categories
local canonical = lang:getCanonicalName()
local tbl = page.wikitext_topic_cat[lang:getCode()]
local sortkey = nil
if tbl then
sortkey = handle_raw_sortkeys(tbl, sortkey, page, lang, lang_cats)
insert(lang_cats, canonical .. " entries with topic categories using raw markup")
end
tbl = page.wikitext_langname_cat[canonical]
if tbl then
handle_raw_sortkeys(tbl, sortkey, page, lang, lang_cats)
insert(lang_cats, canonical .. " entries with language name categories using raw markup")
end
local current_L2 = get_current_L2()
if current_L2 then
local trimmed_L2 = trim(current_L2)
local expected_L2 = ucfirst(canonical)
if trimmed_L2 ~= expected_L2 then
insert(lang_cats, "Mục từ có đề mục ngôn ngữ không đúng " .. canonical)
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/incorrect language header]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/incorrect language header/LANGCODE]]
track("incorrect language header", lang)
end
end
end
end
--[==[This is the primary external entry point.
{{lua|full_headword(data)}}
This is used by {{temp|head}} and various language-specific headword templates (e.g. {{temp|ru-adj}} for Russian adjectives, {{temp|de-noun}} for German nouns, etc.) to display an entire headword line.
See [[#Further explanations for full_headword()]]
]==]
function export.full_headword(data)
-- Prevent data from being destructively modified.
data = shallow_copy(data)
------------ 1. Basic checks for old-style (multi-arg) calling convention. ------------
if data.getCanonicalName then
error("Internal error: In full_headword(), the first argument `data` needs to be a Lua object (table) of properties, not a language object")
end
if not data.lang or type(data.lang) ~= "table" or not data.lang.getCode then
error("Internal error: In full_headword(), the first argument `data` needs to be a Lua object (table) and `data.lang` must be a language object")
end
if data.id and type(data.id) ~= "string" then
error("Internal error: The id in the data table should be a string.")
end
------------ 2. Initialize pagename etc. ------------
local langcode = data.lang:getCode()
local full_langcode = data.lang:getFullCode()
local langname = data.lang:getCanonicalName()
local full_langname = data.lang:getFullName()
local raw_pagename = data.pagename
local page
local m_headword_data = m_data or get_data()
if raw_pagename and raw_pagename ~= m_headword_data.pagename then -- for testing, doc pages, etc.
-- data.pagename is often set on documentation and test pages through the pagename= parameter of various
-- templates, to emulate running on that page. Having a large number of such test templates on a single
-- page often leads to timeouts, because we fetch and parse the contents of each page in turn. However,
-- we don't really need to do that and can function fine without fetching and parsing the contents of a
-- given page, so turn off content fetching/parsing (and also setting the DEFAULTSORT key through a parser
-- function, which is *slooooow*) in certain namespaces where test and documentation templates are likely to
-- be found and where actual content does not live (User, Template, Module).
local actual_namespace = m_headword_data.page.namespace
local no_fetch_content = actual_namespace == "User" or actual_namespace == "Template" or
actual_namespace == "Module"
page = process_page(raw_pagename, no_fetch_content)
else
page = m_headword_data.page
end
local namespace = page.namespace
if data.altform then
-- Temporary tracking for use of old altform=
track("altform", data.lang)
end
local noposcat = data.noposcat
local is_varform_only = data.var and data.var ~= "both"
local is_varform_both = data.var == "both"
------------ 3. Initialize `data.heads` table; if old-style, convert to new-style. ------------
if type(data.heads) == "table" and type(data.heads[1]) == "table" then
-- new-style
if data.translits or data.transcriptions then
error("Internal error: In full_headword(), if `data.heads` is new-style (array of head objects), `data.translits` and `data.transcriptions` cannot be given")
end
else
-- convert old-style `heads`, `translits` and `transcriptions` to new-style
local maxind = max(
init_and_find_maximum_index(data, "heads"),
init_and_find_maximum_index(data, "translits", true),
init_and_find_maximum_index(data, "transcriptions", true)
)
for i = 1, maxind do
data.heads[i] = {
term = data.heads[i],
tr = data.translits[i],
ts = data.transcriptions[i],
}
end
end
-- Make sure there's at least one head.
if not data.heads[1] then
data.heads[1] = {}
end
------------ 4. Initialize and validate `data.categories` and `data.whole_page_categories`, and determine `pos_category` if not given, and add basic categories. ------------
init_and_find_maximum_index(data, "categories")
init_and_find_maximum_index(data, "whole_page_categories")
local pos_category_already_present = false
if data.categories[1] then
local escaped_langname = pattern_escape(full_langname)
local matches_lang_pattern = "^" .. escaped_langname .. " "
for _, cat in ipairs(data.categories) do
-- Does the category begin with the language name? If not, tag it with a tracking category.
if not cat:find(matches_lang_pattern) then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/no lang category]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/no lang category/LANGCODE]]
track("no lang category", data.lang)
end
end
-- If `pos_category` not given, try to infer it from the first specified category. If this doesn't work, we
-- throw an error below.
if not data.pos_category and data.categories[1]:find(matches_lang_pattern) then
data.pos_category = data.categories[1]:gsub(matches_lang_pattern, "")
-- Optimization to avoid inserting category already present.
pos_category_already_present = true
end
end
if not data.pos_category then
error("Internal error: `data.pos_category` not specified and could not be inferred from the categories given in "
.. "`data.categories`. Either specify the plural part of speech in `data.pos_category` "
.. "(e.g. \"proper nouns\") or ensure that the first category in `data.categories` is formed from the "
.. "language's canonical name plus the plural part of speech (e.g. \"Norwegian Bokmål proper nouns\")."
)
end
-- Insert a category at the beginning for the part of speech unless it's already present or `data.noposcat` given.
if not (pos_category_already_present or noposcat or is_varform_only) then
local pos_category = data.pos_category .. " " .. full_langname
-- FIXME: [[User:Theknightwho]] Why is this special case here? Please add an explanatory comment.
if pos_category ~= "Ký tự Chữ Hán đa ngữ" then
insert(data.categories, 1, pos_category)
end
end
-- Try to determine whether the part of speech refers to a lemma or a non-lemma form; if we can figure this out,
-- add an appropriate category.
local postype = export.pos_lemma_or_nonlemma(data.pos_category)
if not postype then
-- We don't know what this category is, so tag it with a tracking category.
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos/LANGCODE]]
track("unrecognized pos", data.lang)
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos/POS]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/unrecognized pos/POS/LANGCODE]]
track("unrecognized pos/pos/" .. data.pos_category, data.lang)
elseif not (noposcat or is_varform_only or data.nolemmacat) then
insert(data.categories, 1, postype .. " " .. full_langname)
end
-- Categorize variant forms into 'variant lemmas' or 'variant non-lemma forms'. Originally proposed in
-- [[Wiktionary:Beer parlour/2024/June#Decluttering the altform mess]] as 'alternative forms'; renamed in
-- [[Wiktionary:Beer parlour/2026/July#Renaming the "alternative forms" categories]].
if (is_varform_only or is_varform_both) then
insert(data.categories, 1, "Mục từ biến thể thay thế " .. full_langname)
end
------------ 5. Create a default headword, and add links to multiword page names. ------------
-- Determine if this is an "anti-asterisk" term, i.e. an attested term in a language that must normally be
-- reconstructed.
local is_anti_asterisk = data.heads[1].term and data.heads[1].term:find("^!!")
local lang_reconstructed = data.lang:hasType("reconstructed")
if is_anti_asterisk then
if not lang_reconstructed then
error("Anti-asterisk feature (head= beginning with !!) can only be used with reconstructed languages")
end
if namespace == "Reconstruction" then
error("Anti-asterisk feature (head= beginning with !!) should be used in mainspace, not in Reconstruction space")
end
lang_reconstructed = false
end
-- Determine if term is reconstructed
local is_reconstructed = namespace == "Từ_tái_tạo" or lang_reconstructed
-- Create a default headword based on the pagename, which is determined in
-- advance by the data module so that it only needs to be done once.
local default_head = page.pagename
-- Add links to multi-word page names when appropriate
if not (is_reconstructed or data.nolinkhead) then
local no_links = m_headword_data.no_multiword_links
if not (no_links[langcode] or no_links[full_langcode]) and export.head_is_multiword(default_head) then
default_head = export.add_multiword_links(default_head, true)
end
end
if is_reconstructed then
default_head = "*" .. default_head
end
------------ 6. Check the namespace against the language type. ------------
if namespace == "Từ_tái_tạo" then
if lang_reconstructed then
error("Entries in " .. langname .. " must be placed in the Reconstruction: namespace")
elseif data.lang:hasType("appendix-constructed") then
error("Entries in " .. langname .. " must be placed in the Appendix: namespace")
end
elseif namespace == "Citations" or namespace == "Thesaurus" then
error("Headword templates should not be used in the " .. namespace .. ": namespace.")
end
------------ 7. Fill in missing values in `data.heads`. ------------
-- True if any script among the headword scripts has spaces in it.
local any_script_has_spaces = false
-- True if any term has a redundant head= param.
local has_redundant_head_param = false
for _, head in ipairs(data.heads) do
------ 7a. If missing head, replace with default head.
if not head.term then
head.term = default_head
elseif head.term == default_head then
has_redundant_head_param = true
elseif is_anti_asterisk and head.term == "!!" then
-- If explicit head=!! is given, it's an anti-asterisk term and we fill in the default head.
head.term = "!!" .. default_head
elseif head.term:find("^[!?]$") then
-- If explicit head= just consists of ! or ?, add it to the end of the default head.
head.term = default_head .. head.term
end
head.term_no_initial_bang_bang = is_anti_asterisk and head.term:sub(3) or head.term
if is_reconstructed then
local head_term = head.term
if head_term:find("%[%[") then
head_term = remove_links(head_term)
end
if head_term:sub(1, 1) ~= "*" then
error("The headword '" .. head_term .. "' must begin with '*' to indicate that it is reconstructed.")
end
end
------ 7b. Try to detect the script(s) if not provided. If a per-head script is provided, that takes precedence,
------ otherwise fall back to the overall script if given. If neither given, autodetect the script.
local auto_sc = data.lang:findBestScript(head.term)
if (
auto_sc:getCode() == "None" and
find_best_script_without_lang(head.term):getCode() ~= "None"
) then
insert(data.categories, "Mục từ có chữ viết không chuẩn " .. full_langname)
end
if not (head.sc or data.sc) then -- No script code given, so use autodetected script.
head.sc = auto_sc
else
if not head.sc then -- Overall script code given.
head.sc = data.sc
end
-- Track uses of sc parameter.
if head.sc:getCode() == auto_sc:getCode() then
track("redundant script code", data.lang)
if not data.no_script_code_cat then
insert(data.categories, "Mục từ có mã chữ viết thừa " .. full_langname)
end
else
track("non-redundant manual script code", data.lang)
if not data.no_script_code_cat then
insert(data.categories, "Mục từ có mã chữ viết thủ công không thừa " .. full_langname)
end
end
end
-- If using a discouraged character sequence, add to maintenance category.
if head.sc:hasNormalizationFixes() == true then
local composed_head = toNFC(head.term)
if head.sc:fixDiscouragedSequences(composed_head) ~= composed_head then
insert(data.whole_page_categories, "Trang có sử dụng chuỗi ký tự không được khuyến khích")
end
end
any_script_has_spaces = any_script_has_spaces or head.sc:hasSpaces()
------ 7c. Create automatic transliterations for any non-Latin headwords without manual translit given
------ (provided automatic translit is available, e.g. not in Persian or Hebrew).
-- Make transliterations
head.tr_manual = nil
-- Try to generate a transliteration if necessary
if head.tr == "-" then
head.tr = nil
else
local notranslit = m_headword_data.notranslit
if not (notranslit[langcode] or notranslit[full_langcode]) and head.sc:isTransliterated() then
head.tr_manual = not not head.tr
local text = head.term_no_initial_bang_bang
if not data.lang:link_tr(head.sc) then
text = remove_links(text)
end
local automated_tr = data.lang:transliterate(text, head.sc)
if automated_tr then
local manual_tr = head.tr
if manual_tr then
if remove_links(manual_tr) == remove_links(automated_tr) then
insert(data.categories, "Mục từ có chuyển tự thừa " .. full_langname)
else
insert(data.categories, "Mục từ có chuyển tự thủ công không thừa " .. full_langname)
end
end
if not manual_tr then
head.tr = automated_tr
end
end
-- There is still no transliteration?
-- Add the entry to a cleanup category.
if not head.tr then
head.tr = "<small>cần chuyển tự</small>"
-- FIXME: No current support for 'Request for transliteration of Classical Persian terms' or similar.
-- Consider adding this support in [[Module:category tree/poscatboiler/data/entry maintenance]].
insert(data.categories, "Yêu cầu chuyển tự mục từ " .. full_langname)
else
-- Otherwise, trim it.
head.tr = trim(head.tr)
end
end
end
-- Link to the transliteration entry for languages that require this.
if head.tr and data.lang:link_tr(head.sc) then
head.tr = full_link{
term = head.tr,
lang = data.lang,
sc = get_script("Latn"),
tr = "-"
}
end
end
------------ 8. Maybe tag the title with the appropriate script code, using the `display_title` mechanism. ------------
-- Assumes that the scripts in "toBeTagged" will never occur in the Reconstruction namespace.
-- (FIXME: Don't make assumptions like this, and if you need to do so, throw an error if the assumption is violated.)
-- Avoid tagging ASCII as Hani even when it is tagged as Hani in the headword, as in [[check]]. The check for ASCII
-- might need to be expanded to a check for any Latin characters and whitespace or punctuation.
local display_title
-- Where there are multiple headwords, use the script for the first. This assumes the first headword is similar to
-- the pagename, and that headwords that are in different scripts from the pagename aren't first. This seems to be
-- about the best we can do (alternatively we could potentially do script detection on the pagename).
local dt_script = data.heads[1].sc
local dt_script_code = dt_script:getCode()
local page_non_ascii = namespace == "" and not page.pagename:find("^[%z\1-\127]+$")
local unsupported_pagename, unsupported = page.full_raw_pagename:gsub("^Tiêu đề không được hỗ trợ/", "")
if unsupported == 1 and page.unsupported_titles[unsupported_pagename] then
display_title = 'Tiêu đề không được hỗ trợ/<span class="' .. dt_script_code .. '">' .. page.unsupported_titles[unsupported_pagename] .. '</span>'
elseif page_non_ascii and m_headword_data.toBeTagged[dt_script_code]
or (dt_script_code == "Jpan" and (text_in_script(page.pagename, "Hira") or text_in_script(page.pagename, "Kana")))
or (dt_script_code == "Kore" and text_in_script(page.pagename, "Hang")) then
display_title = '<span class="' .. dt_script_code .. '">' .. page.full_raw_pagename .. '</span>'
-- Keep Han entries region-neutral in the display title.
elseif page_non_ascii and (dt_script_code == "Hant" or dt_script_code == "Hans") then
display_title = '<span class="Hani">' .. page.full_raw_pagename .. '</span>'
elseif namespace == "Từ tái tạo" then
local matched
display_title, matched = ugsub(
page.full_raw_pagename,
"^(Từ tái tạo:[^/]+/)(.+)$",
function(before, term)
return before .. tag_text(term, data.lang, dt_script)
end
)
if matched == 0 then
display_title = nil
end
end
-- FIXME: Generalize this.
-- If the current language uses Aran (Nastaliq), e.g. Urdu, and there's more than one language on the page, don't
-- set the display title because we don't want Nastaliq for terms that also exist in other languages that don't
-- display in Nastaliq (e.g. Arabic or Persian). Because the word "Urdu" occurs near the end of the alphabet, Urdu
-- fonts tend to override the fonts of other languages. FIXME: This is checking for more than one language on the
-- page but instead needs to check if there are any languages using scripts other than Aran.
if dt_script_code == "Aran" and page.L2_list.n > 1 then
display_title = nil
end
if display_title then
mw.getCurrentFrame():callParserFunction(
"DISPLAYTITLE",
display_title
)
end
------------ 9. Insert additional categories. ------------
if data.force_cat_output then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/force cat output]]
track("force cat output")
end
if has_redundant_head_param then
if not data.no_redundant_head_cat then
-- This is not the right way to go about this; too many exceptions and problems due to language-specific headword
-- handling customization. If we want this, it should be opt-in by a given language passing in the default headword.
-- insert(data.categories, "Mục từ có tham số head thừa " .. full_langname)
end
end
if namespace == "Từ tái tạo" and not lang_reconstructed then
insert(data.categories, "Mục từ tái tạo " .. full_langname)
end
-- If the first head is multiword (after removing links), maybe insert into "LANG multiword terms".
if not data.nomultiwordcat and not is_varform_only and any_script_has_spaces and postype == ucfirst("mục từ") then
local no_multiword_cat = m_headword_data.no_multiword_cat
if not (no_multiword_cat[langcode] or no_multiword_cat[full_langcode]) then
-- Check for spaces or hyphens, but exclude prefixes and suffixes.
-- Use the pagename, not the head= value, because the latter may have extra
-- junk in it, e.g. superscripted text that throws off the algorithm.
local no_hyphen = m_headword_data.hyphen_not_multiword_sep
-- Exclude hyphens if the data module states that they should for this language.
local checkpattern = (no_hyphen[langcode] or no_hyphen[full_langcode]) and ".[%s፡]." or ".[%s%-፡]."
local is_multiword = umatch(page.pagename, checkpattern)
if is_multiword and not non_categorizable(page.full_raw_pagename) then
insert(data.categories, "Mục từ có chứa nhiều từ " .. full_langname)
elseif not is_multiword then
local long_word_threshold = m_headword_data.long_word_thresholds[langcode] or
m_headword_data.long_word_thresholds[full_langcode]
if long_word_threshold and ulen(page.pagename) >= long_word_threshold then
insert(data.categories, "Từ dài " .. full_langname)
end
end
end
end
-- Determine whether to insert a category 'LANGNAME POS in SCRIPT'. If there are multiple heads, we may need to check
-- each head, as the heads may (theoretically) have different scripts.
local default_sccat = m_headword_data.default_sccat
if data.sccat or not is_varform_only and (default_sccat[langcode] or langcode ~= full_langcode and default_sccat[full_langcode]) then
local function needs_sccat(sccat_entry, sc)
if sccat_entry == true or not sccat_entry then
return sccat_entry
end
if type(sccat_entry) == "table" then
local in_list = contains(sccat_entry, sc:getCode())
if sccat_entry[1] == "not" then
in_list = not in_list
end
return in_list
end
return nil
end
for _, head in ipairs(data.heads) do
-- First check the `sccat` specified at the {{head}} level.
local this_needs_sccat = needs_sccat(data.sccat, head.sc)
-- If that wasn't given, check the default sccat at the language level for the lang code.
if this_needs_sccat == nil and not is_varform_only then
this_needs_sccat = needs_sccat(default_sccat[langcode], head.sc)
end
-- If that wasn't found and the lang code is an etym code, check the default sccat at the parent language level.
if this_needs_sccat == nil and not is_varform_only and langcode ~= full_langcode then
this_needs_sccat = needs_sccat(default_sccat[full_langcode], head.sc)
end
if this_needs_sccat then
insert(data.categories, data.pos_category .. " dùng " ..
head.sc:getDisplayForm(data.lang) .. " " .. full_langname)
end
end
end
-- Reconstructed terms often use weird combinations of scripts and realistically aren't spelled so much as notated.
if namespace ~= "Từ tái tạo" and not is_varform_only then
-- Map from languages to a string containing the characters to ignore when considering whether a term has
-- multiple written scripts in it. Typically these are Greek or Cyrillic letters used for their phonetic
-- values.
local characters_to_ignore = {
["aaq"] = "αάὰ", -- Penobscot (Algonquian)
["acy"] = "δθ", -- Cypriot Arabic
["aez"] = "β", -- Aeka (Trans-New Guinea)
["anc"] = "γ", -- Ngas (Chadic/Afroasiatic)
["aou"] = "χ", -- A'ou (Kra-Dai)
["art-blk"] = "ч", -- Bolak (conlang)
["awg"] = "β", -- Anguthimri (Pama-Nyungan)
["az"] = "ь", -- Azerbaijani (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["ba"] = "ь", -- Bashkir (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["bhp"] = "β", -- Bima (Austronesian)
["bjz"] = "β", -- Baruga (Trans-New Guinea)
["byk"] = "θ", -- Biao (Kra-Dai)
["cdy"] = "θ", -- Chadong (Kra-Dai)
["chp"] = "θ", -- Chipewyan (Athabaskan)
["cjh"] = "χ", -- Upper Chehalis (Salishan)
["clm"] = "χ", -- Klallam (Salishan)
["col"] = "χ", -- Colombia-Wenatchi (Salishan)
["coo"] = "χθ", -- Comox (Salishan)
["crx"] = "θ", -- Carrier (Athabaskan)
["ets"] = "θ", -- Yekhee (Edoid/Niger-Congo)
["ett"] = "χ", -- Etruscan (isolate; in romanizations)
["fla"] = "χ", -- Montana Salish (Salishan)
["grt"] = "་", -- Garo (South Asian Sino-Tibetan)
["gmw-gts"] = "χ", -- Gottscheerish (Bavarian variant spoken in Slovenia)
["hur"] = "χθ", -- Halkomelem (Salishan)
["itc-psa"] = "f", -- Pre-Samnite (Italic; normally written in Greek)
["izh"] = "ь", -- Ingrian (Finnic)
["kic"] = "θ", -- Kickapoo (Algonquian)
["kk"] = "ь", -- Kazakh (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["ky"] = "ь", -- Kyrgyz (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["lil"] = "χ", -- Lillooet (Salishan)
["lsi"] = "ꓹ", -- Lashi (Lolo-Burmese/Sino-Tibetan; represents a glottal stop)
["mhz"] = "β", -- Mor (Austronesian)
["mqn"] = "β", -- Moronene (Austronesian)
["neg"]= "ӡā", -- Negidal (Tungusic; normally in Cyrillic)
["oka"] = "χ", -- Okanagan (Salishan)
["ole"] = "θ", -- Olekha (Sino-Tibetan)
["oui"] = "γβ", -- Old Uyghur (Turkic; FIXME: others? E.g. Greek delta (δ)?)
["pox"] = "χ", -- Polabian (West Slavic)
["rif"] = "ε", -- Tarifit (Berber)
["rom"] = "Θθ", -- Romani (Indic: International Standard; two different thetas???)
["rpn"] = "β", -- Repanbitip (Austronesian)
["sah"] = "ь", -- Yakut (Turkic; 1929 - 1939 Latin spelling)
["sit-jap"] = "χ", -- Japhug (Sino-Tibetan)
["sjw"] = "θ", -- Shawnee (Algonquian)
["squ"] = "χ", -- Squamish (Salishan)
["str"] = "χθ", -- Saanich (Salishan)
["teh"] = "χ", -- Tehuelche (Chonan; spoken in Argentina)
["tep"] = "η", -- Tepecano (Uto-Aztecan)
["thp"] = "χ", -- Thompson (Salishan)
["tk"] = "ь", -- Turkmen (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["tt"] = "ь", -- Kazakh (Turkic; Yañalif Latin spelling, c. 1928 - 1938)
["twa"] = "χ", -- Twana (Salishan)
["wbl"] = "ы", -- Wakhi (Iranian)
["xbc"] = "ϸ", -- Bactrian (Iranian; represents š; normally written in Greek)
["yha"] = "θ", -- Baha (Kra-Dai)
["za"] = "зч", -- Zhuang (Tai/Kra-Dai); 1957-1982 alphabet used two Cyrillic letters (as well as some others like
-- ƃ, ƅ, ƨ, ɯ and ɵ that look like Cyrillic or Greek but are actually Latin)
["zlw-slv"] = "χђћ", -- Slovincian (West Slavic; FIXME: χ is Greek, the other two are Cyrillic, but I'm not sure
-- the currect characters are being chosen in the entry names)
["zng"] = "θ", -- Mang (Mon-Khmer)
["ztp"] = "θ", -- Loxicha Zapotec (Zapotecan)
}
-- Determine how many real scripts are found in the pagename, where we exclude symbols and such. We exclude
-- scripts whose `character_category` is false as well as Zmth (mathematical notation symbols), which has a
-- category of "Mathematical notation symbols". When counting scripts, we need to elide language-specific
-- variants because e.g. Beng and as-Beng have slightly different characters but we don't want to consider them
-- two different scripts (e.g. [[এৰ]] has two characters which are detected respectively as Beng and as-Beng).
local seen_scripts = {}
local num_seen_scripts = 0
local num_loops = 0
local canon_pagename = page.pagename
local ch_to_ignore = characters_to_ignore[full_langcode]
if ch_to_ignore then
canon_pagename = ugsub(canon_pagename, "[" .. ch_to_ignore .. "]", "")
end
while true do
if canon_pagename == "" or num_seen_scripts >= 2 or num_loops >= 10 then
break
end
-- Make sure we don't get into a loop checking the same script over and over again; happens with e.g. [[ᠪᡳ]]
num_loops = num_loops + 1
local pagename_script = find_best_script_without_lang(canon_pagename, "None only as last resort")
local script_chars = pagename_script.characters
if not script_chars then
-- we are stuck; this happens with None
break
end
local script_code = pagename_script:getCode()
local replaced
canon_pagename, replaced = ugsub(canon_pagename, "[" .. script_chars .. "]", "")
if (
replaced and
script_code ~= "Zmth" and
(script_data or get_script_data())[script_code] and
script_data[script_code].character_category ~= false
) then
script_code = script_code:gsub("^.-%-", "")
if not seen_scripts[script_code] then
seen_scripts[script_code] = true
num_seen_scripts = num_seen_scripts + 1
end
end
end
if num_seen_scripts > 1 then
insert(data.categories, "Mục từ được viết bằng nhiều chữ viết " .. full_langname)
end
end
-- Categorise for unusual characters. Takes into account combining characters, so that we can categorise for characters with diacritics that aren't encoded as atomic characters (e.g. U̠). These can be in two formats: single combining characters (i.e. character + diacritic(s)) or double combining characters (i.e. character + diacritic(s) + character). Each can have any number of diacritics.
local standard = data.lang:getStandardCharacters()
if not is_varform_only and standard and not non_categorizable(page.full_raw_pagename) then
local function char_category(char)
local specials = {
["#"] = "number sign",
["("] = "parentheses",
[")"] = "parentheses",
["<"] = "angle brackets",
[">"] = "angle brackets",
["["] = "square brackets",
["]"] = "square brackets",
["_"] = "underscore",
["{"] = "braces",
["|"] = "vertical line",
["}"] = "braces",
["ß"] = "ẞ",
["\205\133"] = "", -- this is UTF-8 for U+0345 ( ͅ)
["\239\191\189"] = "replacement character",
}
char = toNFD(char)
:gsub(".[\128-\191]*", function(m)
local new_m = specials[m]
new_m = new_m or m:uupper()
return new_m
end)
return toNFC(char)
end
if full_langcode ~= "hi" and full_langcode ~= "lo" then
local standard_chars_scripts = {}
for _, head in ipairs(data.heads) do
standard_chars_scripts[head.sc:getCode()] = true
end
-- Iterate over the scripts, in case there is more than one (as they can have different sets of standard characters).
for code in pairs(standard_chars_scripts) do
local sc_standard = data.lang:getStandardCharacters(code)
if sc_standard then
if page.pagename_len > 1 then
local explode_standard = {}
local function explode(char)
explode_standard[char] = true
return ""
end
local sc_standard_exploded = ugsub(sc_standard, page.comb_chars.combined_double, explode)
-- The following is correct; it relies on side-effecing the explode_standard[] table.
ugsub(sc_standard_exploded, page.comb_chars.combined_single, explode):gsub(".[\128-\191]*", explode)
local num_cat_inserted
for char in pairs(page.explode_pagename) do
if not explode_standard[char] then
if char:find("[0-9]") then
if not num_cat_inserted then
insert(data.categories, "Từ đánh vần với số " .. full_langname)
num_cat_inserted = true
end
elseif ufind(char, page.emoji_pattern) then
insert(data.categories, "Từ đánh vần với emoji " .. full_langname)
else
local upper = char_category(char)
if not explode_standard[upper] then
char = upper
end
insert(data.categories, "Từ đánh vần với " .. char .. " " .. full_langname)
end
end
end
end
-- If a diacritic doesn't appear in any of the standard characters, also categorise for it generally.
sc_standard = toNFD(sc_standard)
for diacritic in ugmatch(page.decompose_pagename, page.comb_chars.diacritics_single) do
if not umatch(sc_standard, diacritic) then
insert(data.categories, "Từ đánh vần với ◌" .. diacritic .. " " .. full_langname)
end
end
for diacritic in ugmatch(page.decompose_pagename, page.comb_chars.diacritics_double) do
if not umatch(sc_standard, diacritic) then
insert(data.categories, "Từ đánh vần với ◌" .. diacritic .. "◌ " .. full_langname)
end
end
end
end
-- Ancient Greek, Hindi and Lao handled the old way for now, as their standard chars still need to be converted to the new format (because there are a lot of them).
elseif ulen(page.pagename) ~= 1 then
for character in ugmatch(page.pagename, "([^" .. standard .. "])") do
local upper = char_category(character)
if not umatch(upper, "[" .. standard .. "]") then
character = upper
end
insert(data.categories, "Từ đánh vần với " .. character .. " " .. full_langname)
end
end
end
if not is_varform_only and data.heads[1].sc:isSystem("alphabet") then
local pagename, i = page.pagename:ulower(), 2
while umatch(pagename, "(%a)" .. ("%1"):rep(i)) do
i = i + 1
insert(data.categories, full_langname .. " terms with " .. i .. " consecutive instances of the same letter")
end
end
-- Categorise for palindromes
if not is_varform_only and not data.nopalindromecat and namespace ~= "Từ tái tạo" and ulen(page.pagename) > 2
-- FIXME: Use of first script here seems hacky. What is the clean way of doing this in the presence of
-- multiple scripts?
and is_palindrome(page.pagename, data.lang, data.heads[1].sc) then
insert(data.categories, "Mục từ viết xuôi ngược đều giống nhau " .. full_langname)
end
if namespace == "" and not lang_reconstructed then
for _, head in ipairs(data.heads) do
if page.full_raw_pagename ~= get_link_page(remove_links(head.term), data.lang, head.sc) then
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/pagename spelling mismatch]]
-- [[Special:WhatLinksHere/Wiktionary:Tracking/headword/pagename spelling mismatch/LANGCODE]]
track("pagename spelling mismatch", data.lang)
break
end
end
end
-- Add red link category if called for and we're not a "large" page, where such checks are disabled.
if data.checkredlinks and not m_headword_data.large_pages[m_headword_data.pagename] then
local plposcat = type(data.checkredlinks) == "string" and data.checkredlinks or data.pos_category
check_red_link_inflections_top_level(data, plposcat)
end
-- Add to various maintenance categories.
export.maintenance_cats(page, data.lang, data.categories, data.whole_page_categories)
------------ 10. Format and return headwords, genders, inflections and categories. ------------
-- Format and return all the gathered information. This may add more categories (e.g. gender/number categories),
-- so make sure we do it before evaluating `data.categories`.
local text = '<span class="headword-line">' ..
format_headword(data) ..
format_headword_genders(data, is_varform_only) ..
format_top_level_inflections(data) .. '</span>'
-- Language-specific categories.
local cats = format_categories(
data.categories, data.lang, data.sort_key, page.encoded_pagename,
data.force_cat_output or test_force_categories, data.heads[1].sc
)
-- Language-agnostic categories.
local whole_page_cats = format_categories(
data.whole_page_categories, nil, "-"
)
return text .. cats .. whole_page_cats
end
return export
4900x3dn5nbad82cz3cvba75skrcvut
Thành viên:TheHighFighter2/Trang con 3
2
269152
2576406
2574780
2026-11-08T12:29:30Z
TheHighFighter2
42988
2576406
wikitext
text/x-wiki
<div style="text-align: center; font-size: 24px; font-weight: bold;">
Danh Sách Mục Từ Tiếng Việt Còn Thiếu
</div>
==A, Ă, Â==
[[AI tạo sinh]]; [[áo giao lĩnh]]; [[anh em cây khế]]; [[áo tràng vạt]]; [[áo tràng]]; [[ăn của rừng rưng rưng nước mắt]]; [[ăn không nên đọi, nói không nên lời]]; [[ăn không ngon, ngủ không yên]]; [[ăn lồn]]; [[ăn ngon ngủ kĩ]]/[[ăn ngon ngủ kỹ]]; [[ăn ngon ngủ yên]]; [[ấm dâu]];
==B==
[[ba mươi chưa phải là Tết]]; [[bánh kẹo]]; [[bánh mì và rạp xiếc]]; [[băng gâu]]; [[bằng niềm tin]]; [[bề mặt tấn công]]; [[bỉ vỏ]]; [[bói Kiều]]; [[bom xịt]]; [[bồ côi bồ cút]]; [[bổ báo]]; [[bời rời]]; [[bụng ỏng đít beo]]; [[bức xạ kế]];
==C==
[[cạn cợt]]; [[cá sấu lên bờ]]; [[cần cù bù thông minh]]; [[cha mẹ sinh con, trời sinh tính]]; [[cha nó lú, chú nó khôn]]; [[chảy máu chất xám]]; [[chất độc màu da cam]]; [[chém cha không bằng pha tiếng]]; [[chèo nhị thập tứ hiếu]]; [[chí chương]]; [[chị em cây khế]]; [[chim Lạc]]; [[chó cỏ]]; [[chửi cha không bằng pha tiếng]]; [[chữ như gà bới]]; [[cọ ỏm]]; [[cơm búng]]; [[cù lủ]]/[[cù lũ]]/[[cú lủ]];
==D, Đ==
[[dao tem]]; [[dép tổ ong]]; [[di biến động]]; [[đa đảng]]; [[đào hát]]; [[đặc miễn]]; [[đất lâm nghiệp]]; [[đầu buồi]]; [[đầu tro mặt muội]]; [[đầu trời cuối đất]]; [[đi C]]; [[dịch đình]]; [[điện não]]; [[điệp giấy]]; [[đi K]]; [[đòng đành]]; [[đồ bơi]]; [[đổ tháo]]; [[đu càng]]; [[đùm đề]]; [[đùm đùm đề đề]];
==E, Ê==
==G==
[[gái đứng đường]]; [[gà nhà]];
==H==
[[hài độc thoại]]; [[hạn lượng]]; [[hấp diêm]]; [[hậu COVID]]; [[hậu thực dân]]; [[hỏng hẻo]]; [[huyệt mả]];
==I==
==K==
[[khảo lược]]; [[khăn bàn lông]]; [[khét nắng]]; [[khét rẹt]];
==L==
[[lon chon]]; [[lốp dự phòng]]; [[lô rơi]];
==M==
[[mã đáo thành công]]; [[máy bay bà già]]; [[mập cụi]]; [[mèo Ba Tư]]; [[móc nhách]]; [[một chữ là thầy, nửa chữ cũng là thầy]]; [[mới cóng]]/[[mới coóng]];
==N==
[[ngạn giải]]; [[ngoại giao cây tre]]; [[ngục ngoặc]]; [[ngựa bà]]; [[ngựa cu]]; [[nhà mát]]; [[nhân văn số]]; [[nhất quỷ nhì ma, thứ ba học trò]]; [[nông nghiệp thẳng đứng]];
==O, Ô, Ơ==
[[ông kẹ]];
==P==
[[phân biệt vùng miền]]; [[phi công trẻ lái máy bay bà già]]; [[phì đại]]; [[phim mát]]; [[phong ba bão táp không bằng ngữ pháp Việt Nam]]; [[phở bò]];
==Q==
[[quá 180 phút]]; [[quan họ hiếu]]; [[quần sinh]];
==R==
==S==
[[sòng sành]]; [[so se]]; [[sò sè]]; [[sò sò]];
==T==
[[tai biến khí hậu]]; [[ten ben]]; [[tẻn tẻn]]; [[Tết Độc lập]]; [[tháng cô hồn]]; [[thối não]]; [[thừu lựu]]; [[tiêu chuẩn kép]]; [[Tiểu Á]]; [[tiểu mộc]]; [[tình tệ]]; [[toàn đồ]]; [[trí tuệ nhân tạo tạo sinh]]; [[trò Kiều]]; [[tròn vìn]]; [[tù nhân lương tâm]];
==U, Ư==
[[u nguyên bào thần kinh đệm]]; [[ù thông]];
==V==
[[vãi chài]]; [[Va linh tinh]]; [[Việt gian]]; [[Việt hóa]]/[[Việt hoá]]; [[Việt Nam hóa]]/[[Việt Nam hoá]]; [[vũ trang đến tận răng]];
==X==
[[xăng-căng]]/[[xăng căng]]; [[xanh lá]]; [[xanh lục]]; [[xanh nước biển]]; [[xanh xảnh]]; [[xăm hường]]; [[xe bồ câu]]; [[xuntan]]; [[xúp-lê]]/[[xúp lê]];
==Y==
czjg0dx7afbjmxhyy50383txhkueyg2
Mô đun:languages/data/3/a
828
270567
2576441
2576028
2026-11-08T14:26:36Z
Hiyuune
50834
2576441
Scribunto
text/plain
local m_langdata = require("Module:languages/data")
-- Loaded on demand, as it may not be needed (depending on the data).
local function u(...)
u = require("Module:string utilities").char
return u(...)
end
local c = m_langdata.chars
local p = m_langdata.puaChars
local s = m_langdata.shared
local m = {}
m["aaa"] = {
"tiếng Ghotuo",
35463,
"alv-yek",
"Latn",
"Tiếng Ghotuo",
"Ghotuo",
}
m["aab"] = {
"tiếng Alumu-Tesu",
35034,
"nic-alu",
"Latn",
"Tiếng Alumu-Tesu",
"Alumu-Tesu",
}
m["aac"] = {
"tiếng Ari",
1811224,
"paa-pag",
"Latn",
"Tiếng Ari",
"Ari",
}
m["aad"] = {
"tiếng Amal",
56708,
"paa-iwm",
"Latn",
"Tiếng Amal",
"Amal",
}
-- "aae" IS TREATED AS "sq", SEE WT:LT
m["aaf"] = {
"tiếng Aranadan",
3507928,
"dra-mal",
"Mlym",
"Tiếng Aranadan",
"Aranadan",
translit = {Mlym = "ml-translit"},
}
m["aag"] = {
"tiếng Ambrak",
4741706,
"qfa-tor",
"Latn",
"Tiếng Ambrak",
"Ambrak",
}
m["aah"] = {
"Abu' Arapesh",
4670715,
"qfa-tor",
"Latn",
}
m["aai"] = {
"Arifama-Miniafia",
4790560,
"poz-ocw",
"Latn",
}
m["aak"] = {
"tiếng Ankave",
3446690,
"ngf",
"Latn",
"Tiếng Ankave",
"Ankave",
}
m["aal"] = {
"tiếng Afade",
56434,
"cdc-cbm",
"Latn",
"Tiếng Afade",
"Afade",
}
m["aan"] = {
"Anambé",
3507873,
"tup-gua",
"Latn",
}
m["aap"] = {
"Pará Arára",
56807,
"sai-pek",
"Latn",
}
m["aaq"] = {
"tiếng Đông Abenaki",
3515185,
"alg-abp",
"Latn",
"Tiếng Đông Abenaki",
"Đông Abenaki",
}
m["aas"] = {
"tiếng Aasax",
56620,
"cus-sou",
"Latn",
"Tiếng Aasax",
"Aasax",
}
-- "aat" IS TREATED AS "sq", SEE WT:LT
m["aau"] = {
"tiếng Abau",
3073568,
"paa-spk",
"Latn",
"Tiếng Abau",
"Abau",
}
m["aaw"] = {
"tiếng Solong",
7558834,
"poz-ocw",
"Latn",
"Tiếng Solong",
"Solong",
}
m["aax"] = {
"Mandobo Atas",
12636156,
"ngf",
"Latn",
}
m["aaz"] = {
"tiếng Amarasi",
4740192,
"poz-tim",
"Latn",
"Tiếng Amarasi",
"Amarasi",
}
m["aba"] = {
"Abé",
34833,
"alv-lag",
"Latn",
}
m["abb"] = {
"tiếng Bankon",
34860,
"bnt-bsa",
"Latn",
"Tiếng Bankon",
"Bankon",
}
m["abc"] = {
"Ambala Ayta",
3448896,
"phi",
"Latn",
}
m["abd"] = {
"Camarines Norte Agta",
3399682,
"phi",
"Latn",
}
m["abe"] = {
"tiếng Tây Abenaki",
17502788,
"alg-abp",
"Latn",
"Tiếng Tây Abenaki",
"Tây Abenaki",
}
m["abf"] = {
"Abai Sungai",
4663287,
"poz-san",
"Latn",
}
m["abg"] = {
"tiếng Abaga",
3507954,
"paa-kag",
"Latn",
"Tiếng Abaga",
"Abaga",
}
m["abh"] = {
"tiếng Ả Rập Tajikistan",
56833,
"sem-arb",
"Arab",
"Tiếng Ả Rập Tajikistan",
"Ả Rập Tajikistan",
entry_name = "ar-entryname",
}
m["abi"] = {
"tiếng Abidji",
34781,
"alv-lag",
"Latn",
"Tiếng Abidji",
"Abidji",
}
m["abj"] = {
"Aka-Bea",
2356391,
"qfa-ads",
"Latn",
}
m["abl"] = {
"Abung",
49215,
"poz-lgx",
"Latn",
}
m["abm"] = {
"tiếng Abanyom",
7502,
"nic-eko",
"Latn",
"Tiếng Abanyom",
"Abanyom",
}
m["abn"] = {
"Abua",
34835,
"nic-cde",
"Latn",
}
m["abo"] = {
"tiếng Abon",
35121,
"nic-tvn",
"Latn",
"Tiếng Abon",
"Abon",
}
m["abp"] = {
"Abenlen Ayta",
3436621,
"phi",
"Latn",
}
m["abq"] = {
"tiếng Abaza",
27567,
"cau-abz",
"Cyrl, Latn",
"Tiếng Abaza",
"Abaza",
translit = {Cyrl = "abq-translit"},
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {
Cyrl = s["cau-Cyrl-entryname"],
Latn = s["cau-Latn-entryname"],
},
sort_key = {
Cyrl = {
from = {
"гъв", "гъь", "гӏв", "джв", "джь", "къв", "къь", "кӏв", "кӏь", "хъв", "хӏв", "чӏв", -- 3 chars
"гв", "гъ", "гь", "гӏ", "дж", "дз", "ё", "жв", "жь", "кв", "къ", "кь", "кӏ", "ль", "лӏ", "пӏ", "тл", "тш", "тӏ", "фӏ", "хв", "хъ", "хь", "хӏ", "цӏ", "чв", "чӏ", "шв", "шӏ" -- 2 chars
},
to = {
"г" .. p[3], "г" .. p[4], "г" .. p[7], "д" .. p[2], "д" .. p[3], "к" .. p[3], "к" .. p[4], "к" .. p[7], "к" .. p[8], "х" .. p[3], "х" .. p[6], "ч" .. p[3],
"г" .. p[1], "г" .. p[2], "г" .. p[5], "г" .. p[6], "д" .. p[1], "д" .. p[4], "е" .. p[1], "ж" .. p[1], "ж" .. p[2], "к" .. p[1], "к" .. p[2], "к" .. p[5], "к" .. p[6], "л" .. p[1], "л" .. p[2], "п" .. p[1], "т" .. p[1], "т" .. p[2], "т" .. p[3], "ф" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[4], "х" .. p[5], "ц" .. p[1], "ч" .. p[1], "ч" .. p[2], "ш" .. p[1], "ш" .. p[2]
}
},
},
}
m["abr"] = {
"tiếng Abron",
34831,
"alv-ctn",
"Latn",
"Tiếng Abron",
"Abron",
ancestors = "ak",
}
m["abs"] = {
"tiếng Mã Lai Ambon",
3124354,
"crp",
"Latn",
"Tiếng Mã Lai Ambon",
"Mã Lai Ambon",
ancestors = "ms",
}
m["abt"] = {
"tiếng Ambulas",
3508015,
"paa-spk",
"Latn",
"Tiếng Ambulas",
"Ambulas",
}
m["abu"] = {
"tiếng Abure",
34767,
"alv-ptn",
"Latn",
"Tiếng Abure",
"Abure",
}
m["abv"] = {
"Baharna Arabic",
56576,
"sem-arb",
"Arab",
entry_name = "ar-entryname",
}
m["abw"] = {
"Pal",
7126121,
"ngf-mad",
"Latn",
}
m["abx"] = {
"Inabaknon",
2820163,
"poz-sbj",
"Latn",
}
m["aby"] = {
"Aneme Wake",
3508107,
"ngf",
"Latn",
}
m["abz"] = {
"tiếng Abui",
2822110,
"qfa-tap",
"Latn",
"Tiếng Abui",
"Abui",
}
m["aca"] = {
"tiếng Achawa",
2822982,
"awd",
"Latn",
"Tiếng Achawa",
"Achawa",
}
m["acb"] = {
"Áncá",
11130787,
"nic-mom",
"Latn",
}
m["acd"] = {
"Gikyode",
35256,
"alv-gng",
"Latn",
}
m["ace"] = {
"tiếng Aceh",
27683,
"cmc",
"Latn, ms-Arab",
"Tiếng Aceh",
"Aceh",
standardChars = {
Latn = "AaBbCcDdEeÉéÈèËëFfGgHhIiJjKkLlMmNnOoÔôÖöPpQqRrSsTtUuVvWwXxYyZz", -- current orthography (not yet add Arab)
c.punc
},
}
m["ach"] = {
"tiếng Acholi",
34926,
"sdv-los",
"Latn",
"Tiếng Acholi",
"Acholi",
}
m["aci"] = {
"Aka-Cari",
2670418,
"qfa-adn",
"Latn",
}
m["ack"] = {
"Aka-Kora",
3433680,
"qfa-adn",
"Latn",
}
m["acl"] = {
"Akar-Bale",
3436825,
"qfa-ads",
"Latn",
}
m["acm"] = {
"tiếng Ả Rập Iraq",
56232,
"sem-arb",
"Arab",
"Tiếng Ả Rập Iraq",
"Ả Rập Iraq",
entry_name = "ar-entryname",
}
m["acn"] = {
"tiếng A Xương",
56582,
"tbq-brm",
"Latn",
"Tiếng A Xương",
"A Xương",
}
m["acp"] = {
"tiếng Đông Acipa",
5329945,
"nic-kmk",
"Latn",
"Tiếng Đông Acipa",
"Đông Acipa",
}
m["acr"] = {
"tiếng Achi",
34774,
"myn",
"Latn",
"Tiếng Achi",
"Achi",
}
m["acs"] = {
"Acroá",
2829146,
"sai-cje",
"Latn",
}
m["acu"] = {
"tiếng Achuar",
2823170,
"sai-jiv",
"Latn",
"Tiếng Achuar",
"Achuar",
}
m["acv"] = {
"tiếng Achumawi",
56661,
"nai-pal",
"Latn",
"Tiếng Achumawi",
"Achumawi",
}
m["acw"] = {
"tiếng Ả Rập Hijazi",
56608,
"sem-arb",
"Arab",
"Tiếng Ả Rập Hijazi",
"Ả Rập Hijazi",
entry_name = "ar-entryname",
}
m["acx"] = {
"tiếng Ả Rập Oman",
56630,
"sem-arb",
"Arab",
"Tiếng Ả Rập Oman",
"Ả Rập Oman",
entry_name = "ar-entryname",
}
m["acy"] = {
"tiếng Ả Rập Síp",
56416,
"sem-arb",
"Latn, Grek",
"Tiếng Ả Rập Síp",
"Ả Rập Síp",
ancestors = "acm",
standardChars = {
Latn = "AaBbCcDdΔδEeFfGgĠġĊċIiJjKkLlMmNnOoPpΘθRrSsTtUuVvWwXxYyZzŞş",
c.punc
},
entry_name = {remove_diacritics = c.grave .. c.acute .. c.breve},
}
m["acz"] = {
"tiếng Acheron",
34769,
"alv-tal",
"Latn",
"Tiếng Acheron",
"Acheron",
}
m["ada"] = {
"tiếng Adangme",
35141,
"alv-gda",
"Latn",
"Tiếng Adangme",
"Adangme",
}
m["adb"] = { -- rename or remove, see RFM
"Adabe",
36872,
nil,
"Latn",
}
m["add"] = {
"Dzodinka",
35266,
"nic-nka",
"Latn",
}
m["ade"] = {
"Adele",
27740,
"alv-ntg",
"Latn",
}
m["adf"] = {
"Dhofari Arabic",
56565,
"sem-arb",
"Arab",
entry_name = "ar-entryname",
}
m["adg"] = {
"Andegerebinha",
3508123,
"aus-pam",
"Latn",
}
m["adh"] = {
"Adhola",
1971400,
"sdv-los",
"Latn",
}
m["adi"] = {
"tiếng Adi",
56440,
"sit-tan",
"Latn",
"Tiếng Adi",
"Adi",
}
m["adj"] = {
"tiếng Adjukru",
34738,
"alv-lag",
"Latn",
}
m["adl"] = {
"tiếng Galo",
2857892,
"sit-tan",
"Latn",
"Tiếng Galo",
"Galo",
}
m["adn"] = {
"Adang",
3398276,
"qfa-tap",
"Latn",
}
m["ado"] = {
"Abu",
56659,
"paa-ram",
"Latn",
}
m["adp"] = {
"Adap",
3512402,
"sit-tib",
"Tibt",
ancestors = "dz",
translit = "Tibt-translit",
override_translit = true,
display_text = s["Tibt-displaytext"],
entry_name = s["Tibt-entryname"],
sort_key = "Tibt-sortkey",
wikipedia_article = "Dzongkha", -- Considered a dialect of Dzongkha
}
m["adq"] = {
"Adangbe",
34730,
"alv-gda",
"Latn",
ancestors = "ada",
}
m["adr"] = {
"Adonara",
4684505,
"poz-cet",
"Latn",
}
m["ads"] = {
"Adamorobe Sign Language",
27709,
"sgn",
"Latn", -- when documented
}
m["adt"] = {
"tiếng Adnyamathanha",
2225391,
"aus-psw",
"Latn",
"Tiếng Adnyamathanha",
"Adnyamathanha",
}
m["adu"] = {
"Aduge",
34734,
"alv-nwd",
"Latn",
ancestors = "opa",
wikipedia_article = "Okpamheri language",
}
m["adw"] = {
"Amondawa",
12626847,
"tup-gua",
"Latn",
}
m["ady"] = {
"tiếng Adygea",
27776,
"cau-cir",
"Cyrl, Latn, Arab",
"Tiếng Adygea",
"Adygea",
translit = {
Cyrl = "cau-cir-translit",
Arab = "ar-translit",
},
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {
Cyrl = s["cau-Cyrl-entryname"],
Latn = s["cau-Latn-entryname"],
},
sort_key = {
Cyrl = {
from = {
"кхъу", "къӏу", -- 4 chars
"гъу", "джу", "дзу", "жъу", "къу", "кхъ", "къӏ", "кӏу", "кӏь", "лъу", "лӏу", "пӏу", "сӏу", "тӏу", "фӏу", "хъу", "цӏу", "чъу", "чӏу", "шъу", "шӏу", "щӏу", -- 3 chars
"гу", "гъ", "гь", "дж", "дз", "ё", "жъ", "жь", "ку", "къ", "кь", "кӏ", "лъ", "ль", "лӏ", "пӏ", "сӏ", "тӏ", "фӏ", "ху", "хъ", "хь", "цу", "цӏ", "чу", "чъ", "чӏ", "шъ", "шӏ", "щӏ", "ӏу", "ӏь" -- 2 chars
},
to = {
"к" .. p[5], "к" .. p[7],
"г" .. p[3], "д" .. p[2], "д" .. p[4], "ж" .. p[2], "к" .. p[3], "к" .. p[4], "к" .. p[6], "к" .. p[10], "к" .. p[11], "л" .. p[2], "л" .. p[5], "п" .. p[2], "с" .. p[2], "т" .. p[2], "ф" .. p[2], "х" .. p[3], "ц" .. p[3], "ч" .. p[3], "ч" .. p[5], "ш" .. p[2], "ш" .. p[4], "щ" .. p[2],
"г" .. p[1], "г" .. p[2], "г" .. p[4], "д" .. p[1], "д" .. p[3], "е" .. p[1], "ж" .. p[1], "ж" .. p[3], "к" .. p[1], "к" .. p[2], "к" .. p[8], "к" .. p[9], "л" .. p[1], "л" .. p[3], "л" .. p[4], "п" .. p[1], "с" .. p[1], "т" .. p[1], "ф" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[4], "ц" .. p[1], "ц" .. p[2], "ч" .. p[1], "ч" .. p[2], "ч" .. p[4], "ш" .. p[1], "ш" .. p[3], "щ" .. p[1], "ӏ" .. p[1], "ӏ" .. p[2]
}
},
},
}
m["adz"] = {
"tiếng Adzera",
nil,
"poz-ocw",
"Latn",
"Tiếng Adzera",
"Adzera",
}
m["aea"] = {
"Areba",
3509129,
"aus-pam",
"Latn",
}
m["aeb"] = {
"tiếng Ả Rập Tunisia",
56240,
"sem-arb",
"Arab",
"Tiếng Ả Rập Tunisia",
"Ả Rập Tunisia",
entry_name = "ar-entryname",
}
m["aed"] = {
"Argentine Sign Language",
3322073,
"sgn",
"Latn", -- when documented
}
m["aee"] = {
"Northeast Pashayi",
12642198,
"inc-pas",
"fa-Arab, Latn",
}
m["aek"] = {
"Haeke",
5638166,
"poz-cln",
"Latn",
}
m["ael"] = {
"Ambele",
34818,
"nic-grf",
"Latn",
}
m["aem"] = {
"tiếng Arem",
3507920,
"mkh-vie",
"Latn",
"Tiếng Arem",
"Arem",
}
m["aen"] = {
"Armenian Sign Language",
3446604,
"sgn",
}
m["aeq"] = {
"tiếng Aer",
3246741,
"inc-wes",
"Arab",
"Tiếng Aer",
"Aer",
}
m["aer"] = {
"tiếng Arrernte Đông",
10728232,
"aus-pam",
"Latn",
"Tiếng Arrernte Đông",
"Arrernte Đông",
}
m["aes"] = {
"tiếng Alsea",
2395641,
nil,
"Latn",
"Tiếng Alsea",
"Alsea",
}
m["aeu"] = {
"Akeu",
4700657,
"tbq-sil",
"Latn",
}
m["aew"] = {
"Ambakich",
56642,
"paa-ram",
"Latn",
}
m["aey"] = {
"Amele",
3508025,
"ngf-mad",
"Latn",
}
m["aez"] = {
"Aeka",
16110528,
"ngf",
"Latn",
wikipedia_article = "Orokaiva language", -- subvariety?
}
m["afb"] = {
"tiếng Ả Rập vùng Vịnh",
56385,
"sem-arb",
"Arab",
"Tiếng Ả Rập vùng Vịnh",
"Ả Rập vùng Vịnh",
entry_name = "ar-entryname",
}
m["afd"] = {
"Andai",
4753480,
"paa-arf",
"Latn",
}
m["afe"] = {
"Putukwam",
3914930,
"nic-ben",
"Latn",
}
m["afg"] = {
"Afghan Sign Language",
4689093,
"sgn",
}
m["afh"] = {
"Afrihili",
384707,
"art",
"Latn",
type = "appendix-constructed",
}
m["afi"] = {
"Akrukay",
57003,
"paa-ram",
"Latn",
}
m["afk"] = {
"Nanubae",
6964416,
"paa-arf",
"Latn",
}
m["afn"] = {
"Defaka",
35174,
"nic",
"Latn",
}
m["afo"] = {
"Eloyi",
3914066,
"nic-plt",
"Latn",
}
m["afp"] = {
"Tapei",
16887371,
"paa-arf",
"Latn",
}
m["afs"] = {
"Afro-Seminole Creole",
27867,
"crp",
"Latn",
ancestors = "en",
}
m["aft"] = {
"Afitti",
3400829,
"sdv-nyi",
"Latn",
}
m["afu"] = {
"Awutu",
34847,
"alv-gng",
"Latn",
}
m["afz"] = {
"Obokuitai",
7075258,
"paa-lkp",
"Latn",
}
m["aga"] = {
"Aguano",
3331203,
nil,
"Latn",
}
m["agb"] = {
"Legbo",
35584,
"nic-uce",
"Latn",
}
m["agc"] = {
"tiếng Agatu",
34732,
"alv-ido",
"Latn",
"Tiếng Agatu",
"Agatu",
}
m["agd"] = {
"Agarabi",
3399642,
"paa-kag",
"Latn",
}
m["age"] = {
"Angal",
10951553,
"paa-eng",
"Latn",
}
m["agf"] = {
"Arguni",
12473346,
"poz-cet",
"Latn",
}
m["agg"] = {
"Angor",
3508100,
"paa",
"Latn",
}
m["agh"] = {
"Ngelima",
7022266,
"bnt-bta",
"Latn",
}
m["agi"] = {
"tiếng Agariya",
663586,
"mun",
"Deva, Orya",
"Tiếng Agariya",
"Agariya",
}
m["agj"] = {
"tiếng Argobba",
29292,
"sem-eth",
"Ethi",
"Tiếng Argobba",
"Argobba",
}
m["agk"] = {
"Isarog Agta",
6078982,
"phi",
"Latn",
}
m["agl"] = {
"Fembe",
372927,
"ngf",
"Latn",
}
m["agm"] = {
"tiếng Angaataha",
3508001,
"ngf-ang",
"Latn",
}
m["agn"] = {
"Agutaynen",
3399717,
"phi-kal",
"Latn",
}
m["ago"] = {
"Tainae",
7676186,
"ngf",
"Latn",
}
m["agq"] = {
"tiếng Aghem",
34737,
"nic-rnw",
"Latn",
"Tiếng Aghem",
"Aghem",
}
m["agr"] = {
"Aguaruna",
1526530,
"sai-jiv",
"Latn",
"Tiếng Aguaruna",
"Aguaruna",
}
m["ags"] = {
"tiếng Esimbi",
35260,
"nic-bds",
"Latn",
"Tiếng Esimbi",
"Esimbi",
}
m["agt"] = {
"Central Cagayan Agta",
5017296,
"phi",
"Latn",
}
m["agu"] = {
"tiếng Aguacateca",
35091,
"myn",
"Latn",
"Tiếng Aguacateca",
"Aguacateca",
}
m["agv"] = {
"Remontado Agta",
3508085,
"phi",
"Latn",
}
m["agw"] = {
"Kahua",
3191906,
"poz-sls",
"Latn",
}
m["agx"] = {
"tiếng Aghul",
36498,
"cau-esm",
"Cyrl",
"Tiếng Aghul",
"Aghul",
translit = "cau-nec-translit",
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {Cyrl = s["cau-Cyrl-entryname"]},
sort_key = {
from = {"аь", "гъ", "гь", "гӏ", "дж", "ё", "къ", "кь", "кӏ", "оь", "пӏ", "тӏ", "уь", "хъ", "хь", "хӏ", "цӏ", "чӏ"},
to = {"а" .. p[1], "г" .. p[1], "г" .. p[2], "г" .. p[3], "д" .. p[1], "е" .. p[1], "к" .. p[1], "к" .. p[2], "к" .. p[3], "о" .. p[1], "п" .. p[1], "т" .. p[1], "у" .. p[1], "х" .. p[1], "х" .. p[2], "х" .. p[3], "ц" .. p[1], "ч" .. p[1]}
},
}
m["agy"] = {
"Southern Alta",
7569611,
"phi",
"Latn",
}
m["agz"] = {
"Mount Iriga Agta",
6921432,
"phi",
"Latn",
}
m["aha"] = {
"Ahanta",
34729,
"alv-ctn",
"Latn",
}
m["ahb"] = {
"Axamb",
2874710,
"poz-vnc",
"Latn",
}
m["ahg"] = {
"tiếng Qimant",
35663,
"cus-cen",
"Latn",
"Tiếng Qimant",
"Qimant",
}
m["ahh"] = {
"Aghu",
3436645,
"ngf",
"Latn",
}
m["ahi"] = {
"Tiagbamrin Aizi",
3400073,
"kro-aiz",
"Latn",
}
m["ahk"] = {
"tiếng Akha",
56643,
"tbq-han",
"Latn, Mymr, Thai",
"Tiếng Akha",
"Akha",
sort_key = {
Thai = {
from = {"[%pๆ]", "[็-๎]", "([เแโใไ])([ก-ฮ])"},
to = {"", "", "%2%1"}
},
},
}
m["ahl"] = {
"Igo",
35412,
"alv-ktg",
"Latn",
}
m["ahm"] = {
"Mobumrin Aizi",
35967,
"kro-aiz",
"Latn",
}
m["ahn"] = {
"Àhàn",
34723,
"alv-aah",
"Latn",
}
m["aho"] = {
"tiếng Ahom",
34778,
"tai-swe",
"Ahom",
"Tiếng Ahom",
"Ahom",
translit = "Ahom-translit",
}
m["ahp"] = {
"Aproumu Aizi",
34810,
"alv-kwa",
"Latn",
}
m["ahr"] = {
"tiếng Ahiran",
15549890,
"inc-wes",
"Deva",
"Tiếng Ahiran",
"Ahiran",
translit = "mr-translit",
}
m["ahs"] = {
"Ashe",
34823,
"nic-plc",
"Latn",
}
m["aht"] = {
"tiếng Ahtna",
21058,
"ath-nor",
"Latn",
"Tiếng Ahtna",
"Ahtna",
}
m["aia"] = {
"Arosi",
2863483,
"poz-sls",
"Latn",
}
m["aib"] = {
"tiếng Äynu",
27927,
"qfa-mix",
"Arab, Latn",
"Tiếng Äynu",
"Äynu",
ancestors = "ug, fa"
}
m["aic"] = {
"Ainbai",
3332149,
"paa-brd",
"Latn",
}
m["aid"] = {
"Alngith",
3279409,
"aus-pmn",
"Latn",
}
m["aie"] = {
"Amara",
2841180,
"poz-ocw",
"Latn",
}
m["aif"] = {
"Agi",
3331491,
"qfa-tor",
"Latn",
}
m["aig"] = {
"Antigua and Barbuda Creole English",
3244184,
"crp",
"Latn",
ancestors = "en",
}
m["aih"] = {
"Ai-Cham",
2827749,
"qfa-kms",
"Latn, Hani",
sort_key = {Hani = "Hani-sortkey"},
}
m["aii"] = {
"tiếng Tân Aram Assyria",
29440,
"sem-nna",
"Syrc, Cyrl",
"Tiếng Tân Aram Assyria",
"Tân Aram Assyria",
translit = {Syrc = "aii-translit"},
entry_name = "Syrc-entryname",
}
m["aij"] = {
"tiếng Lishanid Noshan",
3436467,
"sem-nna",
"Hebr",
"Tiếng Lishanid Noshan",
"Lishanid Noshan",
}
m["aik"] = {
"Ake",
34808,
"nic-pls",
"Latn",
}
m["ail"] = {
"Aimele",
3327418,
"ngf",
"Latn",
}
m["aim"] = {
"tiếng Aimol",
4697175,
"tbq-kuk",
"Latn, Beng",
"Tiếng Aimol",
"Aimol",
}
m["ain"] = {
"tiếng Ainu",
27969,
"qfa-ain",
"Kana, Latn, Cyrl",
"Tiếng Ainu",
"Ainu",
sort_key = {Kana = "Kana-sortkey"},
}
m["aio"] = {
"tiếng Aiton",
3399725,
"tai-swe",
"Mymr",
"Tiếng Aiton",
"Aiton",
translit = "aio-phk-translit",
entry_name = {remove_diacritics = c.VS01},
}
m["aip"] = {
"Burumakok",
5000984,
"ngf-okk",
"Latn",
}
m["air"] = {
"Airoran",
3321131,
"paa-tkw",
"Latn",
}
m["ait"] = {
"Arikem",
3446679,
"tup",
"Latn",
}
m["aiw"] = {
"tiếng Aari",
7495,
"omv-aro",
"Latn, Ethi",
"Tiếng Aari",
"Aari",
}
m["aix"] = {
"Aighon",
3504287,
"poz-ocw",
"Latn",
}
m["aiy"] = {
"Ali",
34814,
"alv-gbf",
"Latn",
}
m["aja"] = {
"Aja",
3237491,
"csu-bkr",
"Latn",
}
m["ajg"] = {
"tiếng Adja",
35035,
"alv-gbe",
"Latn",
"Tiếng Adja",
"Adja",
}
m["aji"] = {
"tiếng Ajië",
2828867,
"poz-cln",
"Latn",
"Tiếng Ajië",
"Ajië",
}
m["ajn"] = {
"Andajin",
16111302,
"aus-wor",
"Latn",
}
m["ajp"] = {
"tiếng Ả Rập Nam Levant",
nil,
"sem-arb",
"Arab",
"Tiếng Ả Rập Nam Levant",
"Ả Rập Nam Levant",
entry_name = "ar-entryname",
}
m["ajw"] = {
"Ajawa",
56645,
"cdc-wst",
"Latn",
}
m["ajz"] = {
"Amri Karbi",
3508092,
"tbq-kuk",
"Latn",
ancestors = "mjw",
}
m["akb"] = {
"Angkola Batak",
2640686,
"btk",
"Latn, Batk",
}
m["akc"] = {
"Mpur",
3327139,
"paa-wpa",
"Latn",
}
m["akd"] = {
"Ukpet-Ehom",
36618,
"nic-ucr",
"Latn",
}
m["ake"] = {
"tiếng Akawaio",
28059,
"sai-pem",
"Latn",
"Tiếng Akawaio",
"Akawaio",
}
m["akf"] = {
"Akpa",
34801,
"alv-ido",
"Latn",
}
m["akg"] = {
"Anakalangu",
4750964,
"poz-cet",
"Latn",
}
m["akh"] = {
"Angal Heneng",
10950354,
"paa-eng",
"Latn",
}
m["aki"] = {
"Aiome",
56735,
"paa",
"Latn",
}
m["akj"] = {
"tiếng Aka-Jeru",
2919121,
"qfa-adn",
"Latn, Deva",
"Tiếng Aka-Jeru",
"Aka-Jeru",
}
m["akk"] = {
"tiếng Akkad",
35518,
"sem-eas",
"Xsux, Latn",
"Tiếng Akkad",
"Akkad",
}
m["akl"] = {
"tiếng Aklanon",
8773,
"phi",
"Latn",
"Tiếng Aklanon",
"Aklanon",
ancestors = "poz-pro,phi-pro",
}
m["akm"] = {
"tiếng Aka-Bo",
35361,
"qfa-adn",
"Latn",
"Tiếng Aka-Bo",
"Aka-Bo",
}
m["ako"] = {
"Akurio",
56650,
"sai-tar",
"Latn",
}
m["akp"] = {
"tiếng Siwu",
36470,
"alv-ntg",
"Latn",
"Tiếng Siwu",
"Siwu",
}
m["akq"] = {
"Ak",
56654,
"paa",
"Latn",
}
m["akr"] = {
"tiếng Araki",
2699882,
"poz-vnc",
"Latn",
"Tiếng Araki",
"Araki",
}
m["aks"] = {
"tiếng Akaselem",
34817,
"nic-grm",
"Latn",
"Tiếng Akaselem",
"Akaselem",
}
m["akt"] = {
"Akolet",
3330162,
"poz-ocw",
"Latn",
}
m["aku"] = {
"Akum",
34799,
"nic-ykb",
"Latn",
}
m["akv"] = {
"tiếng Akhvakh",
56423,
"cau-and",
"Cyrl",
"Tiếng Akhvakh",
"Akhvakh",
translit = "cau-nec-translit",
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {Cyrl = s["cau-Cyrl-entryname"]},
}
m["akw"] = {
"Akwa",
34802,
"bnt-mbo",
"Latn",
}
m["akx"] = {
"tiếng Aka-Kede",
3436816,
"qfa-adc",
"Latn",
"Tiếng Aka-Kede",
"Aka-Kede",
}
m["aky"] = {
"Aka-Kol",
3436784,
"qfa-adc",
"Latn",
}
m["akz"] = {
"tiếng Alabama",
1815020,
"nai-mus",
"Latn",
"Tiếng Alabama",
"Alabama",
}
m["ala"] = {
"Alago",
34813,
"alv-ido",
"Latn",
}
m["alc"] = {
"tiếng Kawésqar",
56544,
"aqa",
"Latn",
"Tiếng Kawésqar",
"Kawésqar",
}
m["ald"] = {
"Alladian",
34837,
"alv-lag",
"Latn",
}
m["ale"] = {
"tiếng Aleut",
27210,
"esx",
"Latn, Cyrl",
"Tiếng Aleut",
"Aleut",
}
m["alf"] = {
"Alege",
34815,
"nic-ben",
"Latn",
}
m["alh"] = {
"tiếng Alawa",
2147917,
"aus-gun",
"Latn",
"Tiếng Alawa",
"Alawa",
}
m["ali"] = {
"tiếng Amaimon",
3327427,
"ngf-mad",
"Latn",
"Tiếng Amaimon",
"Amaimon",
}
m["alj"] = {
"tiếng Alangan",
3327423,
"phi",
"Latn",
"Tiếng Alangan",
"Alangan",
}
m["alk"] = {
"tiếng Alak",
2714690,
"mkh",
"Latn, Laoo",
"Tiếng Alak",
"Alak"
}
m["all"] = {
"tiếng Allar",
3393634,
"dra-mal",
"Mlym",
"Tiếng Allar",
"Allar",
translit = "ml-translit"
}
-- "aln" IS TREATED AS "sq", SEE WT:LT
m["alm"] = {
"Amblong",
11022615,
"poz-vnc",
"Latn",
}
m["alo"] = {
"Larike-Wakasihu",
3217929,
"poz-cma",
"Latn",
}
m["alp"] = {
"tiếng Alune",
3327367,
"poz-cet",
"Latn",
}
m["alq"] = {
"tiếng Algonquin",
28092,
"alg",
"Latn",
"Tiếng Algonquin",
"Algonquin",
ancestors = "oj",
}
m["alr"] = {
"tiếng Alutor",
28213,
"qfa-ckn",
"Cyrl",
"Tiếng Alutor",
"Alutor",
entry_name = {
from = {"['’]"},
to = {"ʼ"}
},
sort_key = {
from = {"вʼ", "гʼ", "ғ", "ә", "ё", "ӄ", "ӈ"},
to = {"в" .. p[1], "г" .. p[1], "г" .. p[2], "е" .. p[1], "е" .. p[2], "к" .. p[1], "н" .. p[1]}
},
}
m["alt"] = {
"tiếng Nam Altai",
1991779,
"trk-kkp",
"Cyrl",
"Tiếng Nam Altai",
"Nam Altai",
translit = "Altai-translit",
sort_key = {
from = {"ј", "ё", "ҥ", "ӧ", "ӱ"},
to = {"д" .. p[1], "е" .. p[1], "н" .. p[1], "о" .. p[1], "у" .. p[1]}
},
}
m["alu"] = {
"tiếng 'Are'are",
5160,
"poz-sls",
"Latn",
"Tiếng 'Are'are",
"'Are'are",
}
m["alw"] = {
"tiếng Alaba-K’abeena",
56652,
"cus-hec",
"Latn, Ethi",
"Tiếng Alaba-K’abeena",
"Alaba-K’abeena",
}
m["alx"] = {
"Amol",
3504260,
"qfa-tor",
"Latn",
}
m["aly"] = {
"Alyawarr",
3327389,
"aus-pam",
"Latn",
}
m["alz"] = {
"Alur",
56507,
"sdv-los",
"Latn",
}
m["ama"] = {
"Amanayé",
3508053,
"tup-gua",
"Latn",
}
m["amb"] = {
"Ambo",
3450142,
"nic-tvn",
"Latn",
}
m["amc"] = {
"tiếng Amahuaca",
2669150,
"sai-pan",
"Latn",
"Tiếng Amahuaca",
"Amahuaca",
}
m["ame"] = {
"tiếng Yanesha'",
3088540,
"awd",
"Latn",
"Tiếng Yanesha'",
"Yanesha'",
}
m["amf"] = {
"tiếng Hamer-Banna",
35764,
"omv-aro",
"Latn, Ethi",
"Tiếng Hamer-Banna",
"Hamer-Banna",
}
m["amg"] = {
"tiếng Amurdag",
3360016,
"aus-wdj",
"Latn",
"Tiếng Amurdag",
"Amurdag",
}
m["ami"] = {
"tiếng Amis",
35132,
"map",
"Latn",
"Tiếng Amis",
"Amis",
}
m["amj"] = {
"tiếng Amdang",
28335,
"ssa-fur",
"Latn",
"Tiếng Amdang",
"Amdang",
}
m["amk"] = {
"tiếng Ambai",
1875885,
"poz-hce",
"Latn",
"Tiếng Ambai",
"Ambai",
}
m["aml"] = {
"tiếng War-Jaintia",
56321,
"aav-khs",
"Latn",
"Tiếng War-Jaintia",
"War-Jaintia",
}
m["amm"] = {
"tiếng Ama",
3446626,
"qfa-mal",
"Latn",
"Tiếng Ama",
"Ama",
}
m["amn"] = {
"tiếng Amanab",
3327399,
"paa-brd",
"Latn",
"Tiếng Amanab",
"Amanab",
}
m["amo"] = {
"Amo",
34826,
"nic-kne",
"Latn",
}
m["amp"] = {
"tiếng Alamblak",
56688,
"paa",
"Latn",
"Tiếng Alamblak",
"Alamblak",
}
m["amq"] = {
"Amahai",
3327384,
"poz-cma",
"Latn",
}
m["amr"] = {
"Amarakaeri",
35128,
"sai-har",
"Latn",
}
m["ams"] = {
"tiếng Nam Amami Ōshima",
2840986,
"jpx-nry",
"Jpan",
"Tiếng Nam Amami Ōshima",
"Nam Amami Ōshima",
translit = s["jpx-translit"],
display_text = s["jpx-displaytext"],
entry_name = s["jpx-entryname"],
sort_key = s["jpx-sortkey"],
}
m["amt"] = {
"Amto",
56517,
"paa-asa",
"Latn",
}
m["amu"] = {
"tiếng Amuzgo",
3501942,
"omq",
"Latn",
"Tiếng Amuzgo",
"Amuzgo",
}
m["amv"] = {
"Ambelau",
2669214,
"poz-cma",
"Latn",
}
m["amw"] = {
"tiếng Tân Aram Tây",
34226,
"sem-arw",
"Armi, Syrc, Latn",
"Tiếng Tân Aram Tây",
"Tân Aram Tây",
entry_name = {Syrc = "Syrc-entryname"},
}
m["amx"] = {
"Anmatyerre",
10412317,
"aus-pam",
"Latn",
}
m["amy"] = {
"Ami",
12626835,
"aus-dal",
"Latn",
}
m["amz"] = {
"Atampaya",
3446651,
"aus-pam",
"Latn",
}
m["ana"] = {
"Andaqui",
2846078,
nil,
"Latn",
}
m["anb"] = {
"Andoa",
2846171,
"sai-zap",
"Latn",
}
m["anc"] = {
"tiếng Ngas",
35999,
"cdc-wst",
"Latn",
"Tiếng Ngas",
"Ngas",
}
m["and"] = {
"Ansus",
3513300,
"poz-hce",
"Latn",
}
m["ane"] = {
"tiếng Xârâcùù",
3571097,
"poz-cln",
"Latn",
"Tiếng Xârâcùù",
"Xârâcùù",
}
m["anf"] = {
"Animere",
34783,
"alv-ktg",
"Latn",
}
m["ang"] = {
"tiếng Anh cổ",
42365,
"gmw-ang",
"Latn, Runr",
"Tiếng Anh cổ",
"Anh cổ",
translit = {Runr = "Runr-translit"},
entry_name = {
Latn = {
remove_diacritics = c.acute .. c.macron .. c.dotabove,
from = {"Ƿ", "ƿ"},
to = {"W", "w"}
},
},
sort_key = {
Latn = {
from = {"æ", "ð", "þ", "ƿ"},
to = {"ae", "t" .. p[1], "t" .. p[2], "w" .. p[1]}
},
},
}
m["anh"] = {
"Nend",
6991554,
"ngf-mad",
"Latn",
}
m["ani"] = {
"tiếng Andi",
34849,
"cau-and",
"Cyrl",
"Tiếng Andi",
"Andi",
translit = "cau-nec-translit",
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {Cyrl = s["cau-Cyrl-entryname"]},
}
m["anj"] = {
"Anor",
56458,
"paa",
"Latn",
}
m["ank"] = {
"Goemai",
35272,
"cdc-wst",
"Latn",
}
m["anl"] = {
"Anu",
4777679,
"sit-mru",
"Latn",
}
m["anm"] = {
"tiếng Anal",
56235,
"tbq-kuk",
"Latn",
"Tiếng Anal",
"Anal",
}
m["ann"] = {
"Obolo",
36614,
"nic-lcr",
"Latn",
}
m["ano"] = {
"Andoque",
2669225,
"qfa-iso",
"Latn",
}
m["anp"] = {
"tiếng Angika",
28378,
"inc-bih",
"Deva, Kthi",
"Tiếng Angika",
"Angika",
translit = {
Deva = "hi-translit",
Kthi = "bho-Kthi-translit",
},
ancestors = "bh",
}
m["anq"] = {
"tiếng Jarawa",
2475526,
"qfa-ong",
"Latn, Deva",
"Tiếng Jarawa",
"Jarawa",
}
m["anr"] = {
"Andh",
4754314,
"inc-sou",
"Deva",
}
m["ans"] = {
"Anserma",
3446613,
"sai-chc",
"Latn",
}
m["ant"] = {
"Antakarinya",
921304,
"aus-psw",
"Latn",
}
m["anu"] = {
"tiếng Anuak",
56677,
"sdv-lon",
"Latn, Ethi",
"Tiếng Anuak",
"Anuak",
}
m["anv"] = {
"Denya",
35187,
"nic-mam",
"Latn",
}
m["anw"] = {
"tiếng Anaang",
2845320,
"nic-ief",
"Latn",
"Tiếng Anaang",
"Anaang",
}
m["anx"] = {
"Andra-Hus",
2846195,
"poz-aay",
"Latn",
}
m["any"] = {
"tiếng Anyi",
28395,
"alv-ctn",
"Latn",
"Tiếng Anyi",
"Anyi",
}
m["anz"] = {
"Anem",
56512,
"paa",
"Latn",
}
m["aoa"] = {
"tiếng Angola",
34994,
"crp",
"Latn",
"Tiếng Angola",
"Angola",
ancestors = "pt",
}
m["aob"] = {
"Abom",
3446647,
"ngf",
"Latn",
}
m["aoc"] = {
"tiếng Pemon",
10729616,
"sai-pem",
"Latn",
"Tiếng Pemon",
"Pemon",
}
m["aod"] = {
"Andarum",
3507888,
"paa",
"Latn",
}
m["aoe"] = {
"Angal Enen",
10951638,
"paa-eng",
"Latn",
}
m["aof"] = {
"Bragat",
3507977,
"qfa-tor",
"Latn",
}
m["aog"] = {
"Angoram",
56366, -- cf 6754745 for merged dialect
"paa-lsp",
"Latn",
}
m["aoi"] = {
"Anindilyakwa",
2714654,
"aus-arn",
"Latn",
}
m["aoj"] = {
"Mufian",
3507881,
"qfa-tor",
"Latn",
}
m["aok"] = {
"Arhö",
4790086,
"poz-cln",
"Latn",
}
m["aol"] = {
"Alor",
3332062,
"poz",
"Latn",
}
m["aom"] = {
"Ömie",
8078975,
"ngf",
"Latn",
}
m["aon"] = {
"Bumbita Arapesh",
3508044,
"qfa-tor",
"Latn",
}
m["aor"] = {
"Aore",
12627129,
"poz-vnc",
"Latn",
}
m["aos"] = {
"Taikat",
7676018,
"paa-brd",
"Latn",
}
m["aot"] = {
"tiếng Atong (Ấn Độ)",
5646,
"tbq-bdg",
"Latn, Beng",
"Tiếng Atong (Ấn Độ)",
"Atong (Ấn Độ)",
}
m["aou"] = {
"tiếng A'ou",
16109994,
"qfa-gel",
"Latn", -- also Hani?
"Tiếng A'ou",
"A'ou",
}
m["aox"] = {
"Atorada",
3507932,
"awd",
"Latn",
}
m["aoz"] = {
"Uab Meto",
3441962,
"poz-tim",
"Latn",
}
m["apb"] = {
"Sa'a",
36294,
"poz-sls",
"Latn",
}
m["apc"] = {
"tiếng Ả Rập Bắc Levant",
22809485,
"sem-arb",
"Arab",
"Tiếng Ả Rập Bắc Levant",
"Ả Rập Bắc Levant",
entry_name = "ar-entryname",
}
m["apd"] = {
"tiếng Ả Rập Sudan",
56573,
"sem-arb",
"Arab",
"Tiếng Ả Rập Sudan",
"Ả Rập Sudan",
entry_name = "ar-entryname",
}
m["ape"] = {
"tiếng Bukiyip",
3507895,
"paa-ara",
"Latn",
}
m["apf"] = {
"Pahanan Agta",
7135432,
"phi",
"Latn",
}
m["apg"] = {
"Ampanang",
4748035,
"poz",
"Latn",
}
m["aph"] = {
"tiếng Athpariya",
3449126,
"sit-kie",
"Deva, Latn",
"Tiếng Athpariya",
"Athpariya",
}
m["api"] = {
"Apiaká",
3507941,
"tup-gua",
"Latn",
}
m["apj"] = {
"tiếng Jicarilla",
28277,
"apa",
"Latn",
"Tiếng Jicarilla",
"Jicarilla",
}
m["apk"] = {
"tiếng Apache đồng bằng",
27861,
"apa",
"Latn",
"Tiếng Apache đồng bằng",
"Apache đồng bằng"
}
m["apl"] = {
"tiếng Lipan",
28269,
"apa",
"Latn",
"Tiếng Lipan",
"Lipan",
}
m["apm"] = {
"tiếng Chiricahua",
13368,
"apa",
"Latn",
"Tiếng Chiricahua",
"Chiricahua",
}
m["apn"] = {
"tiếng Apinayé",
2858311,
"sai-nje",
"Latn",
"Tiếng Apinayé",
"Apinayé",
}
m["apo"] = {
"Ambul",
12627135,
"poz-ocw",
"Latn",
}
m["app"] = {
"Apma",
2669188,
"poz-vnc",
"Latn",
}
m["apq"] = {
"tiếng Pucikwar",
28466,
"qfa-adc",
"Latn",
"Tiếng Pucikwar",
"Pucikwar",
}
m["apr"] = {
"Arop-Lokep",
2863482,
"poz-ocw",
"Latn",
}
m["aps"] = {
"Arop-Sissano",
12627242,
"poz-ocw",
"Latn",
}
m["apt"] = {
"tiếng Apatani",
56306,
"sit-tan",
"Latn",
"Tiếng Apatani",
"Apatani",
}
m["apu"] = {
"Apurinã",
2859081,
"awd",
"Latn",
}
m["apv"] = {
"Alapmunte",
16110782,
"sai-nmk",
"Latn",
}
m["apw"] = {
"tiếng Apache Tây",
28060,
"apa",
"Latn",
"Tiếng Apache Tây",
"Apache Tây",
}
m["apx"] = {
"tiếng Aputai",
12473343,
"poz-tim",
"Latn",
"Tiếng Aputai",
"Aputai",
}
m["apy"] = {
"tiếng Aparaí",
2736980,
"sai-gui",
"Latn",
"Tiếng Aparaí",
"Aparaí",
}
m["apz"] = {
"Safeyoka",
7398693,
"ngf",
"Latn",
}
m["aqc"] = {
"tiếng Archi",
34915,
"cau-lzg",
"Cyrl",
"Tiếng Archi",
"Archi",
translit = "cau-nec-translit",
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
entry_name = {Cyrl = s["cau-Cyrl-entryname"]},
sort_key = {
from = {
"ккъӏв", "ххьӏв", -- 5 chars
"гъӏв", "ёоӏ", "ккъӏ", "ккъв", "къӏв", "ллъв", "ххьӏ", "хъӏв", "хьӏв", "ццӏв", "ччӏв", -- 4 chars
"ааӏ", "гӏв", "гъӏ", "гъв", "гьв", "ееӏ", "ёӏ", "ёо", "ииӏ", "кӏв", "ккв", "ккъ", "къӏ", "къв", "кьв", "лӏв", "ллъ", "лъв", "льв", "ооӏ", "пӏв", "ппв", "ссв", "тӏв", "ттв", "ууӏ", "хӏв", "ххв", "хъӏ", "хъв", "хьӏ", "цӏв", "ццӏ", "ццв", "чӏв", "ччӏ", "ээӏ", "юуӏ", "яаӏ", -- 3 chars
"аӏ", "аа", "гӏ", "гв", "гъ", "гь", "дв", "еӏ", "ее", "ё", "жв", "зв", "иӏ", "ии", "кӏ", "кв", "кк", "къ", "кь", "лӏ", "лв", "лъ", "ль", "оӏ", "оо", "пӏ", "пв", "пп", "св", "сс", "тӏ", "тв", "тт", "уӏ", "уу", "фв", "хӏ", "хв", "хх", "хъ", "цӏ", "цв", "цц", "чӏ", "чв", "шв", "щв", "эӏ", "ээ", "юӏ", "юу", "яӏ", "яа" -- 2 chars
},
to = {
"к" .. p[8], "х" .. p[7],
"г" .. p[6], "е" .. p[7], "к" .. p[7], "к" .. p[9], "к" .. p[12], "л" .. p[5], "х" .. p[6], "х" .. p[10], "х" .. p[13], "ц" .. p[6], "ч" .. p[5],
"а" .. p[3], "г" .. p[2], "г" .. p[5], "г" .. p[7], "г" .. p[9], "е" .. p[3], "е" .. p[5], "е" .. p[6], "и" .. p[3], "к" .. p[2], "к" .. p[5], "к" .. p[6], "к" .. p[11], "к" .. p[13], "к" .. p[15], "л" .. p[2], "л" .. p[4], "л" .. p[7], "л" .. p[9], "о" .. p[3], "п" .. p[2], "п" .. p[5], "с" .. p[3], "т" .. p[2], "т" .. p[5], "у" .. p[3], "х" .. p[2], "х" .. p[5], "х" .. p[9], "х" .. p[11], "х" .. p[12], "ц" .. p[2], "ц" .. p[5], "ц" .. p[7], "ч" .. p[2], "ч" .. p[4], "э" .. p[3], "ю" .. p[3], "я" .. p[3],
"а" .. p[1], "а" .. p[2], "г" .. p[1], "г" .. p[3], "г" .. p[4], "г" .. p[8], "д" .. p[1], "е" .. p[1], "е" .. p[2], "е" .. p[4], "ж" .. p[1], "з" .. p[1], "и" .. p[1], "и" .. p[2], "к" .. p[1], "к" .. p[3], "к" .. p[4], "к" .. p[10], "к" .. p[14], "л" .. p[1], "л" .. p[3], "л" .. p[6], "л" .. p[8], "о" .. p[1], "о" .. p[2], "п" .. p[1], "п" .. p[3], "п" .. p[4], "с" .. p[1], "с" .. p[2], "т" .. p[1], "т" .. p[3], "т" .. p[4], "у" .. p[1], "у" .. p[2], "ф" .. p[1], "х" .. p[1], "х" .. p[3], "х" .. p[4], "х" .. p[8], "ц" .. p[1], "ц" .. p[3], "ц" .. p[4], "ч" .. p[1], "ч" .. p[3], "ш" .. p[1], "щ" .. p[1], "э" .. p[1], "э" .. p[2], "ю" .. p[1], "ю" .. p[2], "я" .. p[1], "я" .. p[2]
}
},
}
m["aqd"] = {
"Ampari Dogon",
4748057,
"nic-dgw",
"Latn",
}
m["aqg"] = {
"tiếng Arigidi",
34829,
"alv-von",
"Latn",
}
m["aqm"] = {
"Atohwaim",
11732297,
"ngf",
"Latn",
}
m["aqn"] = {
"Northern Alta",
7058116,
"phi",
"Latn",
}
m["aqp"] = {
"Atakapa",
10975683,
"qfa-iso",
"Latn",
}
m["aqr"] = {
"Arhâ",
4790085,
"poz-cln",
"Latn",
}
m["aqt"] = {
"Angaité",
15736037,
"sai-mas",
"Latn",
}
m["aqz"] = {
"tiếng Akuntsu",
4701960,
"tup",
"Latn",
"Tiếng Akuntsu",
"Akuntsu",
}
m["arc"] = {
"tiếng Aram",
28602,
"sem-ara",
"Hebr, Armi, Syrc, Palm, Nbat, Phnx, Mand, Samr, Hatr, Elym",
"Tiếng Aram",
"Aram",
translit = {
Armi = "Armi-translit",
Palm = "Palm-translit",
},
entry_name = {
Hebr = {remove_diacritics = u(0x0591) .. "-" .. u(0x05BD) .. u(0x05BF) .. "-" .. u(0x05C5) .. u(0x05C7)},
Syrc = {remove_diacritics = u(0x0730) .. "-" .. u(0x0748)},
remove_diacritics = c.macron .. c.diaer .. c.macronbelow}, -- Which script(s)?
}
m["ard"] = {
"Arabana",
3507959,
"aus-kar",
"Latn",
}
m["are"] = {
"Western Arrernte",
12645549,
"aus-pam",
"Latn",
}
m["arh"] = {
"tiếng Arhuaco",
2640621,
"cba",
"Latn",
"Tiếng Arhuaco",
"Arhuaco",
}
m["ari"] = {
"Arikara",
56539,
"cdd",
"Latn",
}
m["arj"] = {
"Arapaso",
12627166,
"sai-tuc",
"Latn",
}
m["ark"] = {
"Arikapú",
3446640,
"sai-mje",
"Latn",
}
m["arl"] = {
"Arabela",
2591221,
"sai-zap",
"Latn",
}
m["arn"] = {
"tiếng Mapuche",
33730,
"sai-ara",
"Latn",
"Tiếng Mapuche",
"Mapuche",
}
m["aro"] = {
"Araona",
958414,
"sai-tac",
"Latn",
}
m["arp"] = {
"tiếng Arapaho",
56417,
"alg-ara",
"Latn",
"Tiếng Arapaho",
"Arapaho",
}
m["arq"] = {
"tiếng Ả Rập Algérie",
56499,
"sem-arb",
"Arab",
"Tiếng Ả Rập Algérie",
"Ả Rập Algérie",
entry_name = "ar-entryname",
}
m["arr"] = {
"Arara-Karo",
35539,
"tup",
"Latn",
}
m["ars"] = {
"tiếng Ả Rập Najd",
56574,
"sem-arb",
"Arab",
"Tiếng Ả Rập Najd",
"Ả Rập Najd",
entry_name = "ar-entryname",
}
m["aru"] = {
"Arua",
2746221,
"auf",
"Latn",
}
m["arv"] = {
"Arbore",
56883,
"cus-eas",
"Latn",
}
m["arw"] = {
"tiếng Lokono",
2655664,
"awd-taa",
"Latn",
"Tiếng Lokono",
"Lokono",
}
m["arx"] = {
"Aruá",
3507907,
"tup",
"Latn",
}
m["ary"] = {
"tiếng Ả Rập Maroc",
56426,
"sem-arb",
"Arab",
"Tiếng Ả Rập Maroc",
"Ả Rập Maroc",
entry_name = "ar-entryname",
sort_key = {
from = {"^%f[" .. u(0x5D0) .. "-" .. u(0x5EA) .. "]"},
to = {u(0xFB21)},
},
}
m["arz"] = {
"tiếng Ả Rập Ai Cập",
29919,
"sem-arb",
"Arab",
"Tiếng Ả Rập Ai Cập",
"Ả Rập Ai Cập",
entry_name = "ar-entryname",
}
m["asa"] = {
"Pare",
36403,
"bnt-par",
"Latn",
}
m["asb"] = {
"tiếng Assiniboine",
2591288,
"sio-dkt",
"Latn",
"Tiếng Assiniboine",
"Assiniboine",
}
m["asc"] = {
"Casuarina Coast Asmat",
11732046,
"ngf",
"Latn",
}
m["ase"] = {
"ngôn ngữ ký hiệu Mỹ",
14759,
"sgn",
"Sgnw",
"Ngôn ngữ ký hiệu Mỹ",
"ngôn ngữ ký hiệu Mỹ",
}
m["asf"] = {
"Auslan",
29525,
"sgn",
"Latn", -- when documented
}
m["asg"] = {
"Cishingini",
35199,
"nic-kam",
"Latn",
}
m["ash"] = {
"Abishira",
2871740,
"qfa-iso",
"Latn",
}
m["asi"] = {
"Buruwai",
5001031,
"ngf",
"Latn",
}
m["asj"] = {
"Nsari",
36418,
"nic-bbe",
"Latn",
}
m["ask"] = {
"tiếng Ashkun",
29379,
"nur-sou",
"Arab, Latn",
"Tiếng Ashkun",
"Ashkun",
}
m["asl"] = {
"Asilulu",
12473347,
"poz-cma",
"Latn",
}
m["asn"] = {
"Xingú Asuriní",
8044571,
"tup-gua",
"Latn",
}
m["aso"] = {
"Dano",
5220979,
"paa-kag",
"Latn",
}
m["asp"] = {
"Algerian Sign Language",
3135421,
"sgn",
}
m["asq"] = {
"Austrian Sign Language",
36668,
"sgn",
"Latn", -- when documented
}
m["asr"] = {
"tiếng Asur",
3504321,
"mun",
"Deva, Latn",
"Tiếng Asur",
"Asur"
}
m["ass"] = {
"Ipulo",
35408,
"nic-tvc",
"Latn",
}
m["ast"] = {
"tiếng Asturias",
29507,
"roa-ibe",
"Latn",
"Tiếng Asturias",
"Asturias",
ancestors = "roa-ole",
}
m["asu"] = {
"Tocantins Asurini",
32041490,
"tup-gua",
"Latn",
}
m["asv"] = {
"Asoa",
56296,
"csu-maa",
"Latn",
}
m["asw"] = {
"Australian Aboriginal Sign Language",
955216,
"sgn",
"Latn", -- when documented
}
m["asx"] = {
"Muratayak",
11732766,
"ngf-fin",
"Latn",
}
m["asy"] = {
"Yaosakor Asmat",
16113158,
"ngf",
"Latn",
}
m["asz"] = {
"As",
2866218,
"poz-hce",
"Latn",
}
m["ata"] = {
"Pele-Ata",
56511,
"paa",
"Latn",
}
m["atb"] = {
"tiếng Zaiwa",
56594,
"tbq-brm",
"Latn, Lisu", -- also Hani?
"Tiếng Zaiwa",
"Zaiwa",
translit = {Lisu = "Lisu-translit"},
sort_key = {Lisu = s["Lisu-sortkey"]},
}
m["atc"] = {
"tiếng Atsahuaca",
4817730,
"sai-pan",
"Latn",
"Tiếng Atsahuaca",
"Atsahuaca",
}
m["atd"] = {
"Ata Manobo",
12627315,
"mno",
"Latn",
}
m["ate"] = {
"tiếng Atemble",
4813055,
"ngf-mad",
"Latn",
"Tiếng Atemble",
"Atemble",
}
m["atg"] = {
"Okpela",
7082551,
"alv-yek",
"Latn",
}
m["ati"] = {
"Attié",
34844,
"alv-lag",
"Latn",
}
m["atj"] = {
"tiếng Atikamekw",
56590,
"alg",
"Latn",
ancestors = "cr",
"Tiếng Atikamekw",
"Atikamekw",
}
m["atk"] = {
"Ati",
4815751,
"phi",
"Latn",
}
m["atl"] = {
"Mount Iraya Agta",
6921430,
"phi",
"Latn",
}
m["atm"] = {
"Ata",
4812603,
"phi",
"Latn",
}
m["ato"] = {
"Atong (Cameroon)",
34824,
"nic-grs",
"Latn",
}
m["atp"] = {
"Pudtol Atta",
12640726,
"phi",
"Latn",
}
m["atq"] = {
"Aralle-Tabulahan",
4783889,
"poz-ssw",
"Latn",
}
m["atr"] = {
"Waimiri-Atroari",
56865,
"sai-car",
"Latn",
}
m["ats"] = {
"Gros Ventre",
56628,
"alg-ara",
"Latn",
}
m["att"] = {
"Pamplona Atta",
12639245,
"phi",
"Latn",
}
m["atu"] = {
"Reel",
7306882,
"sdv-dnu",
"Latn",
}
m["atv"] = {
"tiếng Bắc Altai",
2640863,
"trk-ssb",
"Cyrl",
"Tiếng Bắc Altai",
"Bắc Altai",
translit = "Altai-translit",
}
m["atw"] = {
"Atsugewi",
56718,
"nai-pal",
"Latn",
}
m["atx"] = {
"Arutani",
56609,
nil,
"Latn",
}
m["aty"] = {
"Aneityum",
2379113,
"poz-oce",
"Latn",
}
m["atz"] = {
"Arta",
3508067,
"phi",
"Latn",
}
m["aua"] = {
"tiếng Asumboa",
4811870,
"poz-oce",
"Latn",
"Tiếng Asumboa",
"Asumboa",
}
m["aub"] = {
"Alugu",
12626798,
"tbq-urp",
"Latn", -- also Hani?
}
m["auc"] = {
"Huaorani",
758570,
"qfa-iso",
"Latn",
}
m["aud"] = {
"tiếng Anuta",
35326,
"poz-pnp",
"Latn",
}
m["aug"] = {
"Aguna",
34733,
"alv-gbe",
"Latn",
}
m["auh"] = {
"Aushi",
2872082,
"bnt-sbi",
"Latn",
}
m["aui"] = {
"tiếng Anuki",
3508132,
"poz-ocw",
"Latn",
"Tiếng Anuki",
"Anuki",
}
m["auj"] = {
"tiếng Awjila",
56398,
"ber",
"Latn, Arab, Tfng",
"Tiếng Awjila",
"Awjila",
}
m["auk"] = {
"Heyo",
3504295,
"qfa-tor",
"Latn",
}
m["aul"] = {
"Aulua",
427300,
"poz-vnc",
"Latn",
}
m["aum"] = {
"Asu",
34798,
"alv-ngb",
"Latn",
}
m["aun"] = {
"Molmo One",
12637224,
"qfa-tor",
"Latn",
}
m["auo"] = {
"Auyokawa",
56247,
"cdc-wst",
"Latn",
}
m["aup"] = {
"Makayam",
6738863,
"ngf",
"Latn",
}
m["auq"] = {
"Anus",
23855,
"poz-ocw",
"Latn",
}
m["aur"] = {
"Aruek",
3504279,
"qfa-tor",
"Latn",
}
m["aut"] = {
"Austral",
2669261,
"poz-pep",
"Latn",
}
m["auu"] = {
"Auye",
4827334,
"ngf",
"Latn",
}
m["auw"] = {
"Awyi",
3513326,
"paa-brd",
"Latn",
}
m["aux"] = {
"Aurá",
3507995,
"tup-gua",
"Latn",
}
m["auy"] = {
"Auyana",
2873211,
"paa-kag",
"Latn",
}
m["auz"] = {
"tiếng Ả Rập Uzbekistan",
3399507,
"sem-arb",
"Arab",
"Tiếng Ả Rập Uzbekistan",
"Ả Rập Uzbekistan",
entry_name = "ar-entryname",
}
m["avb"] = {
"Avau",
12627412,
"poz-ocw",
"Latn",
}
m["avd"] = {
"Alviri-Vidari",
3327357,
"xme",
"fa-Arab",
ancestors = "xme-mid",
}
m["avi"] = {
"Avikam",
34840,
"alv-lag",
"Latn",
}
m["avk"] = {
"tiếng Kotava",
1377116,
"art",
"Latn",
"Tiếng Kotava",
"Kotava",
type = "appendix-constructed",
}
m["avm"] = {
"Angkamuthi",
nil,
"aus-pmn",
"Latn",
}
m["avn"] = {
"tiếng Avatime",
34796,
"alv-ktg",
"Latn",
"Tiếng Avatime",
"Avatime",
}
m["avo"] = {
"Agavotaguerra",
3508007,
"awd",
"Latn",
}
m["avs"] = {
"Aushiri",
3409318,
"sai-zap",
"Latn",
}
m["avt"] = {
"Au",
3446608,
"qfa-tor",
"Latn",
}
m["avu"] = {
"tiếng Avokaya",
56685,
"csu-mma",
"Latn",
"Tiếng Avokaya",
"Avokaya",
}
m["avv"] = {
"Avá-Canoeiro",
4829584,
"tup-gua",
"Latn",
}
m["awa"] = {
"tiếng Awadh",
29579,
"inc-hie",
"Deva, Kthi, fa-Arab",
"Tiếng Awadh",
"Awadh",
translit = {Deva = "hi-translit"},
}
m["awb"] = {
"Awa (New Guinea)",
2874650,
"paa-kag",
"Latn",
}
m["awc"] = {
"Cicipu",
35193,
"nic-kam",
"Latn",
}
m["awe"] = {
"Awetí",
4830038,
"tup",
"Latn",
}
m["awg"] = {
"tiếng Anguthimri",
4764288,
"aus-pam",
"Latn",
"Tiếng Anguthimri",
"Anguthimri",
}
m["awh"] = {
"Awbono",
3446684,
"ngf",
"Latn",
}
m["awi"] = {
"Aekyom",
3399691,
"ngf",
"Latn",
}
m["awk"] = {
"Awabakal",
3449138,
"aus-pam",
"Latn",
}
m["awm"] = {
"Arawum",
4784537,
"ngf-mad",
"Latn",
}
m["awn"] = {
"tiếng Awngi",
34934,
"cus-cen",
"Ethi",
"Tiếng Awngi",
"Awngi",
}
m["awo"] = {
"Awak",
3446643,
"alv-wjk",
"Latn",
}
m["awr"] = {
"Awera",
56379,
"paa-lkp",
"Latn",
}
m["aws"] = {
"South Awyu",
12633986,
"ngf",
"Latn",
}
m["awt"] = {
"tiếng Araweté",
4784535,
"tup-gua",
"Latn",
"Tiếng Araweté",
"Araweté",
}
m["awu"] = {
"Central Awyu",
12628801,
"ngf",
"Latn",
}
m["awv"] = {
"Jair Awyu",
16110177,
"ngf",
"Latn",
}
m["aww"] = {
"Awun",
56369,
"paa-spk",
"Latn",
}
m["awx"] = {
"Awara",
2874670,
"ngf-fin",
"Latn",
}
m["awy"] = {
"Edera Awyu",
12630425,
"ngf",
"Latn",
}
m["axb"] = {
"Abipon",
11252539,
"sai-guc",
"Latn",
}
m["axe"] = {
"Ayerrerenge",
16112737,
"aus-pam",
"Latn",
}
m["axg"] = {
"Mato Grosso Arára",
3446660,
nil,
"Latn",
}
m["axk"] = {
"Aka (Central Africa)",
11010149,
"bnt-ngn",
"Latn",
}
m["axl"] = {
"Lower Southern Aranda",
6693295,
"aus-pam",
"Latn",
}
m["axm"] = {
"tiếng Armenia trung đại",
4438498,
"hyx",
"Armn",
"Tiếng Armenia trung đại",
"Armenia trung đại",
ancestors = "xcl",
-- Chuyển tự Armn đã có sẵn ở [[Mô đun:scripts/data]]
override_translit = true,
strip_diacritics = {
remove_diacritics = "՞՜՛՟",
from = {"եւ", "ՙ", "՚"},
to = {"և", "ʻ", "’"}
}
}
m["axx"] = {
"Xaragure",
8045635,
"poz-cln",
"Latn",
}
m["aya"] = {
"Awar",
56876,
"paa",
"Latn",
}
m["ayb"] = {
"Ayizo",
34841,
"alv-pph",
"Latn",
}
m["ayd"] = {
"Ayabadhu",
3509164,
"aus-pmn",
"Latn",
}
m["aye"] = {
"tiếng Ayere",
34788,
"alv-aah",
"Latn",
"Tiếng Ayere",
"Ayere",
}
m["ayg"] = {
"Nyanga (Togo)",
35446,
"alv-gng",
"Latn",
}
m["ayi"] = {
"Leyigha",
3914492,
"nic-uce",
"Latn",
}
m["ayk"] = {
"tiếng Akuku",
3450179,
"alv-nwd",
"Latn",
}
m["ayl"] = {
"tiếng Ả Rập Libya",
56503,
"sem-arb",
"Arab",
strip_diacritics = "ar-stripdiacritics",
}
m["ayn"] = {
"tiếng Ả Rập Sana'a",
1686766,
"sem-arb",
"Arab, Hebr",
strip_diacritics = {
Arab = "ar-stripdiacritics",
},
-- Hebr display_text, strip_diacritics, sort_key in [[Module:scripts/data]]
}
m["ayo"] = {
"Ayoreo",
56634,
"sai-zam",
"Latn",
}
m["ayp"] = {
"tiếng Ả Rập Bắc Lưỡng Hà",
56577,
"sem-arb",
"Arab",
"Tiếng Ả Rập Bắc Lưỡng Hà",
"Ả Rập Bắc Lưỡng Hà",
ancestors = "acm",
entry_name = "ar-entryname",
}
m["ayq"] = {
"Ayi",
56449,
"paa-spk",
"Latn",
}
m["ays"] = {
"Sorsogon Ayta",
7563752,
"phi",
"Latn",
}
m["ayt"] = {
"Bataan Ayta",
4921648,
"phi",
"Latn",
}
m["ayu"] = {
"tiếng Ayu",
34786,
"alv",
"Latn",
}
m["ayy"] = {
"Tayabas Ayta",
7689745,
"phi",
"Latn",
}
m["ayz"] = {
"Maybrat",
4830892,
"paa-wpa",
"Latn",
}
m["aza"] = {
"Azha",
4832486,
"tbq-axi",
"Latn",
}
m["azd"] = {
"Eastern Durango Nahuatl",
16115449,
"azc-nah",
"Latn",
}
m["azg"] = {
"San Pedro Amuzgos Amuzgo",
35092,
"omq",
"Latn",
}
m["azm"] = {
"Ipalapa Amuzgo",
12633013,
"omq",
"Latn",
}
m["azn"] = {
"Western Durango Nahuatl",
12645553,
"azc-nah",
"Latn",
}
m["azo"] = {
"tiếng Awing",
34856,
"nic-nge",
"Latn",
"Tiếng Awing",
"Awing",
}
m["azt"] = {
"Faire Atta",
12630884,
"phi",
"Latn",
}
m["azz"] = {
"Highland Puebla Nahuatl",
12953754,
"azc-nah",
"Latn",
}
return require("Module:languages").finalizeData(m, "language")
7wd3hg3jz68e4niyoa9x6fz0719h6ed
Mô đun:languages/data/3/x
828
272279
2576410
2576376
2026-11-08T13:10:36Z
Lcsnes
40261
2576410
Scribunto
text/plain
local m_langdata = require("Module:languages/data")
-- Loaded on demand, as it may not be needed (depending on the data).
local function u(...)
u = require("Module:string utilities").char
return u(...)
end
local c = m_langdata.chars
local p = m_langdata.puaChars
local s = m_langdata.shared
local m = {}
m["xaa"] = {
"tiếng Ả Rập Andalusia",
1137945,
"sem-arb",
"Arab, Latn",
"Tiếng Ả Rập Andalusia",
"Ả Rập Andalusia",
entry_name = {
remove_diacritics = c.kashida .. c.fathatan .. c.dammatan .. c.kasratan .. c.fatha .. c.damma .. c.kasra .. c.shadda .. c.sukun .. c.superalef,
from = {u(0x0671)},
to = {u(0x0627)}
},
}
m["xab"] = {
"Sambe",
36265,
"nic-alu",
"Latn",
}
m["xac"] = {
"Kachari",
3442442,
"tbq-bdg",
}
m["xad"] = {
"Adai",
346744,
}
m["xae"] = {
"Aequian",
930579,
"itc",
}
m["xag"] = {
"tiếng Aghwan",
34931,
"cau-esm",
"Aghb",
"Tiếng Aghwan",
"Aghwan",
translit = "Aghb-translit",
override_translit = true,
}
m["xai"] = {
"Kaimbé",
6348017,
}
m["xaj"] = {
"Ararandewára",
nil,
"tup-gua",
"Latn",
}
m["xak"] = {
"Maku",
2032882,
nil,
"Latn",
}
m["xal"] = {
"tiếng Kalmyk",
33634,
"xgn-cen",
"Cyrl, xwo-Mong",
"Tiếng Kalmyk",
"Kalmyk",
ancestors = "xwo",
translit = "xal-translit",
override_translit = true,
sort_key = "xal-sortkey",
}
m["xam"] = {
"ǀXam",
2086145,
"khi-tuu",
"Latn",
}
m["xan"] = {
"tiếng Xamtanga",
56527,
"cus-cen",
"Ethi",
"Tiếng Xamtanga",
"Xamtanga",
}
m["xao"] = {
"Khao",
3196077,
"mkh-pal",
}
m["xap"] = {
"Apalachee",
686501,
"nai-mus",
"Latn",
}
m["xaq"] = {
"tiếng Aquitani",
500522,
"euq",
"Latn",
"Tiếng Aquitani",
"Aquitani",
}
m["xar"] = {
"Karami",
11732281,
}
m["xas"] = {
"tiếng Kamassia",
35991,
translit = "xas-translit",
"syd",
"Cyrl",
"Tiếng Kamassia",
"Kamassia",
}
m["xat"] = {
"Katawixi",
3440512,
"sai-ktk",
}
m["xau"] = {
"Kauwera",
6378983,
"paa-tkw",
}
m["xav"] = {
"tiếng Xavante",
36962,
"sai-cje",
"Latn",
"Tiếng Xavante",
"Xavante",
}
m["xaw"] = {
"Kawaiisu",
56338,
"azc-num",
"Latn",
}
m["xay"] = {
"Kayan Mahakam",
25337171,
}
m["xbb"] = {
"Lower Burdekin",
6693353,
}
m["xbc"] = {
"tiếng Bactria",
756651,
"ira-sbc",
"Polyt, Mani",
-- Dữ liệu chuyển tự chữ Hy Lạp (Polyt), display_text, strip_diacritics, sort_key đã có trong [[Module:scripts/data]]
-- Dữ liệu chuyển tự chữ Mani đã có trong [[Module:scripts/data]]
}
m["xbd"] = {
"Bindal",
4913975,
}
m["xbe"] = {
"Bigambal",
16841801,
"aus-pam", --unclassified within
}
m["xbg"] = {
"Bunganditj",
4997615,
}
m["xbi"] = {
"Kombio",
6428259,
"qfa-tor",
"Latn",
}
m["xbj"] = {
"Birrpayi",
nil,
}
m["xbm"] = {
"tiếng Breton trung đại",
787610,
"cel-brs",
"Latn",
"Tiếng Breton trung đại",
"Breton trung đại",
ancestors = "obt",
}
m["xbn"] = {
"Kenaboi",
6388752,
}
m["xbo"] = {
"tiếng Bulgar",
36880,
"trk-ogr",
"Arab, Grek",
"Tiếng Bulgar",
"Bulgar",
entry_name = {
Arab = "ar-entryname",
}
}
m["xbp"] = {
"Bibbulman",
22918391,
}
m["xbr"] = {
"tiếng Kambera",
3053279,
"poz-cet",
"Latn",
"Tiếng Kambera",
"Kambera",
}
m["xbw"] = {
"Kambiwá",
9006744,
}
m["xby"] = {
"Butchulla",
31752631,
}
m["xcb"] = {
"tiếng Cumbria",
35965,
"cel-brw",
nil,
"Tiếng Cumbria",
"Cumbria",
}
m["xcc"] = {
"tiếng Camuni",
489011,
nil,
"Ital",
"Tiếng Camuni",
"Camuni",
translit = "Ital-translit",
}
m["xce"] = {
"tiếng Celtiberi",
37012,
"cel-his",
"Latn",
"Tiếng Celtiberi",
"Celtiberi",
}
m["xch"] = {
"Chemakum",
56397,
"chi",
"Latn",
}
m["xcl"] = {
"tiếng Armenia cổ",
181074,
"hyx",
"Armn",
"Tiếng Armenia cổ",
"Armenia cổ",
translit = "Armn-translit",
override_translit = true,
entry_name = {
remove_diacritics = "՞՜՛՟",
from = {"եւ"},
to = {"և"}
},
}
m["xcm"] = {
"Comecrudo",
609808,
"nai-pak",
}
m["xcn"] = {
"Cotoname",
56889,
"nai-pak",
}
m["xco"] = {
"tiếng Khwarezm",
33138,
"ira-sbc",
"Arab, Armi, Chrs, Phlv, Sogd",
"Tiếng Khwarezm",
"Khwarezm",
translit = {Chrs = "Chrs-translit"},
}
m["xcr"] = {
"Carian",
35929,
"ine-luw",
"Cari",
}
m["xct"] = {
"tiếng Tây Tạng cổ điển",
5128314,
"sit-tib",
"Tibt, Hani, Marc, Mong, mnc-Mong, xwo-Mong, Phag, Tang, Zanb",
"Tiếng Tây Tạng cổ điển",
"Tây Tạng cổ điển",
translit = {
Tibt = "Tibt-translit",
Mong = "Mong-translit",
["mnc-Mong"] = "mnc-translit",
["xwo-Mong"] = "xwo-translit",
Tang = "txg-translit",
},
override_translit = true,
display_text = {
Tibt = s["Tibt-displaytext"],
Mong = s["Mong-displaytext"],
},
entry_name = {
Tibt = s["Tibt-entryname"],
Mong = s["Mong-entryname"],
},
sort_key = {
Tibt = "Tibt-sortkey",
Hani = "Hani-sortkey",
},
}
m["xcu"] = {
"Curonian",
35857,
"bat",
"Latn",
}
m["xcv"] = {
"tiếng Chuvan",
3516641,
"qfa-yuk",
"Cyrl",
"Tiếng Chuvan",
"Chuvan",
translit = "xcv-translit"
}
m["xcw"] = {
"Coahuilteco",
2008062,
"nai-pak",
}
m["xcy"] = {
"Cayuse",
2472016,
}
m["xda"] = {
"Darkinjung",
5223660,
"aus-yuk",
"Latn",
}
m["xdc"] = {
"tiếng Dacia",
682547,
"ine",
"Latn, Polyt",
"Tiếng Dacia",
"Dacia",
translit = {Polyt = "grc-translit"},
entry_name = {
Polyt = s["Polyt-entryname"],
},
sort_key = {
Polyt = s["Grek-sortkey"],
},
}
m["xdk"] = {
"tiếng Dharug",
1166814,
"aus-yuk",
"Latn",
"Tiếng Dharug",
"Dharug",
}
m["xdm"] = {
"Edomite",
2363529,
"sem-can",
"Phnx",
translit = "Phnx-translit",
}
m["xdq"] = {
"tiếng Kaitag",
1990659,
"cau-drg",
"Cyrl",
"Tiếng Kaitag",
"Kaitag",
translit = {Cyrl = "dar-translit"},
override_translit = true,
display_text = {Cyrl = s["cau-Cyrl-displaytext"]},
}
m["xdy"] = {
"Malayic Dayak",
3514892,
}
m["xeb"] = {
"tiếng Ebla",
35345,
"sem-eas",
"Xsux",
"Tiếng Ebla",
"Ebla",
}
m["xed"] = {
"Hdi",
56246,
"cdc-cbm",
"Latn",
}
m["xeg"] = {
"ǁXegwi",
3509732,
"khi-tuu",
"Latn",
}
m["xel"] = {
"Kelo",
6386412,
"sdv-eje",
}
m["xem"] = {
"Kembayan",
6386874,
}
m["xep"] = {
"Epi-Olmec",
nil,
}
m["xer"] = {
"Xerénte",
3073436,
"sai-cje",
"Latn",
}
m["xes"] = {
"Kesawai",
6394907,
"ngf-mad",
"Latn",
}
m["xet"] = {
"Xetá",
2980404,
"tup-gua",
"Latn",
}
m["xeu"] = {
"Keoru-Ahia",
11732313,
"ngf",
}
m["xfa"] = {
"tiếng Falisci",
35669,
"itc",
"Ital, Latn",
translit = {Ital = "Ital-translit"},
entry_name = {remove_diacritics = c.macron .. c.breve .. c.diaer},
"Tiếng Falisci",
"Falisci",
}
m["xga"] = {
"tiếng Galati",
27403,
"cel-con",
"Latn, Grek",
"Tiếng Galati",
"Galati",
ancestors = "cel-gau",
}
m["xgb"] = {
"Gbin",
16934745,
"dmn-mse",
"Latn",
}
m["xgd"] = {
"Gudang",
5614528,
}
m["xgf"] = {
"Gabrielino-Fernandeño",
56387,
"azc-tak",
"Latn",
}
m["xgg"] = {
"Goreng",
nil,
}
m["xgi"] = {
"Garingbal",
nil,
}
m["xgl"] = {
"Galindian",
1190494,
"bat",
"Latn",
}
m["xgm"] = {
"Darumbal",
16954400,
}
m["xgr"] = {
"Garza",
3098656,
"nai-pak",
}
m["xgu"] = {
"Unggumi",
62000004,
"aus-wor",
"Latn",
}
m["xgw"] = {
"Guwa",
5621992,
}
m["xha"] = {
"Harami",
41506724,
nil,
"Sarb",
translit = "Sarb-translit",
}
m["xhc"] = {
"Hunnic",
35959,
}
m["xhd"] = {
"Hadrami",
1032453,
"sem-osa",
"Sarb",
translit = "Sarb-translit",
}
m["xhe"] = {
"Khetrani",
2614111,
"inc-pan",
ancestors = "lah",
}
m["xhm"] = {
"tiếng Khmer trung đại",
25226861,
"mkh-kmr",
"Latn, Khmr", --and also Pallava
"Tiếng Khmer trung đại",
"Khmer trung đại",
ancestors = "okz",
}
m["xhr"] = {
"tiếng Hernici",
5908773,
"itc-sbl",
"Ital",
"Tiếng Hernici",
"Hernici",
translit = "Ital-translit",
}
m["xht"] = {
"tiếng Hatti",
31107,
"qfa-iso",
"Xsux",
"Tiếng Hatti",
"Hatti",
}
m["xhu"] = {
"tiếng Hurri",
35740,
"qfa-hur",
"Xsux, Ugar",
"Tiếng Hurri",
"Hurri",
}
m["xhv"] = {
"tiếng Khùa",
22970290,
"mkh-kat",
"Latn",
"Tiếng Khùa",
"Khùa"
}
m["xib"] = {
"Iberian",
855215,
"qfa-iso",
"Latn, Ibrn",
}
m["xii"] = {
"Xiri",
36876,
}
m["xin"] = {
"Xinca",
1546494,
"nai-xin",
"Latn",
}
m["xil"] = {
"Illyrian",
35976,
"ine",
type = "reconstructed",
}
m["xir"] = {
"Xiriâna",
2028772,
"awd",
"Latn",
}
m["xis"] = {
"tiếng Kisan",
63339998,
"dra-kml",
"Orya",
ancestors = "kru",
"Tiếng Kisan",
"Kisan",
}
m["xiv"] = {
"Indus Valley Language",
3428279,
nil,
"Inds",
}
m["xiy"] = {
"Xipaya",
13226,
"tup",
}
m["xjb"] = {
"Minjungbal",
nil,
"aus-pam",
"Latn",
}
m["xka"] = {
"tiếng Kalkot",
3877551,
"inc-shn",
"ur-Arab",
"Tiếng Kalkot",
"Kalkot",
}
m["xkb"] = {
"Manigri-Kambolé Ede Nago",
36042,
"alv-ede",
}
m["xkc"] = {
"Khoini",
6401919,
"xme-ttc",
ancestors = "xme-ttc-wes",
}
m["xkd"] = {
"Mendalam Kayan",
12952597,
}
m["xke"] = {
"Kereho",
6437086,
"poz",
"Latn",
}
m["xkf"] = {
"tiếng Khengkha",
3695207,
"sit-ebo",
"Tibt",
"Tiếng Khengkha",
"Khengkha",
translit = "Tibt-translit",
override_translit = true,
display_text = s["Tibt-displaytext"],
entry_name = s["Tibt-entryname"],
sort_key = "Tibt-sortkey",
}
m["xkg"] = {
"Kagoro",
11159524,
"dmn-wmn",
}
m["xki"] = {
"Kenyan Sign Language",
6392859,
"sgn",
}
m["xkj"] = {
"Kajali",
14916876,
"xme-ttc",
ancestors = "xme-ttc-cen",
}
m["xkk"] = {
"Kaco'",
6344767,
"mkh",
}
m["xkl"] = {
"tiếng Bakung",
6736761,
"poz-swa",
"Latn",
"Tiếng Bakung",
"Bakung",
}
m["xkn"] = {
"Kayan River Kayan",
12473395,
"poz",
}
m["xko"] = {
"Kiorr",
6414519,
"mkh-pal",
}
m["xkp"] = {
"Kabatei",
34165,
"xme-ttc",
ancestors = "xme-ttc-cen",
}
m["xkq"] = {
"Koroni",
3199000,
"poz-btk",
}
m["xkr"] = {
"Xakriabá",
3073441,
"sai-cje",
"Latn",
}
m["xks"] = {
"tiếng Kumbewaha",
6443722,
"poz-mun",
"Latn",
"Tiếng Kumbewaha",
"Kumbewaha"
}
m["xkt"] = {
"Kantosi",
35651,
"nic-dag",
}
m["xku"] = {
"Kaamba",
11042324,
"bnt-kng",
}
m["xkv"] = {
"Kgalagadi",
2088743,
"bnt-sts",
"Latn",
}
m["xkw"] = {
"Kembra",
12953627,
"paa-pau",
}
m["xkx"] = {
"Karore",
6373260,
"poz-ocw",
}
m["xky"] = {
"Uma' Lasan",
nil,
"poz-swa",
}
m["xkz"] = {
"tiếng Kurtokha",
3695193,
"sit-ebo",
"Tibt, Latn",
"Tiếng Kurtokha",
"Kurtokha",
translit = {Tibt = "Tibt-translit"},
display_text = {Tibt = s["Tibt-displaytext"]},
entry_name = {Tibt = s["Tibt-entryname"]},
sort_key = {Tibt = "Tibt-sortkey"},
}
m["xla"] = {
"tiếng Kamula",
10957277,
"ngf",
"Latn",
"Tiếng Kamula",
"Kamula",
}
m["xlb"] = {
"Loup B",
13108281,
"alg-eas",
"Latn",
}
m["xlc"] = {
"tiếng Lycia",
35969,
"ine-luw",
"Lyci",
"Tiếng Lycia",
"Lycia",
translit = "Lyci-translit",
}
m["xld"] = {
"tiếng Lydia",
36095,
"ine-ana",
"Lydi",
"Tiếng Lydia",
"Lydia",
translit = "Lydi-translit",
}
m["xle"] = {
"tiếng Lemnos",
36203,
"qfa-tyn",
"Ital",
translit = "Ital-translit",
"Tiếng Lemnos",
"Lemnos",
}
m["xlg"] = {
"Ancient Ligurian",
36104,
"ine",
}
m["xli"] = {
"Liburnian",
35835,
"ine",
}
--xln is etymology-only
m["xlo"] = {
"Loup A",
27921265,
"alg-eas",
"Latn",
}
m["xlp"] = {
"tiếng Leponti",
35993,
"cel-con",
"Ital",
"Tiếng Leponti",
"Leponti",
translit = "Ital-translit",
}
m["xls"] = {
"Lusitanian",
35960,
"ine",
"Latn",
}
m["xlu"] = {
"tiếng Luwi",
12634577,
"ine-luw",
"Xsux, Hluw",
"Tiếng Luwi",
"Luwi",
}
m["xly"] = {
"tiếng Elymi",
35329,
nil,
"Grek",
"Tiếng Elymi",
"Elymi",
}
m["xmb"] = {
"Mbonga",
36064,
"nic-jrn",
"Latn",
}
m["xmc"] = {
"Makhuwa-Marrevone",
11127231,
"bnt-mak",
ancestors = "vmw",
}
m["xmd"] = {
"Mbudum",
6799790,
"cdc-cbm",
"Latn",
}
m["xmf"] = {
"tiếng Mingrelia",
13359,
"ccs-zan",
"Geor",
"Tiếng Mingrelia",
"Mingrelia",
translit = "Geor-translit",
override_translit = true,
}
m["xmg"] = {
"Mengaka",
36017,
"bai",
"Latn",
}
m["xmh"] = {
"Kugu-Muminh",
10549849,
"aus-pmn",
"Latn",
}
m["xmj"] = {
"Majera",
6737666,
"cdc-cbm",
"Latn",
}
m["xmk"] = {
"tiếng Macedoni cổ đại",
35974,
"grk",
"Polyt",
"Tiếng Macedoni cổ đại",
"Macedoni cổ đại",
translit = "grc-translit",
entry_name = s["Polyt-entryname"],
sort_key = s["Grek-sortkey"],
}
m["xml"] = {
"Malaysian Sign Language",
33420,
"sgn",
}
m["xmm"] = {
"Manado Malay",
1068112,
}
m["xmo"] = {
"Morerebi",
12953749,
"tup",
"Latn",
}
m["xmp"] = {
"Kuku-Mu'inh",
10549852,
nil,
"Latn",
}
m["xmq"] = {
"Kuku-Mangk",
10549851,
"aus-pam",
"Latn",
}
m["xmr"] = {
"Meroitic",
13366,
"afa",
"Mero, Merc, Latn", -- we have entries in Latn
translit = "xmr-translit",
}
m["xms"] = {
"Moroccan Sign Language",
6913107,
"sgn",
}
m["xmt"] = {
"Matbat",
6786187,
"poz-hce",
}
m["xmu"] = {
"Kamu",
6359779,
}
m["xmx"] = {
"Maden",
12952756,
"poz-hce",
}
m["xmy"] = {
"Mayaguduna",
3436736,
}
m["xmz"] = {
"Mori Bawah",
3324069,
"poz-btk",
"Latn",
}
m["xna"] = {
"tiếng Bắc Ả Rập cổ đại",
1472213,
"sem-cen",
"Narb",
"Tiếng Bắc Ả Rập cổ đại",
"Bắc Ả Rập cổ đại",
translit = "Narb-translit",
}
m["xnb"] = {
"tiếng Kanakanavu",
172244,
"map-tsu",
"Latn",
"Tiếng Kanakanavu",
"Kanakanavu",
}
m["xng"] = {
"tiếng Mông Cổ trung đại",
2582455,
"xgn",
"Mong, Phag, Hani, Arab, Armn",
"Tiếng Mông Cổ trung đại",
"Mông Cổ trung đại",
translit = {Mong = "Mong-translit"},
display_text = {Mong = s["Mong-displaytext"]},
entry_name = {Mong = s["Mong-entryname"]},
sort_key = {Hani = "Hani-sortkey"},
}
m["xnh"] = {
"Kuanhua",
6441084,
"mkh-pal",
}
m["xni"] = {
"Ngarigu",
7022072,
"aus-yuk",
}
m["xnk"] = {
"Nganakarti",
33087049,
}
m["xnn"] = {
"Northern Kankanay", -- use this for now; correction must be "Northern Kankanaey"
12953609,
"phi",
}
-- "xno" IS TREATED AS "fro", SEE WT:LT
m["xnr"] = {
"tiếng Kangra",
2331560,
"him",
"Deva, Takr, fa-Arab",
"Tiếng Kangra",
"Kangra",
ancestors = "doi",
translit = {Deva = "hi-translit"},
}
m["xns"] = {
"Kanashi",
6360672,
"sit-whm",
}
m["xnt"] = {
"tiếng Narragansett",
3336118,
"alg-eas",
"Latn, Hebr",
"Tiếng Narragansett",
"Narragansett",
entry_name = {remove_diacritics = c.grave .. c.acute .. c.tilde .. c.macron},
}
m["xnu"] = {
"Nukunul",
7068904,
}
m["xny"] = {
"Nyiyaparli",
16919427,
"aus-nga",
"Latn",
}
m["xoc"] = {
"O'chi'chi'",
3813833,
"nic-cde",
"Latn",
}
m["xod"] = {
"Kokoda",
6426734,
"ngf-sbh",
}
m["xog"] = {
"Soga",
33784,
"bnt-nyg",
"Latn",
}
m["xoi"] = {
"Kominimung",
6428352,
"paa",
"Latn",
}
m["xok"] = {
"Xokleng",
3027930,
"sai-sje",
}
m["xom"] = {
"tiếng Komo",
56681,
"ssa-kom",
"Latn, Ethi",
"Tiếng Komo",
"Komo",
}
m["xon"] = {
"Konkomba",
35674,
"nic-grm",
"Latn",
}
m["xoo"] = { -- contrast kzw, sai-kat, sai-xoc
"Xukurú",
9096758,
}
m["xop"] = {
"Kopar",
11732346,
}
m["xor"] = {
"Korubo",
3199022,
}
m["xow"] = {
"Kowaki",
6434920,
"ngf-mad",
}
m["xpa"] = {
"Pirriya",
16978087,
}
m["xpb"] = {
"Pyemmairre",
7262964,
nil,
"Latn",
}
m["xpc"] = {
"tiếng Pecheneg",
877881,
"trk",
nil,
"Tiếng Pecheneg",
"Pecheneg",
}
m["xpd"] = {
"Paredarerme",
7136678,
nil,
"Latn",
}
m["xpe"] = {
"tiếng Kpelle Liberia",
20527226,
"dmn-msw",
"Latn, Kpel",
"Tiếng Kpelle Liberia",
"Kpelle Liberia",
ancestors = "kpe",
}
m["xpf"] = {
"Southeast Tasmanian",
7068421,
nil,
"Latn",
}
m["xpg"] = {
"tiếng Phrygia",
36751,
"ine-grp",
"Polyt, Latn",
"Tiếng Phrygia",
"Phrygia",
}
m["xph"] = {
"Tyerrernotepanner",
7859815,
nil,
"Latn",
}
m["xpi"] = {
"Pictish",
856383,
"cel-brw",
"Ogam, Latn",
}
m["xpj"] = {
"Mpalitjanh",
6928192,
"aus-pam",
}
m["xpk"] = {
"Kulina",
6443027,
"sai-pan",
}
m["xpl"] = {
"Port Sorell",
7230944,
nil,
"Latn",
}
m["xpm"] = {
"tiếng Pumpokol",
2991985,
"qfa-yso",
"Latn",
"Tiếng Pumpokol",
"Pumpokol",
}
m["xpn"] = {
"Kapinawá",
6366667,
}
m["xpo"] = {
"Pochutec",
2427341,
"azc-nah",
"Latn",
}
m["xpp"] = {
"Puyo-Paekche",
nil,
}
m["xpq"] = {
"tiếng Mohegan-Pequot",
3319130,
"alg-eas",
"Latn",
"Tiếng Mohegan-Pequot",
"Mohegan-Pequot",
}
m["xpr"] = {
"tiếng Parthia",
25953,
"ira-mpr",
"Prti, Mani, Phlv",
"Tiếng Parthia",
"Parthia",
translit = {
Prti = "Prti-translit",
Mani = "Mani-translit",
},
}
m["xps"] = {
"Pisidian",
36580,
"ine-luw",
}
m["xpu"] = {
"tiếng Punic",
535958,
"sem-can",
"Phnx, Latn, Grek",
"Tiếng Punic",
"Punic",
ancestors = "phn",
translit = {Phnx = "Phnx-translit"},
}
m["xpv"] = {
"Tommeginne",
7819095,
nil,
"Latn",
}
m["xpw"] = {
"Peerapper",
7160431,
nil,
"Latn",
}
m["xpx"] = {
"Toogee",
7824008,
nil,
"Latn",
}
m["xpy"] = {
"Buyeo",
5003359,
"qfa-kor",
"Hani",
sort_key = "Hani-sortkey",
}
m["xpz"] = {
"Bruny Island",
4979601,
"qfa-unc",
"Latn",
}
m["xqa"] = {
"tiếng Karakhanid",
4494885,
"trk-kar",
"Arab, Ougr",
"Tiếng Karakhanid",
"Karakhanid",
strip_diacritics = "ar-stripdiacritics",
}
m["xqt"] = {
"Qatabanian",
384101,
"sem-osa",
"Sarb",
translit = "Sarb-translit",
}
m["xra"] = {
"Krahô",
3199549,
"sai-nje",
"Latn",
}
m["xrb"] = {
"Eastern Karaboro",
35716,
"alv-krb",
"Latn",
}
m["xrd"] = {
"Gundungurra",
60611652,
nil,
"Latn",
}
m["xre"] = {
"Kreye",
3199686,
"sai-nje",
}
m["xrg"] = {
"Minang",
22893424,
"aus-pam",
"Latn",
}
m["xri"] = {
"Krikati-Timbira",
3199710,
"sai-nje",
"Latn",
}
m["xrm"] = {
"Armazic",
7599646,
"sem-ara",
"Armi",
}
m["xrn"] = {
"tiếng Arin",
34088,
"qfa-yso",
"Latn",
"Tiếng Arin",
"Arin",
}
m["xrq"] = {
"Karranga",
6373349,
nil,
"Latn",
}
m["xrr"] = {
"tiếng Raetia",
36689,
"qfa-tyn",
"Ital",
"Tiếng Raetia",
"Raetia",
translit = "Ital-translit",
}
m["xrt"] = {
"Aranama-Tamique",
2859505,
}
m["xru"] = {
"Marriammu",
10577724,
"aus-dal",
"Latn",
}
m["xrw"] = {
"Karawa",
6368857,
"paa-sep",
"Latn",
}
m["xsa"] = {
"tiếng Saba",
1070391,
"sem-osa",
"Sarb",
"Tiếng Saba",
"Saba",
translit = "Sarb-translit",
}
m["xsb"] = {
"tiếng Sambali",
2592378,
"phi",
"Latn",
"Tiếng Sambali",
"Sambali",
}
m["xsd"] = {
"Sidetic",
36659,
"ine-luw",
"Sidt",
}
m["xse"] = {
"Sempan",
3504358,
}
m["xsh"] = {
"Shamang",
3914876,
"nic-plc",
}
m["xsi"] = {
"Sio",
3485100,
"poz-ocw",
}
m["xsj"] = {
"Subi",
7631298,
"bnt-haj",
}
m["xsl"] = {
"tiếng Nam Slavey",
28552,
"den",
"Latn, Cans",
"Tiếng Nam Slavey",
"Nam Slavey",
}
m["xsm"] = {
"Kasem",
35552,
"nic-gnn",
}
m["xsn"] = {
"Sanga (Nigeria)",
3915334,
"nic-jer",
"Latn",
}
m["xso"] = {
"Solano",
2474492,
nil,
"Latn",
}
m["xsp"] = {
"Silopi",
7515533,
"ngf-mad",
}
m["xsq"] = {
"Makhuwa-Saka",
11008159,
"bnt-mak",
ancestors = "vmw",
}
m["xsr"] = {
"tiếng Sherpa",
36612,
"sit-tib",
"Tibt, Deva",
"Tiếng Sherpa",
"Sherpa",
ancestors = "xct",
translit = {
Tibt = "Tibt-translit",
Deva = "xsr-Deva-translit",
},
override_translit = true,
display_text = {Tibt = s["Tibt-displaytext"]},
entry_name = {Tibt = s["Tibt-entryname"]},
sort_key = {Tibt = "Tibt-sortkey"},
}
m["xss"] = {
"tiếng Assan",
34089,
"qfa-yso",
"Latn",
"Tiếng Assan",
"Assan",
}
m["xsu"] = {
"Sanumá",
251728,
"sai-ynm",
}
m["xsv"] = {
"Sudovian",
35603,
"bat-wes",
"Latn",
}
m["xsy"] = {
"tiếng Saisiyat",
716695,
"map",
"Latn",
"Tiếng Saisiyat",
"Saisiyat",
}
m["xta"] = {
"tiếng Mixtec Alcozauca",
25559587,
"omq-mxt",
"Latn",
"Tiếng Mixtec Alcozauca",
"Mixtec Alcozauca",
}
m["xtb"] = {
"Chazumba Mixtec",
12182838,
"omq-mxt",
"Latn",
}
m["xtc"] = {
"Kadugli",
3407136,
"qfa-kad",
"Latn",
}
m["xtd"] = {
"Diuxi-Tilantongo Mixtec",
7802048,
"omq-mxt",
"Latn",
}
m["xte"] = {
"Ketengban",
10990152,
}
m["xth"] = {
"Yitha Yitha",
nil,
}
m["xti"] = {
"Sinicahua Mixtec",
12953733,
"omq-mxt",
"Latn",
}
m["xtj"] = {
"San Juan Teita Mixtec",
32093049,
"omq-mxt",
"Latn",
}
m["xtl"] = {
"Tijaltepec Mixtec",
12953738,
"omq-mxt",
"Latn",
}
m["xtm"] = {
"Magdalena Peñasco Mixtec",
7179700,
"omq-mxt",
"Latn",
}
m["xtn"] = {
"Northern Tlaxiaco Mixtec",
25559585,
"omq-mxt",
"Latn",
}
m["xto"] = {
"tiếng Tochari A",
2827041,
"ine-toc",
"Latn",
"Tiếng Tochari A",
"Tochari A",
wikipedia_article = "Ngữ tộc Tochari", -- wikidata id has no associated article
}
m["xtp"] = {
"San Miguel Piedras Mixtec",
7414970,
"omq-mxt",
"Latn",
}
m["xtq"] = {
"tiếng Tumshuq",
nil,
"xsc-sak",
"Brah, Khar",
"Tiếng Tumshuq",
"Tumshuq",
translit = "Brah-translit",
}
m["xtr"] = {
"Early Tripuri",
nil,
}
m["xts"] = {
"Sindihui Mixtec",
13583581,
"omq-mxt",
"Latn",
}
m["xtt"] = {
"Tacahua Mixtec",
7673668,
"omq-mxt",
"Latn",
}
m["xtu"] = {
"Cuyamecalco Mixtec",
12953726,
"omq-mxt",
"Latn",
}
m["xtv"] = {
"Thawa",
7711494,
}
m["xtw"] = {
"Tawandê",
nil,
"sai-nmk",
"Latn",
}
m["xty"] = {
"Yoloxochitl Mixtec",
8054817,
"omq-mxt",
"Latn",
}
m["xua"] = {
"tiếng Kurumba Alu",
12952679,
"dra-kan",
"Knda",
"Tiếng Kurumba Alu",
"Kurumba Alu",
translit = {Knda = "kn-translit"},
}
m["xub"] = {
"tiếng Kurumba Betta",
16841033,
"dra-kan",
"Knda, Mlym, Taml",
"Tiếng Kurumba Betta",
"Kurumba Betta",
translit = {
Knda = "kn-translit",
Mlym = "ml-translit",
Taml = "ta-translit",
},
}
m["xud"] = {
"Umiida",
61999874,
"aus-wor",
"Latn",
}
m["xug"] = {
"tiếng Kunigami",
56558,
"jpx-nry",
"Jpan",
"Tiếng Kunigami",
"Kunigami",
translit = s["Jpan-translit"],
sort_key = s["Jpan-sortkey"],
}
m["xuj"] = {
"tiếng Kurumba Jennu",
21282543,
"dra-kan",
"Knda, Taml",
"Tiếng Kurumba Jennu",
"Kurumba Jennu",
translit = {
Knda = "kn-translit",
Taml = "ta-translit"
},
}
m["xul"] = {
"Ngunawal",
7022712,
"aus-yuk",
"Latn",
}
m["xum"] = {
"tiếng Umbria",
36957,
"itc-sbl",
"Ital, Latn",
"Tiếng Umbria",
"Umbria",
translit = "Ital-translit",
}
m["xun"] = {
"Unggaranggu",
61999823,
"aus-wor",
"Latn",
}
m["xuo"] = {
"tiếng Kuo",
6445233,
"alv-mbm",
"Latn",
"Tiếng Kuo",
"Kuo",
}
m["xup"] = {
"Upper Umpqua",
20607,
"ath-pco",
"Latn",
}
m["xur"] = {
"tiếng Urartu",
36934,
"qfa-hur",
"Xsux",
"Tiếng Urartu",
"Urartu",
}
m["xut"] = {
"Kuthant",
6448417,
}
m["xuu"] = {
"Khwe",
28305,
"khi-kal",
"Latn",
}
m["xve"] = {
"tiếng Veneti",
36871,
"ine",
"Ital",
"Tiếng Veneti",
"Veneti",
translit = "Ital-translit",
}
-- m["xvi"] = { "Kamviri", 1193495, "nur-nor", Arab } moved to etym-only code
m["xvn"] = {
"Vandalic",
36835,
"gme",
"Latn",
}
m["xvo"] = {
"tiếng Volsci",
622110,
"itc-sbl",
"Latn",
"Tiếng Volsci",
"Volsci",
}
m["xvs"] = {
"Vestinian",
2576407,
"itc",
"Latn",
}
m["xwa"] = {
"Kwaza",
3200839,
}
m["xwc"] = {
"Woccon",
3569569,
"nai-cat",
"Latn",
}
m["xwd"] = {
"Wadi Wadi",
7959249,
}
m["xwe"] = {
"Xwela Gbe",
36887,
"alv-pph",
}
m["xwg"] = {
"Kwegu",
56723,
"sdv",
}
m["xwj"] = {
"Wajuk",
33110188,
}
m["xwk"] = {
"Wangkumara",
7967891,
"aus-pam",
"Latn",
}
m["xwl"] = {
"Western Xwla Gbe",
36924,
"alv-pph",
"Latn",
}
m["xwo"] = {
"tiếng Oirat",
56959,
"xgn-cen",
"xwo-Mong",
"Tiếng Oirat",
"Oirat",
translit = "xwo-translit",
}
m["xwr"] = {
"Kwerba Mamberamo",
6450325,
"paa-tkw",
}
m["xww"] = {
"tiếng Wemba-Wemba",
18472819,
"aus-pam",
"Latn",
"Tiếng Wemba-Wemba",
"Wemba-Wemba",
}
m["xxb"] = {
"Boro",
16844787,
nil,
"Latn",
}
m["xxk"] = {
"Ke'o",
3195346,
}
m["xxm"] = {
"Minkin",
6867836,
}
m["xxr"] = {
"Koropó",
6432560,
}
m["xxt"] = {
"Tambora",
36711,
"paa",
"Latn",
}
m["xya"] = {
"Yaygir",
8050525,
"aus-pam",
}
m["xyb"] = {
"Yandjibara",
nil,
nil,
"Latn",
}
m["xyl"] = {
"Yalakalore",
12645352,
"sai-nmk",
"Latn",
}
m["xyt"] = {
"Mayi-Thakurti",
47004719,
"aus-pam",
"Latn",
}
m["xyy"] = {
"Yorta Yorta",
8055849,
"aus-pam",
"Latn",
}
m["xzh"] = {
"Zhang-Zhung",
3437292,
"sit-alm",
"Marc, Tibt",
translit = {Tibt = "Tibt-translit"},
display_text = {Tibt = s["Tibt-displaytext"]},
entry_name = {Tibt = s["Tibt-entryname"]},
sort_key = {Tibt = "Tibt-sortkey"},
}
m["xzm"] = {
"Zemgalian",
47631,
"bat-eas",
}
m["xzp"] = {
"Ancient Zapotec",
nil,
}
return require("Module:languages").finalizeData(m, "language")
fu92cq98d5fpevgc54dh9yjoze7zfvc
Mô đun:languages/canonical names
828
273923
2576442
2576277
2026-11-08T14:27:05Z
Hiyuune
50834
2576442
Scribunto
text/plain
return {
["Aba"] = "utp",
["Abai Sungai"] = "abf",
["Abenlen Ayta"] = "abp",
["Abipon"] = "axb",
["Abishira"] = "ash",
["Abom"] = "aob",
["Abu"] = "ado",
["Abu' Arapesh"] = "aah",
["Abua"] = "abn",
["Abun"] = "kgr",
["Abung"] = "abl",
["Abureni"] = "mgj",
["Abé"] = "aba",
["Ache"] = "yif",
["Aché"] = "guq",
["Acroá"] = "acs",
["Adabe"] = "adb",
["Adai"] = "xad",
["Adamorobe Sign Language"] = "ads",
["Adang"] = "adn",
["Adangbe"] = "adq",
["Adap"] = "adp",
["Adasen"] = "tiu",
["Adele"] = "ade",
["Adhola"] = "adh",
["Tiếng Adjukru"] = "adj",
["Adithinngithigh"] = "dth",
["Adonara"] = "adr",
["Aduge"] = "adu",
["Aeka"] = "aez",
["Aekyom"] = "awi",
["Aequian"] = "xae",
["Afghan Sign Language"] = "afg",
["Afitti"] = "aft",
["Afra"] = "ulf",
["Afrihili"] = "afh",
["Afro-Seminole Creole"] = "afs",
["Agarabi"] = "agd",
["Agariya"] = "agi",
["Agavotaguerra"] = "avo",
["Aghu"] = "ahh",
["Aghu Tharrnggala"] = "gtu",
["Agi"] = "aif",
["Agob"] = "kit",
["Agoi"] = "ibm",
["Aguano"] = "aga",
["Aguaruna"] = "agr",
["Aguna"] = "aug",
["Agusan Manobo"] = "msm",
["Agutaynen"] = "agn",
["Agwagwune"] = "yay",
["Ahanta"] = "aha",
["Ahirani"] = "ahr",
["Ahwai"] = "nfd",
["Ai-Cham"] = "aih",
["Aighon"] = "aix",
["Aikanã"] = "tba",
["Aiklep"] = "mwg",
["Aimele"] = "ail",
["Ainbai"] = "aic",
["Aiome"] = "aki",
["Airoran"] = "air",
["Aisi"] = "mmq",
["Aiwoo"] = "nfl",
["Aja"] = "aja",
["Ajagua"] = "sai-ajg",
["Ajawa"] = "ajw",
["Ajyíninka Apurucayali"] = "cpc",
["Ak"] = "akq",
["Aka (Central Africa)"] = "axk",
["Aka (Sudan)"] = "soh",
["Aka-Bea"] = "abj",
["Aka-Cari"] = "aci",
["Aka-Kol"] = "aky",
["Aka-Kora"] = "ack",
["Akar-Bale"] = "acl",
["Akatek"] = "knj",
["Ake"] = "aik",
["Akebu"] = "keu",
["Akei"] = "tsr",
["Akeu"] = "aeu",
["Akolet"] = "akt",
["Akoye"] = "miw",
["Akpa"] = "akf",
["Tiếng Akpes"] = "ibe",
["Akrukay"] = "afi",
["Tiếng Akuku"] = "ayk",
["Akum"] = "aku",
["Akurio"] = "ako",
["Akuwagel"] = "bey",
["Akwa"] = "akw",
["Akyaung Ari"] = "nqy",
["Al-Sayyid Bedouin Sign Language"] = "syy",
["Alabat Island Agta"] = "dul",
["Alacatlatzala Mixtec"] = "mim",
["Alago"] = "ala",
["Alapmunte"] = "apv",
["Alas-Kluet Batak"] = "btz",
["Alazapa"] = "nai-ala",
["Albanian Sign Language"] = "sqk",
["Alege"] = "alf",
["Algerian Sign Language"] = "asp",
["Ali"] = "aiy",
["Alladian"] = "ald",
["Alngith"] = "aid",
["Alo Phola"] = "ypo",
["Alor"] = "aol",
["Aloápam Zapotec"] = "zaq",
["Alu"] = "mte",
["Alugu"] = "aub",
["Tiếng Alune"] = "alp",
["Alungul"] = "aus-alu",
["Aluo"] = "yna",
["Alur"] = "alz",
["Alutiiq"] = "ems",
["Alviri-Vidari"] = "avd",
["Alyawarr"] = "aly",
["Amahai"] = "amq",
["Amanayé"] = "ama",
["Amara"] = "aie",
["Amarakaeri"] = "amr",
["Amarizana"] = "awd-ama",
["Amasi"] = "alv-ama",
["Amatlán Zapotec"] = "zpo",
["Amba"] = "rwm",
["Ambakich"] = "aew",
["Ambala Ayta"] = "abc",
["Ambelau"] = "amv",
["Ambele"] = "ael",
["Amblong"] = "alm",
["Ambo"] = "amb",
["Ambul"] = "apo",
["Amele"] = "aey",
["Amganad Ifugao"] = "ifa",
["Ami"] = "amy",
["Ammonite"] = "sem-amm",
["Amo"] = "amo",
["Amol"] = "alx",
["Amoltepec Mixtec"] = "mbz",
["Amondawa"] = "adw",
["Amorite"] = "sem-amo",
["Ampanang"] = "apg",
["Ampari Dogon"] = "aqd",
["Amri Karbi"] = "ajz",
["Amto"] = "amt",
["Ana Tinga Dogon"] = "dti",
["Anakalangu"] = "akg",
["Anam"] = "pda",
["Anambé"] = "aan",
["Anamgura"] = "imi",
["Anasi"] = "bpo",
["Ancient Ligurian"] = "xlg",
["Ancient North Arabian"] = "xna",
["Ancient Zapotec"] = "xzp",
["Andai"] = "afd",
["Andajin"] = "ajn",
["Andaman Creole Hindi"] = "hca",
["Andaqui"] = "ana",
["Andarum"] = "aod",
["Andegerebinha"] = "adg",
["Andh"] = "anr",
["Andio"] = "bzb",
["Andjingith"] = "aus-and",
["Andoa"] = "anb",
["Andoque"] = "ano",
["Andoquero"] = "sai-and",
["Andra-Hus"] = "anx",
["Aneityum"] = "aty",
["Anem"] = "anz",
["Aneme Wake"] = "aby",
["Anfillo"] = "myo",
["Tiếng Angaataha"] = "agm",
["Angaité"] = "aqt",
["Angal"] = "age",
["Angal Enen"] = "aoe",
["Angal Heneng"] = "akh",
["Angevin"] = "roa-ang",
["Angkamuthi"] = "avm",
["Angkola Batak"] = "akb",
["Angloromani"] = "rme",
["Angor"] = "agg",
["Angoram"] = "aog",
["Angosturas Tunebo"] = "tnd",
["Anguthimri"] = "awg",
["Ani Phowa"] = "ypn",
["Animere"] = "anf",
["Anindilyakwa"] = "aoi",
["Anjam"] = "boj",
["Anmatyerre"] = "amx",
["Anong"] = "nun",
["Anor"] = "anj",
["Anserma"] = "ans",
["Ansus"] = "and",
["Antakarinya"] = "ant",
["Antigua and Barbuda Creole English"] = "aig",
["Anu"] = "anl",
["Anufo"] = "cko",
["Anus"] = "auq",
["Tiếng Anuta"] = "aud",
["Anyin Morofo"] = "mtb",
["Aoheng"] = "pni",
["Aore"] = "aor",
["Ap Ma"] = "kbx",
["Apalachee"] = "xap",
["Apali"] = "ena",
["Apasco-Apoala Mixtec"] = "mip",
["Apiaká"] = "api",
["Apma"] = "app",
["Apolista"] = "awd-apo",
["Aproumu Aizi"] = "ahp",
["Apurinã"] = "apu",
["Arabana"] = "ard",
["Arabela"] = "arl",
["Aralle-Tabulahan"] = "atq",
["Arammba"] = "stk",
["Aranama-Tamique"] = "xrt",
["Arandai"] = "jbj",
["Araona"] = "aro",
["Arapaso"] = "arj",
["Arara-Karo"] = "arr",
["Ararandewára"] = "xaj",
["Arawum"] = "awm",
["Arbore"] = "arv",
["Are"] = "mwc",
["Areba"] = "aea",
["Argentine Sign Language"] = "aed",
["Arguni"] = "agf",
["Arhâ"] = "aqr",
["Arhö"] = "aok",
["Aribwatsa"] = "laz",
["Aribwaung"] = "ylu",
["Arifama-Miniafia"] = "aai",
["Tiếng Arigidi"] = "aqg",
["Arikapú"] = "ark",
["Arikara"] = "ari",
["Arikem"] = "ait",
["Tiếng Aringa"] = "luc",
["Armazic"] = "xrm",
["Armenian Sign Language"] = "aen",
["Arop-Lokep"] = "apr",
["Arop-Sissano"] = "aps",
["Arosi"] = "aia",
["Arritinngithigh"] = "rrt",
["Arta"] = "atz",
["Arua"] = "aru",
["Aruamu"] = "msy",
["Aruek"] = "aur",
["Aruop"] = "lsr",
["Arutani"] = "atx",
["Aruá"] = "arx",
["As"] = "asz",
["Asaro'o"] = "mtv",
["Ashe"] = "ahs",
["Asháninka"] = "cni",
["Ashéninka Perené"] = "prq",
["Asilulu"] = "asl",
["Asoa"] = "asv",
["Assangori"] = "sjg",
["Asu"] = "aum",
["Asue Awyu"] = "psa",
["Asunción Mixtepec Zapotec"] = "zoo",
["Ata"] = "atm",
["Ata Manobo"] = "atd",
["Atakapa"] = "aqp",
["Atampaya"] = "amz",
["Atanques"] = "cba-ata",
["Atatláhuca Mixtec"] = "mib",
["Ateso"] = "teo",
["Ati"] = "atk",
["Atohwaim"] = "aqm",
["Atong (Cameroon)"] = "ato",
["Atorada"] = "aox",
["Atsam"] = "cch",
["Atsugewi"] = "atw",
["Attié"] = "ati",
["Au"] = "avt",
["Aulua"] = "aul",
["Aurá"] = "aux",
["Aushi"] = "auh",
["Aushiri"] = "avs",
["Auslan"] = "asf",
["Austral"] = "aut",
["Australian Aboriginal Sign Language"] = "asw",
["Austrian Sign Language"] = "asq",
["Austronesian Mari"] = "hob",
["Auwe"] = "smf",
["Auyana"] = "auy",
["Auye"] = "auu",
["Auyokawa"] = "auo",
["Avau"] = "avb",
["Avava"] = "tmb",
["Avikam"] = "avi",
["Avá-Canoeiro"] = "avv",
["Awa (New Guinea)"] = "awb",
["Awa-Cuaiquer"] = "kwi",
["Awabakal"] = "awk",
["Awak"] = "awo",
["Awar"] = "aya",
["Awara"] = "awx",
["Awbono"] = "awh",
["Awera"] = "awr",
["Awetí"] = "awe",
["Awngthim"] = "gwm",
["Awtuw"] = "kmn",
["Awun"] = "aww",
["Awutu"] = "afu",
["Awyi"] = "auw",
["Axamb"] = "ahb",
["Ayabadhu"] = "ayd",
["Ayautla Mazatec"] = "vmy",
["Ayerrerenge"] = "axe",
["Ayi"] = "ayq",
["Ayizi"] = "yyz",
["Ayizo"] = "ayb",
["Ayomán"] = "sai-ayo",
["Ayoquesco Zapotec"] = "zaf",
["Ayoreo"] = "ayo",
["Tiếng Ayu"] = "ayu",
["Ayutla Mixtec"] = "miy",
["Azha"] = "aza",
["Azhe"] = "yiz",
["Baa"] = "kwb",
["Baan"] = "bvj",
["Baangi"] = "bqx",
["Baba"] = "bbw",
["Babango"] = "bbm",
["Babanki"] = "bbk",
["Babine-Witsuwit'en"] = "bcr",
["Babole"] = "bvx",
["Bada"] = "bhz",
["Badeshi"] = "bdz",
["Badimaya"] = "bia",
["Badyara"] = "pbp",
["Baeggu"] = "bvd",
["Baelelea"] = "bvc",
["Baenan"] = "sai-bae",
["Baetora"] = "btr",
["Bafanji"] = "bfj",
["Bafaw"] = "bwt",
["Bafia"] = "ksf",
["Bafut"] = "bfd",
["Baga Kaloum"] = "bqf",
["Baga Koga"] = "bgo",
["Baga Manduri"] = "bmd",
["Baga Pokur"] = "bcg",
["Baga Sitemu"] = "bsp",
["Baga Sobané"] = "bsv",
["Bagheli"] = "bfy",
["Tiếng Bagirmi"] = "bmi",
["Bago-Kusuntu"] = "bqg",
["Bagri"] = "bgq",
["Bagupi"] = "bpi",
["Bagusa"] = "bqb",
["Baha"] = "yha",
["Baham"] = "bdw",
["Bahamian Creole"] = "bah",
["Baharna Arabic"] = "abv",
["Bahau"] = "bhv",
["Bahinemo"] = "bjh",
["Bahonsuai"] = "bsu",
["Bai"] = "bdj",
["Baibai"] = "bbf",
["Baikeno"] = "bkx",
["Baima"] = "bqh",
["Baimak"] = "bmx",
["Bainouk-Gunyaamolo"] = "bcz",
["Bainouk-Samik"] = "bcb",
["Baissa Fali"] = "fah",
["Bajan"] = "bjs",
["Bajelani"] = "bjm",
["Baka"] = "bkc",
["Bakairí"] = "bkq",
["Bakoko"] = "bkh",
["Bakole"] = "kme",
["Bakpinka"] = "bbs",
["Bakulung"] = "bbu",
["Tiếng Bakumpai"] = "bkr",
["Bakwé"] = "bjw",
["Tiếng Balaesang"] = "bls",
["Balangao"] = "blw",
["Balangingi"] = "sse",
["Balau"] = "blg",
["Baldemu"] = "bdn",
["Bali"] = "bcp",
["Baliledo"] = "poz-bal",
["Balinese Malay"] = "mhp",
["Balo"] = "bqo",
["Baloi"] = "biz",
["Balong"] = "bnt-bal",
["Baluan-Pam"] = "blq",
["Bamako Sign Language"] = "bog",
["Bamali"] = "bbq",
["Bambalang"] = "bmo",
["Bambam"] = "ptu",
["Bambili-Bambui"] = "baw",
["Bamenyam"] = "bce",
["Bamu"] = "bcf",
["Bamukumbit"] = "bqt",
["Bamunka"] = "bvm",
["Bamwe"] = "bmg",
["Ban Khor Sign Language"] = "bfk",
["Banam Bay"] = "vrt",
["Banao Itneg"] = "bjx",
["Banaro"] = "byz",
["Banda"] = "bnd",
["Banda Malay"] = "bpq",
["Banda-Bambari"] = "liy",
["Banda-Banda"] = "bpd",
["Banda-Mbrès"] = "bqk",
["Banda-Ndélé"] = "bfl",
["Banda-Yangere"] = "yaj",
["Bandi"] = "bza",
["Bandial"] = "bqj",
["Bangala"] = "bxg",
["Bangandu"] = "bgf",
["Bangba"] = "bbe",
["Bangime"] = "dba",
["Bangka"] = "mfb",
["Bangru"] = "sit-ban",
["Bangubangu"] = "bnx",
["Bangwinji"] = "bsj",
["Baniva"] = "bvv",
["Baniwa"] = "bwi",
["Banka"] = "bxw",
["Bankan Tey Dogon"] = "dbw",
["Banoni"] = "bcm",
["Bantik"] = "bnq",
["Baraamu"] = "brd",
["Baram Kayan"] = "kys",
["Barama"] = "bbg",
["Barambu"] = "brm",
["Baramu"] = "bmz",
["Barapasi"] = "brp",
["Baras"] = "brs",
["Barasana"] = "bsn",
["Barbareño"] = "boi",
["Barclayville Grebo"] = "gry",
["Bardi"] = "bcj",
["Barein"] = "bva",
["Bargam"] = "mlp",
["Bariai"] = "bch",
["Bariji"] = "bjc",
["Barikanchi"] = "bxo",
["Barngarla"] = "bjb",
["Barok"] = "bjk",
["Barranbinya"] = "aus-bra",
["Barro Negro Tunebo"] = "tbn",
["Barrow Point"] = "bpt",
["Baruga"] = "bjz",
["Barunggam"] = "aus-brm",
["Baruya"] = "byr",
["Barwe"] = "bwg",
["Barí"] = "mot",
["Basa"] = "bzw",
["Basa-Gumna"] = "bsl",
["Basa-Gurmana"] = "buj",
["Basap"] = "bdb",
["Bashkardi"] = "bsg",
["Bassa-Kontagora"] = "bsr",
["Bassossi"] = "bsi",
["Bata"] = "bta",
["Bataan Ayta"] = "ayt",
["Batanga"] = "bnm",
["Bateri"] = "btv",
["Bathari"] = "bhm",
["Bati (Cameroon)"] = "btc",
["Bati (Indonesia)"] = "bvt",
["Batu"] = "btu",
["Batui"] = "zbt",
["Bau"] = "bbd",
["Bauchi"] = "bsf",
["Baure"] = "brg",
["Bauria"] = "bge",
["Bauro"] = "bxa",
["Bauwaki"] = "bwk",
["Bauzi"] = "bvz",
["Bawm Chin"] = "bgr",
["Bay Miwok"] = "mkq",
["Bayali"] = "bjy",
["Baybayanon"] = "bvy",
["Baygo"] = "byg",
["Bayogoula"] = "nai-bay",
["Bayono"] = "byl",
["Bayot"] = "bda",
["Bayungu"] = "bxj",
["Bazigar"] = "bfr",
["Baïnounk Gubëeher"] = "alv-bgu",
["Beami"] = "beo",
["Beba"] = "bfp",
["Bebe"] = "bzv",
["Bebele"] = "beb",
["Bebeli"] = "bek",
["Bebil"] = "bxp",
["Bedik"] = "tnr",
["Bedoanas"] = "bed",
["Beeke"] = "bkf",
["Beele"] = "bxq",
["Beembe"] = "beq",
["Beezen"] = "bnz",
["Befang"] = "bby",
["Begbere-Ejar"] = "bqv",
["Bekati'"] = "bei",
["Bekwarra"] = "bkv",
["Bekwel"] = "bkw",
["Belait"] = "beg",
["Belanda Bor"] = "bxb",
["Belanda Viri"] = "bvi",
["Belizean Creole"] = "bzj",
["Tiếng Bembe"] = "bmb",
["Ben Tey"] = "dbt",
["Bena"] = "yun",
["Benabena"] = "bef",
["Bende"] = "bdp",
["Bendi"] = "bct",
["Beneraf"] = "bnv",
["Beng"] = "nhb",
["Benga"] = "bng",
["Benggoi"] = "bgy",
["Bengkala Sign Language"] = "bqy",
["Bentong"] = "bnu",
["Benyadu'"] = "byd",
["Beothuk"] = "bue",
["Bepour"] = "bie",
["Bera"] = "brf",
["Berakou"] = "bxv",
["Berau Malay"] = "bve",
["Berawan"] = "lod",
["Bergish"] = "gmw-bgh",
["Berinomo"] = "bit",
["Berom"] = "bom",
["Berta"] = "wti",
["Berti"] = "byt",
["Besme"] = "bes",
["Besoa"] = "bep",
["Betaf"] = "bfe",
["Bete"] = "byf",
["Bete-Bendi"] = "btt",
["Betoi"] = "sai-bet",
["Bhalay"] = "bhx",
["Bharia"] = "bha",
["Bhaya"] = "bhe",
["Bhele"] = "bhy",
["Bhilali"] = "bhi",
["Bhoti Kinnauri"] = "nes",
["Biafada"] = "bif",
["Biage"] = "bdf",
["Biak"] = "bhw",
["Biali"] = "beh",
["Bian Marind"] = "bpv",
["Biangai"] = "big",
["Biao"] = "byk",
["Biao Mon"] = "bmt",
["Biao-Jiao Mien"] = "bje",
["Bibaali"] = "bcn",
["Bibbulman"] = "xbp",
["Bidiyo"] = "bid",
["Bidyara"] = "bym",
["Bidyogo"] = "bjg",
["Biem"] = "bmc",
["Bierebo"] = "bnk",
["Bieria"] = "brj",
["Biete"] = "biu",
["Big Nambas"] = "nmb",
["Biga"] = "bhc",
["Bigambal"] = "xbe",
["Bikaru"] = "bic",
["Bikya"] = "byb",
["Bila"] = "bip",
["Bilakura"] = "bql",
["Bilba"] = "bpz",
["Bilbil"] = "brz",
["Bile"] = "bil",
["Biliau"] = "bcu",
["Biloxi"] = "bll",
["Bilur"] = "bxf",
["Bimin"] = "bhl",
["Bimoba"] = "bim",
["Bina"] = "bmn",
["Binahari"] = "bxz",
["Binandere"] = "bhg",
["Binawa"] = "byj",
["Bindal"] = "xbd",
["Bine"] = "bon",
["Binji"] = "bpj",
["Binongan Itneg"] = "itb",
["Bintauna"] = "bne",
["Bintulu"] = "bny",
["Binumarien"] = "bjr",
["Bipi"] = "biq",
["Birgid"] = "brk",
["Biri"] = "bzr",
["Biritai"] = "bqq",
["Birri"] = "bvq",
["Birrpayi"] = "xbj",
["Birwa"] = "brl",
["Biseni"] = "ije",
["Bishuo"] = "bwh",
["Bisis"] = "bnw",
["Bisorio"] = "bir",
["Bitare"] = "brt",
["Bitur"] = "mcc",
["Biwat"] = "bwm",
["Biyo"] = "byo",
["Biyom"] = "bpm",
["Blablanga"] = "blp",
["Black Speech"] = "art-bsp",
["Blafe"] = "bfh",
["Bo"] = "bgl",
["Bo-Rukul"] = "mae",
["Bo-Ung"] = "mux",
["Boano (Maluku)"] = "bzn",
["Boano (Sulawesi)"] = "bzl",
["Bobongko"] = "bgb",
["Bobot"] = "bty",
["Bodo (Central Africa)"] = "boy",
["Bofi"] = "bff",
["Boga"] = "bvw",
["Bogaya"] = "boq",
["Boguru"] = "bqu",
["Boikin"] = "bzf",
["Bokha"] = "ybk",
["Bokoto"] = "bdt",
["Bokyi"] = "bky",
["Bolak"] = "art-blk",
["Bolango"] = "bld",
["Bole"] = "bol",
["Bolgo"] = "bvo",
["Bolia"] = "bli",
["Tiếng Bolinao"] = "smk",
["Bolivian Sign Language"] = "bvl",
["Bolon"] = "bof",
["Bolondo"] = "bzm",
["Bolongan"] = "blj",
["Bom"] = "bmf",
["Boma Nkuu"] = "bnt-bon",
["Boma Yumu"] = "bnt-boy",
["Bomboli"] = "bml",
["Bomboma"] = "bws",
["Bomitaba"] = "zmx",
["Bomwali"] = "bmw",
["Bon Gula"] = "glc",
["Bondei"] = "bou",
["Tiếng Kulango Bondoukou"] = "kzc",
["Bondum Dom Dogon"] = "dbu",
["Bonerate"] = "bna",
["Bonggi"] = "bdg",
["Bonggo"] = "bpg",
["Bongili"] = "bui",
["Tiếng Bongo"] = "bot",
["Bongu"] = "bpu",
["Bonjo"] = "bok",
["Bonkeng"] = "bvg",
["Bonkiman"] = "bop",
["Bookan"] = "bnb",
["Boor"] = "bvf",
["Bora"] = "boa",
["Border Kuna"] = "kvn",
["Borei"] = "gai",
["Boro"] = "xxb",
["Borong"] = "ksr",
["Boruca"] = "brn",
["Boselewa"] = "bwf",
["Bosngun"] = "bqs",
["Bote-Majhi"] = "bmj",
["Tiếng Kulango Bouna"] = "nku",
["Bourbonnais-Berrichon"] = "roa-bbn",
["Bozaba"] = "bzo",
["Bragat"] = "aof",
["Brazilian Sign Language"] = "bzs",
["Brek Karen"] = "kvl",
["Tiếng Brem"] = "buq",
["Bribri"] = "bzd",
["British Sign Language"] = "bfi",
["Brokskat"] = "bkk",
["Broome Pearling Lugger Pidgin"] = "bpl",
["Brunei Bisaya"] = "bsb",
["Bruny Island"] = "xpz",
["Bu"] = "jid",
["Bu-Nao Bunu"] = "bwx",
["Bua"] = "bub",
["Bualkhaw Chin"] = "cbl",
["Buamu"] = "box",
["Bubi"] = "buw",
["Bubia"] = "bbx",
["Budibud"] = "btp",
["Budong-Budong"] = "bdx",
["Budu"] = "buu",
["Buduma"] = "bdm",
["Budza"] = "bja",
["Buena Vista Yokuts"] = "nai-bvy",
["Buglere"] = "sab",
["Bugun"] = "bgg",
["Buhutu"] = "bxh",
["Bujhyal"] = "byh",
["Bukar-Sadung Bidayuh"] = "sdo",
["Bukat"] = "bvk",
["Bukawa"] = "buk",
["Bukit Malay"] = "bvu",
["Bukitan"] = "bkn",
["Buksa"] = "tkb",
["Bukusu"] = "bxk",
["Bulgarian Sign Language"] = "bqn",
["Bulgebi"] = "bmp",
["Buli (Ghana)"] = "bwu",
["Buli (Indonesia)"] = "bzq",
["Bulu (Cameroon)"] = "bum",
["Bulu (New Guinea)"] = "bjl",
["Bum"] = "bmv",
["Bumaji"] = "byp",
["Bumbita Arapesh"] = "aon",
["Bun"] = "buv",
["Buna"] = "bvn",
["Bunaba"] = "bck",
["Bunak"] = "bfn",
["Tiếng Bunama"] = "bdd",
["Bundeli"] = "bns",
["Bung"] = "bqd",
["Bungain"] = "but",
["Bunganditj"] = "xbg",
["Bungu"] = "wun",
["Bunoge"] = "dgb",
["Buol"] = "blf",
["Bura"] = "bwr",
["Burak"] = "bys",
["Buraka"] = "bkg",
["Burarra"] = "bvr",
["Burate"] = "bti",
["Burduna"] = "bxn",
["Bure"] = "bvh",
["Burgundian"] = "gem-bur",
["Burmeso"] = "bzu",
["Buru (Indonesia)"] = "mhs",
["Buru (Nigeria)"] = "bqw",
["Burui"] = "bry",
["Burumakok"] = "aip",
["Burun"] = "bdi",
["Burusu"] = "bqr",
["Buruwai"] = "asi",
["Busam"] = "bxs",
["Busami"] = "bsm",
["Busang Kayan"] = "bfg",
["Bushoong"] = "buf",
["Buso"] = "bso",
["Busoa"] = "bup",
["Busuu"] = "bju",
["Butbut Kalinga"] = "kyb",
["Butchulla"] = "xby",
["Butmas-Tur"] = "bnr",
["Buwal"] = "bhs",
["Buyeo"] = "xpy",
["Buyu"] = "byi",
["Buyuan Jino"] = "jiy",
["Bwa"] = "bww",
["Bwaidoka"] = "bwd",
["Bwala"] = "bnt-bwa",
["Bwanabwana"] = "tte",
["Bwatoo"] = "bwa",
["Bwela"] = "bwl",
["Bwile"] = "bwc",
["Bwisi"] = "bwz",
["Byangsi"] = "bee",
["Byep"] = "mkk",
["Bädi Kanum"] = "khd",
["Caac"] = "msq",
["Cabiyarí"] = "cbb",
["Cabécar"] = "cjp",
["Cacaloxtepec Mixtec"] = "miu",
["Cacaopera"] = "ccr",
["Cacua"] = "cbv",
["Cacán"] = "sai-cac",
["Caddo"] = "cad",
["Cafundó"] = "ccd",
["Cahuarano"] = "cah",
["Caka"] = "ckx",
["Cakchiquel-Quiché Mixed Language"] = "ckz",
["Cakfem-Mushere"] = "cky",
["Calabrian Greek"] = "grk-cal",
["Callawalla"] = "caw",
["Calusa"] = "nai-cal",
["Caluyanun"] = "clu",
["Caló"] = "rmq",
["Camarines Norte Agta"] = "abd",
["Cameroon Mambila"] = "mcu",
["Cameroon Pidgin"] = "wes",
["Campalagian"] = "cml",
["Camsá"] = "kbh",
["Camtho"] = "cmt",
["Candoshi-Shapra"] = "cbu",
["Canichana"] = "caz",
["Cao Miao"] = "cov",
["Capiznon"] = "cps",
["Caquinte"] = "cot",
["Cara"] = "cfd",
["Carabayo"] = "cby",
["Caramanta"] = "crf",
["Caranqui"] = "sai-caq",
["Carapana"] = "cbc",
["Carian"] = "xcr",
["Cariay"] = "awd-kar",
["Carijona"] = "cbd",
["Carolina Algonquian"] = "crr",
["Carolinian"] = "cal",
["Carpathian Romani"] = "rmc",
["Cashibo-Cacataibo"] = "cbr",
["Cashinahua"] = "cbs",
["Casiguran Dumagat Agta"] = "dgc",
["Casuarina Coast Asmat"] = "asc",
["Catacao"] = "sai-cat",
["Catalan Sign Language"] = "csc",
["Catuquinaru"] = "sai-ctq",
["Catío Chibcha"] = "cba-cat",
["Cauca"] = "cca",
["Cavere"] = "awd-cav",
["Cavineña"] = "cav",
["Cayubaba"] = "cyb",
["Cayuse"] = "xcy",
["Cazcan"] = "azc-caz",
["Cañari"] = "sai-cnr",
["Cebaara Senoufo"] = "sef",
["Cemuhî"] = "cam",
["Cen"] = "cen",
["Central Asmat"] = "cns",
["Central Awyu"] = "awu",
["Tiếng Bontoc Trung"] = "lbk",
["Central Cagayan Agta"] = "agt",
["Central Grebo"] = "grv",
["Central Huishui Hmong"] = "hmc",
["Central Maewo"] = "mwo",
["Central Mahuatlán Zapoteco"] = "zam",
["Central Malay"] = "pse",
["Central Masela"] = "mxz",
["Central Mashan Hmong"] = "hmm",
["Central Melanau"] = "mel",
["Central Ojibwa"] = "ojc",
["Central Palawano"] = "plc",
["Central Pame"] = "pbs",
["Central Pomo"] = "poo",
["Central Sierra Miwok"] = "csm",
["Central Subanen"] = "syb",
["Central Tagbanwa"] = "tgt",
["Central Tarahumara"] = "tar",
["Central Teke"] = "nzu",
["Central Tunebo"] = "tuf",
["Centúúm"] = "cet",
["Cerma"] = "cme",
["Ch'olti'"] = "myn-chl",
["Chaap Wuurong"] = "tjw",
["Chadian Sign Language"] = "cds",
["Chaha"] = "sem-cha",
["Chairel"] = "sit-cha",
["Chakali"] = "cli",
["Chala"] = "cll",
["Chali"] = "tgf",
["Chamacoco"] = "ceg",
["Chamba Daka"] = "ccg",
["Chamba Leko"] = "ndi",
["Chambri"] = "can",
["Champenois"] = "roa-cha",
["Chang"] = "nbc",
["Changriwa"] = "cga",
["Chaná"] = "sai-chn",
["Chané"] = "caj",
["Chapacura"] = "sai-chp",
["Chara"] = "cra",
["Charrua"] = "sai-chr",
["Chaudangsi"] = "cdn",
["Chayahuita"] = "cbt",
["Chazumba Mixtec"] = "xtb",
["Che"] = "ruk",
["Cheke Holo"] = "mrn",
["Chemakum"] = "xch",
["Chenapian"] = "cjn",
["Chepya"] = "ycp",
["Cherepon"] = "cpn",
["Chesu"] = "ych",
["Chetco-Tolowa"] = "ctc",
["Chhintange"] = "ctn",
["Chhulung"] = "cur",
["Chiangmai Sign Language"] = "csd",
["Chiapanec"] = "cip",
["Chichicapan Zapotec"] = "zpv",
["Chichimeca-Jonaz"] = "pei",
["Chichonyi-Chidzihana-Chikauma"] = "coh",
["Chicomuceltec"] = "cob",
["Chiduruma"] = "dug",
["Chigmecatitlán Mixtec"] = "mii",
["Chilean Sign Language"] = "csg",
["Chilisso"] = "clh",
["Chiltepec Chinantec"] = "csa",
["Chimalapa Zoque"] = "zoh",
["Chimariko"] = "cid",
["Chimila"] = "cbg",
["Chimwiini"] = "bnt-cmw",
["Chinbon Chin"] = "cnb",
["Chinese Pidgin English"] = "cpi",
["Chinese Sign Language"] = "csl",
["Chipaya"] = "cap",
["Chiquihuitlán Mazatec"] = "maq",
["Chiquimulilla"] = "nai-chi",
["Chiquitano"] = "cax",
["Chirino"] = "sai-chi",
["Chiripá"] = "nhd",
["Chitimacha"] = "ctm",
["Chitkuli Kinnauri"] = "cik",
["Chitwania Tharu"] = "the",
["Tiếng Zapotec Choapan"] = "zpc",
["Chochotec"] = "coz",
["Chokri Naga"] = "nri",
["Chokwe"] = "cjk",
["Cholón"] = "cht",
["Chono"] = "sai-cno",
["Chopi"] = "cce",
["Chuabo"] = "chw",
["Chuanqiandian Cluster Miao"] = "cqd",
["Chuave"] = "cjv",
["Chug"] = "cvg",
["Chuj"] = "cac",
["Chuka"] = "cuh",
["Chukwa"] = "cuw",
["Chumburung"] = "ncu",
["Churuya"] = "sai-chu",
["Chácobo"] = "cao",
["Ci Gbe"] = "cib",
["Cibak"] = "ckl",
["Cicipu"] = "awc",
["Ciguayo"] = "nai-cig",
["Cinamiguin Manobo"] = "mkx",
["Cinda-Regi-Tiyal"] = "cdr",
["Cineni"] = "cie",
["Cinta Larga"] = "cin",
["Cishingini"] = "asg",
["Citak"] = "txt",
["Ciwogai"] = "tgd",
["Tiếng Gael cổ điển"] = "ghc",
["Classical Guaraní"] = "gn-cls",
["Tiếng Manda cổ điển"] = "myz",
["Classical Newar"] = "nwc",
["Classical Quechua"] = "qwc",
["Coahuilteco"] = "xcw",
["Coast Miwok"] = "csi",
["Coastal Konjo"] = "kjc",
["Coatecas Altas Zapotec"] = "zca",
["Coatepec Nahuatl"] = "naz",
["Coatlán Mixe"] = "mco",
["Coatlán Zapotec"] = "zps",
["Coatzospan Mixtec"] = "miz",
["Cocopa"] = "coc",
["Cocos Islands Malay"] = "coa",
["Coeruna"] = "sai-coe",
["Cogui"] = "kog",
["Col"] = "liw",
["Colombian Sign Language"] = "csn",
["Colonia Tovar German"] = "gct",
["Columbia-Wenatchi"] = "col",
["Colán"] = "sai-col",
["Comaltepec Chinantec"] = "cco",
["Comechingon"] = "sai-cmg",
["Comecrudo"] = "xcm",
["Communicationssprache"] = "art-com",
["Como Karim"] = "cfg",
["Con"] = "cno",
["Coos"] = "csz",
["Copainalá Zoque"] = "zoc",
["Copallén"] = "sai-cop",
["Coquille"] = "coq",
["Cora"] = "crn",
["Cori"] = "cry",
["Coroado Puri"] = "sai-crd",
["Cosoleacaque Nahuatl"] = "nhk",
["Costa Rican Sign Language"] = "csr",
["Cotabato Manobo"] = "mta",
["Cotoname"] = "xcn",
["Coyaima"] = "coy",
["Coyotepec Popoloca"] = "pbf",
["Coyutla Totonac"] = "toc",
["Crimean Gothic"] = "gme-cgo",
["Croatian Sign Language"] = "csq",
["Cruzeño"] = "crz",
["Cuban Sign Language"] = "csf",
["Cubeo"] = "cub",
["Cueva"] = "sai-cva",
["Cuiba"] = "cui",
["Cuitlatec"] = "cuy",
["Culina"] = "cul",
["Tiếng Culli"] = "sai-cul",
["Cun"] = "cuq",
["Cung"] = "cug",
["Curonian"] = "xcu",
["Curripaco"] = "kpc",
["Cutchi-Swahili"] = "ccl",
["Cuvok"] = "cuv",
["Cuyamecalco Mixtec"] = "xtu",
["Cwi Bwamu"] = "bwy",
["Czech Sign Language"] = "cse",
["Da'a Kaili"] = "kzf",
["Daai Chin"] = "dao",
["Daantanai'"] = "lni",
["Daba"] = "dbq",
["Dabe"] = "dbe",
["Dadanitic"] = "sem-dad",
["Dadi Dadi"] = "dda",
["Dadiya"] = "dbd",
["Tiếng Daga"] = "dgz",
["Dagaari Dioula"] = "dgd",
["Dagik"] = "dec",
["Dagoman"] = "dgn",
["Daho-Doo"] = "das",
["Dai"] = "dij",
["Dair"] = "drb",
["Dairi Batak"] = "btd",
["Dakaka"] = "bpa",
["Dakka"] = "dkk",
["Daloa Bété"] = "bev",
["Dama (Nigeria)"] = "dmm",
["Dama (Sierra Leone)"] = "dmn-dam",
["Damakawa"] = "dam",
["Damal"] = "uhn",
["Dampelas"] = "dms",
["Danaru"] = "dnr",
["Dandami Maria"] = "daq",
["Dangaura Tharu"] = "thl",
["Danish Sign Language"] = "dsl",
["Dano"] = "aso",
["Dao"] = "daz",
["Daonda"] = "dnd",
["Dar Fur Daju"] = "daj",
["Dar Sila Daju"] = "dau",
["Darai"] = "dry",
["Darkinjung"] = "xda",
["Darlong"] = "dln",
["Darmiya"] = "drd",
["Daro-Matu Melanau"] = "dro",
["Darumbal"] = "xgm",
["Dass"] = "dot",
["Datooga"] = "tcc",
["Daungwurrung"] = "dgw",
["Davawenyo"] = "daw",
["Dawawa"] = "dww",
["Dawera-Daweloor"] = "ddw",
["Day"] = "dai",
["Dayi"] = "dax",
["Dazaga"] = "dzg",
["Deccani"] = "dcc",
["Dedua"] = "ded",
["Defaka"] = "afn",
["Defi Gbe"] = "gbh",
["Deg"] = "mzw",
["Degenan"] = "dge",
["Dehwari"] = "deh",
["Dek"] = "dek",
["Dela-Oenale"] = "row",
["Delo"] = "ntr",
["Delta Yokuts"] = "nai-dly",
["Dem"] = "dem",
["Dema"] = "dmx",
["Demisa"] = "dei",
["Demta"] = "dmy",
["Tiếng Dena'ina"] = "tfn",
["Dendi"] = "ddn",
["Dengese"] = "dez",
["Dengka"] = "dnk",
["Deno"] = "dbb",
["Denya"] = "anv",
["Dení"] = "dny",
["Desano"] = "des",
["Dewas Rai"] = "dwz",
["Dewoin"] = "dee",
["Dezfuli"] = "def",
["Dghwede"] = "dgh",
["Dhaiso"] = "dhs",
["Dhalandji"] = "dhl",
["Dhao"] = "nfa",
["Dhofari Arabic"] = "adf",
["Dhudhuroa"] = "ddr",
["Dhungaloo"] = "dhx",
["Dhurga"] = "dhu",
["Dhuwal"] = "dwu",
["Dhuwaya"] = "dwy",
["Dia"] = "dia",
["Dibiyaso"] = "dby",
["Dibo"] = "dio",
["Dicamay Agta"] = "duy",
["Didinga"] = "did",
["Digo"] = "dig",
["Tiếng Dii"] = "dur",
["Dijim-Bwilim"] = "cfa",
["Dilling"] = "dil",
["Dima"] = "jma",
["Dimbong"] = "dii",
["Dinapigue Agta"] = "phi-din",
["Dineor"] = "mrx",
["Ding"] = "diz",
["Diodio"] = "ddi",
["Diri"] = "dwa",
["Dirim"] = "dir",
["Disa"] = "dsi",
["Diuwe"] = "diy",
["Diuxi-Tilantongo Mixtec"] = "xtd",
["Dixon Reef"] = "dix",
["Djadjawurrung"] = "dja",
["Djambarrpuyngu"] = "djr",
["Djangun"] = "djf",
["Djauan"] = "djn",
["Djawi"] = "djw",
["Djimini"] = "dyi",
["Djinba"] = "djb",
["Djiwarli"] = "djl",
["Dobel"] = "kvo",
["Dobu"] = "dob",
["Doe"] = "doe",
["Doga"] = "dgg",
["Doghoro"] = "dgx",
["Dogoso"] = "dgs",
["Dogosé"] = "dos",
["Dogul Dom"] = "dbg",
["Doka"] = "dbi",
["Doko-Uyanga"] = "uya",
["Dom"] = "doa",
["Dominican Sign Language"] = "doq",
["Dompo"] = "doy",
["Domu"] = "dof",
["Domung"] = "dev",
["Dondo"] = "dok",
["Dong"] = "doh",
["Dongo"] = "doo",
["Dongotono"] = "ddd",
["Dongshanba Lalo"] = "yik",
["Donno So Dogon"] = "dds",
["Doondo"] = "dde",
["Dorasque"] = "cba-dor",
["Dori'o"] = "dor",
["Dorig"] = "wwo",
["Doromu-Koki"] = "kqc",
["Dorze"] = "doz",
["Doso"] = "dol",
["Dothraki"] = "art-dtk",
["Doura"] = "don",
["Doutai"] = "tds",
["Doyayo"] = "dow",
["Drehu"] = "dhv",
["Duala"] = "dua",
["Duano"] = "dup",
["Duau"] = "dva",
["Dubu"] = "dmu",
["Dugun"] = "ndu",
["Duguri"] = "dbm",
["Dugwor"] = "dme",
["Duhwa"] = "kbz",
["Duit"] = "cba-dui",
["Duke"] = "nke",
["Dulbu"] = "dbo",
["Duli"] = "duz",
["Duma"] = "dma",
["Dumaitic"] = "sem-dum",
["Dumbea"] = "duf",
["Dumpas"] = "dmv",
["Dumun"] = "dui",
["Duna"] = "duc",
["Dungmali"] = "raa",
["Dungu"] = "dbv",
["Dura"] = "drq",
["Duri"] = "mvp",
["Duriankere"] = "dbn",
["Dusner"] = "dsn",
["Dusun Deyah"] = "dun",
["Dusun Malang"] = "duq",
["Dutch Sign Language"] = "dse",
["Duupa"] = "dae",
["Duvle"] = "duv",
["Duwai"] = "dbp",
["Duwet"] = "gve",
["Dwang"] = "nnu",
["Dyaabugay"] = "dyy",
["Dyaberdyaber"] = "dyb",
["Dyan"] = "dya",
["Dyangadi"] = "dyn",
["Dyugun"] = "dyd",
["Dza"] = "jen",
["Dzando"] = "dzn",
["Dzao Min"] = "bpn",
["Dzodinka"] = "add",
["Dâw"] = "kwa",
["E'ma Buyang"] = "yzg",
["Early Modern Korean"] = "ko-ear",
["Early Tripuri"] = "xtr",
["East Damar"] = "dmr",
["East Franconian"] = "vmf",
["East Kewa"] = "kjs",
["East Limba"] = "lma",
["East Makian"] = "mky",
["East Masela"] = "vme",
["East Nyala"] = "nle",
["East Tarangan"] = "tre",
["Eastern Bolivian Guaraní"] = "gui",
["Eastern Durango Nahuatl"] = "azd",
["Eastern Gurung"] = "ggn",
["Eastern Highland Chatino"] = "cly",
["Eastern Highland Otomi"] = "otm",
["Eastern Huasteca Nahuatl"] = "nhe",
["Eastern Huishui Hmong"] = "hme",
["Eastern Karaboro"] = "xrb",
["Eastern Keres"] = "kee",
["Eastern Lalu"] = "yit",
["Tiếng Maninkakan Đông"] = "emk",
["Eastern Meohang"] = "emg",
["Eastern Muria"] = "emu",
["Eastern Ngad'a"] = "nea",
["Eastern Nisu"] = "nos",
["Eastern Penan"] = "pez",
["Eastern Pomo"] = "peb",
["Eastern Qiandong Miao"] = "hmq",
["Eastern Subanun"] = "sfe",
["Eastern Tawbuid"] = "bnj",
["Eastern Xiangxi Miao"] = "muq",
["Eastern Xwla Gbe"] = "gbx",
["Ebira"] = "igb",
["Ecuadorian Sign Language"] = "ecs",
["Ede Cabe"] = "cbj",
["Ede Ije"] = "ijj",
["Edera Awyu"] = "awy",
["Edolo"] = "etr",
["Edomite"] = "xdm",
["Edopi"] = "dbf",
["Efutop"] = "ofu",
["Egyptian Sign Language"] = "esl",
["Ejamat"] = "eja",
["Ekajuk"] = "eka",
["Ekari"] = "ekg",
["Ekele"] = "khy",
["Eki"] = "eki",
["Ekit"] = "eke",
["Ekpeye"] = "ekp",
["El Alto Zapotec"] = "zpp",
["El Hugeirat"] = "elh",
["Eleme"] = "elm",
["Elepi"] = "ele",
["Elip"] = "ekm",
["Elkei"] = "elk",
["Eloi"] = "art-elo",
["Elotepec Zapotec"] = "zte",
["Eloyi"] = "afo",
["Elseng"] = "mrf",
["Elu"] = "elu",
["Emae"] = "mmw",
["Emai"] = "ema",
["Eman"] = "emn",
["Embaloh"] = "emb",
["Emberá-Baudó"] = "bdc",
["Emberá-Catío"] = "cto",
["Emem"] = "enr",
["Emerillon"] = "eme",
["Emplawas"] = "emw",
["Enawené-Nawé"] = "unk",
["Ende"] = "end",
["Enga"] = "enq",
["Enggano"] = "eno",
["Enlhet"] = "enl",
["Enrekang"] = "ptt",
["Enu"] = "enu",
["Enwan"] = "env",
["Enwang"] = "enw",
["Enxet"] = "enx",
["Enya"] = "gey",
["Epena"] = "sja",
["Epi-Olmec"] = "xep",
["Epigraphic Mayan"] = "emy",
["Erave"] = "kjy",
["Ere"] = "twp",
["Erie"] = "iro-ere",
["Eritai"] = "ert",
["Erokwanas"] = "erw",
["Erre"] = "err",
["Erromintxela"] = "emx",
["Eruwa"] = "erh",
["Ese Ejja"] = "ese",
["Eshtehardi"] = "esh",
["Eskayan"] = "esy",
["Esmeralda"] = "sai-esm",
["Esselen"] = "esq",
["Estado de México Otomi"] = "ots",
["Estonian Sign Language"] = "eso",
["Esuma"] = "esm",
["Etchemin"] = "etc",
["Etebi"] = "etb",
["Eten"] = "etx",
["Eteocypriot"] = "ecy",
["Ethiopian Sign Language"] = "eth",
["Etkywan"] = "ich",
["Eton (Cameroon)"] = "eto",
["Eton (Vanuatu)"] = "etn",
["Etulo"] = "utr",
["Evant"] = "bzz",
["Ewage-Notu"] = "nou",
["Ewarhuyana"] = "sai-ewa",
["Ewondo"] = "ewo",
["Extremaduran"] = "ext",
["Eyak"] = "eya",
["Ezaa"] = "eza",
["Fagani"] = "faf",
["Faire Atta"] = "azt",
["Faita"] = "faj",
["Faiwol"] = "fai",
["Fakkanci"] = "gel",
["Fali"] = "fli",
["Fam"] = "fam",
["Fanamaket"] = "bjp",
["Fang (Beboid)"] = "fak",
["Fania"] = "fni",
["Fas"] = "fqs",
["Fasu"] = "faa",
["Fataleka"] = "far",
["Tiếng Fataluku"] = "ddg",
["Fayu"] = "fau",
["Fedan"] = "pdn",
["Fembe"] = "agl",
["Fer"] = "kah",
["Feroge"] = "fer",
["Filomena Mata-Coahuitlán Totonac"] = "tlp",
["Finisterre Yau"] = "yuw",
["Finnish Sign Language"] = "fse",
["Finnish-Swedish Sign Language"] = "fss",
["Finongan"] = "fag",
["Fipa"] = "fip",
["Firan"] = "fir",
["Fiwaga"] = "fiw",
["Flemish Sign Language"] = "vgt",
["Flinders Island"] = "fln",
["Foau"] = "flh",
["Foia Foia"] = "ffi",
["Folopa"] = "ppo",
["Foma"] = "fom",
["Fongoro"] = "fgr",
["Foodo"] = "fod",
["Forak"] = "frq",
["Fordata"] = "frd",
["Fore"] = "for",
["Forest Nenets"] = "yrk-for",
["Fortsenal"] = "frt",
["French Belgian Sign Language"] = "sfb",
["French Sign Language"] = "fsl",
["Fuliiru"] = "flr",
["Fulniô"] = "fun",
["Fum"] = "fum",
["Tiếng Fungwa"] = "ula",
["Furu"] = "fuu",
["Futuna-Aniwa"] = "fut",
["Fuyug"] = "fuy",
["Fwe"] = "fwe",
["Fwâi"] = "fwa",
["Fyam"] = "pym",
["Fyer"] = "fie",
["Ga'anda"] = "gqa",
["Ga'dang"] = "gdg",
["Gaa"] = "ttb",
["Gaam"] = "tbi",
["Gabadi"] = "kbt",
["Gabi"] = "gbw",
["Gabrielino-Fernandeño"] = "xgf",
["Gadang"] = "gdk",
["Gade"] = "ged",
["Gadjerawang"] = "gdh",
["Gadsup"] = "gaj",
["Gafat"] = "gft",
["Gagadu"] = "gbu",
["Gagnoa Bété"] = "btg",
["Gaikundi"] = "gbf",
["Gaina"] = "gcn",
["Gal"] = "gap",
["Galambu"] = "glo",
["Galela"] = "gbi",
["Galeya"] = "gar",
["Galice"] = "gce",
["Galindian"] = "xgl",
["Gallaecian"] = "cel-gal",
["Galoli"] = "gal",
["Gambera"] = "gma",
["Gamela"] = "sai-gam",
["Gamkonora"] = "gak",
["Gamo-Ningi"] = "bte",
["Gana"] = "gnq",
["Ganang"] = "gne",
["Gane"] = "gzn",
["Ganggalida"] = "gcd",
["Ganglau"] = "ggl",
["Gangte"] = "gnb",
["Gangulu"] = "gnl",
["Gants"] = "gao",
["Ganzi"] = "gnz",
["Gao"] = "gga",
["Gapapaiwa"] = "pwg",
["Garawa"] = "wrk",
["Garingbal"] = "xgi",
["Garus"] = "gyb",
["Garza"] = "xgr",
["Gashowu"] = "nai-gsy",
["Gavak"] = "dmc",
["Gavar"] = "gou",
["Gavião do Jiparaná"] = "gvo",
["Gayo"] = "gay",
["Gayón"] = "sai-gay",
["Gbagyi"] = "gbr",
["Gban"] = "ggu",
["Gbanu"] = "gbv",
["Gbanziri"] = "gbg",
["Gbari"] = "gby",
["Gbaya"] = "gba",
["Gbaya-Bossangoa"] = "gbp",
["Gbaya-Bozoum"] = "gbq",
["Gbaya-Mbodomo"] = "gmm",
["Gbayi"] = "gyg",
["Gbesi Gbe"] = "gbs",
["Gbii"] = "ggb",
["Gbin"] = "xgb",
["Gboloo Grebo"] = "gec",
["Gciriku"] = "diu",
["Gcwi"] = "gwj",
["Ge"] = "hmj",
["Gebe"] = "gei",
["Gedaged"] = "gdd",
["Geji"] = "gji",
["Gela"] = "nlg",
["Gelao"] = "gio",
["Gele'"] = "sbc",
["Geme"] = "geq",
["Gende"] = "gaf",
["Gengle"] = "geg",
["Gepo"] = "ygp",
["Gera"] = "gew",
["German Sign Language"] = "gsg",
["Geruma"] = "gea",
["Geser-Gorom"] = "ges",
["Gey"] = "guv",
["Ghanaian Sign Language"] = "gse",
["Ghandruk Sign Language"] = "gds",
["Ghanongga"] = "ghn",
["Ghari"] = "gri",
["Ghayavi"] = "bmk",
["Ghera"] = "ghr",
["Ghulfan"] = "ghl",
["Giangan"] = "bgi",
["Gibanawa"] = "gib",
["Gidar"] = "gid",
["Gikyode"] = "acd",
["Gilima"] = "gix",
["Gimi (Austronesian)"] = "gip",
["Gimme"] = "kmp",
["Gimnime"] = "gmn",
["Ginuman"] = "gnm",
["Girawa"] = "bbr",
["Githabul"] = "gih",
["Gitua"] = "ggt",
["Giyug"] = "giy",
["Gizrra"] = "tof",
["Glaro-Twabo"] = "glr",
["Glavda"] = "glw",
["Glio-Oubi"] = "oub",
["Gnau"] = "gnu",
["Goa'uld"] = "art-gld",
["Goaria"] = "gig",
["Gobasi"] = "goi",
["Gobu"] = "gox",
["Godié"] = "god",
["Godwari"] = "gdx",
["Goemai"] = "ank",
["Gogo"] = "gog",
["Gogodala"] = "ggw",
["Gokana"] = "gkn",
["Gokhy"] = "sit-gkh",
["Gola"] = "gol",
["Golin"] = "gvf",
["Golpa"] = "lja",
["Gondi"] = "gon",
["Gongduk"] = "goe",
["Gonja"] = "gjn",
["Goo"] = "gov",
["Gor"] = "gqr",
["Gorakor"] = "goc",
["Gorap"] = "goq",
["Goreng"] = "xgg",
["Gorovu"] = "grq",
["Gottscheerish"] = "gmw-gts",
["Goundo"] = "goy",
["Gowlan"] = "goj",
["Gowro"] = "gwf",
["Gozarkhani"] = "goz",
["Grangali"] = "nli",
["Grass Koiari"] = "kbk",
["Grebo"] = "grb",
["Greek Sign Language"] = "gss",
["Green Gelao"] = "giq",
["Green Hmong"] = "hnj",
["Grenadian Creole English"] = "gcl",
["Gresi"] = "grs",
["Groma"] = "gro",
["Gros Ventre"] = "ats",
["Gua"] = "gwx",
["Guahibo"] = "guh",
["Guambiano"] = "gum",
["Guamo"] = "sai-gmo",
["Guanano"] = "gvc",
["Guatemalan Sign Language"] = "gsm",
["Guató"] = "gta",
["Guayabero"] = "guo",
["Guazacapán"] = "nai-guz",
["Gudang"] = "xgd",
["Gudanji"] = "nji",
["Gude"] = "gde",
["Gudu"] = "gdu",
["Guduf-Gava"] = "gdf",
["Guerrero Nahuatl"] = "ngu",
["Guevea de Humboldt Zapotec"] = "zpg",
["Gugadj"] = "ggd",
["Gugu Badhun"] = "gdc",
["Gugu Warra"] = "wrw",
["Guhu-Samane"] = "ghs",
["Guianese Creole"] = "gcr",
["Guiberoua Bété"] = "bet",
["Guinau"] = "awd-gnu",
["Guinea-Bissau Sign Language"] = "lgs",
["Guinean Sign Language"] = "gus",
["Guiqiong"] = "gqi",
["Gula"] = "glu",
["Gula'alaa"] = "gmb",
["Gule"] = "gly",
["Gullah"] = "gul",
["Gumalu"] = "gmu",
["Gumatj"] = "gnn",
["Gumawana"] = "gvs",
["Gundi"] = "gdi",
["Gunditjmara"] = "gjm",
["Gundungurra"] = "xrd",
["Gungabula"] = "gyf",
["Gungu"] = "rub",
["Guntai"] = "gnt",
["Gunu"] = "yas",
["Gunwinggu"] = "gup",
["Tiếng Gunya"] = "gyy",
["Gupa-Abawa"] = "gpa",
["Gupapuyngu"] = "guf",
["Guragone"] = "gge",
["Guramalum"] = "grz",
["Gureng Gureng"] = "gnr",
["Gurgula"] = "ggg",
["Guriaso"] = "grx",
["Gurindji"] = "gue",
["Gurjar Apabhramsa"] = "inc-gup",
["Gurmana"] = "gvm",
["Guro"] = "goa",
["Guruntum"] = "grd",
["Gusan"] = "gsn",
["Gusii"] = "guz",
["Gusilay"] = "gsl",
["Guwa"] = "xgw",
["Guwamu"] = "gwu",
["Guwar"] = "aus-guw",
["Guya"] = "gka",
["Guyanese Creole English"] = "gyn",
["Guyani"] = "gvy",
["Guébie"] = "gie",
["Gvoko"] = "ngs",
["Gwa"] = "gwb",
["Gwahatike"] = "dah",
["Gwak"] = "jgk",
["Gwamhi-Wuri"] = "bga",
["Gwandara"] = "gwn",
["Gwara"] = "alv-gwa",
["Gweda"] = "grw",
["Gweno"] = "gwe",
["Gwere"] = "gwr",
["Gyalsumdo"] = "gyo",
["Gyele"] = "gyi",
["Gyem"] = "gye",
["Güenoa"] = "sai-gue",
["Habu"] = "hbu",
["Hadothi"] = "hoj",
["Hadrami"] = "xhd",
["Hadza"] = "hts",
["Haeke"] = "aek",
["Hahon"] = "hah",
["Haigwai"] = "hgw",
["Hainyaxo Bozo"] = "bzx",
["Haiphong Sign Language"] = "haf",
["Haitian Vodoun Culture Language"] = "hvc",
["Haiǁom"] = "hgm",
["Haji"] = "hji",
["Hakö"] = "hao",
["Halang Doan"] = "hld",
["Halia"] = "hla",
["Hamap"] = "hmu",
["Hamba"] = "hba",
["Hamtai"] = "hmt",
["Hanga"] = "hag",
["Hanga Hundi"] = "wos",
["Hanoi Sign Language"] = "hab",
["Harami"] = "xha",
["Haraza"] = "nub-har",
["Haruai"] = "tmd",
["Haruku"] = "hrk",
["Harzani"] = "hrz",
["Hasaitic"] = "sem-has",
["Hasha"] = "ybj",
["Tiếng Ả Rập Hassaniya"] = "mey",
["Tiếng Hatam"] = "had",
["Hausa Sign Language"] = "hsl",
["Haveke"] = "hvk",
["Havu"] = "hav",
["Hawai'i Pidgin Sign Language"] = "hps",
["Hawaiian Creole"] = "hwc",
["Haya"] = "hay",
["Hdi"] = "xed",
["Hehe"] = "heh",
["Helong"] = "heg",
["Helu"] = "elu-prk",
["Hema"] = "nix",
["Hemba"] = "hem",
["Herdé"] = "hed",
["Hermit"] = "llf",
["Hewa"] = "ham",
["Heyo"] = "auk",
["Hibito"] = "hib",
["Hidatsa"] = "hid",
["Highland Konjo"] = "kjk",
["Highland Oaxaca Chontal"] = "chd",
["Highland Puebla Nahuatl"] = "azz",
["Hijuk"] = "hij",
["Himarimã"] = "hir",
["Himyaritic"] = "sem-him",
["Hismaic"] = "sem-his",
["Hitchiti"] = "nai-hit",
["Hitu"] = "htu",
["Hixkaryana"] = "hix",
["Hlepho Phowa"] = "yhl",
["Hlersu"] = "hle",
["Hmar"] = "hmr",
["Hmong Dô"] = "hmv",
["Hmong Shua"] = "hmz",
["Hmwaveke"] = "mrk",
["Ho Chi Minh City Sign Language"] = "hos",
["Hobyót"] = "hoh",
["Hoia Hoia"] = "hhi",
["Holikachuk"] = "hoi",
["Holma"] = "hod",
["Holoholo"] = "hoo",
["Holu"] = "hol",
["Homa"] = "hom",
["Honduran Lenca"] = "len",
["Honduras Sign Language"] = "hds",
["Hone"] = "juh",
["Hong Kong Sign Language"] = "hks",
["Honi"] = "how",
["Horned Miao"] = "hrm",
["Horo"] = "hor",
["Horom"] = "hoe",
["Hote"] = "hot",
["Hoti"] = "hti",
["Hovongan"] = "hov",
["Hoyahoya"] = "hhy",
["Hrangkhol"] = "hra",
["Hruso"] = "hru",
["Huachipaeri"] = "hug",
["Huambisa"] = "hub",
["Huaorani"] = "auc",
["Huarijio"] = "var",
["Huaulu"] = "hud",
["Huautla Mazatec"] = "mau",
["Huave"] = "huv",
["Huaxcaleca Nahuatl"] = "nhq",
["Huba"] = "hbb",
["Huehuetla Tepehua"] = "tee",
["Huetar"] = "cba-hue",
["Huichol"] = "hch",
["Huilliche"] = "huh",
["Huitepec Mixtec"] = "mxs",
["Hukumina"] = "huw",
["Hula"] = "hul",
["Tiếng Huli"] = "hui",
["Hulung"] = "huk",
["Humene"] = "huf",
["Hun"] = "uth",
["Hunde"] = "hke",
["Hungana"] = "hum",
["Hungarian Sign Language"] = "hsh",
["Hungworo"] = "nat",
["Hunjara-Kaina Ke"] = "hkk",
["Hunnic"] = "xhc",
["Hupla"] = "hap",
["Hutterisch"] = "geh",
["Hwana"] = "hwo",
["Hya"] = "hya",
["Hän"] = "haa",
["Hértevin"] = "hrt",
["I-Wak"] = "iwk",
["Iamalele"] = "yml",
["Iatmul"] = "ian",
["Iau"] = "tmu",
["Ibali Teke"] = "tek",
["Ibani"] = "iby",
["Iberian"] = "xib",
["Iboko"] = "bkp",
["Ibu"] = "ibu",
["Icelandic Sign Language"] = "icl",
["Iceve-Maci"] = "bec",
["Idakho-Isukha-Tiriki"] = "ida",
["Idaté"] = "idt",
["Idere"] = "ide",
["Idesa"] = "ids",
["Idi"] = "idi",
["Idoma"] = "idu",
["Idon"] = "idc",
["Idun"] = "ldb",
["Iduna"] = "viv",
["Ifo"] = "iff",
["Igana"] = "igg",
["Igede"] = "ige",
["Ignaciano"] = "ign",
["Igo"] = "ahl",
["Iguta"] = "nar",
["Igwe"] = "igw",
["Iha"] = "ihp",
["Ihievbe"] = "ihi",
["Ija-Zuba"] = "vki",
["Ik"] = "ikx",
["Ika"] = "ikk",
["Ikaranggal"] = "ikr",
["Ikizu"] = "ikz",
["Iko"] = "iki",
["Ikobi-Mena"] = "meb",
["Ikoma"] = "ntk",
["Ikpeng"] = "txi",
["Ikpeshi"] = "ikp",
["Iku-Gora-Ankwa"] = "ikv",
["Ikulu"] = "ikl",
["Ikwo"] = "iqw",
["Ila"] = "ilb",
["Ile Ape"] = "ila",
["Ilgar"] = "ilg",
["Ili'uun"] = "ilu",
["Ilianen Manobo"] = "mbi",
["Illyrian"] = "xil",
["Ilongot"] = "ilk",
["Ilue"] = "ilv",
["Ilwana"] = "mlk",
["Imbongu"] = "imo",
["Imonda"] = "imn",
["Imroing"] = "imr",
["Inabaknon"] = "abx",
["Inapang"] = "mzu",
["Indanga"] = "bnt-ind",
["Indian Sign Language"] = "ins",
["Indonesian Bajau"] = "bdl",
["Indonesian Sign Language"] = "inl",
["Indri"] = "idr",
["Indus Valley Language"] = "xiv",
["Inebu One"] = "oin",
["Ineseño"] = "inz",
["Inga"] = "inb",
["Inlaod Itneg"] = "iti",
["Inoke-Yate"] = "ino",
["Inonhan"] = "loc",
["Inpui Naga"] = "nkf",
["International Sign"] = "ils",
["Inuinnaqtun"] = "esx-inq",
["Inuit Sign Language"] = "iks",
["Inuktun"] = "esx-ink",
["Ipai"] = "nai-ipa",
["Ipalapa Amuzgo"] = "azm",
["Ipiko"] = "ipo",
["Ipili"] = "ipi",
["Ipulo"] = "ass",
["Iquito"] = "iqu",
["Ir"] = "irr",
["Irantxe"] = "irn",
["Iranun"] = "ill",
["Irarutu"] = "irh",
["Iraya"] = "iry",
["Iresim"] = "ire",
["Iriga Bicolano"] = "bto",
["Irish Sign Language"] = "isg",
["Isabi"] = "isa",
["Isanzu"] = "isn",
["Isarog Agta"] = "agk",
["Isaurian"] = "und-isa",
["Isconahua"] = "isc",
["Isebe"] = "igo",
["Isinai"] = "inn",
["Isirawa"] = "srl",
["Islander Creole English"] = "icr",
["Israeli Sign Language"] = "isr",
["Isthmus Mixe"] = "mir",
["Isu"] = "isu",
["Isubu"] = "szv",
["Italian Sign Language"] = "ise",
["Itawit"] = "itv",
["Iteri"] = "itr",
["Itik"] = "itx",
["Ito"] = "itw",
["Itundujia Mixtec"] = "mce",
["Itzá"] = "itz",
["Iwal"] = "kbm",
["Iwam"] = "iwm",
["Iwur"] = "iwo",
["Ixcatec"] = "ixc",
["Ixcatlán Mazatec"] = "mzi",
["Ixtayutla Mixtec"] = "vmj",
["Ixtenco Otomi"] = "otz",
["Iyayu"] = "iya",
["Iyive"] = "uiv",
["Iyo"] = "nca",
["Iyo'wujwa Chorote"] = "crq",
["Iyojwa'ja Chorote"] = "crt",
["Izere"] = "izr",
["Izi"] = "izz",
["Izi-Ezaa-Ikwo-Mgbo"] = "izi",
["Izora"] = "cbo",
["Iñapari"] = "inp",
["Jabem"] = "jae",
["Jabutí"] = "jbt",
["Jad"] = "jda",
["Jadgali"] = "jdg",
["Jahanka"] = "jad",
["Jair Awyu"] = "awv",
["Jakati"] = "jat",
["Jalapa de Díaz Mazatec"] = "maj",
["Jalkunan"] = "bxl",
["Jamaican Country Sign Language"] = "jcs",
["Jamaican Sign Language"] = "jls",
["Jambi Malay"] = "jax",
["Jamiltepec Mixtec"] = "mxt",
["Jaminjung"] = "djd",
["Jamsay"] = "djm",
["Jamtish"] = "gmq-jmk",
["Jandavra"] = "jnd",
["Janday"] = "jan",
["Jangkang"] = "djo",
["Jangshung"] = "jna",
["Janji"] = "jni",
["Japanese Sign Language"] = "jsl",
["Japrería"] = "jru",
["Jara"] = "jaf",
["Jaru"] = "ddj",
["Jassic"] = "ysc",
["Jawe"] = "jaz",
["Jaya"] = "jyy",
["Jebero"] = "jeb",
["Jeikó"] = "sai-jko",
["Jenaama Bozo"] = "bze",
["Jeng"] = "jeg",
["Jere"] = "jer",
["Jeri Kuo"] = "jek",
["Jerung"] = "jee",
["Jhankot Sign Language"] = "jhs",
["Jiamao"] = "jio",
["Jiba"] = "juo",
["Jibu"] = "jib",
["Jilbe"] = "jie",
["Jili"] = "mgi",
["Jilim"] = "jil",
["Jimi"] = "jmi",
["Jimjimen"] = "jim",
["Jina"] = "jia",
["Jingulu"] = "jig",
["Jiongnai Bunu"] = "pnu",
["Jirajara"] = "sai-jrj",
["Jiru"] = "jrr",
["Jita"] = "jit",
["Joba"] = "job",
["Jofotek-Bromnya"] = "jbr",
["Jola-Fonyi"] = "dyo",
["Jola-Kasa"] = "csk",
["Jonkor Bourmataguil"] = "jeu",
["Jordanian Sign Language"] = "jos",
["Jorá"] = "jor",
["Jowulu"] = "jow",
["Ju"] = "juu",
["Jumla Sign Language"] = "jus",
["Jumli"] = "jml",
["Jungle Inga"] = "inj",
["Juquila Mixe"] = "mxq",
["Jur Modo"] = "bex",
["Jurúna"] = "jur",
["Jutiapa"] = "nai-jtp",
["Juwal"] = "mwb",
["Juxtlahuaca Mixtec"] = "vmc",
["Jwira-Pepesa"] = "jwi",
["Júma"] = "jua",
["Kaamba"] = "xku",
["Kaan"] = "ldl",
["Kaang Chin"] = "ckn",
["Kaansa"] = "gna",
["Kaapor Sign Language"] = "uks",
["Kaba"] = "ksp",
["Kabalai"] = "kvf",
["Kabatei"] = "xkp",
["Kabba-Laka"] = "lap",
["Kabishiana"] = "tup-kab",
["Kabola"] = "klz",
["Kabore One"] = "onk",
["Kabras"] = "lkb",
["Kaburi"] = "uka",
["Kabutra"] = "kbu",
["Kabwa"] = "cwa",
["Kabwari"] = "kcw",
["Kachari"] = "xac",
["Kacipo-Balesi"] = "koe",
["Kaco'"] = "xkk",
["Kadai"] = "kzd",
["Kadara"] = "kad",
["Kadaru"] = "kdu",
["Kadiwéu"] = "kbc",
["Kado"] = "kdv",
["Kadugli"] = "xtc",
["Kaduo"] = "ktp",
["Kaera"] = "jka",
["Kafoa"] = "kpu",
["Kagan Kalagan"] = "kll",
["Kagate"] = "syw",
["Kagoma"] = "kdm",
["Kagoro"] = "xkg",
["Kagulu"] = "kki",
["Kahe"] = "hka",
["Kahua"] = "agw",
["Kaian"] = "kct",
["Kaibobo"] = "kzb",
["Kaidipang"] = "kzp",
["Kaiep"] = "kbw",
["Kaike"] = "kzq",
["Kaiku"] = "kkq",
["Kaimbulawa"] = "zka",
["Kaimbé"] = "xai",
["Kairak"] = "ckr",
["Kairiru"] = "kxa",
["Kairui-Midiki"] = "krd",
["Kais"] = "kzm",
["Kaivi"] = "kce",
["Kaiwá"] = "kgk",
["Kaiy"] = "tcq",
["Kajakse"] = "ckq",
["Kajali"] = "xkj",
["Kajaman"] = "kag",
["Kakabe"] = "kke",
["Kakanda"] = "kka",
["Kakihum"] = "kxe",
["Kako"] = "kkj",
["Kakwa"] = "keo",
["Kala"] = "kcl",
["Kala Lagaw Ya"] = "mwp",
["Kalaamaya"] = "lkm",
["Kalabakan"] = "kve",
["Kalabari"] = "ijn",
["Kalabra"] = "kzz",
["Kalagan"] = "kqe",
["Kalaktang Monpa"] = "kkf",
["Kalam"] = "kmh",
["Kalamsé"] = "knz",
["Kalanadi"] = "wkl",
["Kalanga"] = "kck",
["Kalapuya"] = "kyl",
["Kalarko"] = "kba",
["Kalasuri"] = "xme-kls",
["Kalenjin"] = "kln",
["Kalinago"] = "crb",
["Kalkatungu"] = "ktg",
["Kalou"] = "ywa",
["Kaluli"] = "bco",
["Kalumpang"] = "kli",
["Kam"] = "kdx",
["Kamakan"] = "vkm",
["Kamang"] = "woi",
["Kamano"] = "kbq",
["Kamantan"] = "kci",
["Kamar"] = "keq",
["Kamara"] = "jmr",
["Kamarian"] = "kzx",
["Kamaru"] = "kgx",
["Kamasa"] = "klp",
["Kamasau"] = "kms",
["Kamayurá"] = "kay",
["Kamba"] = "kam",
["Kambaira"] = "kyy",
["Kamberataro"] = "kbv",
["Kamberau"] = "irx",
["Kambiwá"] = "xbw",
["Kami"] = "kmi",
["Kamkata-viri"] = "bsh",
["Kamo"] = "kcq",
["Kamoro"] = "kgq",
["Kamu"] = "xmu",
["Kamwe"] = "hig",
["Kanakuru"] = "kna",
["Kanamari"] = "knm",
["Kanashi"] = "xns",
["Kanasi"] = "soq",
["Kandas"] = "kqw",
["Kandawo"] = "gam",
["Kande"] = "kbs",
["Kang"] = "kyp",
["Kanga"] = "kcp",
["Kanggape"] = "igm",
["Kango"] = "kty",
["Kango-Sua"] = "kzy",
["Kaniet"] = "ktk",
["Kanikkaran"] = "kev",
["Kaningdon-Nindem"] = "kdp",
["Kaningi"] = "kzo",
["Kaningra"] = "knr",
["Kaninuwa"] = "wat",
["Kanite"] = "kmu",
["Kanjari"] = "kft",
["Kanju"] = "kbe",
["Kanowit"] = "kxn",
["Kanoé"] = "kxo",
["Kansa"] = "ksk",
["Kantosi"] = "xkt",
["Kanu"] = "khx",
["Kanufi"] = "kni",
["Kanyok"] = "kny",
["Kao"] = "kax",
["Kaonde"] = "kqn",
["Kap"] = "ykm",
["Kapauri"] = "khp",
["Kapin"] = "tbx",
["Kapinawá"] = "xpn",
["Kapriman"] = "dju",
["Kaptiau"] = "kbi",
["Kapya"] = "klo",
["Kara (New Guinea)"] = "leu",
["Kara (Tanzania)"] = "reg",
["Karadjeri"] = "gbd",
["Karaga Mandaya"] = "mry",
["Karami"] = "xar",
["Karamojong"] = "kdj",
["Karang"] = "kzr",
["Karanga"] = "kth",
["Karankawa"] = "zkk",
["Karas"] = "kgv",
["Karawa"] = "xrw",
["Kare (Africa)"] = "kbn",
["Kare (New Guinea)"] = "kmf",
["Karey"] = "kyd",
["Kari"] = "kbj",
["Karingani"] = "kgn",
["Karipuna"] = "kuq",
["Karipúna"] = "kgm",
["Karipúna Creole French"] = "kmv",
["Kariya"] = "kil",
["Kariyarra"] = "vka",
["Karkar-Yuri"] = "yuj",
["Karkin"] = "krb",
["Karko"] = "kko",
["Karnai"] = "bbv",
["Karo Batak"] = "btx",
["Karok"] = "kyh",
["Karolanos"] = "kyn",
["Karon"] = "krx",
["Karon Dori"] = "kgw",
["Karore"] = "xkx",
["Karranga"] = "xrq",
["Karuwali"] = "rxw",
["Kasanga"] = "ccj",
["Kasem"] = "xsm",
["Kasiguranin"] = "ksn",
["Kaska"] = "kkz",
["Kaskean"] = "zsk",
["Kaskihá"] = "gva",
["Kassite"] = "und-kas",
["Kassonke"] = "kao",
["Kasua"] = "khs",
["Kataang"] = "kgd",
["Katabaga"] = "ktq",
["Katawixi"] = "xat",
["Katembri"] = "sai-kat",
["Kathlamet"] = "nai-kat",
["Kathoriya Tharu"] = "tkt",
["Kathu"] = "ykt",
["Katkari"] = "kfu",
["Katla"] = "kcr",
["Kato"] = "ktw",
["Katso"] = "kaf",
["Katukina"] = "knt",
["Kaulong"] = "pss",
["Kaur"] = "vkk",
["Kaure"] = "bpp",
["Kauwera"] = "xau",
["Kawacha"] = "kcb",
["Kawaiisu"] = "xaw",
["Kawe"] = "kgb",
["Kawishana"] = "awd-kaw",
["Kaxararí"] = "ktx",
["Kaxuyana"] = "kbb",
["Kaya"] = "zra",
["Kayabí"] = "kyz",
["Kayagar"] = "kyt",
["Kayan Mahakam"] = "xay",
["Kayan River Kayan"] = "xkn",
["Kayardild"] = "gyd",
["Kayeli"] = "kzl",
["Kaytetye"] = "gbb",
["Kayupulau"] = "kzu",
["Kazukuru"] = "kzk",
["Ke'o"] = "xxk",
["Keak"] = "keh",
["Keapara"] = "khz",
["Kedang"] = "ksx",
["Keder"] = "kdy",
["Kehu"] = "khh",
["Kei"] = "kei",
["Keiga"] = "kec",
["Kein"] = "bmh",
["Keiyo"] = "eyo",
["Kela-Yela"] = "kel",
["Kelabit"] = "kzi",
["Keley-I Kallahan"] = "ify",
["Tiếng Keliko"] = "kbo",
["Kelo"] = "xel",
["Kelon"] = "kyo",
["Kemak"] = "kem",
["Kembayan"] = "xem",
["Kemberano"] = "bzp",
["Kembra"] = "xkw",
["Kemezung"] = "dmo",
["Kemi Sami"] = "sjk",
["Kemiehua"] = "kfj",
["Kemtuik"] = "kmt",
["Kenaboi"] = "xbn",
["Kenati"] = "gat",
["Kendayan"] = "knx",
["Kendeje"] = "klf",
["Kendem"] = "kvm",
["Kenga"] = "kyq",
["Keningau Murut"] = "kxi",
["Keninjal"] = "knl",
["Kenswei Nsei"] = "ndb",
["Kenyan Sign Language"] = "xki",
["Kenyi"] = "lke",
["Keoru-Ahia"] = "xeu",
["Kepkiriwát"] = "kpn",
["Kepo'"] = "kuk",
["Kera"] = "ker",
["Kerak"] = "hhr",
["Kereho"] = "xke",
["Kerewe"] = "ked",
["Kerewo"] = "kxz",
["Kerinci"] = "kvr",
["Kesawai"] = "xes",
["Ketangalan"] = "kae",
["Kete"] = "kcv",
["Ketengban"] = "xte",
["Ketum"] = "ktt",
["Kewa"] = "kew",
["Keyagana"] = "kyg",
["Kgalagadi"] = "xkv",
["Khana"] = "ogo",
["Khandeshi"] = "khn",
["Khao"] = "xao",
["Kharam Naga"] = "kfw",
["Kharia Thar"] = "ksy",
["Khayo"] = "lko",
["Khe"] = "kqg",
["Khehek"] = "tlx",
["Khetrani"] = "xhe",
["Khezha Naga"] = "nkh",
["Khirwar"] = "kwx",
["Khisa"] = "kqm",
["Khlor"] = "llo",
["Khlula"] = "ykl",
["Khoibu Naga"] = "nkb",
["Khoini"] = "xkc",
["Kholok"] = "ktc",
["Khumi Chin"] = "cnk",
["Khwe"] = "xuu",
["Kibala"] = "blv",
["Kibena"] = "bez",
["Kibet"] = "kie",
["Kibiri"] = "prm",
["Kichwa"] = "qwe-kch",
["Kikami"] = "kcu",
["Kilit"] = "xme-klt",
["Kilivila"] = "kij",
["Kiliwa"] = "klb",
["Kilmeri"] = "kih",
["Kimaama"] = "kig",
["Kimaragang"] = "kqr",
["Kimbu"] = "kiv",
["Kimki"] = "sbt",
["Kimré"] = "kqp",
["Kinabalian"] = "cbw",
["Kinalakna"] = "kco",
["Kinga"] = "zga",
["Kings River Yokuts"] = "nai-kry",
["Kinikinao"] = "gqn",
["Kinuku"] = "kkd",
["Kioko"] = "ues",
["Kiong"] = "kkm",
["Kiorr"] = "xko",
["Kipfokomo"] = "pkb",
["Kipsigis"] = "sgc",
["Kiput"] = "kyi",
["Kir-Balar"] = "kkr",
["Kire"] = "geb",
["Kirfi"] = "kks",
["Kirikiri"] = "kiy",
["Kirya-Konzel"] = "fkk",
["Kis"] = "kis",
["Kisa"] = "lks",
["Kisankasa"] = "kqh",
["Kisar"] = "kje",
["Kisi"] = "kiz",
["Kita Maninkakan"] = "mwk",
["Kitanemuk"] = "azc-ktn",
["Kitembo"] = "tbt",
["Kitja"] = "gia",
["Kitsai"] = "kii",
["Kiunum"] = "wei",
["Kla"] = "lda",
["Klamath-Modoc"] = "kla",
["Klao"] = "klu",
["Klias River Kadazan"] = "kqt",
["Ko"] = "fuj",
["Koasati"] = "cku",
["Koba"] = "kpd",
["Kobiana"] = "kcj",
["Kobol"] = "kgu",
["Kochila Tharu"] = "thq",
["Kodaku"] = "ksz",
["Kodeoha"] = "vko",
["Kodi"] = "kod",
["Kodia"] = "kwp",
["Koenoem"] = "kcs",
["Kofa"] = "kso",
["Kofei"] = "kpi",
["Kofyar"] = "kwl",
["Kohin"] = "kkx",
["Kohumono"] = "bcs",
["Koi"] = "kkt",
["Koireng"] = "nkd",
["Koitabu"] = "kqi",
["Koiwat"] = "kxt",
["Kok-Nar"] = "gko",
["Kok-Paponk"] = "okg",
["Kokata"] = "ktd",
["Koke"] = "kou",
["Koko-Bera"] = "kkp",
["Kokoda"] = "xod",
["Kokola"] = "kzn",
["Kokota"] = "kkk",
["Kol (Cameroon)"] = "biw",
["Kol (New Guinea)"] = "kol",
["Kola"] = "kvv",
["Kolbila"] = "klc",
["Kolibugan Subanon"] = "skn",
["Kolom"] = "klm",
["Koluwawa"] = "klx",
["Kom (India)"] = "kmm",
["Koma"] = "kmy",
["Komba"] = "kpf",
["Kombai"] = "tyn",
["Kombio"] = "xbi",
["Komering"] = "kge",
["Kominimung"] = "xoi",
["Kompane"] = "kvp",
["Komyandaret"] = "kzv",
["Kon Keu"] = "kkn",
["Konai"] = "kxw",
["Konda"] = "knd",
["Koneraw"] = "kdw",
["Konkomba"] = "xon",
["Konni"] = "kma",
["Kono (Guinea)"] = "knu",
["Kono (Nigeria)"] = "klk",
["Kono (Sierra Leone)"] = "kno",
["Konomala"] = "koa",
["Konomihu"] = "nai-knm",
["Konongo"] = "kcz",
["Konyak Naga"] = "nbe",
["Konyanka Maninka"] = "mku",
["Konzo"] = "koo",
["Kopar"] = "xop",
["Kopkaka"] = "opk",
["Korafe-Yegha"] = "kpr",
["Korak"] = "koz",
["Korana"] = "kqz",
["Korandje"] = "kcy",
["Korean Sign Language"] = "kvk",
["Koreguaje"] = "coe",
["Koresh-e Rostam"] = "okh",
["Korlai Creole Portuguese"] = "vkp",
["Koro (India)"] = "jkr",
["Koro (New Guinea)"] = "kxr",
["Koro (Vanuatu)"] = "krf",
["Koro (West Africa)"] = "kfo",
["Koromfé"] = "kfz",
["Koromira"] = "kqj",
["Koronadal Blaan"] = "bpr",
["Koroni"] = "xkq",
["Korop"] = "krp",
["Koropó"] = "xxr",
["Koroshi"] = "ktl",
["Korowai"] = "khe",
["Korubo"] = "xor",
["Korupun-Sela"] = "kpq",
["Kosadle"] = "kiq",
["Kosarek Yale"] = "kkl",
["Kosena"] = "kze",
["Koshin"] = "kid",
["Kota (Gabon)"] = "koq",
["Kota Bangun Kutai Malay"] = "mqg",
["Kota Marudu Talantang"] = "grm",
["Kota Marudu Tinagas"] = "ktr",
["Kotafon Gbe"] = "kqk",
["Koti"] = "eko",
["Kou"] = "snz",
["Kouya"] = "kyf",
["Kovai"] = "kqb",
["Kove"] = "kvc",
["Kowaki"] = "xow",
["Kowiai"] = "kwh",
["Koy Sanjaq Surat"] = "kqd",
["Koyaga"] = "kga",
["Koyo"] = "koh",
["Koyra Chiini"] = "khq",
["Koyukon"] = "koy",
["Kpagua"] = "kuw",
["Kpala"] = "kpl",
["Kpan"] = "kpk",
["Kpasam"] = "pbn",
["Kpati"] = "koc",
["Kpatili"] = "kym",
["Kpee"] = "cpo",
["Kpelle"] = "kpe",
["Kpessi"] = "kef",
["Kplang"] = "kph",
["Krache"] = "kye",
["Krahô"] = "xra",
["Krenak"] = "kqq",
["Krevinian"] = "zkv",
["Kreye"] = "xre",
["Krikati-Timbira"] = "xri",
["Krim"] = "krm",
["Krisa"] = "ksi",
["Kristang"] = "mcm",
["Krobu"] = "kxb",
["Krongo"] = "kgo",
["Kua"] = "tyu",
["Kua-nsi"] = "ykn",
["Kuamasi"] = "yku",
["Kuan"] = "uan",
["Kuanhua"] = "xnh",
["Kube"] = "kgf",
["Kubi"] = "kof",
["Kubo"] = "jko",
["Kubu"] = "kvb",
["Kucong"] = "lkc",
["Kudu-Camo"] = "kov",
["Kugama"] = "kow",
["Kugbo"] = "kes",
["Kugu-Muminh"] = "xmh",
["Kui (Indonesia)"] = "kvd",
["Kuijau"] = "dkr",
["Kuikúro"] = "kui",
["Kujarge"] = "vkj",
["Kuk"] = "kfn",
["Kukatja"] = "kux",
["Kukele"] = "kez",
["Kukkuzi"] = "urj-kuk",
["Kuku-Mangk"] = "xmq",
["Kuku-Mu'inh"] = "xmp",
["Kuku-Thaypan"] = "typ",
["Kuku-Ugbanh"] = "ugb",
["Kuku-Uwanh"] = "uwa",
["Kuku-Yalanji"] = "gvn",
["Kula"] = "tpg",
["Kulaal"] = "glj",
["Kulere"] = "kul",
["Kulfa"] = "kxj",
["Kulina"] = "xpk",
["Kulisusu"] = "vkl",
["Kulon"] = "uon",
["Kulung"] = "kle",
["Kumak"] = "nee",
["Kumalu"] = "ksl",
["Kumam"] = "kdi",
["Kuman"] = "kue",
["Kumaoni"] = "kfy",
["Kumba"] = "ksm",
["Kumbainggar"] = "kgs",
["Kumbaran"] = "wkb",
["Kumhali"] = "kra",
["Kumu"] = "kmw",
["Kumukio"] = "kuo",
["Kunama"] = "kun",
["Kunbarlang"] = "wlg",
["Kunda"] = "kdn",
["Kunduvadi"] = "wku",
["Kung"] = "kfl",
["Kungarakany"] = "ggk",
["Kungardutyi"] = "gdt",
["Kunggari"] = "kgl",
["Kungkari"] = "lku",
["Kuni"] = "kse",
["Kuni-Boazi"] = "kvg",
["Kunimaipa"] = "kup",
["Kunja"] = "pep",
["Kunjen"] = "kjn",
["Kunyi"] = "njx",
["Kunza"] = "kuz",
["Kuot"] = "kto",
["Kupa"] = "kug",
["Kupang Malay"] = "mkn",
["Kupsabiny"] = "kpz",
["Kur"] = "kuv",
["Kura Ede Nago"] = "nqk",
["Kurama"] = "krh",
["Kuranko"] = "knk",
["Tiếng Kuri"] = "nbn",
["Kuria"] = "kuj",
["Kurmukar"] = "kfv",
["Kurnai"] = "unn",
["Kurrama"] = "vku",
["Kurti"] = "ktm",
["Kurtjar"] = "gdj",
["Kurudu"] = "kjr",
["Kuruáya"] = "kyr",
["Tiếng Kusaal"] = "kus",
["Kusaghe"] = "ksg",
["Kustenau"] = "awd-kus",
["Kusu"] = "ksv",
["Kusunda"] = "kgg",
["Kuthant"] = "xut",
["Kutto"] = "kpa",
["Kutu"] = "kdc",
["Kuturmi"] = "khj",
["Kuuk Thaayorre"] = "thd",
["Kuuk Yak"] = "uky",
["Kuuku-Ya'u"] = "kuy",
["Kuvale"] = "olu",
["Kuwaa"] = "blh",
["Kuwaataay"] = "cwt",
["Kuwani"] = "paa-kwn",
["Kwa'"] = "bko",
["Kwaami"] = "ksq",
["Kwadi"] = "kwz",
["Kwaio"] = "kwd",
["Kwaja"] = "kdz",
["Kwak"] = "kwq",
["Kwakum"] = "kwu",
["Kwalhioqua-Tlatskanai"] = "qwt",
["Kwama"] = "kmq",
["Kwambi"] = "kwm",
["Kwamera"] = "tnk",
["Kwami"] = "ktf",
["Kwamtim One"] = "okk",
["Kwang"] = "kvi",
["Kwanga"] = "kwj",
["Kwangali"] = "kwn",
["Kwanka"] = "bij",
["Kwara'ae"] = "kwf",
["Kwasio"] = "nmg",
["Kwaya"] = "kya",
["Kwaza"] = "xwa",
["Kwegu"] = "xwg",
["Kwer"] = "kwr",
["Kwerba"] = "kwe",
["Kwerba Mamberamo"] = "xwr",
["Kwere"] = "cwe",
["Kwerisa"] = "kkb",
["Kwese"] = "kws",
["Kwesten"] = "kwt",
["Kwini"] = "gww",
["Kwinsu"] = "kuc",
["Kwoma"] = "kmo",
["Kwomtari"] = "kwo",
["Kyak"] = "bka",
["Kyaka"] = "kyc",
["Kyan-Karyaw Naga"] = "nqq",
["Kyenele"] = "kql",
["Kyenga"] = "tye",
["Kyerung"] = "kgy",
["Kélé"] = "keb",
["Kómnzo"] = "paa-kom",
["La'bi"] = "lbi",
["Laal"] = "gdm",
["Laba"] = "lau",
["Label"] = "lbb",
["Labir"] = "jku",
["Labo"] = "mwi",
["Labo Phowa"] = "ypb",
["Labu"] = "lbu",
["Labuk-Kinabatangan Kadazan"] = "dtb",
["Lacandon"] = "lac",
["Lachi"] = "lbt",
["Lachiguiri Zapotec"] = "zpa",
["Lachixío Zapotec"] = "zpl",
["Ladji-Ladji"] = "llj",
["Laeko-Libuat"] = "lkl",
["Lafofa"] = "laf",
["Laghu"] = "lgb",
["Laghuu"] = "lgh",
["Lagwan"] = "kot",
["Laha (Indonesia)"] = "lhh",
["Tiếng La Ha"] = "lha",
["Lahanan"] = "lhn",
["Lahu Shi"] = "lhi",
["Lahul Lohar"] = "lhl",
["Laimbue"] = "lmx",
["Laitu Chin"] = "clj",
["Laiyolo"] = "lji",
["Laka"] = "lak",
["Lake Miwok"] = "lmw",
["Lakha"] = "lkh",
["Lakkia"] = "lbc",
["Lakon"] = "lkn",
["Lakondê"] = "lkd",
["Lakota Dida"] = "dic",
["Lala (New Guinea)"] = "nrz",
["Lala (South Africa)"] = "bnt-lal",
["Lala-Bisa"] = "leb",
["Lala-Roba"] = "lla",
["Lalana Chinantec"] = "cnl",
["Lamaholot"] = "slp",
["Lamalera"] = "lmr",
["Lamang"] = "hia",
["Lamatuka"] = "lmq",
["Lamba"] = "lam",
["Lambichhong"] = "lmh",
["Lambya"] = "lai",
["Lame"] = "bma",
["Lamenu"] = "lmu",
["Lamet"] = "lbn",
["Lamja-Dengsa-Tola"] = "ldh",
["Lamma"] = "lev",
["Lamnso'"] = "lns",
["Lamogai"] = "lmg",
["Lampung Api"] = "ljp",
["Lamu"] = "llh",
["Lamu-Lamu"] = "lby",
["Lanas Lobu"] = "ruu",
["Landoma"] = "ldm",
["Lang'e"] = "yne",
["Langam"] = "lnm",
["Langbashe"] = "lna",
["Langi"] = "lag",
["Langnian Buyang"] = "yln",
["Lango (Sudan)"] = "lno",
["Lango (Uganda)"] = "laj",
["Lanima"] = "lnw",
["Lao Naga"] = "nlq",
["Laopang"] = "lbg",
["Laos Sign Language"] = "lso",
["Lapaguía-Guivini Zapotec"] = "ztl",
["Lapine"] = "art-lap",
["Lapuyan Subanun"] = "laa",
["Laragia"] = "lrg",
["Larantuka Malay"] = "lrt",
["Lardil"] = "lbz",
["Larevat"] = "lrv",
["Larike-Wakasihu"] = "alo",
["Laro"] = "lro",
["Larteh"] = "lar",
["Laru"] = "lan",
["Lasgerdi"] = "lsa",
["Lasi"] = "lss",
["Latu"] = "ltu",
["Latvian Sign Language"] = "lsl",
["Lau"] = "llu",
["Laua"] = "luf",
["Lauan"] = "llx",
["Lauje"] = "law",
["Laura"] = "lur",
["Laurentian"] = "lre",
["Lavatbura-Lamusong"] = "lbv",
["Lawangan"] = "lbx",
["Lawu"] = "lwu",
["Lawunuia"] = "tgi",
["Laze"] = "tbq-laz",
["Lealao Chinantec"] = "cle",
["Leco"] = "lec",
["Ledo Kaili"] = "lew",
["Leelau"] = "ldk",
["Lefa"] = "lfa",
["Lega-Mwenga"] = "lgm",
["Lega-Shabunda"] = "lea",
["Legbo"] = "agb",
["Legenyem"] = "lcc",
["Lehali"] = "tql",
["Lehalurup"] = "urr",
["Leinong Naga"] = "lzn",
["Leipon"] = "lek",
["Lela"] = "dri",
["Lelak"] = "llk",
["Lele (Chad)"] = "lln",
["Lele (Congo)"] = "lel",
["Lele (Guinea)"] = "llc",
["Lele (New Guinea)"] = "lle",
["Lelepa"] = "lpa",
["Lembena"] = "leq",
["Lemerig"] = "lrz",
["Lemio"] = "lei",
["Lemolang"] = "ley",
["Lemoro"] = "ldj",
["Lenakel"] = "tnl",
["Lendu"] = "led",
["Lengilu"] = "lgi",
["Lengo"] = "lgr",
["Lengola"] = "lej",
["Lenje"] = "leh",
["Lenkau"] = "ler",
["Lenyima"] = "ldg",
["Lepki"] = "lpe",
["Lere"] = "gnh",
["Lese"] = "les",
["Lesing-Gelimi"] = "let",
["Letemboi"] = "nms",
["Leti (Cameroon)"] = "leo",
["Leti (Indonesia)"] = "lti",
["Levuka"] = "lvu",
["Lewo Eleng"] = "lwe",
["Lewotobi"] = "lwt",
["Leyigha"] = "ayi",
["Lhokpu"] = "lhp",
["Li'o"] = "ljl",
["Liana-Seti"] = "ste",
["Liangmai Naga"] = "njn",
["Liberian Kreyol"] = "lir",
["Libinza"] = "liz",
["Libon Bikol"] = "lbl",
["Liburnian"] = "xli",
["Libyan Sign Language"] = "lbs",
["Ligbi"] = "lig",
["Ligenza"] = "lgz",
["Lihir"] = "lih",
["Lika"] = "lik",
["Liki"] = "lio",
["Likila"] = "lie",
["Likuba"] = "kxx",
["Likum"] = "lib",
["Likwala"] = "kwc",
["Lilau"] = "lll",
["Limassa"] = "bme",
["Limbu"] = "lif",
["Limi"] = "ylm",
["Limilngan"] = "lmc",
["Linear A"] = "lab",
["Lingkhim"] = "lii",
["Lingua Franca Nova"] = "lfn",
["Linngithigh"] = "lnj",
["Lipo"] = "lpo",
["Lisabata-Nuniali"] = "lcs",
["Lisela"] = "lcl",
["Lish"] = "lsh",
["Lishán Didán"] = "trg",
["Lithuanian Sign Language"] = "lls",
["Little Swanport"] = "aus-lsw",
["Litzlitz"] = "lzl",
["Lizu"] = "sit-liz",
["Lo-Toga"] = "lht",
["Loarki"] = "lrk",
["Lobala"] = "loq",
["Logo"] = "log",
["Logol"] = "lof",
["Logooli"] = "rag",
["Logorik"] = "liu",
["Lokaa"] = "yaz",
["Loko"] = "lok",
["Lokoya"] = "lky",
["Lola"] = "lcd",
["Lolak"] = "llq",
["Lole"] = "llg",
["Lolo"] = "llb",
["Loloda"] = "loa",
["Lolopo"] = "ycl",
["Lomaiviti"] = "lmv",
["Lomakka"] = "loi",
["Lombi"] = "lmi",
["Lombo"] = "loo",
["Lomwe"] = "ngl",
["Loncong"] = "lce",
["Long Phuri Naga"] = "lpn",
["Long Wat"] = "ttw",
["Longgu"] = "lgu",
["Longto"] = "wok",
["Longuda"] = "lnu",
["Loniu"] = "los",
["Lonwolwol"] = "crc",
["Loo"] = "ldo",
["Lopa"] = "lop",
["Lope"] = "yiu",
["Lopi"] = "lov",
["Lopit"] = "lpx",
["Lorang"] = "lrn",
["Lorediakarkar"] = "lnn",
["Lote"] = "uvl",
["Lotud"] = "dtr",
["Lotuko"] = "lot",
["Loun"] = "lox",
["Loup A"] = "xlo",
["Loup B"] = "xlb",
["Lovono"] = "vnk",
["Lower Burdekin"] = "xbb",
["Lower Chehalis"] = "cea",
["Lower Grand Valley Dani"] = "dni",
["Lower Nossob"] = "nsb",
["Lower Southern Aranda"] = "axl",
["Lower Ta'oih"] = "tto",
["Lowland Oaxaca Chontal"] = "clo",
["Lowland Tarahumara"] = "tac",
["Loxicha Zapotec"] = "ztp",
["Lozi"] = "loz",
["Luang"] = "lex",
["Tiếng Luba-Kasai"] = "lua",
["Lubila"] = "kcc",
["Lubu"] = "lcf",
["Tiếng Kalinga Lubuagan"] = "knb",
["Luchazi"] = "lch",
["Lufu"] = "ldq",
["Lugbara"] = "lgg",
["Luguru"] = "ruf",
["Luhu"] = "lcq",
["Luimbi"] = "lum",
["Luiseño"] = "lui",
["Lule"] = "ule",
["Lule Sami"] = "smj",
["Lumba-Yakkha"] = "luu",
["Lumbee"] = "lmz",
["Lumun"] = "lmd",
["Lun Bawang"] = "lnd",
["Luna"] = "luj",
["Lunda"] = "lun",
["Lungga"] = "lga",
["Luo"] = "luo",
["Luopohe Hmong"] = "hml",
["Luri (Nigeria)"] = "ldd",
["Lusengo"] = "lse",
["Lusi"] = "khl",
["Lusitanian"] = "xls",
["Lutachoni"] = "lts",
["Lutos"] = "ndy",
["Luvale"] = "lue",
["Luwati"] = "luv",
["Luwo"] = "lwo",
["Luyana"] = "lyn",
["Lwalu"] = "lwa",
["Lwel"] = "lvl",
["Lyélé"] = "lee",
["Tiếng Láadan"] = "ldn",
["Láá Láá Bwamu"] = "bwj",
["Ma"] = "msj",
["Tiếng Ma Manda"] = "skc",
["Ma'di"] = "mhi",
["Ma'ya"] = "slz",
["Maba"] = "mqa",
["Mabaale"] = "mmz",
["Mabaka Valley Kalinga"] = "kkg",
["Mabire"] = "muj",
["Maca"] = "mca",
["Macaguaje"] = "mcl",
["Macaguán"] = "mbn",
["Macanese"] = "mzs",
["Macau Pidgin Portuguese"] = "crp-mpp",
["Machame"] = "jmc",
["Machiguenga"] = "mcb",
["Machinere"] = "mpd",
["Machinga"] = "mvw",
["Macoris"] = "nai-mac",
["Macuna"] = "myy",
["Mada (Cameroon)"] = "mxu",
["Mada (Nigeria)"] = "mda",
["Madagascar Sign Language"] = "mzc",
["Madak"] = "mmx",
["Maden"] = "xmx",
["Madhi Madhi"] = "dmd",
["Madi"] = "grg",
["Madngele"] = "zml",
["Madukayang Kalinga"] = "kmd",
["Mae"] = "mme",
["Maek"] = "hmk",
["Maeng Itneg"] = "itt",
["Mafa"] = "maf",
["Mafea"] = "mkv",
["Mag-Anchi Ayta"] = "sgb",
["Mag-Indi Ayta"] = "blx",
["Magadhi Prakrit"] = "inc-mgd",
["Magahat"] = "mtw",
["Magdalena Peñasco Mixtec"] = "xtm",
["Magiyi"] = "gmg",
["Magoma"] = "gmx",
["Magɨ"] = "gkd",
["Mahican"] = "mjy",
["Mahongwe"] = "mhb",
["Mahou"] = "mxx",
["Tiếng Maia"] = "sks",
["Maiadomu"] = "mzz",
["Maiani"] = "tnh",
["Maii"] = "mmm",
["Mailu"] = "mgu",
["Maindo"] = "cwb",
["Mairasi"] = "zrs",
["Maisin"] = "mbq",
["Maiwa (Indonesia)"] = "wmm",
["Maiwa (New Guinea)"] = "mti",
["Maiwala"] = "mum",
["Majera"] = "xmj",
["Majhi"] = "mjz",
["Majhwar"] = "mmj",
["Mak (China)"] = "mkg",
["Mak (Nigeria)"] = "pbl",
["Makaa"] = "mcp",
["Makah"] = "myh",
["Tiếng Makalero"] = "mjb",
["Tiếng Makasae"] = "mkz",
["Makassar Malay"] = "mfp",
["Makayam"] = "aup",
["Makhuwa"] = "vmw",
["Makhuwa-Marrevone"] = "xmc",
["Makhuwa-Meetto"] = "mgh",
["Makhuwa-Moniga"] = "mhm",
["Makhuwa-Saka"] = "xsq",
["Makhuwa-Shirima"] = "vmk",
["Maklew"] = "mgf",
["Makolkol"] = "zmh",
["Makonde"] = "kde",
["Maku"] = "xak",
["Maku'a"] = "lva",
["Makuri Naga"] = "jmn",
["Makuráp"] = "mpu",
["Makwe"] = "ymk",
["Makyan Naga"] = "umn",
["Mal Paharia"] = "mkb",
["Mala (New Guinea)"] = "ped",
["Mala (Nigeria)"] = "ruy",
["Malaccan Creole Malay"] = "ccm",
["Malalamai"] = "mmt",
["Malalí"] = "sai-mal",
["Malango"] = "mln",
["Malas"] = "mkr",
["Malasanga"] = "mqz",
["Malawi Lomwe"] = "lon",
["Malawian Sign Language"] = "lws",
["Malayic Dayak"] = "xdy",
["Malaynon"] = "mlz",
["Malaysian Sign Language"] = "xml",
["Malba Birifor"] = "bfo",
["Male"] = "mdc",
["Maleu-Kilenge"] = "mgl",
["Malfaxal"] = "mlx",
["Malgana"] = "vml",
["Malgbe"] = "mxf",
["Mali"] = "gcc",
["Malibu"] = "sai-mlb",
["Malila"] = "mgq",
["Malimba"] = "mzd",
["Malimpung"] = "mli",
["Malol"] = "mbk",
["Maltese Sign Language"] = "mdl",
["Malua Bay"] = "mll",
["Malvi"] = "mup",
["Maléku Jaíka"] = "gut",
["Mam"] = "mam",
["Mama"] = "mma",
["Mamaa"] = "mhf",
["Mamaindé"] = "wmd",
["Mamanwa"] = "mmn",
["Tiếng Senoufo Mamara"] = "myk",
["Mamasa"] = "mqj",
["Mambae"] = "mgm",
["Mambai"] = "mcs",
["Mamboru"] = "mvd",
["Mambwe-Lungu"] = "mgr",
["Mamuju"] = "mqx",
["Mamulique"] = "emm",
["Mamusi"] = "kdf",
["Mamvu"] = "mdi",
["Man Met"] = "mml",
["Manado Malay"] = "xmm",
["Manam"] = "mva",
["Manambu"] = "mle",
["Manangba"] = "nmm",
["Manangkari"] = "znk",
["Manao"] = "awd-man",
["Manda (Australia)"] = "zma",
["Manda (Tanzania)"] = "mgs",
["Tiếng Manda"] = "mid",
["Mandailing Batak"] = "btm",
["Mandalorian"] = "art-man",
["Mandan"] = "mhq",
["Mandandanyi"] = "zmk",
["Mandar"] = "mdr",
["Mandari"] = "mqu",
["Mander"] = "mqr",
["Mandingo"] = "man",
["Mandjak"] = "mfv",
["Mandobo Atas"] = "aax",
["Mandobo Bawah"] = "bwp",
["Manem"] = "jet",
["Mangala"] = "mem",
["Mangarayi"] = "mpc",
["Mangarevan"] = "mrv",
["Mangayat"] = "myj",
["Mangbetu"] = "mdj",
["Mangbutu"] = "mdk",
["Mangerr"] = "zme",
["Mangga Buang"] = "mmo",
["Tiếng Mango"] = "mge",
["Mangole"] = "mqc",
["Mangseng"] = "mbh",
["Manigri-Kambolé Ede Nago"] = "xkb",
["Manikion"] = "mnx",
["Manipa"] = "mqp",
["Mankiyali"] = "nlm",
["Tiếng Manna-Dora"] = "mju",
["Manombai"] = "woo",
["Mansoanka"] = "msw",
["Manta"] = "myg",
["Mantsi"] = "nty",
["Manusela"] = "wha",
["Manya"] = "mzj",
["Manyawa"] = "mny",
["Manza"] = "mzv",
["Mao Naga"] = "nbi",
["Mape"] = "mlh",
["Mapena"] = "mnm",
["Mapia"] = "mpy",
["Mapidian"] = "mpw",
["Mapoyo"] = "mcg",
["Mapun"] = "sjm",
["Mara"] = "mec",
["Mara Chin"] = "mrh",
["Marachi"] = "lri",
["Maraghei"] = "vmh",
["Maragus"] = "mrs",
["Maram Naga"] = "nma",
["Marama"] = "lrm",
["Maranungku"] = "zmr",
["Mararit"] = "mgb",
["Maratino"] = "sai-mar",
["Marawan"] = "awd-mar",
["Marba"] = "mpg",
["Marenje"] = "vmr",
["Marfa"] = "mvu",
["Margany"] = "zmc",
["Marghi South"] = "mfm",
["Margi"] = "mrt",
["Maria"] = "mds",
["Mariaté"] = "awd-mrt",
["Maridan"] = "zmd",
["Maridjabin"] = "zmj",
["Marik"] = "dad",
["Marimanindji"] = "zmm",
["Marind"] = "mrz",
["Maring"] = "mbw",
["Maringarr"] = "zmt",
["Marino"] = "mrb",
["Mariri"] = "mqi",
["Maritime Sign Language"] = "nsr",
["Maritsauá"] = "msp",
["Mariyedi"] = "zmy",
["Marka"] = "rkm",
["Markweeta"] = "enb",
["Maroon Spirit Language"] = "cpe-mar",
["Marovo"] = "mvo",
["Marrgu"] = "mhg",
["Marriammu"] = "xru",
["Marrithiyel"] = "mfr",
["Martha's Vineyard Sign Language"] = "mre",
["Marti Ke"] = "zmg",
["Martu Wangka"] = "mpj",
["Marúbo"] = "mzr",
["Masaba"] = "myx",
["Masadiit Itneg"] = "tis",
["Masakará"] = "sai-msk",
["Masalit"] = "mls",
["Masana"] = "mcn",
["Masbate Sorsogon"] = "bks",
["Mashco Piro"] = "cuj",
["Mashi"] = "mho",
["Masimasi"] = "ism",
["Masiwang"] = "bnf",
["Maslam"] = "msv",
["Masmaje"] = "mes",
["Massachusett"] = "wam",
["Massalat"] = "mdg",
["Massep"] = "mvs",
["Matagalpa"] = "mtn",
["Matanawi"] = "sai-mat",
["Matbat"] = "xmt",
["Matengo"] = "mgv",
["Matepi"] = "mqe",
["Matigsalug Manobo"] = "mbt",
["Matipuhy"] = "mzo",
["Matlatzinca"] = "mat",
["Mato"] = "met",
["Mato Grosso Arára"] = "axg",
["Matsés"] = "mcf",
["Mattole"] = "mvb",
["Matukar"] = "mjk",
["Matumbi"] = "mgw",
["Matya Samo"] = "stj",
["Matís"] = "mpq",
["Mauritian Sign Language"] = "lsy",
["Mauwake"] = "mhl",
["Mawa"] = "mcw",
["Mawak"] = "mjj",
["Mawan"] = "mcz",
["Mawayana"] = "mzx",
["Mawchi"] = "mke",
["Mawes"] = "mgk",
["Maxakalí"] = "mbl",
["Maxi Gbe"] = "mxl",
["Maya Samo"] = "sym",
["Mayaguduna"] = "xmy",
["Mayangna"] = "yan",
["Mayawali"] = "yxa",
["Maybrat"] = "ayz",
["Mayeka"] = "myc",
["Mayi-Thakurti"] = "xyt",
["Maykulan"] = "mnt",
["Maynas"] = "sai-mys",
["Mayo"] = "mfy",
["Mayogo"] = "mdm",
["Mayoyao Ifugao"] = "ifu",
["Maypure"] = "awd-mpr",
["Mazagway"] = "dkx",
["Mazaltepec Zapotec"] = "zpy",
["Mazatlán Mazatec"] = "vmz",
["Mazatlán Mixe"] = "mzl",
["Mba"] = "mfc",
["Mbala"] = "mdp",
["Mbalanhu"] = "lnb",
["Mbandja"] = "zmz",
["Mbangala"] = "mxg",
["Mbangi"] = "mgn",
["Mbangwe"] = "zmn",
["Mbara (Australia)"] = "mvl",
["Mbara (Chad)"] = "mpk",
["Mbariman-Gudhinma"] = "zmv",
["Mbati"] = "mdn",
["Mbato"] = "gwa",
["Mbay"] = "myb",
["Mbe"] = "mfo",
["Mbe'"] = "mtk",
["Mbelime"] = "mql",
["Mbere"] = "mdt",
["Mbesa"] = "zms",
["Mbiywom"] = "aus-mbi",
["Mbo (Cameroon)"] = "mbo",
["Mbo (Congo)"] = "zmw",
["Mboi"] = "moi",
["Mboko"] = "mdu",
["Mbole"] = "mdq",
["Mbonga"] = "xmb",
["Mbongno"] = "bgu",
["Mbosi"] = "mdw",
["Mbowe"] = "mxo",
["Mbre"] = "mka",
["Mbu'"] = "muc",
["Mbudum"] = "xmd",
["Mbugu"] = "mhd",
["Mbugwe"] = "mgz",
["Mbuko"] = "mqb",
["Mbukushu"] = "mhw",
["Mbula"] = "mna",
["Mbula-Bwazza"] = "mbu",
["Mbule"] = "mlb",
["Mbulungish"] = "mbv",
["Mbum"] = "mdd",
["Mbunda"] = "mck",
["Mbunga"] = "mgy",
["Mburku"] = "bbt",
["Mbuun"] = "zmp",
["Mbwela"] = "mfu",
["Mea"] = "meg",
["Mebu"] = "mjn",
["Mecayapan Nahuatl"] = "nhx",
["Medebur"] = "mjm",
["Medefaidrin"] = "dmf",
["Mednyj Aleut"] = "mud",
["Mefele"] = "mfj",
["Megam"] = "mef",
["Mehek"] = "nux",
["Mehináku"] = "mmh",
["Mekeo"] = "mek",
["Mekmek"] = "mvk",
["Mekwei"] = "msf",
["Mekéns"] = "skf",
["Mel-Khaonh"] = "hkn",
["Mele-Fila"] = "mxe",
["Mendalam Kayan"] = "xkd",
["Mengaka"] = "xmg",
["Mengen"] = "mee",
["Menien"] = "sai-men",
["Menka"] = "mea",
["Menya"] = "mcr",
["Meoswar"] = "mvx",
["Mer"] = "mnu",
["Meramera"] = "mxm",
["Merei"] = "lmb",
["Merey"] = "meq",
["Merlav"] = "mrm",
["Meroitic"] = "xmr",
["Meru"] = "mer",
["Mese"] = "mci",
["Mesme"] = "zim",
["Mesmes"] = "mys",
["Meta'"] = "mgo",
["Metlatónoc Mixtec"] = "mxv",
["Mewari"] = "mtr",
["Mewati"] = "wtm",
["Mexican Sign Language"] = "mfs",
["Meyah"] = "mej",
["Mezontla Popoloca"] = "pbe",
["Mfinu"] = "zmf",
["Mfumte"] = "nfu",
["Mgbo"] = "gmz",
["Mian"] = "mpt",
["Miani"] = "pla",
["Micha"] = "yiq",
["Michif"] = "crg",
["Michigamea"] = "cmm",
["Michoacán Nahuatl"] = "ncl",
["Mid Grand Valley Dani"] = "dnt",
["Mid-Southern Banda"] = "bjo",
["Middle Assamese"] = "inc-mas",
["Middle Bengali"] = "inc-mbn",
["Tiếng Cornwall trung đại"] = "cnx",
["Middle Kannada"] = "dra-mkn",
["Middle Median"] = "xme-mid",
["Middle Newar"] = "nwx",
["Tiếng Na Uy trung đại"] = "gmq-mno",
["Middle Watut"] = "mpl",
["Midob"] = "mei",
["Migaama"] = "mmy",
["Migabac"] = "mpp",
["Miji"] = "sjl",
["Miju"] = "mxj",
["Mikasuki"] = "mik",
["Milang"] = "und-mil",
["Mili"] = "ymh",
["Millcayac"] = "sai-mil",
["Miltu"] = "mlj",
["Miluk"] = "iml",
["Milyan"] = "imy",
["Mimi of Decorse"] = "und-mmd",
["Mimi of Nachtigal"] = "und-mmn",
["Mina"] = "hna",
["Minaean"] = "inm",
["Minang"] = "xrg",
["Minanibai"] = "mcv",
["Minaveha"] = "mvn",
["Minderico"] = "drc",
["Mindiri"] = "mpn",
["Mingang Doso"] = "mko",
["Mingo"] = "iro-min",
["Tiếng Huitoto Minica"] = "hto",
["Minidien"] = "wii",
["Minigir"] = "vmg",
["Minjungbal"] = "xjb",
["Minkin"] = "xxm",
["Minoan"] = "omn",
["Minokok"] = "mqq",
["Miraya Bikol"] = "rbl",
["Mire"] = "mvh",
["Miriti"] = "mmv",
["Miriwoong Sign Language"] = "rsm",
["Miriwung"] = "mep",
["Mirpur Panjabi"] = "pmu",
["Misantla Totonac"] = "tlc",
["Miship"] = "mjs",
["Misima-Paneati"] = "mpx",
["Mitlatongo Mixtec"] = "vmm",
["Mittu"] = "mwu",
["Mituku"] = "zmq",
["Miu"] = "mpo",
["Miwa"] = "vmi",
["Mixed Great Andamanese"] = "gac",
["Mixifore"] = "mfg",
["Mixtepec Mixtec"] = "mix",
["Mixtepec Zapotec"] = "zpm",
["Miya"] = "mkf",
["Miyobe"] = "soy",
["Mlap"] = "kja",
["Mlomp"] = "mlo",
["Mmaala"] = "mmu",
["Mmani"] = "buy",
["Mmen"] = "bfm",
["Mo"] = "wkd",
["Mo'da"] = "gbn",
["Moabite"] = "obm",
["Moba"] = "mfq",
["Mobilian"] = "mod",
["Mobumrin Aizi"] = "ahm",
["Mocana"] = "sai-mcn",
["Mochi"] = "old",
["Mochica"] = "omc",
["Mocho"] = "mhc",
["Mocoví"] = "moc",
["Modang"] = "mxd",
["Modole"] = "mqo",
["Moere"] = "mvq",
["Mofu-Gudur"] = "mif",
["Mogum"] = "mou",
["Moi (Congo)"] = "mow",
["Moi (Indonesia)"] = "mxn",
["Moikodi"] = "mkp",
["Moingi"] = "mwz",
["Mojave"] = "mov",
["Moji"] = "ymi",
["Mok"] = "mqt",
["Mokerang"] = "mft",
["Mokole"] = "mkl",
["Mokpwe"] = "bri",
["Molale"] = "mbe",
["Moldova Sign Language"] = "vsi",
["Molengue"] = "bxc",
["Molima"] = "mox",
["Molmo One"] = "aun",
["Molo"] = "zmo",
["Molof"] = "msl",
["Moloko"] = "mlw",
["Mom Jango"] = "ver",
["Moma"] = "myl",
["Momare"] = "msz",
["Mombo Dogon"] = "dmb",
["Mombum"] = "mso",
["Momina"] = "mmb",
["Momuna"] = "mqf",
["Monastic Sign Language"] = "mzg",
["Mondropolon"] = "npn",
["Mondé"] = "mnd",
["Mongol"] = "mgt",
["Mongolian Sign Language"] = "msr",
["Moni"] = "mnz",
["Monimbo"] = "mom",
["Mono (California)"] = "mnr",
["Mono (Cameroon)"] = "mru",
["Mono (Congo)"] = "mnh",
["Monsang Naga"] = "nmh",
["Montagnais"] = "moe",
["Montana Salish"] = "fla",
["Montol"] = "mtl",
["Monumbo"] = "mxk",
["Monzombo"] = "moj",
["Moo"] = "gwg",
["Mopan Maya"] = "mop",
["Mor (Austronesian)"] = "mhz",
["Mor (Papuan)"] = "moq",
["Moraid"] = "msg",
["Moran"] = "sit-mor",
["Morawa"] = "mze",
["Morelos Nahuatl"] = "nhm",
["Morerebi"] = "xmo",
["Moresada"] = "msx",
["Mori Atas"] = "mzq",
["Mori Bawah"] = "xmz",
["Morigi"] = "mdb",
["Moroccan Sign Language"] = "xms",
["Morom"] = "bdo",
["Moronene"] = "mqn",
["Morori"] = "mok",
["Morouas"] = "mrp",
["Mortlockese"] = "mrl",
["Moru"] = "mgd",
["Mosimo"] = "mqv",
["Moskona"] = "mtj",
["Motembo"] = "tmv",
["Mouk-Aria"] = "mwh",
["Mount Iraya Agta"] = "atl",
["Mount Iriga Agta"] = "agz",
["Mountain Koiari"] = "kpx",
["Mouwase"] = "jmw",
["Movima"] = "mzp",
["Moyadan Itneg"] = "ity",
["Mozambican Sign Language"] = "mzy",
["Mpalitjanh"] = "xpj",
["Mpiemo"] = "mcx",
["Mpiin"] = "bnt-mpi",
["Mpinda"] = "pnd",
["Mpongmpong"] = "mgg",
["Mpoto"] = "mpa",
["Mpotovoro"] = "mvt",
["Mpuono"] = "bnt-mpu",
["Mpur"] = "akc",
["Mro Chin"] = "cmr",
["Mru"] = "mro",
["Mser"] = "kqx",
["Mualang"] = "mtd",
["Mubami"] = "tsx",
["Mubi"] = "mub",
["Mucuchí"] = "sai-muc",
["Muda"] = "ymd",
["Muduapa"] = "wiv",
["Muellama"] = "sai-mue",
["Mufian"] = "aoj",
["Muher"] = "sem-mhr",
["Muinane"] = "bmr",
["Mukha-Dora"] = "mmk",
["Mukulu"] = "moz",
["Mulaha"] = "mfw",
["Mulam"] = "mlm",
["Mulao"] = "giu",
["Mullukmulluk"] = "mpb",
["Muluridyi"] = "vmu",
["Mum"] = "kqa",
["Mumuye"] = "mzm",
["Mundang"] = "mua",
["Tiếng Mundani"] = "mnf",
["Mundat"] = "mmf",
["Mundolinco"] = "art-mun",
["Mundurukú"] = "myu",
["Mungaka"] = "mhk",
["Mungbam"] = "mij",
["Mungkip"] = "mpv",
["Muniche"] = "myr",
["Munit"] = "mtc",
["Mur Pano"] = "tkv",
["Muratayak"] = "asx",
["Murik (Malaysia)"] = "mxr",
["Murik (New Guinea)"] = "mtf",
["Murkim"] = "rmh",
["Murrinh-Patha"] = "mwf",
["Tiếng Huitoto Murui"] = "huu",
["Murupi"] = "mqw",
["Muruwari"] = "zmu",
["Musan"] = "mmp",
["Musar"] = "mmi",
["Musasa"] = "smm",
["Musey"] = "mse",
["Musgu"] = "mug",
["Muskum"] = "mje",
["Musom"] = "msu",
["Mussau-Emira"] = "emi",
["Mutu"] = "tuc",
["Muya"] = "mvm",
["Muyang"] = "muy",
["Muyuw"] = "myw",
["Muzi"] = "ymz",
["Muzo"] = "sai-muz",
["Mvanip"] = "mcj",
["Mvuba"] = "mxh",
["Mwaghavul"] = "sur",
["Mwali Comorian"] = "wlc",
["Mwani"] = "wmw",
["Mwatebu"] = "mwa",
["Mwera"] = "mwe",
["Mwimbi-Muthambi"] = "mws",
["Mysian"] = "yms",
["Mzieme Naga"] = "nme",
["Mághdì"] = "gmd",
["Mün Chin"] = "mwq",
["Mündü"] = "muh",
["N'Ko"] = "nqo",
["Na"] = "nbt",
["Na'vi"] = "art-nav",
["Naaba"] = "nao",
["Naba"] = "mne",
["Nabak"] = "naf",
["Nabi"] = "mty",
["Nachering"] = "ncd",
["Nadruvian"] = "ndf",
["Nadëb"] = "mbj",
["Nafi"] = "srf",
["Nafri"] = "nxx",
["Naga Pidgin"] = "nag",
["Nagarchal"] = "nbg",
["Nage"] = "nxe",
["Nagtipunan Agta"] = "phi-nag",
["Nagu"] = "ngr",
["Nagumi"] = "ngv",
["Nahali"] = "nlx",
["Nahari"] = "nhh",
["Nahavaq"] = "sns",
["Nai"] = "bio",
["Najdi Arabic"] = "ars",
["Naka'ela"] = "nae",
["Nakai"] = "nkj",
["Nakame"] = "nib",
["Nakanai"] = "nak",
["Nakara"] = "nck",
["Nake"] = "nbk",
["Naki"] = "mff",
["Nakwi"] = "nax",
["Nalca"] = "nlc",
["Nali"] = "nss",
["Nalik"] = "nal",
["Nalu"] = "naj",
["Nalögo"] = "nlz",
["Namakura"] = "nmk",
["Namat"] = "nkm",
["Nambo"] = "ncm",
["Nambya"] = "nmq",
["Namia"] = "nnm",
["Namiae"] = "nvm",
["Namibian Sign Language"] = "nbs",
["Namla"] = "naa",
["Namo"] = "mxw",
["Namonuito"] = "nmt",
["Namosi-Naitasiri-Serua"] = "bwb",
["Namuyi"] = "nmy",
["Nancere"] = "nnc",
["Nande"] = "nnb",
["Nandi"] = "niq",
["Nanerigé Sénoufo"] = "sen",
["Nanga Dama Dogon"] = "nzz",
["Nanti"] = "cox",
["Nanticoke"] = "nnt",
["Nanubae"] = "afk",
["Naolan"] = "nai-nao",
["Napu"] = "npy",
["Nar Phu"] = "npa",
["Nara"] = "nrb",
["Narak"] = "nac",
["Narango"] = "nrg",
["Narau"] = "nxu",
["Narim"] = "loh",
["Naro"] = "nhr",
["Narom"] = "nrm",
["Narragansett"] = "xnt",
["Narungga"] = "nnr",
["Naruo"] = "ylo",
["Nasal"] = "nsy",
["Nasarian"] = "nvh",
["Nasioi"] = "nas",
["Nasu"] = "ywq",
["Natagaimas"] = "nts",
["Natchez"] = "ncz",
["Nathembo"] = "nte",
["Natioro"] = "nti",
["Natú"] = "sai-nat",
["Natügu"] = "ntu",
["Nauete"] = "nxa",
["Nauna"] = "ncn",
["Nauo"] = "nwo",
["Navarro-Aragonese"] = "roa-oan",
["Navut"] = "nsw",
["Nawaru"] = "nwr",
["Nawathinehena"] = "nwa",
["Nawdm"] = "nmz",
["Nawuri"] = "naw",
["Nayi"] = "noz",
["Ncane"] = "ncr",
["Nchumbulu"] = "nlu",
["Nda'nda'"] = "nnz",
["Ndai"] = "gke",
["Ndaka"] = "ndk",
["Ndali"] = "ndh",
["Ndam"] = "ndm",
["Ndamba"] = "ndj",
["Ndambomo"] = "nxo",
["Ndasa"] = "nda",
["Nde-Gbite"] = "ned",
["Nde-Nsele-Nta"] = "ndd",
["Ndemli"] = "nml",
["Ndendeule"] = "dne",
["Ndengereko"] = "ndg",
["Nding"] = "eli",
["Ndjébbana"] = "djj",
["Ndo"] = "ndp",
["Ndobo"] = "ndw",
["Ndoe"] = "nbb",
["Ndolo"] = "ndl",
["Ndom"] = "nqm",
["Ndombe"] = "ndq",
["Ndoola"] = "ndr",
["Ndrulo"] = "dno",
["Nduga"] = "ndx",
["Ndumu"] = "nmd",
["Ndunda"] = "nuh",
["Ndunga"] = "ndt",
["Ndut"] = "ndv",
["Ndyuka-Trio Pidgin"] = "njt",
["Ndzwani Comorian"] = "wni",
["Nedebang"] = "nec",
["Nefamese"] = "nef",
["Negeri Sembilan Malay"] = "zmi",
["Nehan"] = "nsn",
["Nek"] = "nif",
["Nekgini"] = "nkg",
["Neko"] = "nej",
["Neku"] = "nek",
["Neme"] = "nex",
["Nemi"] = "nem",
["Nen"] = "nqn",
["Nend"] = "anh",
["Nengone"] = "nen",
["Neo"] = "neu",
["Nepalese Sign Language"] = "nsp",
["Nepali Kurux"] = "kxl",
["Nete"] = "net",
["Neve'ei"] = "vnm",
["Neverver"] = "lgk",
["New Caledonian Javanese"] = "jas",
["New River Shasta"] = "nai-nrs",
["New Zealand Sign Language"] = "nzs",
["Neyo"] = "ney",
["Nez Perce"] = "nez",
["Nga La"] = "hlt",
["Ngaanyatjarra"] = "ntj",
["Ngadjunmaya"] = "nju",
["Ngadjuri"] = "jui",
["Ngaing"] = "nnf",
["Ngaju"] = "nij",
["Ngala"] = "nud",
["Ngalakan"] = "nig",
["Ngalkbun"] = "ngk",
["Ngamambo"] = "nbv",
["Ngamini"] = "nmv",
["Ngamo"] = "nbh",
["Ngan'gityemerri"] = "nam",
["Nganakarti"] = "xnk",
["Ngandi"] = "nid",
["Ngando (Central African Republic)"] = "ngd",
["Ngando (Congo)"] = "nxd",
["Ngandyera"] = "nne",
["Ngangam"] = "gng",
["Ngantangarra"] = "ntg",
["Nganyaywana"] = "nyx",
["Ngardi"] = "rxd",
["Ngarigu"] = "xni",
["Ngarinman"] = "nbj",
["Ngarinyin"] = "ung",
["Ngarla"] = "nrk",
["Ngarluma"] = "nrl",
["Ngarrindjeri"] = "nay",
["Ngasa"] = "nsg",
["Ngatik Men's Creole"] = "ngm",
["Ngawn Chin"] = "cnw",
["Ngawun"] = "nxn",
["Ngazidja Comorian"] = "zdj",
["Tiếng Ngbaka"] = "nga",
["Ngbaka Ma'bo"] = "nbm",
["Ngbaka Manza"] = "ngg",
["Ngbee"] = "jgb",
["Ngbinda"] = "nbd",
["Ngbundu"] = "nuu",
["Ngelima"] = "agh",
["Ngemba"] = "nge",
["Ngen"] = "gnj",
["Ngendelengo"] = "nql",
["Ngeq"] = "ngt",
["Ngete"] = "nnn",
["Nggem"] = "nbq",
["Nggwahyi"] = "ngx",
["Ngie"] = "ngj",
["Ngile"] = "jle",
["Ngindo"] = "nnq",
["Tiếng Ngiti"] = "niy",
["Ngizim"] = "ngi",
["Ngkoth"] = "aus-ngk",
["Ngkâlmpw Kanum"] = "kcd",
["Ngochang"] = "tbq-ngo",
["Ngom"] = "nra",
["Ngombale"] = "nla",
["Ngombe (Central African Republic)"] = "nmj",
["Ngong"] = "nnx",
["Ngongo"] = "noq",
["Ngoni"] = "ngo",
["Ngoreme"] = "ngq",
["Ngoshie"] = "nsh",
["Ngul"] = "nlo",
["Ngulu"] = "ngp",
["Nguluwan"] = "nuw",
["Ngumbi"] = "nui",
["Ngunawal"] = "xul",
["Ngundi"] = "ndn",
["Ngundu"] = "nue",
["Ngungwel"] = "ngz",
["Ngurmbur"] = "nrx",
["Ngwaba"] = "ngw",
["Ngwe"] = "nwe",
["Ngwo"] = "ngn",
["Ngäbere"] = "gym",
["Nhanda"] = "nha",
["Nhirrpi"] = "hrp",
["Nhuwala"] = "nhf",
["Nicaraguan Creole"] = "bzk",
["Nicaraguan Sign Language"] = "ncs",
["Nicola"] = "ath-nic",
["Niellim"] = "nie",
["Nigeria Mambila"] = "mzk",
["Nigerian Pidgin"] = "pcm",
["Nigerian Sign Language"] = "nsi",
["Nihali"] = "nll",
["Nii"] = "nii",
["Niksek"] = "gbe",
["Nila"] = "nil",
["Nilamba"] = "nim",
["Nimadi"] = "noe",
["Nimanbur"] = "nmp",
["Nimbari"] = "nmr",
["Nimboran"] = "nir",
["Nimi"] = "nis",
["Nimo"] = "niw",
["Nimoa"] = "nmw",
["Ninam"] = "shb",
["Nindi"] = "nxi",
["Ningera"] = "nby",
["Ninggerum"] = "nxr",
["Ningil"] = "niz",
["Ninia Yali"] = "nlk",
["Ninzo"] = "nin",
["Nipsan"] = "nps",
["Nisa"] = "njs",
["Nisenan"] = "nsz",
["Nisi"] = "yso",
["Niuafo'ou"] = "num",
["Niuatoputapu"] = "nkp",
["Niwer Mil"] = "hrc",
["Njalgulgule"] = "njl",
["Njebi"] = "nzb",
["Njen"] = "njj",
["Njerep"] = "njr",
["Njyem"] = "njy",
["Nkami"] = "nkq",
["Nkangala"] = "nkn",
["Nkem-Nkum"] = "isi",
["Nkhumbi"] = "khu",
["Nkongho"] = "nkc",
["Nkoroo"] = "nkx",
["Nkoya"] = "nka",
["Nkukoli"] = "nbo",
["Nkutu"] = "nkw",
["Nnam"] = "nbp",
["Nocamán"] = "nom",
["Nocte Naga"] = "njb",
["Noiri"] = "noi",
["Nokuku"] = "nkk",
["Nomaande"] = "lem",
["Nomane"] = "nof",
["Nomatsiguenga"] = "not",
["Nomlaki"] = "nol",
["Nomu"] = "noh",
["Nonuya"] = "noj",
["Nooksack"] = "nok",
["Tiếng Noone"] = "nhu",
["Nopala Chatino"] = "cya",
["Norn"] = "nrn",
["Norra"] = "nrr",
["North Ambrym"] = "mmg",
["North Asmat"] = "nks",
["North Awyu"] = "yir",
["North Babar"] = "bcd",
["North Boma"] = "boh",
["North Central Mixe"] = "neq",
["North Fali"] = "fll",
["North Giziga"] = "gis",
["North Mofu"] = "mfk",
["North Muyu"] = "kti",
["North Nuaulu"] = "nni",
["North Tairora"] = "tbg",
["North Tanna"] = "tnn",
["North Wahgi"] = "whg",
["North Watut"] = "una",
["Northeast Kiwai"] = "kiw",
["Northeast Maidu"] = "nmu",
["Northeast Pashayi"] = "aee",
["Northeastern Dinka"] = "dip",
["Northeastern Pomo"] = "pef",
["Northern Alta"] = "aqn",
["Northern Bontoc"] = "rbk",
["Northern Ghale"] = "ghh",
["Tiếng Grebo Bắc"] = "gbo",
["Northern Guiyang Hmong"] = "huj",
["Northern Haida"] = "hdn",
["Northern Huishui Hmong"] = "hmi",
["Northern Kalapuya"] = "nrt",
["Northern Kam"] = "doc",
["Northern Kankanay"] = "xnn",
["Northern Kissi"] = "kqs",
["Northern Lorung"] = "lbr",
["Northern Mashan Hmong"] = "hmp",
["Northern Muji"] = "ymx",
["Northern Ngbandi"] = "ngb",
["Northern Nuni"] = "nuv",
["Northern Oaxaca Nahuatl"] = "nhy",
["Northern Ohlone"] = "cst",
["Northern One"] = "onr",
["Northern Pame"] = "pmq",
["Northern Pinghua"] = "cnp",
["Northern Pomo"] = "pej",
["Northern Puebla Nahuatl"] = "ncj",
["Northern Pumi"] = "pmi",
["Northern Qiandong Miao"] = "hea",
["Northern Rengma Naga"] = "nnl",
["Northern Sierra Miwok"] = "nsq",
["Northern Subanen"] = "stb",
["Northern Tarahumara"] = "thh",
["Northern Tidong"] = "ntd",
["Northern Tlaxiaco Mixtec"] = "xtn",
["Northern Toussian"] = "tsp",
["Northern Tutchone"] = "ttm",
["Northern Valley Yokuts"] = "nai-nvy",
["Northwest Maidu"] = "mjd",
["Northwest Oaxaca Mixtec"] = "mxa",
["Northwest Pashayi"] = "glh",
["Northwestern Dinka"] = "diw",
["Northwestern Fars"] = "faz",
["Northwestern Tamang"] = "tmk",
["Norwegian Sign Language"] = "nsl",
["Notre"] = "bly",
["Notsi"] = "ncf",
["Nottoway"] = "ntw",
["Nottoway-Meherrin"] = "nwy",
["Noxilo"] = "art-nox",
["Noy"] = "noy",
["Nsari"] = "asj",
["Nsenga"] = "nse",
["Nshi"] = "nsc",
["Nsong"] = "soo",
["Nsongo"] = "nsx",
["Ntomba"] = "nto",
["Ntra'ngith"] = "dgt",
["Nuguria"] = "nur",
["Nuk"] = "noc",
["Nukak Makú"] = "mbr",
["Nukna"] = "klt",
["Nukuini"] = "nuc",
["Nukumanu"] = "nuq",
["Nukunu"] = "nnv",
["Nukunul"] = "xnu",
["Nukuoro"] = "nkr",
["Numana"] = "nbr",
["Numanggang"] = "nop",
["Numbami"] = "sij",
["Nume"] = "tgs",
["Numee"] = "kdk",
["Nungali"] = "nug",
["Nunggubuyu"] = "nuy",
["Nungon"] = "paa-nun",
["Nungu"] = "rin",
["Nupbikha"] = "npb",
["Nusa Laut"] = "nul",
["Nusu"] = "nuf",
["Nutabe"] = "cba-nut",
["Nyabwa"] = "nwb",
["Nyaheun"] = "nev",
["Nyakyusa"] = "nyy",
["Nyali"] = "nlj",
["Nyam"] = "nmi",
["Nyamal"] = "nly",
["Nyambo"] = "now",
["Nyamusa-Molo"] = "nwm",
["Nyamwanga"] = "mwn",
["Nyamwezi"] = "nym",
["Nyaneka"] = "nyk",
["Nyang'i"] = "nyp",
["Nyanga (Congo)"] = "nyj",
["Nyanga (Togo)"] = "ayg",
["Nyanga-li"] = "nyc",
["Nyangatom"] = "nnj",
["Nyangbo"] = "nyb",
["Nyangga"] = "nny",
["Nyangumarta"] = "nna",
["Nyankole"] = "nyn",
["Nyaturu"] = "rim",
["Nyawaygi"] = "nyt",
["Nyemba"] = "nba",
["Nyengo"] = "nye",
["Nyenkha"] = "neh",
["Nyigina"] = "nyh",
["Nyiha"] = "nih",
["Nyika"] = "nkt",
["Nyimang"] = "nyi",
["Nyindrou"] = "lid",
["Nyindu"] = "nyg",
["Nyiyaparli"] = "xny",
["Nyokon"] = "nvo",
["Nyole (Kenya)"] = "nyd",
["Nyole (Uganda)"] = "nuj",
["Nyong"] = "muo",
["Nyulnyul"] = "nyv",
["Nyungwe"] = "nyu",
["Nyâlayu"] = "yly",
["Nzakambay"] = "nzy",
["Nzakara"] = "nzk",
["Nzanyi"] = "nja",
["Nzima"] = "nzi",
["Tiếng Huitoto Nüpode"] = "hux",
["O'chi'chi'"] = "xoc",
["Obanliku"] = "bzy",
["Obispeño"] = "obi",
["Oblo"] = "obl",
["Obo Manobo"] = "obo",
["Obokuitai"] = "afz",
["Obolo"] = "ann",
["Obulom"] = "obu",
["Ocotepec Mixtec"] = "mie",
["Ocotlán Zapotec"] = "zac",
["Od"] = "odk",
["Odiai"] = "bhf",
["Odoodee"] = "kkc",
["Odual"] = "odu",
["Odut"] = "oda",
["Ofayé"] = "opy",
["Ofo"] = "ofo",
["Ogbah"] = "ogc",
["Ogbia"] = "ogb",
["Ogbogolo"] = "ogg",
["Ogea"] = "eri",
["Tiếng Oirata"] = "oia",
["Okiek"] = "oki",
["Oko-Eni-Osayen"] = "oks",
["Oko-Juwoi"] = "okj",
["Okobo"] = "okb",
["Okodia"] = "okd",
["Okolod"] = "kqv",
["Okpamheri"] = "opa",
["Okpe (Northwestern Edo)"] = "okx",
["Okpe (Southwestern Edo)"] = "oke",
["Okpela"] = "atg",
["Oksapmin"] = "opm",
["Oku"] = "oku",
["Okwanuchu"] = "nai-okw",
["Old Avar"] = "oav",
["Old Hungarian"] = "ohu",
["Old Kamta"] = "inc-ork",
["Old Kentish Sign Language"] = "okl",
["Old Manipuri"] = "omp",
["Old Punjabi"] = "inc-opa",
["Old Tati"] = "xme-ott",
["Old Tibetan"] = "otb",
["Tiếng Wales cổ"] = "owl",
["Olekha"] = "ole",
["Ollari"] = "gdb",
["Olo"] = "ong",
["Oloma"] = "olm",
["Olrat"] = "olr",
["Olu'bo"] = "lul",
["Olulumo-Ikom"] = "iko",
["Oluta Popoluca"] = "plo",
["Olutsotso"] = "lto",
["Omagua"] = "omg",
["Omba"] = "omb",
["Ombamba"] = "mbm",
["Ombo"] = "oml",
["Tiếng Nahuatl Ometepec"] = "nht",
["Omi"] = "omi",
["Omotik"] = "omt",
["Omurano"] = "omu",
["Ong"] = "oog",
["Onin"] = "oni",
["Onjob"] = "onj",
["Ono"] = "ons",
["Onobasulu"] = "onn",
["Onondaga"] = "ono",
["Ontenu"] = "ont",
["Ontong Java"] = "ojv",
["Oorlams"] = "oor",
["Opao"] = "opo",
["Opata"] = "opt",
["Opuuo"] = "lgn",
["Opón"] = "sai-opo",
["Oraon Sadri"] = "sdr",
["Orejón"] = "ore",
["Oring"] = "org",
["Orizaba Nahuatl"] = "nlv",
["Orléanais"] = "roa-orl",
["Oro"] = "orx",
["Oro Win"] = "orw",
["Oroha"] = "ora",
["Orokaiva"] = "okv",
["Oroko"] = "bdu",
["Orokolo"] = "oro",
["Orowe"] = "bpk",
["Oruma"] = "orr",
["Orya"] = "ury",
["Osamayi"] = "syx",
["Ososo"] = "oso",
["Ot Danum"] = "otd",
["Otank"] = "uta",
["Oti"] = "oti",
["Otomaco"] = "sai-oto",
["Ottawa"] = "otw",
["Ouma"] = "oum",
["Oune"] = "oue",
["Owa"] = "stn",
["Owenia"] = "wsr",
["Owiniga"] = "owi",
["Oy"] = "oyb",
["Oya'oya"] = "oyy",
["Ozolotepec Zapotec"] = "zao",
["Pa"] = "ppt",
["Tiếng Pa Dí"] = "pdi",
["Pa'a"] = "pqa",
["Paama"] = "pma",
["Paasaal"] = "sig",
["Pacahuara"] = "pcp",
["Padoe"] = "pdo",
["Paeonian"] = "ine-pae",
["Pagi"] = "pgi",
["Pagibete"] = "pae",
["Pahanan Agta"] = "apf",
["Pahi"] = "lgt",
["Pahlavani"] = "phv",
["Pai Tavytera"] = "pta",
["Pai-lang"] = "tbq-plg",
["Paicî"] = "pri",
["Paikoneka"] = "awd-pai",
["Paipai"] = "ppi",
["Pajapan Nahuatl"] = "nhp",
["Pak-Tong"] = "pkg",
["Pakanha"] = "pkn",
["Pakistan Sign Language"] = "pks",
["Paku Karen"] = "kpp",
["Pal"] = "abw",
["Palaka Senoufo"] = "plr",
["Palantla Chinantec"] = "cpa",
["Palawan Batak"] = "bya",
["Paleni"] = "pnl",
["Palewyami"] = "nai-ply",
["Palikur"] = "plu",
["Pallanganmiddang"] = "pmd",
["Palta"] = "sai-pal",
["Palu'e"] = "ple",
["Paluan"] = "plz",
["Palya Bareli"] = "bpx",
["Pam"] = "pmn",
["Pambia"] = "pmb",
["Pamigua"] = "sai-pam",
["Pamlico"] = "pmk",
["Pamona"] = "pmf",
["Pamosu"] = "hih",
["Pamplona Atta"] = "att",
["Pana (Central Africa)"] = "pnz",
["Pana (West Africa)"] = "pnq",
["Panamanian Sign Language"] = "lsp",
["Panamint"] = "par",
["Panare"] = "pbh",
["Panará"] = "kre",
["Panasuan"] = "psn",
["Panawa"] = "pwb",
["Pande"] = "bkj",
["Pangseng"] = "pgs",
["Pangutaran Sama"] = "slm",
["Pangwa"] = "pbr",
["Panim"] = "pnr",
["Pankararé"] = "pax",
["Pankararú"] = "paz",
["Pankhu"] = "pkh",
["Pannei"] = "pnc",
["Panobo"] = "pno",
["Panyi Bai"] = "bfc",
["Panyjima"] = "pnw",
["Panzaleo"] = "sai-pnz",
["Pao"] = "ppa",
["Papapana"] = "ppn",
["Papar"] = "dpp",
["Papasena"] = "pas",
["Papel"] = "pbo",
["Papi"] = "ppe",
["Papitalai"] = "pat",
["Papora"] = "ppu",
["Papua New Guinean Sign Language"] = "pgz",
["Papuan Malay"] = "pmy",
["Para Naga"] = "pzn",
["Paraguayan Sign Language"] = "pys",
["Parakanã"] = "pak",
["Paranan"] = "prf",
["Paranawát"] = "paf",
["Paratió"] = "sai-par",
["Parawen"] = "prw",
["Pardhan"] = "pch",
["Pardhi"] = "pcl",
["Pare"] = "asa",
["Paredarerme"] = "xpd",
["Pará Arára"] = "aap",
["Pará Gavião"] = "gvp",
["Pasi"] = "psq",
["Pass Valley Yali"] = "yac",
["Passé"] = "awd-pas",
["Patagón"] = "sai-ptg",
["Patamona"] = "pbc",
["Patani"] = "ptn",
["Pataxó Hã-Ha-Hãe"] = "pth",
["Patep"] = "ptp",
["Pathiya"] = "pty",
["Patpatar"] = "gfk",
["Pattani"] = "lae",
["Pattapu"] = "ptq",
["Patwin"] = "pwi",
["Paulohi"] = "plh",
["Paumarí"] = "pad",
["Pauri Bareli"] = "bfb",
["Pauserna"] = "psm",
["Pawaia"] = "pwa",
["Payaguá"] = "sai-pyg",
["Paynamar"] = "pmr",
["Pe"] = "pai",
["Pech"] = "pay",
["Peerapper"] = "xpw",
["Peere"] = "pfe",
["Pei"] = "ppq",
["Pekal"] = "pel",
["Pele-Ata"] = "ata",
["Penang Sign Language"] = "psg",
["Penchal"] = "pek",
["Pendau"] = "ums",
["Penrhyn"] = "pnh",
["Pentlatch"] = "ptw",
["Perai"] = "wet",
["Perema"] = "wom",
["Pericú"] = "nai-per",
["Pero"] = "pip",
["Persian Sign Language"] = "psc",
["Peruvian Sign Language"] = "prl",
["Petapa Zapotec"] = "zpe",
["Petats"] = "pex",
["Peñoles Mixtec"] = "mil",
["Phala"] = "ypa",
["Phana'"] = "phq",
["Phangduwali"] = "phw",
["Phende"] = "pem",
["Philippine Sign Language"] = "psp",
["Philistine"] = "und-phi",
["Phimbi"] = "phm",
["Phola"] = "ypg",
["Pholo"] = "yip",
["Phom"] = "nph",
["Phudagi"] = "phd",
["Phuie"] = "pug",
["Phukha"] = "phh",
["Phuma"] = "ypm",
["Phunoi"] = "pho",
["Phupa"] = "ypp",
["Phupha"] = "yph",
["Phuthi"] = "bnt-phu",
["Phuza"] = "ypz",
["Piamatsina"] = "ptr",
["Piame"] = "pin",
["Piapoco"] = "pio",
["Piaroa"] = "pid",
["Tiếng Pichinglis"] = "fpe",
["Pichis Ashéninka"] = "cpu",
["Pictish"] = "xpi",
["Picuris"] = "nai-pic",
["Pidgin Delaware"] = "dep",
["Pidgin Iha"] = "ihb",
["Pidgin Onin"] = "onx",
["Pijao"] = "pij",
["Pije"] = "piz",
["Tiếng Pijin"] = "pis",
["Pileni"] = "piv",
["Pima Bajo"] = "pia",
["Pimbwe"] = "piw",
["Pinai-Hagahai"] = "pnn",
["Pingelapese"] = "pif",
["Pini"] = "pii",
["Pinigura"] = "pnv",
["Pinjarup"] = "pnj",
["Pinji"] = "pic",
["Pinotepa Nacional Mixtec"] = "mio",
["Pintiini"] = "pti",
["Pintupi-Luritja"] = "piu",
["Pirahã"] = "myp",
["Piratapuyo"] = "pir",
["Pirlatapa"] = "bxi",
["Piro"] = "pie",
["Pirriya"] = "xpa",
["Pisabo"] = "pig",
["Pisaflores Tepehua"] = "tpp",
["Piscataway"] = "psy",
["Pisidian"] = "xps",
["Pitcairn-Norfolk"] = "pih",
["Pite Sami"] = "sje",
["Piti"] = "pcn",
["Pitta-Pitta"] = "pit",
["Piu"] = "pix",
["Piya-Kwonci"] = "piy",
["Plains Indian Sign Language"] = "psd",
["Plains Miwok"] = "pmw",
["Plapo Krumen"] = "ktj",
["Playero"] = "gob",
["Pochuri Naga"] = "npo",
["Pochutec"] = "xpo",
["Podoko"] = "pbi",
["Pogali"] = "hkh",
["Pogolo"] = "poy",
["Poitevin-Saintongeais"] = "roa-poi",
["Pokangá"] = "pok",
["Poke"] = "pof",
["Pol"] = "pmm",
["Polish Sign Language"] = "pso",
["Polonombauk"] = "plb",
["Pom"] = "pmo",
["Ponam"] = "ncc",
["Pongu"] = "png",
["Ponyo"] = "npg",
["Poqomam"] = "poc",
["Poqomchi'"] = "poh",
["Porohanon"] = "prh",
["Port Sandwich"] = "psw",
["Port Sorell"] = "xpl",
["Port Vato"] = "ptv",
["Portuguese Sign Language"] = "psr",
["Potiguára"] = "pog",
["Poumei Naga"] = "pmx",
["Pouye"] = "bye",
["Powari"] = "pwr",
["Powhatan"] = "pim",
["Poyanáwa"] = "pyn",
["Tiếng Ireland nguyên thủy"] = "pgl",
["Principense"] = "pre",
["Proto-Amuesha-Chamicuro"] = "awd-amc-pro",
["Tiếng Tiểu Á nguyên thủy"] = "ine-ana-pro",
["Proto-Apachean"] = "apa-pro",
["Proto-Arawa"] = "auf-pro",
["Tiếng Armenia nguyên thủy"] = "hyx-pro",
["Proto-Arnhem"] = "aus-arn-pro",
["Proto-Atayalic"] = "map-ata-pro",
["Proto-Batak"] = "btk-pro",
["Tiếng Bongo-Bagirmi nguyên thủy"] = "csu-bba-pro",
["Proto-Boran"] = "sai-bor-pro",
["Proto-Bua"] = "alv-bua-pro",
["Proto-Bungku-Tolaki"] = "poz-btk-pro",
["Tiếng Miến nguyên thủy"] = "tbq-brm-pro",
["Proto-Caddoan"] = "cdd-pro",
["Proto-Cangin"] = "alv-cng-pro",
["Proto-Central Chadic"] = "cdc-cbm-pro",
["Proto-Central Indo-Aryan"] = "inc-cen-pro",
["Proto-Central Jê"] = "sai-cje-pro",
["Tiếng Trung New South Wales nguyên thủy"] = "aus-cww-pro",
["Tiếng Trung Sudan nguyên thủy"] = "csu-pro",
["Proto-Central Togo"] = "alv-gtm-pro",
["Proto-Chatino"] = "omq-cha-pro",
["Proto-Chibchan"] = "cba-pro",
["Proto-Chimakuan"] = "chi-pro",
["Proto-Chinookan"] = "nai-ckn-pro",
["Tiếng Chukotka-Kamchatka nguyên thủy"] = "qfa-cka-pro",
["Proto-Chumash"] = "nai-chu-pro",
["Proto-Cupan"] = "azc-cup-pro",
["Proto-Daju"] = "sdv-daj-pro",
["Proto-Daly"] = "aus-dal-pro",
["Proto-Eastern Jebel"] = "sdv-eje-pro",
["Proto-Eastern Oti-Volta"] = "nic-eov-pro",
["Proto-Fali"] = "alv-fli-pro",
["Proto-Grassfields"] = "nic-grf-pro",
["Proto-Great Andamanese"] = "qfa-adm-pro",
["Proto-Guang"] = "alv-gng-pro",
["Proto-Gur"] = "nic-gur-pro",
["Proto-Gurunsi"] = "nic-gns-pro",
["Proto-Halmahera-Cenderawasih"] = "poz-hce-pro",
["Proto-Heiban"] = "alv-hei-pro",
["Proto-Highland East Cushitic"] = "cus-hec-pro",
["Proto-Hmong"] = "hmn-pro",
["Proto-Hrusish"] = "sit-hrs-pro",
["Proto-Huitoto-Ocaina"] = "sai-hoc-pro",
["Proto-Hurro-Urartian"] = "qfa-hur-pro",
["Proto-Idomoid"] = "alv-ido-pro",
["Proto-Igboid"] = "alv-igb-pro",
["Proto-Ijoid"] = "ijo-pro",
["Tiếng Iwaidja nguyên thủy"] = "aus-wdj-pro",
["Proto-Jukunoid"] = "nic-jkn-pro",
["Proto-Kadu"] = "qfa-kad-pro",
["Proto-Kalamian"] = "phi-kal-pro",
["Proto-Kalapuyan"] = "nai-klp-pro",
["Proto-Kampa"] = "awd-kmp-pro",
["Proto-Kham"] = "sit-kha-pro",
["Proto-Khoe"] = "khi-kho-pro",
["Proto-Komisenian"] = "ira-kms-pro",
["Proto-Kru"] = "kro-pro",
["Proto-Kuliak"] = "ssa-klk-pro",
["Proto-Kurdish"] = "ku-pro",
["Proto-Kwa"] = "alv-kwa-pro",
["Proto-Lalo"] = "tbq-lal-pro",
["Proto-Lampungic"] = "poz-lgx-pro",
["Tiếng Lô Lô nguyên thủy"] = "tbq-lol-pro",
["Proto-Lower Cross River"] = "nic-lcr-pro",
["Proto-Luish"] = "sit-luu-pro",
["Proto-Maidun"] = "nai-mdu-pro",
["Proto-Mangbetu"] = "csu-maa-pro",
["Proto-Masa"] = "cdc-mas-pro",
["Proto-Mazatec"] = "omq-maz-pro",
["Proto-Medo-Parthian"] = "ira-mpr-pro",
["Proto-Mixe-Zoque"] = "nai-miz-pro",
["Proto-Mixtec"] = "omq-mxt-pro",
["Proto-Mumuye"] = "alv-mum-pro",
["Proto-Munji-Yidgha"] = "ira-mny-pro",
["Proto-Na-Dene"] = "xnd-pro",
["Proto-Nawiki"] = "awd-nwk-pro",
["Proto-Nilotic"] = "sdv-nil-pro",
["Proto-North Caucasian"] = "ccn-pro",
["Proto-North Halmahera"] = "paa-nha-pro",
["Proto-North Sarawak"] = "poz-swa-pro",
["Proto-Nubian"] = "nub-pro",
["Proto-Numic"] = "azc-num-pro",
["Proto-Nupoid"] = "alv-nup-pro",
["Proto-Nyima"] = "sdv-nyi-pro",
["Proto-Nyulnyulan"] = "aus-nyu-pro",
["Proto-Ogoni"] = "nic-ogo-pro",
["Proto-Ossetic"] = "os-pro",
["Proto-Oti-Volta"] = "nic-ovo-pro",
["Proto-Oto-Manguean"] = "omq-pro",
["Proto-Oto-Pamean"] = "omq-otp-pro",
["Proto-Otomi"] = "oto-otm-pro",
["Proto-Otomian"] = "oto-pro",
["Proto-Paresi-Waura"] = "awd-prw-pro",
["Proto-Plateau Penutian"] = "nai-plp-pro",
["Proto-Pomeranian"] = "zlw-pom-pro",
["Proto-Pomo"] = "nai-pom-pro",
["Proto-Saka"] = "xsc-sak-pro",
["Proto-Sanglechi-Ishkashimi"] = "ira-sgi-pro",
["Proto-Sara"] = "csu-sar-pro",
["Proto-Siouan-Catawban"] = "nai-sca-pro",
["Proto-Songhay"] = "son-pro",
["Proto-Sotho-Tswana"] = "bnt-sts-pro",
["Proto-South Cushitic"] = "cus-sou-pro",
["Proto-South Sulawesi"] = "poz-ssw-pro",
["Proto-Southern Jê"] = "sai-sje-pro",
["Proto-Sunda-Sulawesi"] = "poz-sus-pro",
["Proto-Ta-Arawak"] = "awd-taa-pro",
["Proto-Takic"] = "azc-tak-pro",
["Proto-Taman"] = "sdv-tmn-pro",
["Proto-Tani"] = "sit-tan-pro",
["Proto-Taranoan"] = "sai-tar-pro",
["Proto-Tatic"] = "xme-ttc-pro",
["Proto-Totozoquean"] = "nai-tot-pro",
["Tiếng Liên New Guinea nguyên thủy"] = "ngf-pro",
["Proto-Tsezian"] = "cau-tsz-pro",
["Proto-Tsimshianic"] = "nai-tsi-pro",
["Proto-Upper Cross River"] = "nic-ucr-pro",
["Proto-Utian"] = "nai-utn-pro",
["Proto-Western Mande"] = "dmn-mdw-pro",
["Proto-Witotoan"] = "sai-wit-pro",
["Proto-Yupik"] = "ypk-pro",
["Proto-Zapotecan"] = "omq-zap-pro",
["Providencia Sign Language"] = "prz",
["Psikye"] = "kvj",
["Puare"] = "pux",
["Pudtol Atta"] = "atp",
["Puebla Mazatec"] = "pbm",
["Puelche"] = "pue",
["Puerto Rican Sign Language"] = "psl",
["Puimei Naga"] = "npu",
["Puiron"] = "sit-prn",
["Pukapukan"] = "pkp",
["Pulabu"] = "pup",
["Puluwat"] = "puw",
["Puma"] = "pum",
["Pumé"] = "yae",
["Punan Aput"] = "pud",
["Punan Bah-Biau"] = "pna",
["Punan Batu"] = "pnm",
["Punan Merah"] = "puf",
["Punan Merap"] = "puc",
["Punan Tubu"] = "puj",
["Punu"] = "puu",
["Puquina"] = "puq",
["Puragi"] = "pru",
["Purari"] = "iar",
["Purepecha"] = "pua",
["Puri"] = "prr",
["Purik"] = "prx",
["Purisimeño"] = "puy",
["Puruborá"] = "pur",
["Puruhá"] = "sai-prh",
["Purukotó"] = "sai-pur",
["Purum"] = "pub",
["Putai"] = "mfl",
["Putoh"] = "put",
["Putukwam"] = "afe",
["Puyo-Paekche"] = "xpp",
["Pwaamei"] = "pme",
["Pwapwa"] = "pop",
["Pyapun"] = "pcw",
["Pye Krumen"] = "pye",
["Pyemmairre"] = "xpb",
["Pyen"] = "pyy",
["Pykobjê"] = "sai-pyk",
["Pyu"] = "pby",
["Páez"] = "pbb",
["Pááfang"] = "pfa",
["Päri"] = "lkr",
["Pémono"] = "pev",
["Pévé"] = "lme",
["Pökoot"] = "pko",
["Q'anjob'al"] = "kjb",
["Q'eqchi"] = "kek",
["Qabiao"] = "laq",
["Qaqet"] = "byx",
["Qatabanian"] = "xqt",
["Qau"] = "gqu",
["Qila Muji"] = "ymq",
["Quebec Sign Language"] = "fcs",
["Querétaro Otomi"] = "otq",
["Quetzaltepec Mixe"] = "pxm",
["Queyu"] = "qvy",
["Quiavicuzas Zapotec"] = "zpj",
["Quileute"] = "qui",
["Quimbaya"] = "sai-qmb",
["Quinigua"] = "nai-qng",
["Quinqui"] = "quq",
["Quioquitani-Quierí Zapotec"] = "ztq",
["Quiotepec Chinantec"] = "chq",
["Quitemo"] = "sai-qtm",
["Rabona"] = "sai-rab",
["Rahambuu"] = "raz",
["Rajah Kabunsuwan Manobo"] = "mqk",
["Raji"] = "rji",
["Rajong"] = "rjg",
["Rakahanga-Manihiki"] = "rkh",
["Ralte"] = "ral",
["Ramandi"] = "tks",
["Ramanos"] = "sai-ram",
["Ramoaaina"] = "rai",
["Ramopa"] = "kjx",
["Rampi"] = "lje",
["Rana Tharu"] = "thr",
["Rang"] = "rax",
["Rangkas"] = "rgk",
["Ranglong"] = "rnl",
["Rao"] = "rao",
["Rapa"] = "ray",
["Rapoisi"] = "kyx",
["Rapting"] = "rpt",
["Rara Bakati'"] = "lra",
["Ratahan"] = "rth",
["Rathawi"] = "rtw",
["Rathwi Bareli"] = "bgd",
["Rawa"] = "rwo",
["Rawat"] = "jnl",
["Rawo"] = "rwa",
["Rayón Zoque"] = "zor",
["Razajerdi"] = "rat",
["Razihi"] = "rzh",
["Reang"] = "ria",
["Red Gelao"] = "gir",
["Reel"] = "atu",
["Rejang Kayan"] = "ree",
["Rema"] = "bow",
["Rembarunga"] = "rmb",
["Rembong"] = "reb",
["Remo"] = "rem",
["Remontado Agta"] = "agv",
["Rempi"] = "rmp",
["Remun"] = "lkj",
["Rennellese"] = "mnv",
["Repanbitip"] = "rpn",
["Rer Bare"] = "rer",
["Rerau"] = "rea",
["Rerep"] = "pgk",
["Reshe"] = "res",
["Resígaro"] = "rgr",
["Retta"] = "ret",
["Reyesano"] = "rey",
["Rhine Franconian"] = "gmw-rfr",
["Riang"] = "ril",
["Riantana"] = "ran",
["Ribun"] = "rir",
["Rigwe"] = "iri",
["Rikbaktsa"] = "rkb",
["Ringgou"] = "rgu",
["Ririo"] = "rri",
["Ritarungo"] = "rit",
["Riung"] = "riu",
["Riverain Sango"] = "snj",
["Rogo"] = "rod",
["Roma"] = "rmm",
["Romani Greek"] = "rge",
["Romanian Sign Language"] = "rms",
["Romano-Serbian"] = "rsb",
["Romanova"] = "rmv",
["Romblomanon"] = "rol",
["Rombo"] = "rof",
["Romkun"] = "rmk",
["Ron"] = "cla",
["Ronga"] = "rng",
["Rongga"] = "ror",
["Rongmei Naga"] = "nbu",
["Rongpo"] = "rnp",
["Ronji"] = "roe",
["Roon"] = "rnn",
["Roria"] = "rga",
["Roro"] = "rro",
["Rotokas"] = "roo",
["Roviana"] = "rug",
["Rudbari"] = "rdb",
["Rufiji"] = "rui",
["Ruga"] = "ruh",
["Rukiga"] = "cgg",
["Ruma"] = "ruz",
["Rumu"] = "klq",
["Runga"] = "rou",
["Rungtu"] = "rtc",
["Rungwa"] = "rnw",
["Russenorsk"] = "crp-rsn",
["Russian Sign Language"] = "rsl",
["Ruuli"] = "ruc",
["Ruwund"] = "rnd",
["Rwa"] = "rwk",
["Rwanda-Rundi"] = "rw",
["Sa"] = "sax",
["Sa'a"] = "apb",
["Sa'ban"] = "snv",
["Sa'och"] = "scq",
["Saafi-Saafi"] = "sav",
["Saam"] = "raq",
["Saamia"] = "lsm",
["Saare"] = "uss",
["Sabah Malay"] = "msi",
["Sabanê"] = "sae",
["Sabaot"] = "spy",
["Sabine"] = "sbv",
["Sabir"] = "pml",
["Sabu"] = "hvn",
["Sacapulteco"] = "quv",
["Saep"] = "spd",
["Safaitic"] = "sem-saf",
["Safaliba"] = "saf",
["Safeyoka"] = "apz",
["Safwa"] = "sbk",
["Sagala"] = "sbm",
["Sagalla"] = "tga",
["Sahaptin"] = "nai-spt",
["Sahu"] = "saj",
["Sajau Basap"] = "sjb",
["Sakachep"] = "sch",
["Sakam"] = "skm",
["Sakao"] = "sku",
["Sakata"] = "skt",
["Sake"] = "sak",
["Sala"] = "shq",
["Salampasu"] = "slx",
["Salas"] = "sgu",
["Salchuq"] = "slq",
["Saleman"] = "sau",
["Saliba (Colombia)"] = "slc",
["Saliba (New Guinea)"] = "sbe",
["Salinan"] = "sln",
["Salt-Yui"] = "sll",
["Saluan"] = "loe",
["Salumá"] = "slj",
["Salvadoran Lenca"] = "nai-sln",
["Salvadoran Sign Language"] = "esn",
["Sam"] = "snx",
["Sama"] = "smd",
["Samaritan Aramaic"] = "sam",
["Samaritan Hebrew"] = "smp",
["Samarokena"] = "tmj",
["Samatao"] = "ysd",
["Samba"] = "smx",
["Sambe"] = "xab",
["Samberigi"] = "ssx",
["Samburu"] = "saq",
["Samoan Plantation Pidgin"] = "cpe-spp",
["Samosa"] = "swm",
["Sampang"] = "rav",
["Samre"] = "sxm",
["Samvedi"] = "smv",
["San Agustín Mixtepec Zapotec"] = "ztm",
["San Baltazar Loxicha Zapotec"] = "zpx",
["San Felipe Otlaltepec Popoloca"] = "pow",
["San Jerónimo Tecóatl Mazatec"] = "maa",
["San Juan Atzingo Popoloca"] = "poe",
["San Juan Colorado Mixtec"] = "mjc",
["San Juan Quiahije Chatino"] = "ctp-san",
["San Juan Teita Mixtec"] = "xtj",
["San Luís Temalacayuca Popoloca"] = "pps",
["San Marcos Tlalcoyalco Popoloca"] = "pls",
["San Miguel Creole French"] = "scf",
["San Miguel Piedras Mixtec"] = "xtp",
["San Miguel el Grande Mixtec"] = "mig",
["San Pablo Güilá Zapotec"] = "ztu",
["San Pedro Amuzgos Amuzgo"] = "azg",
["San Pedro Quiatoni Zapotec"] = "zpf",
["San Vicente Coatlán Zapotec"] = "zpt",
["Sanapaná"] = "spn",
["Sanaviron"] = "sai-san",
["Sandawe"] = "sad",
["Sanga (Congo)"] = "sng",
["Sanga (Nigeria)"] = "xsn",
["Sanggau"] = "scg",
["Sangil"] = "snl",
["Sangkong"] = "sgk",
["Sanglechi"] = "sgy",
["Sangtam Naga"] = "nsa",
["Sangu (Gabon)"] = "snq",
["Sangu (Tanzania)"] = "sbp",
["Sani"] = "ysn",
["Sanie"] = "ysy",
["Saniyo-Hiyewe"] = "sny",
["Sankaran Maninka"] = "msc",
["Sansi"] = "ssi",
["Santa Catarina Albarradas Zapotec"] = "ztn",
["Santa Inés Ahuatempan Popoloca"] = "pca",
["Santa Inés Yatzechi Zapotec"] = "zpn",
["Santa Lucía Monteverde Mixtec"] = "mdv",
["Santa María La Alta Nahuatl"] = "nhz",
["Santa María Quiegolani Zapotec"] = "zpi",
["Santa María Zacatepec Mixtec"] = "mza",
["Santa Teresa Cora"] = "cok",
["Santiago Xanica Zapotec"] = "zpr",
["Santo Domingo Albarradas Zapotec"] = "zas",
["Sanumá"] = "xsu",
["Saparua"] = "spr",
["Sapará"] = "sai-sap",
["Sapo"] = "krn",
["Saponi"] = "spi",
["Sapuan"] = "spu",
["Sapé"] = "spc",
["Sar"] = "mwm",
["Sara"] = "sre",
["Sara Kaba"] = "sbz",
["Sara Kaba Deme"] = "kwg",
["Sara Kaba Náà"] = "kwv",
["Sarangani Blaan"] = "bps",
["Sarangani Manobo"] = "mbs",
["Sarasira"] = "zsa",
["Saraveca"] = "sar",
["Sarli"] = "sdf",
["Sartang"] = "onp",
["Sarua"] = "swy",
["Sarudu"] = "sdu",
["Saruga"] = "sra",
["Sasaru"] = "sxs",
["Tiếng Sassari"] = "sdc",
["Satawalese"] = "stw",
["Sateré-Mawé"] = "mav",
["Sathmar Swabian"] = "gmw-stm",
["Saudi Arabian Sign Language"] = "sdl",
["Sauraseni Apabhramsa"] = "inc-sap",
["Sauri"] = "srt",
["Sause"] = "sao",
["Sausi"] = "ssj",
["Tiếng Savosavo"] = "svs",
["Sawai"] = "szw",
["Saweru"] = "swr",
["Sawi"] = "saw",
["Sawila"] = "swt",
["Saya"] = "say",
["Sayula Popoluca"] = "pos",
["Scanian"] = "gmq-scy",
["Seba"] = "kdg",
["Seberuang"] = "sbx",
["Sebop"] = "sib",
["Sebuyau"] = "snb",
["Sechura"] = "sai-sec",
["Secoya"] = "sey",
["Sedoa"] = "tvw",
["Seenku"] = "sos",
["Segai"] = "sge",
["Segeju"] = "seg",
["Seget"] = "sbg",
["Sehwi"] = "sfw",
["Seim"] = "sim",
["Seimat"] = "ssg",
["Seit-Kaitetu"] = "hik",
["Sekani"] = "sek",
["Sekapan"] = "skp",
["Sekar"] = "skz",
["Seke"] = "skj",
["Sekele"] = "vaj",
["Seki"] = "syi",
["Seko Padang"] = "skx",
["Seko Tengah"] = "sko",
["Sekpele"] = "lip",
["Selangor Sign Language"] = "kgi",
["Selaru"] = "slu",
["Selayar"] = "sly",
["Selee"] = "snw",
["Selepet"] = "spl",
["Selk'nam"] = "ona",
["Selonian"] = "sxl",
["Selungai Murut"] = "slg",
["Seluwasan"] = "sws",
["Sema"] = "nsm",
["Semandang"] = "sdm",
["Sembakung Murut"] = "sbr",
["Semimi"] = "etz",
["Semnani"] = "smy",
["Sempan"] = "xse",
["Senara Sénoufo"] = "seq",
["Senaya"] = "syn",
["Sene"] = "sej",
["Sengele"] = "szg",
["Senggi"] = "snu",
["Sengo"] = "spk",
["Sengseng"] = "ssz",
["Sensi"] = "sni",
["Sentani"] = "set",
["Senthang Chin"] = "sez",
["Sentinelese"] = "std",
["Sepa (Indonesia)"] = "spb",
["Sepa (New Guinea)"] = "spe",
["Sepen"] = "spm",
["Sepik Iwam"] = "iws",
["Sepik Mari"] = "mbx",
["Sera"] = "sry",
["Sere"] = "swf",
["Serili"] = "sve",
["Seroa"] = "kqu",
["Serrano"] = "ser",
["Seru"] = "szd",
["Serua"] = "srw",
["Serudung Murut"] = "srk",
["Serui-Laut"] = "seu",
["Seta"] = "stf",
["Setaman"] = "stm",
["Seti"] = "sbi",
["Sewa Bay"] = "sew",
["Seychellois Creole"] = "crs",
["Sha"] = "scw",
["Shahmirzadi"] = "srz",
["Shahrudi"] = "shm",
["Shall-Zwall"] = "sha",
["Shama-Sambuga"] = "sqa",
["Shamang"] = "xsh",
["Shambala"] = "ksb",
["Shanenawa"] = "swo",
["Shanga"] = "sho",
["Shangzhai"] = "jih",
["Shaozhou Tuhua"] = "zhx-sht",
["Sharanahua"] = "mcd",
["Shark Bay"] = "ssv",
["Sharwa"] = "swq",
["Shasta"] = "sht",
["Shatt"] = "shj",
["Shau"] = "sqh",
["Shawnee"] = "sjw",
["Tiếng Xa"] = "shx",
["Shehri"] = "shv",
["Sheko"] = "she",
["Shelta"] = "sth",
["Shendu"] = "shl",
["Sheni"] = "scv",
["Sherbro"] = "bun",
["Sherdukpen"] = "sdp",
["Shi"] = "shr",
["Shihhi Arabic"] = "ssh",
["Shiki"] = "gua",
["Shilluk"] = "shk",
["Shipibo-Conibo"] = "shp",
["Shixing"] = "sxg",
["Shoo-Minda-Nye"] = "bcv",
["Shoshone"] = "shh",
["Shua"] = "shg",
["Shuar"] = "jiv",
["Shuba"] = "cbq",
["Shumashti"] = "sts",
["Shumcho"] = "scu",
["Shuwa-Zamani"] = "ksa",
["Shwai"] = "shw",
["Sialum"] = "slw",
["Siamou"] = "sif",
["Sian"] = "spg",
["Siane"] = "snp",
["Siang"] = "sya",
["Siar-Lak"] = "sjr",
["Sibe"] = "nco",
["Sibu Melanau"] = "sdx",
["Sicanian"] = "sxc",
["Siculo-Arabic"] = "sqr",
["Sidetic"] = "xsd",
["Sie"] = "erg",
["Sierra Leone Sign Language"] = "sgx",
["Sierra Negra Nahuatl"] = "nsu",
["Sierra de Juárez Zapotec"] = "zaa",
["Sighu"] = "sxe",
["Sihan"] = "snr",
["Sika"] = "ski",
["Sikaiana"] = "sky",
["Sikaritai"] = "tty",
["Sikiana"] = "sik",
["Sikule"] = "skh",
["Sila"] = "slt",
["Silacayoapan Mixtec"] = "mks",
["Sileibi"] = "sbq",
["Silimo"] = "wul",
["Siliput"] = "mkc",
["Silopi"] = "xsp",
["Simaa"] = "sie",
["Simba"] = "sbw",
["Simbali"] = "smg",
["Simbari"] = "smb",
["Simbo"] = "sbb",
["Simeku"] = "smz",
["Simeulue"] = "smr",
["Simte"] = "smt",
["Sinacantán"] = "nai-sin",
["Sinagen"] = "siu",
["Sinasina"] = "sst",
["Sindarin"] = "sjn",
["Sindhi Bhil"] = "sbn",
["Sindihui Mixtec"] = "xts",
["Singa"] = "sgm",
["Singapore Sign Language"] = "sls",
["Singpho"] = "sgp",
["Sinicahua Mixtec"] = "xti",
["Sininkere"] = "skq",
["Sinte Romani"] = "rmo",
["Sinyar"] = "sys",
["Sinúfana"] = "sai-sin",
["Sio"] = "xsi",
["Siona"] = "snn",
["Sipakapense"] = "qum",
["Sira"] = "swj",
["Siri"] = "sir",
["Siriano"] = "sri",
["Sirionó"] = "srq",
["Siroi"] = "ssd",
["Siuslaw"] = "sis",
["Sivandi"] = "siy",
["Siwai"] = "siw",
["Siyin Chin"] = "csy",
["Skagit"] = "ska",
["Skalvian"] = "svx",
["Ske"] = "ske",
["Skou"] = "skv",
["Slavomolisano"] = "svm",
["Slovakian Sign Language"] = "svk",
["Small Flowery Miao"] = "sfm",
["Smärky Kanum"] = "kxq",
["Snohomish"] = "sno",
["So'a"] = "ssq",
["Sobei"] = "sob",
["Sochiapam Chinantec"] = "cso",
["Soga"] = "xog",
["Sok"] = "skk",
["Soko"] = "soc",
["Sokoro"] = "sok",
["Solano"] = "xso",
["Soli"] = "sby",
["Solos"] = "sol",
["Som"] = "smc",
["Somba-Siawari"] = "bmu",
["Somra"] = "ntx",
["Somrai"] = "sor",
["Somray"] = "smu",
["Somyev"] = "kgt",
["Sonaga"] = "ysg",
["Sonde"] = "shc",
["Songe"] = "sop",
["Songomeno"] = "soe",
["Songoora"] = "sod",
["Sonha"] = "soi",
["Sonia"] = "siq",
["Soo"] = "teu",
["Sop"] = "urw",
["Sori-Harengan"] = "sbh",
["Sorkhei"] = "sqo",
["Sorothaptic"] = "sxo",
["Sorsogon Ayta"] = "ays",
["Sos Kundi"] = "sdk",
["Sota Kanum"] = "krz",
["Sou"] = "sqq",
["South African Sign Language"] = "sfs",
["South Awyu"] = "aws",
["South Boma"] = "bnt-sbo",
["Tiếng Banda Trung Nam"] = "lnl",
["South Central Dinka"] = "dib",
["South Fali"] = "fal",
["South Giziga"] = "giz",
["South Lembata"] = "lmf",
["South Muyu"] = "kts",
["South Nuaulu"] = "nxl",
["South Tairora"] = "omw",
["South Ucayali Ashéninka"] = "cpy",
["South Watut"] = "mcy",
["Southeast Ambrym"] = "tvk",
["Southeast Babar"] = "vbb",
["Southeast Ijo"] = "ijs",
["Southeast Pashayi"] = "psi",
["Southeast Tasmanian"] = "xpf",
["Southeastern Dinka"] = "dks",
["Southeastern Ixtlán Zapotec"] = "zpd",
["Southeastern Nochixtlán Mixtec"] = "mxy",
["Southeastern Pomo"] = "pom",
["Southeastern Puebla Nahuatl"] = "npl",
["Southeastern Tarahumara"] = "tcu",
["Southern Alta"] = "agy",
["Southern Birifor"] = "biv",
["Southern Bobo"] = "bwq",
["Southern Bontoc"] = "obk",
["Southern Catanduanes Bicolano"] = "bln",
["Southern Dagaare"] = "dga",
["Southern Ghale"] = "ghe",
["Southern Grebo"] = "grj",
["Southern Guiyang Hmong"] = "hmy",
["Southern Haida"] = "hax",
["Southern Hindko"] = "hnd",
["Southern Kalapuya"] = "sxk",
["Southern Kalinga"] = "ksc",
["Southern Khanty"] = "kca-sou",
["Tiếng Kissi Nam"] = "kss",
["Southern Kiwai"] = "kjd",
["Tiếng Xwarin"] = "sdh",
["Southern Lolopo"] = "ysp",
["Southern Lorung"] = "lrr",
["Southern Ma'di"] = "snm",
["Southern Mashan Hmong"] = "hma",
["Southern Muji"] = "ymc",
["Southern Ngbandi"] = "nbw",
["Southern Nisu"] = "nsd",
["Southern Nuni"] = "nnw",
["Southern Ohlone"] = "css",
["Southern One"] = "osu",
["Southern Pame"] = "pmz",
["Southern Pinghua"] = "csp",
["Southern Pomo"] = "peq",
["Southern Puebla Mixtec"] = "mit",
["Southern Puget Sound Salish"] = "slh",
["Southern Pumi"] = "pmj",
["Southern Qiandong Miao"] = "hms",
["Southern Rengma Naga"] = "nre",
["Southern Sama"] = "ssb",
["Southern Sierra Miwok"] = "skd",
["Southern Tidong"] = "itd",
["Southern Tiwa"] = "tix",
["Southern Toussian"] = "wib",
["Southern Tutchone"] = "tce",
["Southern Valley Yokuts"] = "nai-svy",
["Southwest Gbaya"] = "gso",
["Southwest Palawano"] = "plv",
["Southwest Pashayi"] = "psh",
["Southwest Tanna"] = "nwi",
["Southwestern Bontoc"] = "vbk",
["Southwestern Dinka"] = "dik",
["Southwestern Fars"] = "fay",
["Southwestern Guiyang Hmong"] = "hmg",
["Southwestern Huishui Hmong"] = "hmh",
["Southwestern Nisu"] = "nsv",
["Southwestern Tamang"] = "tsf",
["Southwestern Tarahumara"] = "twr",
["Southwestern Tepehuan"] = "tla",
["Southwestern Tlaxiaco Mixtec"] = "meh",
["Sowa"] = "sww",
["Sowanda"] = "sow",
["Soyaltepec Mazatec"] = "vmp",
["Soyaltepec Mixtec"] = "vmq",
["Spanish Sign Language"] = "ssp",
["Spiti Bhoti"] = "spt",
["Spokane"] = "spo",
["Sri Lankan Creole Malay"] = "sci",
["Sri Lankan Sign Language"] = "sqs",
["Stod Bhoti"] = "sbu",
["Stoney"] = "sto",
["Suabo"] = "szp",
["Suarmin"] = "seo",
["Suau"] = "swp",
["Suba"] = "sxb",
["Suba-Simbiti"] = "ssc",
["Subi"] = "xsj",
["Subiya"] = "sbs",
["Subtiaba"] = "sut",
["Sudest"] = "tgo",
["Sudovian"] = "xsv",
["Suena"] = "sue",
["Suga"] = "sgi",
["Suganga"] = "sug",
["Sugut Dusun"] = "kzs",
["Suki"] = "sui",
["Suku"] = "sub",
["Sukuma"] = "suk",
["Sukur"] = "syk",
["Sukurum"] = "zsu",
["Sula"] = "szn",
["Sulka"] = "sua",
["Sulod"] = "srg",
["Suma"] = "sqm",
["Sumariup"] = "siv",
["Sumau"] = "six",
["Tiếng Sumbawa"] = "smw",
["Sumbwa"] = "suw",
["Sumtu Chin"] = "csv",
["Sunam"] = "ssk",
["Sunum"] = "ymn",
["Sunwar"] = "suz",
["Suoy"] = "syo",
["Supyire"] = "spp",
["Sur"] = "tdl",
["Surbakhal"] = "sbj",
["Surigaonon"] = "sgd",
["Sursurunga"] = "sgz",
["Suruahá"] = "swx",
["Surubu"] = "sde",
["Suruí"] = "sru",
["Suruí Do Pará"] = "mdz",
["Susquehannock"] = "sqn",
["Susuami"] = "ssu",
["Suundi"] = "sdj",
["Suwawa"] = "swu",
["Suyá"] = "suy",
["Swabian"] = "swg",
["Swampy Cree"] = "csw",
["Swedish Sign Language"] = "swl",
["Swiss-French Sign Language"] = "ssr",
["Swiss-German Sign Language"] = "sgg",
["Swiss-Italian Sign Language"] = "slf",
["Swo"] = "sox",
["Syenara Senoufo"] = "shz",
["Sácata"] = "sai-sac",
["São Paulo Kaingáng"] = "zkp",
["Sãotomense"] = "cri",
["Sìcìté Sénoufo"] = "sep",
["T'en"] = "tct",
["Tabaa Zapotec"] = "zat",
["Tabancale"] = "sai-tab",
["Tabaru"] = "tby",
["Tabasco Chontal"] = "chf",
["Tabasco Nahuatl"] = "nhc",
["Tabasco Zoque"] = "zoq",
["Tabla"] = "tnm",
["Tabo"] = "knv",
["Tabriak"] = "tzx",
["Tacahua Mixtec"] = "xtt",
["Tacana"] = "tna",
["Tadaksahak"] = "dsq",
["Tae'"] = "rob",
["Tafreshi"] = "xme-taf",
["Tagabawa"] = "bgs",
["Tagakaulu Kalagan"] = "klg",
["Tagbanwa"] = "tbw",
["Tagbu"] = "tbm",
["Tagish"] = "tgx",
["Tagwana Senoufo"] = "tgw",
["Tai"] = "taw",
["Tai Hang Tong"] = "thc",
["Tai Hongjin"] = "tiz",
["Tai Long"] = "thi",
["Tai Thanh"] = "tmm",
["Tai Ya"] = "cuu",
["Taiap"] = "gpn",
["Taikat"] = "aos",
["Tainae"] = "ago",
["Tairuma"] = "uar",
["Taita"] = "dav",
["Taiwan Sign Language"] = "tss",
["Taje"] = "pee",
["Tiếng Tajio"] = "tdj",
["Tajuasohn"] = "tja",
["Takelma"] = "tkm",
["Takia"] = "tbc",
["Takka Apabhramsa"] = "inc-tak",
["Takua"] = "tkz",
["Takuu"] = "nho",
["Takwane"] = "tke",
["Talaud"] = "tld",
["Taliabu"] = "tlv",
["Talieng"] = "tdf",
["Talinga-Bwisi"] = "tlj",
["Talise"] = "tlr",
["Tallán"] = "sai-tal",
["Talodi"] = "tlo",
["Taloki"] = "tlk",
["Talondo'"] = "tln",
["Talu"] = "yta",
["Tama (Chad)"] = "tma",
["Tama (Colombia)"] = "ten",
["Tamagario"] = "tcg",
["Tamambo"] = "mla",
["Taman (Indonesia)"] = "tmn",
["Taman (Myanmar)"] = "tcl",
["Tamanaku"] = "tmz",
["Tamazola Mixtec"] = "vmx",
["Tambas"] = "tdk",
["Tambora"] = "xxt",
["Tambotalo"] = "tls",
["Tambunan Dusun"] = "kzt",
["Tami"] = "tmy",
["Tamnim Citak"] = "tml",
["Tampias Lobu"] = "low",
["Tampulma"] = "tpm",
["Tanacross"] = "tcb",
["Tanahmerah"] = "tcm",
["Tanapag"] = "tpv",
["Tandaganon"] = "tgn",
["Tandia"] = "tni",
["Tanema"] = "tnx",
["Tangale"] = "tan",
["Tangam"] = "sit-tgm",
["Tanggu"] = "tgu",
["Tangko"] = "tkx",
["Tangsa"] = "nst",
["Tanguat"] = "tbs",
["Tiếng Tanimuca-Retuarã"] = "tnc",
["Tanjijili"] = "uji",
["Tanudan Kalinga"] = "kml",
["Tanzanian Sign Language"] = "tza",
["Tapachultec"] = "nai-tap",
["Taparita"] = "sai-tpr",
["Tapayuna"] = "sai-tap",
["Tapeba"] = "tbb",
["Tapei"] = "afp",
["Tapieté"] = "tpj",
["Tar Gula"] = "kcm",
["Tarairiú"] = "sai-trr",
["Tarao"] = "tro",
["Taraon"] = "mhu",
["Tareng"] = "tgr",
["Tarjumo"] = "txj",
["Tarok"] = "yer",
["Tarpia"] = "tpf",
["Tartessian"] = "txr",
["Taruma"] = "tdm",
["Tasmate"] = "tmt",
["Tataltepec Chatino"] = "cta",
["Tatana"] = "txx",
["Tataviam"] = "azc-tat",
["Tauade"] = "ttd",
["Taulil"] = "tuh",
["Taupota"] = "tpa",
["Taushiro"] = "trr",
["Tauya"] = "tya",
["Taveta"] = "tvs",
["Tawala"] = "tbo",
["Tawandê"] = "xtw",
["Tawang Monpa"] = "twm",
["Tawasa"] = "nai-taw",
["Taworta"] = "tbp",
["Tawoyan"] = "twy",
["Tawr Chin"] = "tcp",
["Tay Khang"] = "tnu",
["Tayabas Ayta"] = "ayy",
["Tayo"] = "cks",
["Tboli"] = "tbl",
["Tchitchege"] = "tck",
["Tchumbuli"] = "bqa",
["Te'un"] = "tve",
["Teanu"] = "tkw",
["Tebul Sign Language"] = "tsy",
["Tebul Ure Dogon"] = "dtu",
["Tecpatlán Totonac"] = "tcw",
["Tedaga"] = "tuq",
["Tee"] = "tkq",
["Tefaro"] = "tfo",
["Tegali"] = "ras",
["Tehit"] = "kps",
["Tehuelche"] = "teh",
["Teiwa"] = "twe",
["Tejalapan Zapotec"] = "ztt",
["Teke-Fuumu"] = "ifm",
["Teke-Kukuya"] = "kkw",
["Teke-Laali"] = "lli",
["Teke-Tege"] = "teg",
["Teke-Tsaayi"] = "tyi",
["Teke-Tyee"] = "tyx",
["Tektiteko"] = "ttc",
["Tela-Masbuar"] = "tvm",
["Telefol"] = "tlf",
["Teluti"] = "tlt",
["Tembé"] = "tqb",
["Teme"] = "tdo",
["Temein"] = "teq",
["Temi"] = "soz",
["Temne"] = "tem",
["Temoaya Otomi"] = "ott",
["Tempasuk Dusun"] = "tdu",
["Tenango Otomi"] = "otn",
["Tene Kan Dogon"] = "dtk",
["Tenggarong Kutai Malay"] = "vkt",
["Tenino"] = "tqn",
["Tenis"] = "tns",
["Tennet"] = "tex",
["Teojomulco Chatino"] = "omq-teo",
["Teop"] = "tio",
["Teor"] = "tev",
["Tepecano"] = "tep",
["Tepetotutla Chinantec"] = "cnt",
["Tepeuxila Cuicatec"] = "cux",
["Tepo Krumen"] = "ted",
["Tiếng Mixtec Teposcolula"] = "omq-tel",
["Tequistlatec"] = "nai-teq",
["Tera"] = "ttr",
["Terebu"] = "trb",
["Terei"] = "buo",
["Tereno"] = "ter",
["Tereweng"] = "twg",
["Terik"] = "tec",
["Termanu"] = "twu",
["Ternateño"] = "tmg",
["Tese"] = "keg",
["Teshenawa"] = "twc",
["Tetela"] = "tll",
["Tetelcingo Nahuatl"] = "nhg",
["Tetete"] = "teb",
["Tetun Dili"] = "tdt",
["Teushen"] = "sai-teu",
["Teutila Cuicatec"] = "cut",
["Tewa"] = "tew",
["Texcatepec Otomi"] = "otx",
["Texistepec Popoluca"] = "poq",
["Texmelucan Zapotec"] = "zpz",
["Tezoatlán Mixtec"] = "mxb",
["Tha"] = "thy",
["Thado Chin"] = "tcz",
["Thai Sign Language"] = "tsq",
["Thaiphum Chin"] = "cth",
["Thakali"] = "ths",
["Thamudic"] = "sem-tha",
["Thangmi"] = "thf",
["Thao"] = "ssf",
["Tharaka"] = "thk",
["Tharrgari"] = "dhr",
["Thawa"] = "xtv",
["Thopho"] = "ytp",
["Thu Lao"] = "tyl",
["Thulung"] = "tdh",
["Thurawal"] = "tbh",
["Thuri"] = "thu",
["Tiagbamrin Aizi"] = "ahi",
["Tiale"] = "mnl",
["Tibea"] = "ngy",
["Ticuna"] = "tca",
["Tidaá Mixtec"] = "mtx",
["Tidore"] = "tvo",
["Tiemacèwè Bozo"] = "boo",
["Tiene"] = "tii",
["Tifal"] = "tif",
["Tigak"] = "tgc",
["Tii"] = "txq",
["Tijaltepec Mixtec"] = "xtl",
["Tikar"] = "tik",
["Tikopia"] = "tkp",
["Tilapa Otomi"] = "otl",
["Tillamook"] = "til",
["Tilquiapan Zapotec"] = "zts",
["Tilung"] = "tij",
["Tima"] = "tms",
["Timbe"] = "tim",
["Timor Pidgin"] = "tvy",
["Timote"] = "sai-tim",
["Timucua"] = "tjm",
["Timugon Murut"] = "tih",
["Tinani"] = "lbf",
["Tingui-Boto"] = "tgv",
["Tinigua"] = "tit",
["Tinoc Kallahan"] = "tne",
["Tinputz"] = "tpz",
["Tira"] = "tic",
["Tirahi"] = "tra",
["Tiranige Diga Dogon"] = "tde",
["Tircul"] = "pyx",
["Tiri"] = "cir",
["Tita"] = "tdq",
["Titan"] = "ttv",
["Tiv"] = "tiv",
["Tiéfo"] = "tiq",
["Tiéyaxo Bozo"] = "boz",
["Tjurruru"] = "tju",
["Tlacoatzintepec Chinantec"] = "ctl",
["Tlacolulita Zapotec"] = "zpk",
["Tlahuica"] = "ocu",
["Tlahuitoltepec Mixe"] = "mxp",
["Tlamacazapa Nahuatl"] = "nuz",
["Tlazoyaltepec Mixtec"] = "mqh",
["To"] = "toz",
["To'abaita"] = "mlu",
["Toaripi"] = "tqo",
["Toba"] = "tob",
["Toba Batak"] = "bbc",
["Toba-Maskoy"] = "tmf",
["Tobagonian Creole English"] = "tgh",
["Tobanga"] = "tng",
["Tobati"] = "tti",
["Tobelo"] = "tlb",
["Tobilung"] = "tgb",
["Tobo"] = "tbv",
["Tocantins Asurini"] = "asu",
["Tofanma"] = "tlg",
["Tofin Gbe"] = "tfi",
["Togbo-Vara Banda"] = "tor",
["Togoyo"] = "tgy",
["Tojolabal"] = "toj",
["Toka-Leya"] = "dov",
["Tokano"] = "zuh",
["Tol"] = "jic",
["Tolai"] = "ksd",
["Tolaki"] = "lbw",
["Tolomako"] = "tlm",
["Tolowa"] = "tol",
["Toloza"] = "ytl",
["Tomadino"] = "tdi",
["Tombelala"] = "ttp",
["Tombonuo"] = "txa",
["Tombulu"] = "tom",
["Tomini"] = "txm",
["Tommeginne"] = "xpv",
["Tommo So"] = "dto",
["Tomo Kan Dogon"] = "dtm",
["Tomoip"] = "tqp",
["Tondano"] = "tdn",
["Tonga (Malawi)"] = "tog",
["Tonga (Mozambique)"] = "toh",
["Tonga (Zambia)"] = "toi",
["Tongwe"] = "tny",
["Tonjon"] = "tjn",
["Tonsawang"] = "tnw",
["Tonsea"] = "txs",
["Tontemboan"] = "tnt",
["Toogee"] = "xpx",
["Topoiyo"] = "toy",
["Toposa"] = "toq",
["Toraja-Sa'dan"] = "sda",
["Toram"] = "trj",
["Torau"] = "ttu",
["Toro"] = "tdv",
["Toro So Dogon"] = "dts",
["Toro Tegu Dogon"] = "dtt",
["Toromono"] = "tno",
["Torona"] = "tqr",
["Torres Strait Creole"] = "tcs",
["Torricelli"] = "tei",
["Torricelli Yau"] = "yyu",
["Torá"] = "trz",
["Tosu"] = "sit-tos",
["Totela"] = "ttl",
["Totoli"] = "txe",
["Totomachapan Zapotec"] = "zph",
["Totontepec Mixe"] = "mto",
["Totoro"] = "ttk",
["Touo"] = "tqu",
["Toura"] = "neb",
["Tourangeau"] = "roa-tou",
["Towei"] = "ttn",
["Traveller Danish"] = "rmd",
["Traveller Norwegian"] = "rmg",
["Traveller Scottish"] = "trl",
["Tregami"] = "trm",
["Tremembé"] = "tme",
["Trieng"] = "stg",
["Trimuris"] = "tip",
["Tring"] = "tgq",
["Tringgus"] = "trx",
["Trinidad and Tobago Sign Language"] = "lst",
["Trinidadian Creole English"] = "trf",
["Trinitario"] = "trn",
["Truká"] = "tka",
["Trumai"] = "tpy",
["Ts'ün-Lao"] = "tsl",
["Tsaangi"] = "tsa",
["Tsafiki"] = "cof",
["Tsakwambo"] = "kvz",
["Tsetsaut"] = "txc",
["Tshobdun"] = "sit-tsh",
["Tshwa"] = "hio",
["Tsikimba"] = "kdl",
["Tsimané"] = "cas",
["Tsishingini"] = "tsw",
["Tso"] = "ldp",
["Tsogo"] = "tsv",
["Tsotsitaal"] = "fly",
["Tsum"] = "ttz",
["Tsuvadi"] = "tvd",
["Tsuvan"] = "tsh",
["Tswa"] = "tsc",
["Tswapong"] = "two",
["Tubar"] = "tbu",
["Tucano"] = "tuo",
["Tugen"] = "tuy",
["Tugun"] = "tzn",
["Tugutil"] = "tuj",
["Tukpa"] = "tpq",
["Tukudede"] = "tkd",
["Tukumanféd"] = "tkf",
["Tula"] = "tul",
["Tule-Kaweah Yokuts"] = "nai-tky",
["Tulehu"] = "tlu",
["Tulishi"] = "tey",
["Tulu-Bohuai"] = "rak",
["Tulua"] = "aus-tul",
["Tuma-Irumu"] = "iou",
["Tumak"] = "tmc",
["Tumi"] = "kku",
["Tumleo"] = "tmq",
["Tumshuqese"] = "xtq",
["Tumtum"] = "tbr",
["Tumulung Sisaala"] = "sil",
["Tunen"] = "tvu",
["Tungag"] = "lcm",
["Tunggare"] = "trt",
["Tunia"] = "tug",
["Tunisian Sign Language"] = "tse",
["Tunjung"] = "tjg",
["Tunumiisut"] = "esx-tut",
["Tunzu"] = "dza",
["Tuotomb"] = "ttf",
["Tuparí"] = "tpr",
["Tupinikin"] = "tpk",
["Tupuri"] = "tui",
["Turaka"] = "trh",
["Turi"] = "trd",
["Turiwára"] = "twt",
["Turka"] = "tuz",
["Turkana"] = "tuv",
["Turkish Sign Language"] = "tsm",
["Turks and Caicos Creole English"] = "tch",
["Turumsa"] = "tqm",
["Turung"] = "try",
["Tuscarora"] = "tus",
["Tutelo"] = "tta",
["Tutong"] = "ttg",
["Tutsa Naga"] = "tvt",
["Tutuba"] = "tmi",
["Tututepec Mixtec"] = "mtu",
["Tututni"] = "tuu",
["Tuwali Ifugao"] = "ifk",
["Tuwari"] = "tww",
["Tuxináwa"] = "tux",
["Tuxá"] = "tud",
["Tuyuca"] = "tue",
["Twana"] = "twa",
["Twendi"] = "twn",
["Tyaraity"] = "woa",
["Tyerrernotepanner"] = "xph",
["Tz'utujil"] = "tzj",
["Tzeltal"] = "tzh",
["Tày Tac"] = "tyt",
["Téén"] = "lor",
["Tübatulabal"] = "tub",
["Uab Meto"] = "aoz",
["Uamué"] = "uam",
["Uare"] = "ksj",
["Ubaghara"] = "byc",
["Ubang"] = "uba",
["Ubi"] = "ubi",
["Ubir"] = "ubr",
["Ucayali-Yurúa Ashéninka"] = "cpb",
["Uda"] = "uda",
["Ufim"] = "ufi",
["Ugandan Sign Language"] = "ugn",
["Ughele"] = "uge",
["Uhami"] = "uha",
["Uisai"] = "uis",
["Ujir"] = "udj",
["Ukaan"] = "kcf",
["Ukhwejo"] = "ukh",
["Ukit"] = "umi",
["Ukpe-Bayobiri"] = "ukp",
["Ukpet-Ehom"] = "akd",
["Ukrainian Sign Language"] = "ukl",
["Ukue"] = "uku",
["Ukuriguma"] = "ukg",
["Ukwa"] = "ukq",
["Ukwuani-Aboh-Ndoni"] = "ukw",
["Ulau-Suain"] = "svb",
["Uldeme"] = "udl",
["Ulithian"] = "uli",
["Ulumanda'"] = "ulm",
["Ulwa"] = "ulw",
["Uma"] = "ppk",
["Uma' Lasan"] = "xky",
["Uma' Lung"] = "ulu",
["Umanakaina"] = "gdn",
["Umatilla"] = "uma",
["Umbindhamu"] = "umd",
["Umbu-Ungu"] = "ubu",
["Umbugarla"] = "umr",
["Umbuygamu"] = "umg",
["Umeda"] = "upi",
["Umiida"] = "xud",
["Umiray Dumaget Agta"] = "due",
["Umon"] = "umm",
["Umotína"] = "umo",
["Umpila"] = "ump",
["Una"] = "mtg",
["Unas"] = "art-una",
["Unde Kaili"] = "unz",
["Uneme"] = "une",
["Unggaranggu"] = "xun",
["Unggumi"] = "xgu",
["Tiếng Uni"] = "uni",
["Unserdeutsch"] = "uln",
["Unua"] = "onu",
["Unubahe"] = "unu",
["Uokha"] = "uok",
["Upper Chehalis"] = "cjh",
["Upper Grand Valley Dani"] = "dna",
["Upper Kuskokwim"] = "kuu",
["Upper Necaxa Totonac"] = "tku",
["Upper Tanana"] = "tau",
["Upper Taromi"] = "tov",
["Upper Umpqua"] = "xup",
["Ura (New Guinea)"] = "uro",
["Ura (Vanuatu)"] = "uur",
["Uradhi"] = "urf",
["Urapmin"] = "urm",
["Urarina"] = "ura",
["Urat"] = "urt",
["Urhobo"] = "urh",
["Uri"] = "uvh",
["Urigina"] = "urg",
["Urim"] = "uri",
["Urimo"] = "urx",
["Urningangg"] = "urc",
["Uru"] = "ure",
["Uru-Eu-Wau-Wau"] = "urz",
["Uru-Pa-In"] = "urp",
["Uruangnirin"] = "urn",
["Uruava"] = "urv",
["Uruguayan Sign Language"] = "ugy",
["Urumi"] = "uru",
["Usaghade"] = "usk",
["Usan"] = "wnu",
["Usarufa"] = "usa",
["Usila Chinantec"] = "cuc",
["Uspanteco"] = "usp",
["Utarmbung"] = "omo",
["Ute"] = "ute",
["Utu"] = "utu",
["Uwinymil"] = "aus-uwi",
["Uya"] = "usu",
["Uyajitaya"] = "duk",
["Uzekwe"] = "eze",
["Vaghua"] = "tva",
["Vagla"] = "vag",
["Vai"] = "vai",
["Vaiphei"] = "vap",
["Vale"] = "vae",
["Valencian Sign Language"] = "vsv",
["Valle Nacional Chinantec"] = "cvn",
["Valley Maidu"] = "vmv",
["Valman"] = "van",
["Valpei"] = "vlp",
["Vamale"] = "mkt",
["Vame"] = "mlr",
["Vandalic"] = "xvn",
["Vangunu"] = "mpr",
["Vanimo"] = "vam",
["Vanji"] = "ira-wnj",
["Vanuma"] = "vau",
["Vao"] = "vao",
["Varhadi"] = "vah",
["Varisi"] = "vrs",
["Vayu"] = "vay",
["Veddah"] = "ved",
["Vehes"] = "val",
["Vemgo-Mabas"] = "vem",
["Venezuelan Sign Language"] = "vsl",
["Ventureño"] = "veo",
["Vera'a"] = "vra",
["Vestinian"] = "xvs",
["Vidunda"] = "vid",
["Viemo"] = "vig",
["Vilela"] = "vil",
["Vili"] = "vif",
["Villa Viciosa Agta"] = "dyg",
["Vincentian Creole English"] = "svc",
["Viti"] = "vit",
["Vitou"] = "vto",
["Viya"] = "gev",
["Vlax Romani"] = "rmy",
["Volga German"] = "gmw-vog",
["Vono"] = "kch",
["Voro"] = "vor",
["Vracada Apabhramsa"] = "inc-vra",
["Vumbu"] = "vum",
["Vunapu"] = "vnp",
["Vunjo"] = "vun",
["Vute"] = "vut",
["Wa"] = "wbm",
["Wa'ema"] = "wag",
["Waamwang"] = "wmn",
["Wab"] = "wab",
["Wabo"] = "wbb",
["Waboda"] = "kmx",
["Wadaginam"] = "wdg",
["Waddar"] = "wbq",
["Wadi Wadi"] = "xwd",
["Wadjabangayi"] = "wdy",
["Wadjiginy"] = "wdj",
["Wadjigu"] = "wdu",
["Wae Rana"] = "wrx",
["Waffa"] = "waj",
["Wagawaga"] = "wgb",
["Wagaya"] = "wga",
["Wagdi"] = "wbr",
["Wageman"] = "waq",
["Wahau Kayan"] = "whu",
["Wahau Kenyah"] = "whk",
["Waigali"] = "wbk",
["Waigeo"] = "wgo",
["Waikuri"] = "nai-wai",
["Wailaki"] = "wlk",
["Wailapa"] = "wlr",
["Waima'a"] = "wmh",
["Waimiri-Atroari"] = "atr",
["Wainumá"] = "awd-wai",
["Waioli"] = "wli",
["Waitaká"] = "sai-wai",
["Waja"] = "wja",
["Wajarri"] = "wbv",
["Wajuk"] = "xwj",
["Waka"] = "wav",
["Wakawaka"] = "wkw",
["Wakoná"] = "waf",
["Wala"] = "lgl",
["Walak"] = "wlw",
["Walangama"] = "nlw",
["Wali (Ghana)"] = "wlx",
["Wali (Sudan)"] = "wll",
["Waling"] = "wly",
["Walio"] = "wla",
["Walla Walla"] = "waa",
["Walmajarri"] = "wmt",
["Wam"] = "wmo",
["Wamas"] = "wmc",
["Wambaya"] = "wmb",
["Wambon"] = "wms",
["Wamey"] = "cou",
["Wamin"] = "wmi",
["Wampar"] = "lbq",
["Wampur"] = "waz",
["Wan"] = "wan",
["Wanambre"] = "wnb",
["Wanap"] = "wnp",
["Wanda"] = "wbh",
["Wandala"] = "mfi",
["Wandamen"] = "wad",
["Wandarang"] = "wnd",
["Wandji"] = "wdd",
["Wanga"] = "lwg",
["Wanggamala"] = "wnm",
["Wangganguru"] = "wgg",
["Wanggom"] = "wng",
["Wangkayutyuru"] = "wky",
["Wangkumara"] = "xwk",
["Wanham"] = "sai-wnm",
["Wanji"] = "wbi",
["Wanman"] = "wbt",
["Wannu"] = "jub",
["Wano"] = "wno",
["Wantoat"] = "wnc",
["Wanukaka"] = "wnk",
["Wanyi"] = "wny",
["Wané"] = "hwa",
["Wapan"] = "juk",
["Wapishana"] = "wap",
["Wappo"] = "wao",
["Wara"] = "wbf",
["Warao"] = "wba",
["Warapu"] = "wra",
["Waray Sorsogon"] = "srv",
["Wardandi"] = "wxw",
["Warembori"] = "wsa",
["Wari'"] = "pav",
["Waris"] = "wrs",
["Waritai"] = "wbe",
["Wariyangga"] = "wri",
["Warkay-Bipim"] = "bgv",
["Warlmanpa"] = "wrl",
["Tiếng Warlpiri"] = "wbp",
["Warluwara"] = "wrb",
["Warnang"] = "wrn",
["Waropen"] = "wrp",
["Warray"] = "wrz",
["Warrgamay"] = "wgy",
["Warrwa"] = "wwr",
["Waru"] = "wru",
["Warumungu"] = "wrm",
["Waruna"] = "wrv",
["Warungu"] = "wrg",
["Warwar Feni"] = "hrw",
["Wasa"] = "wss",
["Wasco-Wishram"] = "wac",
["Wasembo"] = "gsp",
["Washo"] = "was",
["Waskia"] = "wsk",
["Wasu"] = "wsu",
["Watakataui"] = "wtk",
["Watam"] = "wax",
["Wathaurong"] = "wth",
["Watiwa"] = "wtf",
["Watubela"] = "wah",
["Waube"] = "kop",
["Wauja"] = "wau",
["Wauyai"] = "wuy",
["Wawa"] = "www",
["Tiếng Ngõa Hương"] = "wxa",
["Wayoró"] = "wyr",
["Wayumará"] = "sai-way",
["Wedau"] = "wed",
["Weh"] = "weh",
["Welaung"] = "weu",
["Weliki"] = "klh",
["Welsh Romani"] = "rmw",
["Wemale"] = "weo",
["Weme Gbe"] = "wem",
["Wendat"] = "wdt",
["Weri"] = "wer",
["Wersing"] = "kvw",
["West Albay Bikol"] = "fbl",
["West Ambae"] = "nnd",
["West Central Banda"] = "bbp",
["West Damar"] = "drn",
["West Greenlandic Pidgin"] = "crp-gep",
["West Lembata"] = "lmj",
["West Masela"] = "mss",
["West Tarangan"] = "txn",
["West Uvean"] = "uve",
["West-Central Limba"] = "lia",
["Western Arrernte"] = "are",
["Western Bolivian Guaraní"] = "gnw",
["Western Bukidnon Manobo"] = "mbb",
["Western Dani"] = "dnw",
["Western Durango Nahuatl"] = "azn",
["Western Fijian"] = "wyy",
["Western Gurung"] = "gvr",
["Western Jicaque"] = "und-wji",
["Western Juxtlahuaca Mixtec"] = "jmx",
["Western Karaboro"] = "kza",
["Western Keres"] = "kjq",
["Tiếng Krahn"] = "krw",
["Western Lalu"] = "ywl",
["Western Maninkakan"] = "mlq",
["Western Mashan Hmong"] = "hmw",
["Western Meohang"] = "raf",
["Western Muria"] = "mut",
["Western Panjabi"] = "pnb",
["Western Penan"] = "pne",
["Western Sisaala"] = "ssl",
["Western Subanon"] = "suc",
["Western Tawbuid"] = "twb",
["Western Totonac"] = "tqt",
["Western Tunebo"] = "tnb",
["Western Xwla Gbe"] = "xwl",
["Westrobothnian"] = "gmq-bot",
["Weyewa"] = "wew",
["White Lachi"] = "lwh",
["Whitesands"] = "tnp",
["Wiarumus"] = "tua",
["Wichita"] = "wic",
["Wichí Lhamtés Güisnay"] = "mzh",
["Wichí Lhamtés Nocten"] = "mtp",
["Wichí Lhamtés Vejoz"] = "wlv",
["Wik-Epa"] = "wie",
["Wik-Iiyanh"] = "wij",
["Wik-Keyangan"] = "wif",
["Wik-Me'anha"] = "wih",
["Wik-Mungkan"] = "wim",
["Wik-Ngathana"] = "wig",
["Wikalkan"] = "wik",
["Wikngenchera"] = "wua",
["Wilawila"] = "wil",
["Wintu"] = "wnw",
["Winyé"] = "kst",
["Wipi"] = "gdr",
["Wiraféd"] = "wir",
["Wirangu"] = "wgu",
["Wiru"] = "wiu",
["Wirö"] = "wpc",
["Wiwa"] = "mbp",
["Woccon"] = "xwc",
["Wogamusin"] = "wog",
["Wogeo"] = "woc",
["Woi"] = "wbw",
["Wojenaka"] = "jod",
["Wolani"] = "wod",
["Woleaian"] = "woe",
["Womo"] = "wmx",
["Wong-gie"] = "aus-won",
["Wongo"] = "won",
["Woods Cree"] = "cwd",
["Woria"] = "wor",
["Worimi"] = "kda",
["Worodougou"] = "jud",
["Worora"] = "wro",
["Wotapuri-Katarqalai"] = "wsv",
["Woun Meu"] = "noa",
["Wudu"] = "wud",
["Wulguru"] = "aus-wul",
["Wuliwuli"] = "wlu",
["Wulna"] = "wux",
["Wumboko"] = "bqm",
["Wumbvu"] = "wum",
["Wumeng"] = "ywu",
["Wunai Bunu"] = "bwn",
["Wunambal"] = "wub",
["Wurrugu"] = "wur",
["Wusa"] = "yig",
["Wushi"] = "bse",
["Wusi"] = "wsi",
["Wutung"] = "wut",
["Wuvulu-Aua"] = "wuv",
["Wyandot"] = "wya",
["Wára"] = "tci",
["Wãpha"] = "juw",
["Wè Southern"] = "gxx",
["Wè Western"] = "wec",
["Xadani Zapotec"] = "zax",
["Xakriabá"] = "xkr",
["Xanaguía Zapotec"] = "ztg",
["Xaragure"] = "axx",
["Xerénte"] = "xer",
["Xetá"] = "xet",
["Xicotepec de Juárez Totonac"] = "too",
["Xinca"] = "xin",
["Xingú Asuriní"] = "asn",
["Xipaya"] = "xiy",
["Xiri"] = "xii",
["Xiriâna"] = "xir",
["Xishanba Lalo"] = "ywt",
["Xocó"] = "sai-xoc",
["Xokleng"] = "xok",
["Xukurú"] = "xoo",
["Xwela Gbe"] = "xwe",
["Yaa"] = "iyx",
["Yabarana"] = "yar",
["Yabaâna"] = "ybn",
["Yaben"] = "ybm",
["Yabong"] = "ybo",
["Yabula Yabula"] = "yxy",
["Yace"] = "ekr",
["Yafi"] = "wfg",
["Yagara"] = "yxg",
["Yagaria"] = "ygr",
["Yagomi"] = "ygm",
["Yagua"] = "yad",
["Yagwoia"] = "ygw",
["Yahadian"] = "ner",
["Yahang"] = "rhp",
["Yahuna"] = "ynu",
["Yaka"] = "yaf",
["Yakaikeke"] = "ykk",
["Yakoma"] = "yky",
["Tiếng Yala"] = "yba",
["Yalahatan"] = "jal",
["Yalakalore"] = "xyl",
["Yalarnnga"] = "ylr",
["Yale"] = "nce",
["Yaleba"] = "ylb",
["Yalunka"] = "yal",
["Yalálag Zapotec"] = "zpu",
["Yamap"] = "ymp",
["Yamba"] = "yam",
["Yambes"] = "ymb",
["Yambeta"] = "yat",
["Yamdena"] = "jmd",
["Yameo"] = "yme",
["Yaminahua"] = "yaa",
["Yamongeri"] = "ymg",
["Yan-nhangu"] = "jay",
["Yana"] = "ynn",
["Yanda"] = "yda",
["Yanda Dogon"] = "dym",
["Yandjibara"] = "xyb",
["Yandruwandha"] = "ynd",
["Yangben"] = "yav",
["Yangkaal"] = "aus-ynk",
["Yangkam"] = "bsx",
["Yangman"] = "jng",
["Yango"] = "yng",
["Yangulam"] = "ynl",
["Yangum Dey"] = "yde",
["Yangum Gel"] = "ygl",
["Yangum Mon"] = "ymo",
["Yankunytjatjara"] = "kdd",
["Yanomamö"] = "guu",
["Yanomámi"] = "wca",
["Yansi"] = "yns",
["Yaosakor Asmat"] = "asy",
["Yaouré"] = "yre",
["Yaqay"] = "jaq",
["Yaqui"] = "yaq",
["Yarawata"] = "yrw",
["Yareba"] = "yrb",
["Yareni Zapotec"] = "zae",
["Yarli"] = "yxl",
["Yarluyandi"] = "yry",
["Yarumá"] = "sai-yar",
["Yarí"] = "yri",
["Yasa"] = "yko",
["Yatay"] = "yty",
["Yaul"] = "yla",
["Yaur"] = "jau",
["Yautepec Zapotec"] = "zpb",
["Yavitero"] = "yvt",
["Yawa"] = "yva",
["Yawalapití"] = "yaw",
["Yawanawa"] = "ywn",
["Yawarawarga"] = "yww",
["Yaweyuha"] = "yby",
["Yawijibaya"] = "jbw",
["Yawiyo"] = "ybx",
["Yawuru"] = "ywr",
["Yaygir"] = "xya",
["Yei"] = "jei",
["Yekhee"] = "ets",
["Yekora"] = "ykr",
["Yelmek"] = "jel",
["Yelogu"] = "ylg",
["Yemba"] = "ybb",
["Tiếng Ả Rập Sana'a"] = "ayn",
["Yendang"] = "yen",
["Yeni"] = "yei",
["Yeniche"] = "yec",
["Yerakai"] = "yra",
["Yeretuar"] = "gop",
["Yerukula"] = "yeu",
["Yeskwa"] = "yes",
["Yessan-Mayo"] = "yss",
["Yetfa"] = "yet",
["Yeyi"] = "yey",
["Yil"] = "yll",
["Yimas"] = "yee",
["Yimchungru Naga"] = "yim",
["Yinbaw Karen"] = "kvu",
["Yindjilandji"] = "yil",
["Yine"] = "pib",
["Yinggarda"] = "yia",
["Yinhawangka"] = "ywg",
["Yiningayi"] = "ygi",
["Yintale Karen"] = "kvy",
["Yinwum"] = "yxm",
["Yir-Yoront"] = "yiy",
["Yirandali"] = "ljw",
["Yis"] = "yis",
["Yitha Yitha"] = "xth",
["Yoba"] = "yob",
["Yocoboué Dida"] = "gud",
["Yoidik"] = "ydk",
["Yoke"] = "yki",
["Yolngu Sign Language"] = "ygs",
["Yoloxochitl Mixtec"] = "xty",
["Yombe"] = "yom",
["Yopno"] = "yut",
["Yora"] = "mts",
["Yorta Yorta"] = "xyy",
["Younuo Bunu"] = "buh",
["Yout Wam"] = "ytw",
["Yuaga"] = "nua",
["Yucatec Maya Sign Language"] = "msd",
["Yuchi"] = "yuc",
["Yucuañe Mixtec"] = "mvg",
["Yucuna"] = "ycn",
["Yugambal"] = "yub",
["Yugoslavian Sign Language"] = "ysl",
["Yugul"] = "ygu",
["Yuhup"] = "yab",
["Yuki"] = "yuk",
["Yukpa"] = "yup",
["Yukuben"] = "ybl",
["Yulu"] = "yul",
["Yuma"] = "yum",
["Yumana"] = "awd-yum",
["Yupiltepeque"] = "nai-yup",
["Yupua"] = "sai-yup",
["Yuqui"] = "yuq",
["Yuracare"] = "yuz",
["Yuru"] = "ljx",
["Yurumanguí"] = "sai-yur",
["Yurutí"] = "yui",
["Yutanduchi Mixtec"] = "mab",
["Yuwana"] = "yau",
["Yuyu"] = "yxu",
["Zaachila Zapotec"] = "ztx",
["Zabana"] = "kji",
["Zacatlán-Ahuacatlán-Tepetzintla Nahuatl"] = "nhi",
["Zakhring"] = "zkr",
["Zambian Sign Language"] = "zsl",
["Zan Gula"] = "zna",
["Zanaki"] = "zak",
["Zande"] = "zne",
["Zangwal"] = "zah",
["Zaramo"] = "zaj",
["Zari"] = "zaz",
["Zauzou"] = "zal",
["Zazao"] = "jaj",
["Zbu"] = "sit-zbu",
["Zeem"] = "zua",
["Zemba"] = "dhm",
["Zeme Naga"] = "nzm",
["Zemgalian"] = "xzm",
["Zenag"] = "zeg",
["Zenzontepec Chatino"] = "czn",
["Zhang-Zhung"] = "xzh",
["Zhire"] = "zhi",
["Zhoa"] = "zhw",
["Zhár"] = "jjr",
["Zia"] = "zia",
["Zialo"] = "zil",
["Zigula"] = "ziw",
["Zimakani"] = "zik",
["Zimba"] = "zmb",
["Zimbabwe Sign Language"] = "zib",
["Zinza"] = "zin",
["Zipser German"] = "gmw-zps",
["Zire"] = "sih",
["Ziriya"] = "zir",
["Zizilivakan"] = "ziz",
["Zo'é"] = "pto",
["Zokhuo"] = "yzk",
["Zotung Chin"] = "czt",
["Zulgo-Gemzek"] = "gnd",
["Zumaya"] = "zuy",
["Zuni"] = "zun",
["Zuwara"] = "ber-zuw",
["Zyphe"] = "zyp",
["Záparo"] = "zro",
["Biệt ngữ Chinook"] = "chn",
["Không xác định ngôn ngữ"] = "und",
["Ngôn ngữ ký hiệu Mỹ"] = "ase",
["Tiếng 'Are'are"] = "alu",
["Tiếng A Xương"] = "acn",
["Tiếng A'ou"] = "aou",
["Tiếng A-Hmao"] = "hmd",
["Tiếng Aari"] = "aiw",
["Tiếng Aari nguyên thủy"] = "omv-aro-pro",
["Tiếng Aasax"] = "aas",
["Tiếng Abaga"] = "abg",
["Tiếng Abai"] = "poz-abi",
["Tiếng Abanyom"] = "abm",
["Tiếng Abau"] = "aau",
["Tiếng Abaza"] = "abq",
["Tiếng Abidji"] = "abi",
["Tiếng Abinomn"] = "bsa",
["Tiếng Abkhaz"] = "ab",
["Tiếng Abkhaz-Abaza nguyên thủy"] = "cau-abz-pro",
["Tiếng Abon"] = "abo",
["Tiếng Abron"] = "abr",
["Tiếng Abui"] = "abz",
["Tiếng Abure"] = "abu",
["Tiếng Aceh"] = "ace",
["Tiếng Achawa"] = "aca",
["Tiếng Acheron"] = "acz",
["Tiếng Achi"] = "acr",
["Tiếng Acholi"] = "ach",
["Tiếng Achuar"] = "acu",
["Tiếng Achumawi"] = "acv",
["Tiếng Adangme"] = "ada",
["Tiếng Adi"] = "adi",
["Tiếng Adja"] = "ajg",
["Tiếng Adnyamathanha"] = "adt",
["Tiếng Adygea"] = "ady",
["Tiếng Adzera"] = "adz",
["Tiếng Aer"] = "aeq",
["Tiếng Afade"] = "aal",
["Tiếng Afar"] = "aa",
["Tiếng Afrikaans"] = "af",
["Tiếng Agatu"] = "agc",
["Tiếng Agawam"] = "alg-aga",
["Tiếng Aghem"] = "agq",
["Tiếng Aghul"] = "agx",
["Tiếng Aghwan"] = "xag",
["Tiếng Agta Dupaningan"] = "duo",
["Tiếng Aguacateca"] = "agu",
["Tiếng Ahom"] = "aho",
["Tiếng Ahtna"] = "aht",
["Tiếng Ai"] = "eee",
["Tiếng Ai Cập"] = "egy",
["Tiếng Ai Cập bình dân"] = "egx-dem",
["Tiếng Aimol"] = "aim",
["Tiếng Ainu"] = "ain",
["Tiếng Aiton"] = "aio",
["Tiếng Ajië"] = "aji",
["Tiếng Aka-Bo"] = "akm",
["Tiếng Aka-Jeru"] = "akj",
["Tiếng Aka-Kede"] = "akx",
["Tiếng Akan"] = "ak",
["Tiếng Akaselem"] = "aks",
["Tiếng Akawaio"] = "ake",
["Tiếng Akha"] = "ahk",
["Tiếng Akhvakh"] = "akv",
["Tiếng Akkad"] = "akk",
["Tiếng Aklanon"] = "akl",
["Tiếng Akoose"] = "bss",
["Tiếng Akuntsu"] = "aqz",
["Tiếng Alaba-K’abeena"] = "alw",
["Tiếng Alabama"] = "akz",
["Tiếng Alagwa"] = "wbj",
["Tiếng Alak"] = "alk",
["Tiếng Alamblak"] = "amp",
["Tiếng Alangan"] = "alj",
["Tiếng Alawa"] = "alh",
["Tiếng Albani"] = "sq",
["Tiếng Albani nguyên thủy"] = "sqj-pro",
["Tiếng Alchuka"] = "tuw-alk",
["Tiếng Alekano"] = "gah",
["Tiếng Aleut"] = "ale",
["Tiếng Algic nguyên thủy"] = "aql-pro",
["Tiếng Algonquin"] = "alq",
["Tiếng Algonquin nguyên thủy"] = "alg-pro",
["Tiếng Allar"] = "all",
["Tiếng Alsea"] = "aes",
["Tiếng Alumu-Tesu"] = "aab",
["Tiếng Alutor"] = "alr",
["Tiếng Alyentiyak"] = "sai-all",
["Tiếng Ama"] = "amm",
["Tiếng Amahuaca"] = "amc",
["Tiếng Amaimon"] = "ali",
["Tiếng Amal"] = "aad",
["Tiếng Amanab"] = "amn",
["Tiếng Amarasi"] = "aaz",
["Tiếng Ambai"] = "amk",
["Tiếng Ambrak"] = "aag",
["Tiếng Ambulas"] = "abt",
["Tiếng Amdang"] = "amj",
["Tiếng Amhara"] = "am",
["Tiếng Amis"] = "ami",
["Tiếng Amurdag"] = "amg",
["Tiếng Amuzgo"] = "amu",
["Tiếng Anaang"] = "anw",
["Tiếng Anal"] = "anm",
["Tiếng Anauyá"] = "awd-ana",
["Tiếng Andi"] = "ani",
["Tiếng Angami"] = "njm",
["Tiếng Angika"] = "anp",
["Tiếng Angkula"] = "aus-ang",
["Tiếng Angola"] = "aoa",
["Tiếng Anh"] = "en",
["Tiếng Anh Solombala"] = "crp-slb",
["Tiếng Anh cổ"] = "ang",
["Tiếng Anh trung đại"] = "enm",
["Tiếng Anii"] = "blo",
["Tiếng Ankave"] = "aak",
["Tiếng Annobón"] = "fab",
["Tiếng Anuak"] = "anu",
["Tiếng Anuki"] = "aui",
["Tiếng Anyi"] = "any",
["Tiếng Ao"] = "njo",
["Tiếng Apabhramsa"] = "inc-apa",
["Tiếng Apache Tây"] = "apw",
["Tiếng Apache đồng bằng"] = "apk",
["Tiếng Aparaí"] = "apy",
["Tiếng Apatani"] = "apt",
["Tiếng Apinayé"] = "apn",
["Tiếng Aputai"] = "apx",
["Tiếng Aquitani"] = "xaq",
["Tiếng Aragon"] = "an",
["Tiếng Araki"] = "akr",
["Tiếng Arakwal"] = "rkw",
["Tiếng Aram"] = "arc",
["Tiếng Aranadan"] = "aaf",
["Tiếng Arapaho"] = "arp",
["Tiếng Arawak nguyên thủy"] = "awd-pro",
["Tiếng Araweté"] = "awt",
["Tiếng Archi"] = "aqc",
["Tiếng Arem"] = "aem",
["Tiếng Argobba"] = "agj",
["Tiếng Arhuaco"] = "arh",
["Tiếng Ari"] = "aac",
["Tiếng Arin"] = "xrn",
["Tiếng Armenia"] = "hy",
["Tiếng Armenia cổ"] = "xcl",
["Tiếng Armenia trung đại"] = "axm",
["Tiếng Aromania"] = "rup",
["Tiếng Arrernte Đông"] = "aer",
["Tiếng Ashkun"] = "ask",
["Tiếng Ashraaf"] = "cus-ash",
["Tiếng Ashéninka Pajonal"] = "cjo",
["Tiếng Asi"] = "bno",
["Tiếng Askopan"] = "eiv",
["Tiếng Asli nguyên thủy"] = "mkh-asl-pro",
["Tiếng Assam"] = "as",
["Tiếng Assam cận đại"] = "inc-oas",
["Tiếng Assan"] = "xss",
["Tiếng Assiniboine"] = "asb",
["Tiếng Asturias"] = "ast",
["Tiếng Asumboa"] = "aua",
["Tiếng Asur"] = "asr",
["Tiếng Atayal"] = "tay",
["Tiếng Atemble"] = "ate",
["Tiếng Athabasca nguyên thủy"] = "ath-pro",
["Tiếng Athpariya"] = "aph",
["Tiếng Atikamekw"] = "atj",
["Tiếng Atong (Ấn Độ)"] = "aot",
["Tiếng Atsahuaca"] = "atc",
["Tiếng Auhelawa"] = "kud",
["Tiếng Aukan"] = "djk",
["Tiếng Avar"] = "av",
["Tiếng Avar-Andic nguyên thủy"] = "cau-ava-pro",
["Tiếng Avatime"] = "avn",
["Tiếng Avesta"] = "ae",
["Tiếng Avokaya"] = "avu",
["Tiếng Awa (Trung Quốc)"] = "vwa",
["Tiếng Awadh"] = "awa",
["Tiếng Awadh cổ"] = "inc-oaw",
["Tiếng Aweer"] = "bob",
["Tiếng Awing"] = "azo",
["Tiếng Awjila"] = "auj",
["Tiếng Awngi"] = "awn",
["Tiếng Axi"] = "yix",
["Tiếng Ayere"] = "aye",
["Tiếng Aymara"] = "ay",
["Tiếng Azerbaijan"] = "az",
["Tiếng Ba Lan"] = "pl",
["Tiếng Ba Lan cổ"] = "zlw-opl",
["Tiếng Ba Na"] = "bdq",
["Tiếng Ba Tư"] = "fa",
["Tiếng Ba Tư cổ"] = "peo",
["Tiếng Ba Tư trung đại"] = "pal",
["Tiếng Ba Tư-Do Thái"] = "jpr",
["Tiếng Baagandji"] = "drl",
["Tiếng Baatonum"] = "bba",
["Tiếng Babatana"] = "baa",
["Tiếng Babungo"] = "bav",
["Tiếng Babuza"] = "bzg",
["Tiếng Bacama"] = "bcy",
["Tiếng Bactria"] = "xbc",
["Tiếng Badaga"] = "bfq",
["Tiếng Badanchi"] = "bau",
["Tiếng Bade"] = "bde",
["Tiếng Badui"] = "bac",
["Tiếng Bagua"] = "sai-bag",
["Tiếng Bagvalal"] = "kva",
["Tiếng Bahing"] = "bhj",
["Tiếng Bahnar nguyên thủy"] = "mkh-ban-pro",
["Tiếng Bainouk-Gunyuño"] = "bab",
["Tiếng Baiso"] = "bsw",
["Tiếng Bajjika"] = "vjk",
["Tiếng Bakaka"] = "bqz",
["Tiếng Bakhtiari"] = "bqi",
["Tiếng Baki"] = "bki",
["Tiếng Bakung"] = "xkl",
["Tiếng Bala"] = "tuw-bal",
["Tiếng Balanta-Ganja"] = "bjt",
["Tiếng Balanta-Kentohe"] = "ble",
["Tiếng Balantak"] = "blz",
["Tiếng Bali"] = "ban",
["Tiếng Baloch"] = "bal",
["Tiếng Balt-Slav nguyên thủy"] = "ine-bsl-pro",
["Tiếng Balti"] = "bft",
["Tiếng Bambara"] = "bm",
["Tiếng Bambassi"] = "myf",
["Tiếng Bamum"] = "bax",
["Tiếng Bana"] = "bcw",
["Tiếng Bandjalang"] = "bdy",
["Tiếng Banggai"] = "bgz",
["Tiếng Bangi"] = "bni",
["Tiếng Bangolan"] = "bgj",
["Tiếng Banjar"] = "bjn",
["Tiếng Bankon"] = "abb",
["Tiếng Bantawa"] = "bap",
["Tiếng Bantayanon"] = "bfx",
["Tiếng Bantoid nguyên thủy"] = "nic-bod-pro",
["Tiếng Bantu nguyên thủy"] = "bnt-pro",
["Tiếng Banyumas"] = "map-bms",
["Tiếng Baoule"] = "bci",
["Tiếng Barai"] = "bbb",
["Tiếng Barakai"] = "baj",
["Tiếng Bari"] = "bfa",
["Tiếng Barikewa"] = "jbk",
["Tiếng Barombi"] = "bbi",
["Tiếng Baré"] = "bae",
["Tiếng Basaa"] = "bas",
["Tiếng Basay"] = "byq",
["Tiếng Bashkir"] = "ba",
["Tiếng Basketo"] = "bst",
["Tiếng Basque"] = "eu",
["Tiếng Basque nguyên thủy"] = "euq-pro",
["Tiếng Bassa"] = "bsq",
["Tiếng Bassari"] = "bsc",
["Tiếng Batak Simalungun"] = "bts",
["Tiếng Batek"] = "btq",
["Tiếng Bats"] = "bbl",
["Tiếng Batuley"] = "bay",
["Tiếng Bayern"] = "bar",
["Tiếng Beaver"] = "bea",
["Tiếng Bedjond"] = "bjv",
["Tiếng Beja"] = "bej",
["Tiếng Belarus"] = "be",
["Tiếng Belhariya"] = "byw",
["Tiếng Beli"] = "blm",
["Tiếng Bella Coola"] = "blc",
["Tiếng Bellara"] = "brw",
["Tiếng Belnəng"] = "glb",
["Tiếng Bemba"] = "bem",
["Tiếng Bench"] = "bcq",
["Tiếng Bengal"] = "bn",
["Tiếng Bengal cổ"] = "inc-obn",
["Tiếng Benue-Congo nguyên thủy"] = "nic-bco-pro",
["Tiếng Berber Bắc Sahara"] = "mzb",
["Tiếng Berber Tunisia"] = "sds",
["Tiếng Berber nguyên thủy"] = "ber-pro",
["Tiếng Berber-Do Thái"] = "jbe",
["Tiếng Berik"] = "bkl",
["Tiếng Betawi"] = "bew",
["Tiếng Bezhta"] = "kap",
["Tiếng Bhadrawah"] = "bhd",
["Tiếng Bhatri"] = "bgw",
["Tiếng Bhattiyat"] = "bht",
["Tiếng Bhil"] = "bhb",
["Tiếng Bhil Dungra"] = "duh",
["Tiếng Bhnong"] = "mkh-bhn",
["Tiếng Bhojpur"] = "bho",
["Tiếng Bhumij"] = "aav-bhu",
["Tiếng Bhunjia"] = "bhu",
["Tiếng Bidayuh Bau"] = "sne",
["Tiếng Bidayuh Biatah"] = "bth",
["Tiếng Bih"] = "ibh",
["Tiếng Bihari"] = "bh",
["Tiếng Bikol Buhi'non"] = "ubl",
["Tiếng Bilaspur"] = "kfs",
["Tiếng Bilen"] = "byn",
["Tiếng Bilua"] = "blb",
["Tiếng Bima"] = "bhp",
["Tiếng Binukid"] = "bkd",
["Tiếng Birao"] = "brr",
["Tiếng Birgit"] = "btf",
["Tiếng Birhor"] = "biy",
["Tiếng Birjia"] = "bix",
["Tiếng Bisaya Sabah"] = "bsy",
["Tiếng Bishnupriya"] = "bpy",
["Tiếng Bislama"] = "bi",
["Tiếng Bissa"] = "bib",
["Tiếng Bisu"] = "bzi",
["Tiếng Bit"] = "bgk",
["Tiếng Blackfoot"] = "bla",
["Tiếng Blagar"] = "beu",
["Tiếng Blang"] = "blr",
["Tiếng Bod nguyên thủy"] = "sit-bdi-pro",
["Tiếng Bodo (Ấn Độ)"] = "brx",
["Tiếng Bodo Parja"] = "bdv",
["Tiếng Bodo-Garo nguyên thủy"] = "tbq-bdg-pro",
["Tiếng Boghom"] = "bux",
["Tiếng Bokar"] = "sit-bok",
["Tiếng Boko"] = "bqc",
["Tiếng Bokobaru"] = "bus",
["Tiếng Bola"] = "bnp",
["Tiếng Boloki"] = "bkt",
["Tiếng Bomu"] = "bmq",
["Tiếng Bondo"] = "bfw",
["Tiếng Boon"] = "bnl",
["Tiếng Borôro"] = "bor",
["Tiếng Botlikh"] = "bph",
["Tiếng Bourguignon"] = "roa-brg",
["Tiếng Brahui"] = "brh",
["Tiếng Braj"] = "bra",
["Tiếng Breri"] = "brq",
["Tiếng Breton"] = "br",
["Tiếng Breton cổ"] = "obt",
["Tiếng Breton trung đại"] = "xbm",
["Tiếng Britton nguyên thủy"] = "cel-bry-pro",
["Tiếng Brokkat"] = "bro",
["Tiếng Brokpa"] = "sgt",
["Tiếng Bru"] = "bru",
["Tiếng Bru Tây"] = "brv",
["Tiếng Brâu"] = "brb",
["Tiếng Buang Mapos"] = "bzh",
["Tiếng Bube"] = "bvb",
["Tiếng Budukh"] = "bdk",
["Tiếng Bughotu"] = "bgt",
["Tiếng Bugis"] = "bug",
["Tiếng Buhid"] = "bku",
["Tiếng Bukhara"] = "bhh",
["Tiếng Bukiyip"] = "ape",
["Tiếng Bulgar"] = "xbo",
["Tiếng Bulgaria"] = "bg",
["Tiếng Bumthang"] = "kjz",
["Tiếng Bungku"] = "bkz",
["Tiếng Bunun"] = "bnn",
["Tiếng Burji"] = "bji",
["Tiếng Burunge"] = "bds",
["Tiếng Burushaski"] = "bsk",
["Tiếng Buryat"] = "bua",
["Tiếng Busa"] = "bqp",
["Tiếng Bushi"] = "buc",
["Tiếng Bussa"] = "dox",
["Tiếng Butuanon"] = "btw",
["Tiếng Bách Tế"] = "pkc",
["Tiếng Bạch Lạp Mã"] = "lay",
["Tiếng Bạch Nam"] = "bfs",
["Tiếng Bạch Trung"] = "bca",
["Tiếng Bạch nguyên thủy"] = "sit-bai-pro",
["Tiếng Bảo An"] = "peh",
["Tiếng Bắc Altai"] = "atv",
["Tiếng Bắc Amami Ōshima"] = "ryn",
["Tiếng Bắc Catanduanes Bikol"] = "cts",
["Tiếng Bắc Emberá"] = "emp",
["Tiếng Bắc Friesland"] = "frr",
["Tiếng Bắc Iroquois nguyên thủy"] = "iro-nor-pro",
["Tiếng Bắc Khanty"] = "kca-nor",
["Tiếng Bắc Mansi"] = "mns-nor",
["Tiếng Bắc Ndebele"] = "nd",
["Tiếng Bắc Nisu"] = "yiv",
["Tiếng Bắc Paiute"] = "pao",
["Tiếng Bắc Sami"] = "se",
["Tiếng Bắc Selkup"] = "sel-nor",
["Tiếng Bắc Slavey"] = "scs",
["Tiếng Bắc Thái"] = "nod",
["Tiếng Bắc Yukaghir"] = "ykg",
["Tiếng Bắc Âu cổ"] = "non",
["Tiếng Bắc Âu nguyên thủy"] = "gmq-pro",
["Tiếng Bố Cam"] = "bbh",
["Tiếng Bố Lưu"] = "ply",
["Tiếng Bố Mang"] = "bvp",
["Tiếng Bố Y"] = "pcc",
["Tiếng Bối-Thái nguyên thủy"] = "qfa-bet-pro",
["Tiếng Bồ Đào Nha"] = "pt",
["Tiếng Bổ trợ Quốc tế"] = "ia",
["Tiếng Ca Dong"] = "kxy",
["Tiếng Ca Tua"] = "kta",
["Tiếng Cahuilla"] = "chl",
["Tiếng Camling"] = "rab",
["Tiếng Camuni"] = "xcc",
["Tiếng Canela"] = "ram",
["Tiếng Cao Câu Ly"] = "zkg",
["Tiếng Capanahua"] = "kaq",
["Tiếng Carib nguyên thủy"] = "sai-car-pro",
["Tiếng Carrier"] = "crx",
["Tiếng Carrier Nam"] = "caf",
["Tiếng Catalan"] = "ca",
["Tiếng Catalan cổ"] = "roa-oca",
["Tiếng Catawba"] = "chc",
["Tiếng Cayuga"] = "cay",
["Tiếng Cebu"] = "ceb",
["Tiếng Celt nguyên thủy"] = "cel-pro",
["Tiếng Celtiberi"] = "xce",
["Tiếng Cerrado nguyên thủy"] = "sai-cer-pro",
["Tiếng Ch'orti'"] = "caa",
["Tiếng Chachi"] = "cbi",
["Tiếng Chagatai"] = "chg",
["Tiếng Chaima"] = "ciy",
["Tiếng Chak"] = "ckh",
["Tiếng Chakma"] = "ccp",
["Tiếng Chamalal"] = "cji",
["Tiếng Chamba"] = "cdh",
["Tiếng Chamicuro"] = "ccc",
["Tiếng Chamorro"] = "ch",
["Tiếng Chantyal"] = "chx",
["Tiếng Chatino cao nguyên Tây"] = "ctp",
["Tiếng Chaura"] = "crv",
["Tiếng Chavacano"] = "cbk",
["Tiếng Chechen"] = "ce",
["Tiếng Chenchu"] = "cde",
["Tiếng Chenoua"] = "cnu",
["Tiếng Chepang"] = "cdm",
["Tiếng Cherokee"] = "chr",
["Tiếng Chetti Moundadan"] = "cty",
["Tiếng Chetti Wayanad"] = "ctt",
["Tiếng Chewong"] = "cwg",
["Tiếng Cheyenne"] = "chy",
["Tiếng Chhattisgarh"] = "hne",
["Tiếng Chibcha"] = "chb",
["Tiếng Chichewa"] = "ny",
["Tiếng Chickasaw"] = "cic",
["Tiếng Chilcotin"] = "clc",
["Tiếng Chin Asho"] = "csh",
["Tiếng Chin Ekai"] = "cey",
["Tiếng Chin Falam"] = "cfm",
["Tiếng Chin Hakha"] = "cnh",
["Tiếng Chin Songlai"] = "csj",
["Tiếng Chin Tedim"] = "ctd",
["Tiếng Chinal"] = "cih",
["Tiếng Chinantec Ojitlán"] = "chj",
["Tiếng Chinantec Ozumacín"] = "chz",
["Tiếng Chinantec Tepinapa"] = "cte",
["Tiếng Chinook"] = "chh",
["Tiếng Chiricahua"] = "apm",
["Tiếng Chiru"] = "cdf",
["Tiếng Chittagong"] = "ctg",
["Tiếng Chiwere"] = "iow",
["Tiếng Chocangacakha"] = "cgk",
["Tiếng Choctaw"] = "cho",
["Tiếng Chodri"] = "cdi",
["Tiếng Chol"] = "ctu",
["Tiếng Chong"] = "cog",
["Tiếng Chu Ru"] = "cje",
["Tiếng Chukot"] = "ckt",
["Tiếng Chulym"] = "clw",
["Tiếng Churah"] = "cdj",
["Tiếng Chuuk"] = "chk",
["Tiếng Chuvan"] = "xcv",
["Tiếng Chuvash"] = "cv",
["Tiếng Châu Đại Dương nguyên thủy"] = "poz-oce-pro",
["Tiếng Chăm Tây"] = "cja",
["Tiếng Chăm cổ"] = "ocm",
["Tiếng Chăm nguyên thủy"] = "cmc-pro",
["Tiếng Chăm Đông"] = "cjm",
["Tiếng Chơ Ro"] = "crw",
["Tiếng Chứt"] = "scb",
["Tiếng Cia-Cia"] = "cia",
["Tiếng Cimbri"] = "cim",
["Tiếng Circassia nguyên thủy"] = "cau-cir-pro",
["Tiếng Co"] = "cua",
["Tiếng Cocama"] = "cod",
["Tiếng Cochimi"] = "coj",
["Tiếng Coeur d'Alene"] = "crd",
["Tiếng Cofán"] = "con",
["Tiếng Comanche"] = "com",
["Tiếng Comoros Maore"] = "swb",
["Tiếng Comox"] = "coo",
["Tiếng Copt"] = "cop",
["Tiếng Cornwall"] = "kw",
["Tiếng Cornwall cổ"] = "oco",
["Tiếng Corse"] = "co",
["Tiếng Cowlitz"] = "cow",
["Tiếng Cree"] = "cr",
["Tiếng Cree Moose"] = "crm",
["Tiếng Cree Đông Bắc"] = "crl",
["Tiếng Cree Đông Nam"] = "crj",
["Tiếng Cree đồng bằng"] = "crk",
["Tiếng Creole Antilles"] = "gcf",
["Tiếng Creole Guinea-Bissau"] = "pov",
["Tiếng Creole Haiti"] = "ht",
["Tiếng Creole Hà Lan Berbice"] = "brc",
["Tiếng Creole Jamaica"] = "jam",
["Tiếng Creole Louisiana"] = "lou",
["Tiếng Creole Mauritius"] = "mfe",
["Tiếng Creole Nghi Lan"] = "ycr",
["Tiếng Creole Réunion"] = "rcf",
["Tiếng Creole quần đảo Virgin"] = "vic",
["Tiếng Crow"] = "cro",
["Tiếng Cuman"] = "qwm",
["Tiếng Cumanagoto"] = "cuo",
["Tiếng Cumbria"] = "xcb",
["Tiếng Cupeño"] = "cup",
["Tiếng Cushit nguyên thủy"] = "cus-pro",
["Tiếng Cuyunon"] = "cyo",
["Tiếng Càn-đà-la"] = "pgd",
["Tiếng Cám"] = "gan",
["Tiếng Cơ Nặc Du Lạc"] = "jiu",
["Tiếng Cơ Tu"] = "ktv",
["Tiếng Cơ Tu Phương"] = "phg",
["Tiếng Cơ Tu Tây"] = "kuf",
["Tiếng Cơ Tu nguyên thủy"] = "mkh-kat-pro",
["Tiếng Cống"] = "cnc",
["Tiếng Cờ Lao Trắng"] = "giw",
["Tiếng Daasanach"] = "dsh",
["Tiếng Dabarre"] = "dbr",
["Tiếng Dacia"] = "xdc",
["Tiếng Dadibi"] = "mps",
["Tiếng Dagara Bắc"] = "dgi",
["Tiếng Dagba"] = "dgk",
["Tiếng Dagbani"] = "dag",
["Tiếng Dahalik"] = "dlk",
["Tiếng Dahalo"] = "dal",
["Tiếng Dakota"] = "dak",
["Tiếng Dakpa"] = "dka",
["Tiếng Dalmatia"] = "dlm",
["Tiếng Dambi"] = "dac",
["Tiếng Damel"] = "dml",
["Tiếng Dan"] = "dnj",
["Tiếng Danau"] = "dnu",
["Tiếng Dangaléat"] = "daa",
["Tiếng Danu"] = "dnv",
["Tiếng Danuwar"] = "dhw",
["Tiếng Dar Daju Daju"] = "djc",
["Tiếng Dargwa"] = "dar",
["Tiếng Dargwa nguyên thủy"] = "cau-drg-pro",
["Tiếng Daur"] = "dta",
["Tiếng Dawro"] = "dwr",
["Tiếng Deg Xinag"] = "ing",
["Tiếng Degema"] = "deg",
["Tiếng Denesuline"] = "chp",
["Tiếng Deori"] = "der",
["Tiếng Desiya"] = "dso",
["Tiếng Dhangu"] = "dhg",
["Tiếng Dhanka"] = "dhn",
["Tiếng Dharug"] = "xdk",
["Tiếng Dhatki"] = "mki",
["Tiếng Dhimal"] = "dhi",
["Tiếng Dhivehi"] = "dv",
["Tiếng Dhodia"] = "dho",
["Tiếng Dhundhar"] = "dhd",
["Tiếng Dibabawon"] = "mbd",
["Tiếng Dieri"] = "dif",
["Tiếng Digan"] = "rom",
["Tiếng Digan Balkan"] = "rmn",
["Tiếng Digan Baltic"] = "rml",
["Tiếng Digan Tavringer"] = "rmu",
["Tiếng Dimasa"] = "dis",
["Tiếng Dime"] = "dim",
["Tiếng Dinka"] = "din",
["Tiếng Dirasha"] = "gdl",
["Tiếng Ditidaht"] = "dtd",
["Tiếng Dizi"] = "mdx",
["Tiếng Dizi nguyên thủy"] = "omv-diz-pro",
["Tiếng Djinang"] = "dji",
["Tiếng Do Thái"] = "he",
["Tiếng Dogri"] = "doi",
["Tiếng Dogri Hindi"] = "dgo",
["Tiếng Dogrib"] = "dgr",
["Tiếng Dolgan"] = "dlg",
["Tiếng Dolpo"] = "dre",
["Tiếng Domaaki"] = "dmk",
["Tiếng Domari"] = "rmt",
["Tiếng Dongolawi"] = "kzh",
["Tiếng Doteli"] = "dty",
["Tiếng Dravida nguyên thủy"] = "dra-pro",
["Tiếng Dubla"] = "dub",
["Tiếng Dukha"] = "trk-dkh",
["Tiếng Dumi"] = "dus",
["Tiếng Duruwa"] = "pci",
["Tiếng Dusun Witu"] = "duw",
["Tiếng Duun"] = "dux",
["Tiếng Duy Ngô Nhĩ"] = "ug",
["Tiếng Duy Ngô Nhĩ cổ"] = "oui",
["Tiếng Dyirbal"] = "dbl",
["Tiếng Dyula"] = "dyu",
["Tiếng Dzala"] = "dzl",
["Tiếng Dzongkha"] = "dz",
["Tiếng Dzuun"] = "dnn",
["Tiếng Ebla"] = "xeb",
["Tiếng Ebrié"] = "ebr",
["Tiếng Ebughu"] = "ebg",
["Tiếng Ede Ica"] = "ica",
["Tiếng Ede Idaca"] = "idd",
["Tiếng Ede Nago"] = "nqg",
["Tiếng Edekiri nguyên thủy"] = "alv-edk-pro",
["Tiếng Edo"] = "bin",
["Tiếng Edoid nguyên thủy"] = "alv-edo-pro",
["Tiếng Efai"] = "efa",
["Tiếng Efate Bắc"] = "llp",
["Tiếng Efate Nam"] = "erk",
["Tiếng Efe"] = "efe",
["Tiếng Efik"] = "efi",
["Tiếng Ega"] = "ega",
["Tiếng Eggon"] = "ego",
["Tiếng Ehueun"] = "ehu",
["Tiếng Eipomek"] = "eip",
["Tiếng Eitiep"] = "eit",
["Tiếng Ejagham"] = "etu",
["Tiếng El Molo"] = "elo",
["Tiếng Elam"] = "elx",
["Tiếng Elymi"] = "xly",
["Tiếng Emberá-Chamí"] = "cmi",
["Tiếng Emberá-Tadó"] = "tdc",
["Tiếng Embu"] = "ebu",
["Tiếng Emilia"] = "egl",
["Tiếng Enets lãnh nguyên"] = "enh",
["Tiếng Enets rừng"] = "enf",
["Tiếng Engenni"] = "enn",
["Tiếng Enisei nguyên thủy"] = "qfa-yen-pro",
["Tiếng Eotile"] = "eot",
["Tiếng Epie"] = "epi",
["Tiếng Eravalla"] = "era",
["Tiếng Erzya"] = "myv",
["Tiếng Esan"] = "ish",
["Tiếng Ese"] = "mcq",
["Tiếng Esimbi"] = "ags",
["Tiếng Eskimo nguyên thủy"] = "esx-esk-pro",
["Tiếng Eskimo-Aleut nguyên thủy"] = "esx-pro",
["Tiếng Estonia"] = "et",
["Tiếng Eteocrete"] = "ecr",
["Tiếng Etrusca"] = "ett",
["Tiếng Even"] = "eve",
["Tiếng Evenk"] = "evn",
["Tiếng Ewe"] = "ee",
["Tiếng Fala"] = "fax",
["Tiếng Falisci"] = "xfa",
["Tiếng Fanagalo"] = "fng",
["Tiếng Fang (Bantu)"] = "fan",
["Tiếng Faroe"] = "fo",
["Tiếng Fe'fe'"] = "fmp",
["Tiếng Fiji"] = "fj",
["Tiếng Finn nguyên thủy"] = "urj-fin-pro",
["Tiếng Flemish Tây"] = "vls",
["Tiếng Fogaha"] = "ber-fog",
["Tiếng Foi"] = "foi",
["Tiếng Fon"] = "fon",
["Tiếng Fox"] = "sac",
["Tiếng Franche-Comté"] = "roa-fcm",
["Tiếng Franco-Provençal"] = "frp",
["Tiếng Franken Trung"] = "gmw-cfr",
["Tiếng Frisia Saterland"] = "stq",
["Tiếng Frisia cổ"] = "ofs",
["Tiếng Friuli"] = "fur",
["Tiếng Fula"] = "ff",
["Tiếng Fur"] = "fvr",
["Tiếng Ga"] = "gaa",
["Tiếng Gabri"] = "gab",
["Tiếng Gadaba Bodo"] = "gbj",
["Tiếng Gaddang"] = "gad",
["Tiếng Gaddi"] = "gbk",
["Tiếng Gael Scotland"] = "gd",
["Tiếng Gagauz"] = "gag",
["Tiếng Gahri"] = "bfu",
["Tiếng Galati"] = "xga",
["Tiếng Galicia"] = "gl",
["Tiếng Galicia-Bồ Đào Nha"] = "roa-opt",
["Tiếng Gallo"] = "roa-gal",
["Tiếng Gallura"] = "sdn",
["Tiếng Galo"] = "adl",
["Tiếng Gamilaraay"] = "kld",
["Tiếng Gamit"] = "gbl",
["Tiếng Gamo"] = "gmv",
["Tiếng Ganza"] = "gza",
["Tiếng Garasia Adiwasi"] = "gas",
["Tiếng Garasia Rajput"] = "gra",
["Tiếng Garhwal"] = "gbm",
["Tiếng Garifuna"] = "cab",
["Tiếng Garo"] = "grt",
["Tiếng Garre"] = "gex",
["Tiếng Gata'"] = "gaq",
["Tiếng Gaul"] = "cel-gau",
["Tiếng Gawar-Bati"] = "gwt",
["Tiếng Gawwada"] = "gwd",
["Tiếng Gayil"] = "gyl",
["Tiếng Gbe Saxwe"] = "sxw",
["Tiếng Gbe Waci"] = "wci",
["Tiếng Gbe nguyên thủy"] = "alv-gbe-pro",
["Tiếng Gbiri-Niragu"] = "grh",
["Tiếng Gedeo"] = "drs",
["Tiếng Gen"] = "gej",
["Tiếng German Tây nguyên thủy"] = "gmw-pro",
["Tiếng German nguyên thủy"] = "gem-pro",
["Tiếng Graeco-Phrygia nguyên thủy"] = "ine-grp-pro",
["Tiếng Geʽez"] = "gez",
["Tiếng Ghadames"] = "gha",
["Tiếng Ghomala'"] = "bbj",
["Tiếng Ghomara"] = "gho",
["Tiếng Ghotuo"] = "aaa",
["Tiếng Gia Rai"] = "jra",
["Tiếng Gikuyu"] = "ki",
["Tiếng Gilak"] = "glk",
["Tiếng Gimi (Goroka)"] = "gim",
["Tiếng Girirra"] = "gii",
["Tiếng Giryama"] = "nyf",
["Tiếng Gitxsan"] = "git",
["Tiếng Giẻ"] = "jeh",
["Tiếng Glosa"] = "igs",
["Tiếng Godoberi"] = "gdo",
["Tiếng Gofa"] = "gof",
["Tiếng Gone Dau"] = "goo",
["Tiếng Gooniyandi"] = "gni",
["Tiếng Goran"] = "hac",
["Tiếng Gorontalo"] = "gor",
["Tiếng Gorowa"] = "gow",
["Tiếng Goth"] = "got",
["Tiếng Gotland"] = "gmq-gut",
["Tiếng Gotland cổ"] = "gmq-ogt",
["Tiếng Greenland"] = "kl",
["Tiếng Gruzia"] = "ka",
["Tiếng Gruzia cổ"] = "oge",
["Tiếng Gruzia-Do Thái"] = "jge",
["Tiếng Gruzia-Zan nguyên thủy"] = "ccs-gzn-pro",
["Tiếng Guajajára"] = "gub",
["Tiếng Guajá"] = "gvj",
["Tiếng Guanche"] = "gnc",
["Tiếng Guarani Mbya"] = "gun",
["Tiếng Guarani Paraguay"] = "gug",
["Tiếng Guaraní"] = "gn",
["Tiếng Guarayu"] = "gyr",
["Tiếng Gujar"] = "gju",
["Tiếng Gujarat"] = "gu",
["Tiếng Gujarat cổ"] = "inc-ogu",
["Tiếng Gujarat trung đại"] = "inc-mgu",
["Tiếng Gulay"] = "gvl",
["Tiếng Gulimancema"] = "gux",
["Tiếng Gumuz"] = "guk",
["Tiếng Gun"] = "guw",
["Tiếng Gurenne"] = "gur",
["Tiếng Guugu Yimidhirr"] = "kky",
["Tiếng Gwichʼin"] = "gwi",
["Tiếng H'Mông Tương Tây Tây"] = "mmr",
["Tiếng H'Mông-Miền nguyên thủy"] = "hmx-pro",
["Tiếng H'roi"] = "hro",
["Tiếng Hachijō"] = "jpx-hcj",
["Tiếng Hadiyya"] = "hdy",
["Tiếng Haida"] = "hai",
["Tiếng Haisla"] = "has",
["Tiếng Hajong"] = "haj",
["Tiếng Halba"] = "hlb",
["Tiếng Halkomelem"] = "hur",
["Tiếng Hamer-Banna"] = "amf",
["Tiếng Hano"] = "lml",
["Tiếng Hanunoo"] = "hnn",
["Tiếng Harari"] = "har",
["Tiếng Harsusi"] = "hss",
["Tiếng Haryanvi"] = "bgc",
["Tiếng Hatti"] = "xht",
["Tiếng Hausa"] = "ha",
["Tiếng Haush"] = "sai-hau",
["Tiếng Havasupai-Walapai-Yavapai"] = "yuf",
["Tiếng Hawaii"] = "haw",
["Tiếng Hazara"] = "haz",
["Tiếng Heiban"] = "hbn",
["Tiếng Heiltsuk"] = "hei",
["Tiếng Hellen nguyên thủy"] = "grk-pro",
["Tiếng Herero"] = "hz",
["Tiếng Hernici"] = "xhr",
["Tiếng Higaonon"] = "mba",
["Tiếng Hiligaynon"] = "hil",
["Tiếng Hindi"] = "hi",
["Tiếng Hindi Fiji"] = "hif",
["Tiếng Hindi cổ"] = "inc-ohi",
["Tiếng Hindko Bắc"] = "hno",
["Tiếng Hinduri"] = "hii",
["Tiếng Hindustan Caribe"] = "hns",
["Tiếng Hinukh"] = "gin",
["Tiếng Hiri Motu"] = "ho",
["Tiếng Hitti"] = "hit",
["Tiếng Hiw"] = "hiw",
["Tiếng Hlai"] = "lic",
["Tiếng Hlai nguyên thủy"] = "qfa-lic-pro",
["Tiếng Ho"] = "hoc",
["Tiếng Hoava"] = "hoa",
["Tiếng Hocak"] = "win",
["Tiếng Holiya"] = "hoy",
["Tiếng Hopi"] = "hop",
["Tiếng Horpa"] = "ero",
["Tiếng Hozo"] = "hoz",
["Tiếng Hpon"] = "hpo",
["Tiếng Hrê"] = "hre",
["Tiếng Hu"] = "huo",
["Tiếng Hulaulá"] = "huy",
["Tiếng Hungary"] = "hu",
["Tiếng Hunsrik"] = "hrx",
["Tiếng Hunzib"] = "huz",
["Tiếng Hupa"] = "hup",
["Tiếng Hupdë"] = "jup",
["Tiếng Hurri"] = "xhu",
["Tiếng Huy"] = "czh",
["Tiếng Hy Lạp"] = "el",
["Tiếng Hy Lạp Cappadocia"] = "cpg",
["Tiếng Hy Lạp Italiot"] = "grk-ita",
["Tiếng Hy Lạp Mariupol"] = "grk-mar",
["Tiếng Hy Lạp Mycenae"] = "gmy",
["Tiếng Hy Lạp Pontos"] = "pnt",
["Tiếng Hy Lạp cổ"] = "grc",
["Tiếng Hyam"] = "jab",
["Tiếng Hà Lan"] = "nl",
["Tiếng Hà Lan Jersey"] = "gmw-jdt",
["Tiếng Hà Lan cổ"] = "odt",
["Tiếng Hà Lan trung đại"] = "dum",
["Tiếng Hà Lăng"] = "hal",
["Tiếng Hà Nhì"] = "hni",
["Tiếng Hán thượng cổ"] = "och",
["Tiếng Hán trung cổ"] = "ltc",
["Tiếng Hán-Tạng nguyên thủy"] = "sit-pro",
["Tiếng Hạ Saxon Hà Lan"] = "nds-nl",
["Tiếng Hạ Sorb"] = "dsb",
["Tiếng Hạ Tanana"] = "taa",
["Tiếng Hạ Đức"] = "nds",
["Tiếng Hạ Đức Mennonite"] = "pdt",
["Tiếng Hạ Đức trung đại"] = "gml",
["Tiếng Hạ Đức tại Đức"] = "nds-de",
["Tiếng Iaai"] = "iai",
["Tiếng Ibaloi"] = "ibl",
["Tiếng Iban"] = "iba",
["Tiếng Ibanag"] = "ibg",
["Tiếng Ibatan"] = "ivb",
["Tiếng Ibibio"] = "ibb",
["Tiếng Ibino"] = "ibn",
["Tiếng Ibuoro"] = "ibr",
["Tiếng Iceland"] = "is",
["Tiếng Ida'an"] = "dbj",
["Tiếng Ido"] = "io",
["Tiếng Idu"] = "clk",
["Tiếng Ifugao Batad"] = "ifb",
["Tiếng Ifè"] = "ife",
["Tiếng Igala"] = "igl",
["Tiếng Igbo"] = "ig",
["Tiếng Ikposo"] = "kpo",
["Tiếng Ikwere"] = "ikw",
["Tiếng Ili Turki"] = "ili",
["Tiếng Ilokano"] = "ilo",
["Tiếng Indo-Bồ Đào Nha"] = "idb",
["Tiếng Indonesia"] = "id",
["Tiếng Indonesia Peranakan"] = "pea",
["Tiếng Ingria"] = "izh",
["Tiếng Ingush"] = "inh",
["Tiếng Inor"] = "ior",
["Tiếng Interlingue"] = "ie",
["Tiếng Intha"] = "int",
["Tiếng Inuit nguyên thủy"] = "esx-inu-pro",
["Tiếng Inuktitut"] = "iu",
["Tiếng Inuktitut Đông Canada"] = "ike",
["Tiếng Inupiaq"] = "ik",
["Tiếng Inuvialuktun"] = "ikt",
["Tiếng Iran nguyên thủy"] = "ira-pro",
["Tiếng Iraqw"] = "irk",
["Tiếng Ireland"] = "ga",
["Tiếng Ireland cổ"] = "sga",
["Tiếng Ireland trung đại"] = "mga",
["Tiếng Iroquois nguyên thủy"] = "iro-pro",
["Tiếng Irula"] = "iru",
["Tiếng Isan"] = "tts",
["Tiếng Ishkashim"] = "isk",
["Tiếng Isnag"] = "isd",
["Tiếng Isoko"] = "iso",
["Tiếng Istria"] = "ist",
["Tiếng Istria Rumani"] = "ruo",
["Tiếng Italic nguyên thủy"] = "itc-pro",
["Tiếng Itaŋikom"] = "bkm",
["Tiếng Itelmen"] = "itl",
["Tiếng Itene"] = "ite",
["Tiếng Itonama"] = "ito",
["Tiếng Itsekiri"] = "its",
["Tiếng Itu Mbon Uzo"] = "itm",
["Tiếng Ivatan"] = "ivv",
["Tiếng Iwaidja"] = "ibd",
["Tiếng Ixil"] = "ixl",
["Tiếng Izon"] = "ijc",
["Tiếng Jacaltec"] = "jac",
["Tiếng Jah Hut"] = "jah",
["Tiếng Jamamadí"] = "jaa",
["Tiếng Japhug"] = "sit-jap",
["Tiếng Jaqaru"] = "jqr",
["Tiếng Jarawa"] = "anq",
["Tiếng Jaunsar"] = "jns",
["Tiếng Java"] = "jv",
["Tiếng Java Caribe"] = "jvn",
["Tiếng Java cổ"] = "kaw",
["Tiếng Javindo"] = "jvd",
["Tiếng Jehai"] = "jhi",
["Tiếng Jeju"] = "jje",
["Tiếng Jemez"] = "tow",
["Tiếng Jicarilla"] = "apj",
["Tiếng Jiiddu"] = "jii",
["Tiếng Jirel"] = "jul",
["Tiếng Jju"] = "kaj",
["Tiếng Jru'"] = "lbo",
["Tiếng Juang"] = "jun",
["Tiếng Jukun Takum"] = "jbu",
["Tiếng Jumaytepeque"] = "nai-jum",
["Tiếng Jumjum"] = "jum",
["Tiếng Juray"] = "juy",
["Tiếng Juǀ'hoan"] = "ktz",
["Tiếng Jylland"] = "jut",
["Tiếng Jê Bắc nguyên thủy"] = "sai-nje-pro",
["Tiếng Jê nguyên thủy"] = "sai-jee-pro",
["Tiếng K'Ho"] = "kpm",
["Tiếng K'iche'"] = "quc",
["Tiếng Kabardia"] = "kbd",
["Tiếng Kabiye"] = "kbp",
["Tiếng Kabuverdianu"] = "kea",
["Tiếng Kabyle"] = "kab",
["Tiếng Kachama-Ganjule"] = "kcx",
["Tiếng Kachin"] = "kac",
["Tiếng Kadar"] = "kej",
["Tiếng Kadazan bờ biển"] = "kzj",
["Tiếng Kadu"] = "zkd",
["Tiếng Kafa"] = "kbr",
["Tiếng Kagayanen"] = "cgc",
["Tiếng Kaikadi"] = "kep",
["Tiếng Kaingang"] = "kgp",
["Tiếng Kaitag"] = "xdq",
["Tiếng Kakabai"] = "kqf",
["Tiếng Kaki Ae"] = "tbd",
["Tiếng Kalam"] = "gwc",
["Tiếng Kalanguya"] = "kak",
["Tiếng Kalao"] = "kly",
["Tiếng Kalash"] = "kls",
["Tiếng Kalinga Limos"] = "kmk",
["Tiếng Kalkot"] = "xka",
["Tiếng Kalmyk"] = "xal",
["Tiếng Kalo Phần Lan"] = "rmf",
["Tiếng Kamarupi Prakrit"] = "inc-kam",
["Tiếng Kamassia"] = "xas",
["Tiếng Kamayo"] = "kyk",
["Tiếng Kambaata"] = "ktb",
["Tiếng Kambera"] = "xbr",
["Tiếng Kamula"] = "xla",
["Tiếng Kanakanavu"] = "xnb",
["Tiếng Kanan"] = "zkn",
["Tiếng Kangean"] = "kkv",
["Tiếng Kangra"] = "xnr",
["Tiếng Kankanaey"] = "kne",
["Tiếng Kannada"] = "kn",
["Tiếng Kannada cổ"] = "dra-okn",
["Tiếng Kannauj"] = "bjj",
["Tiếng Kanuri"] = "kr",
["Tiếng Kapampangan"] = "pam",
["Tiếng Kapingamarangi"] = "kpg",
["Tiếng Kaqchikel"] = "cak",
["Tiếng Karachay-Balkar"] = "krc",
["Tiếng Karaim"] = "kdr",
["Tiếng Karajá"] = "kpj",
["Tiếng Karakalpak"] = "kaa",
["Tiếng Karakhanid"] = "xqa",
["Tiếng Karao"] = "kyj",
["Tiếng Karata"] = "kpt",
["Tiếng Karbi"] = "mjw",
["Tiếng Karekare"] = "kai",
["Tiếng Karelia"] = "krl",
["Tiếng Karen Bwe"] = "bwe",
["Tiếng Karen Geba"] = "kvq",
["Tiếng Karen Geko"] = "ghk",
["Tiếng Karen Mobwa"] = "jkm",
["Tiếng Karen Paku"] = "jkp",
["Tiếng Karen S'gaw"] = "ksw",
["Tiếng Karen Zayein"] = "kxk",
["Tiếng Karen nguyên thủy"] = "kar-pro",
["Tiếng Kari'na"] = "car",
["Tiếng Kariri"] = "kzw",
["Tiếng Karitiâna"] = "ktn",
["Tiếng Karo"] = "kxh",
["Tiếng Kartvelia nguyên thủy"] = "ccs-pro",
["Tiếng Kashaya"] = "kju",
["Tiếng Kashmir"] = "ks",
["Tiếng Kaszëb"] = "csb",
["Tiếng Katang Bắc"] = "ncq",
["Tiếng Kaurna"] = "zku",
["Tiếng Kavalan"] = "ckv",
["Tiếng Kavet"] = "krv",
["Tiếng Kawésqar"] = "alc",
["Tiếng Kayan"] = "pdu",
["Tiếng Kayapó"] = "txu",
["Tiếng Kayort"] = "kyv",
["Tiếng Kazakh"] = "kk",
["Tiếng Kensiu"] = "kns",
["Tiếng Kenyang"] = "ken",
["Tiếng Kerek"] = "krk",
["Tiếng Kerman"] = "xme-ker",
["Tiếng Ket"] = "ket",
["Tiếng Khakas"] = "kjh",
["Tiếng Khalaj"] = "klj",
["Tiếng Khaling"] = "klr",
["Tiếng Kham Gamale"] = "kgj",
["Tiếng Kham Parbate Tây"] = "kjl",
["Tiếng Kham Parbate Đông"] = "kif",
["Tiếng Kham Sheshi"] = "kip",
["Tiếng Khamba"] = "kbg",
["Tiếng Khamti"] = "kht",
["Tiếng Khamyang"] = "ksu",
["Tiếng Khang Gia"] = "kxs",
["Tiếng Khanty"] = "kca",
["Tiếng Kharia"] = "khr",
["Tiếng Khasa Prakrit"] = "inc-kha",
["Tiếng Khasi"] = "kha",
["Tiếng Khasi nguyên thủy"] = "aav-khs-pro",
["Tiếng Khazar"] = "zkz",
["Tiếng Khengkha"] = "xkf",
["Tiếng Khiamniungan"] = "kix",
["Tiếng Khinalug"] = "kjj",
["Tiếng Khiết Đan"] = "zkt",
["Tiếng Khmer"] = "km",
["Tiếng Khmer Surin"] = "kxm",
["Tiếng Khmer cổ"] = "okz",
["Tiếng Khmer nguyên thủy"] = "mkh-kmr-pro",
["Tiếng Khmer trung đại"] = "xhm",
["Tiếng Khoekhoe"] = "naq",
["Tiếng Kholosi"] = "inc-kho",
["Tiếng Khotan"] = "kho",
["Tiếng Khowar"] = "khw",
["Tiếng Khroskyabs"] = "jiq",
["Tiếng Khuen"] = "khf",
["Tiếng Khvarshi"] = "khv",
["Tiếng Khwarezm"] = "xco",
["Tiếng Khách Gia"] = "hak",
["Tiếng Kháng"] = "kjm",
["Tiếng Khùa"] = "xhv",
["Tiếng Khün"] = "kkh",
["Tiếng Khơ Mú"] = "kjg",
["Tiếng Khơ Mú nguyên thủy"] = "mkh-khm-pro",
["Tiếng Khương Bắc"] = "cng",
["Tiếng Khương Nam"] = "qxs",
["Tiếng Khương Đường"] = "cna",
["Tiếng Kickapoo"] = "kic",
["Tiếng Kikai"] = "kzg",
["Tiếng Kili"] = "tuw-kil",
["Tiếng Kim"] = "kia",
["Tiếng Kim Môn"] = "mji",
["Tiếng Kimbundu"] = "kmb",
["Tiếng Kinaray-a"] = "krj",
["Tiếng Kinnaur"] = "kfk",
["Tiếng Kinnaur Harija"] = "kjo",
["Tiếng Kintaq"] = "knq",
["Tiếng Kiowa"] = "kio",
["Tiếng Gilbert"] = "gil",
["Tiếng Kirike"] = "okr",
["Tiếng Kisan"] = "xis",
["Tiếng Kistane"] = "gru",
["Tiếng Kituba"] = "ktu",
["Tiếng Klallam"] = "clm",
["Tiếng Klingon"] = "tlh",
["Tiếng Knaan"] = "czk",
["Tiếng Koalib"] = "kib",
["Tiếng Kobon"] = "kpw",
["Tiếng Koch"] = "kdq",
["Tiếng Koda"] = "cdz",
["Tiếng Kodava"] = "kfa",
["Tiếng Kohistan"] = "mvy",
["Tiếng Koibal"] = "zkb",
["Tiếng Kok Borok"] = "trp",
["Tiếng Kolami"] = "kfb",
["Tiếng Kolhe"] = "ekl",
["Tiếng Koli Kachi"] = "gjk",
["Tiếng Koli Parkar"] = "kvx",
["Tiếng Koli Wadiyara"] = "kxp",
["Tiếng Koman nguyên thủy"] = "ssa-kom-pro",
["Tiếng Komi cổ"] = "urj-koo",
["Tiếng Komi-Permyak"] = "koi",
["Tiếng Komi-Yazva"] = "urj-kya",
["Tiếng Komi-Zyrian"] = "kpv",
["Tiếng Komo"] = "xom",
["Tiếng Komodo"] = "kvh",
["Tiếng Konabéré"] = "bbo",
["Tiếng Konda-Dora"] = "kfc",
["Tiếng Kondekor"] = "gau",
["Tiếng Kongo"] = "kg",
["Tiếng Konkan"] = "kok",
["Tiếng Konobo"] = "kqo",
["Tiếng Konso"] = "kxc",
["Tiếng Koonzime"] = "ozm",
["Tiếng Koore"] = "kqy",
["Tiếng Koraga Korra"] = "kfd",
["Tiếng Koraga Mudu"] = "vmd",
["Tiếng Korku"] = "kfq",
["Tiếng Korwa"] = "kfp",
["Tiếng Koryak"] = "kpy",
["Tiếng Kosrae"] = "kos",
["Tiếng Kota (Ấn Độ)"] = "kfe",
["Tiếng Kotava"] = "avk",
["Tiếng Kott"] = "zko",
["Tiếng Koya"] = "kff",
["Tiếng Kpelle Guinea"] = "gkp",
["Tiếng Kpelle Liberia"] = "xpe",
["Tiếng Kra nguyên thủy"] = "qfa-kra-pro",
["Tiếng Kra-Dai nguyên thủy"] = "qfa-tak-pro",
["Tiếng Kraol"] = "rka",
["Tiếng Kresh"] = "krs",
["Tiếng Krio"] = "kri",
["Tiếng Kriol Úc"] = "rop",
["Tiếng Krung"] = "krr",
["Tiếng Krymchak"] = "jct",
["Tiếng Kryts"] = "kry",
["Tiếng Ktunaxa"] = "kut",
["Tiếng Kubachi"] = "ugh",
["Tiếng Kudiya"] = "kfg",
["Tiếng Kudmal"] = "kyw",
["Tiếng Kui (Ấn Độ)"] = "uki",
["Tiếng Kui Dawik"] = "dwk",
["Tiếng Kuke"] = "ght",
["Tiếng Kuki-Chin nguyên thủy"] = "tbq-kuk-pro",
["Tiếng Kukna"] = "kex",
["Tiếng Kullu"] = "kfx",
["Tiếng Kulon-Pazeh"] = "uun",
["Tiếng Kumbewaha"] = "xks",
["Tiếng Kumeyaay"] = "nai-kum",
["Tiếng Kumyk"] = "kum",
["Tiếng Kumzar"] = "zum",
["Tiếng Kuna"] = "cuk",
["Tiếng Kundal Shahi"] = "shd",
["Tiếng Kunigami"] = "xug",
["Tiếng Kuo"] = "xuo",
["Tiếng Kupia"] = "key",
["Tiếng Kurichiya"] = "kfh",
["Tiếng Kurmanji"] = "kmr",
["Tiếng Kurtokha"] = "xkz",
["Tiếng Kurukh"] = "kru",
["Tiếng Kurumba Alu"] = "xua",
["Tiếng Kurumba Attapady"] = "pkr",
["Tiếng Kurumba Betta"] = "xub",
["Tiếng Kurumba Jennu"] = "xuj",
["Tiếng Kurumba Kannada"] = "kfi",
["Tiếng Kurumba Mullu"] = "kpb",
["Tiếng Kushi"] = "kuh",
["Tiếng Kutch"] = "kfr",
["Tiếng Kutep"] = "kub",
["Tiếng Kuvi"] = "kxv",
["Tiếng Kuy"] = "kdt",
["Tiếng Kven"] = "fkv",
["Tiếng Kw'adza"] = "wka",
["Tiếng Kwak'wala"] = "kwk",
["Tiếng Kwanja"] = "knp",
["Tiếng Kwanyama"] = "kj",
["Tiếng Kwinti"] = "kww",
["Tiếng Kyakala"] = "tuw-kkl",
["Tiếng Kyrgyz"] = "ky",
["Tiếng Kyrgyz Phú Dụ"] = "trk-fyk",
["Tiếng Kâte"] = "kmg",
["Tiếng La Hủ"] = "lhu",
["Tiếng Laalaa"] = "cae",
["Tiếng Ladakh"] = "lbj",
["Tiếng Ladin"] = "lld",
["Tiếng Ladino"] = "lad",
["Tiếng Lahnda"] = "lah",
["Tiếng Lahta"] = "kvt",
["Tiếng Lak"] = "lbe",
["Tiếng Lakalei"] = "lka",
["Tiếng Laki"] = "lki",
["Tiếng Lakota"] = "lkt",
["Tiếng Lama Gur"] = "las",
["Tiếng Lambadi"] = "lmn",
["Tiếng Lamboya"] = "lmy",
["Tiếng Lamkang"] = "lmk",
["Tiếng Lanoh"] = "lnh",
["Tiếng Laomian"] = "lwm",
["Tiếng Lar"] = "lrl",
["Tiếng Lasalimu"] = "llm",
["Tiếng Lashi"] = "lsi",
["Tiếng Latgale"] = "ltg",
["Tiếng Latinh"] = "la",
["Tiếng Latundê"] = "ltn",
["Tiếng Latvia"] = "lv",
["Tiếng Lavukaleve"] = "lvk",
["Tiếng Lawa Tây"] = "lcp",
["Tiếng Lawa Đông"] = "lwl",
["Tiếng Lawi"] = "lvi",
["Tiếng Laya"] = "lya",
["Tiếng Laz"] = "lzz",
["Tiếng Lelemi"] = "lef",
["Tiếng Lemnos"] = "xle",
["Tiếng Lepcha"] = "lep",
["Tiếng Leponti"] = "xlp",
["Tiếng Lewo"] = "lww",
["Tiếng Lezgi"] = "lez",
["Tiếng Lezgi nguyên thủy"] = "cau-lzg-pro",
["Tiếng León"] = "roa-leo",
["Tiếng León cổ"] = "roa-ole",
["Tiếng Lhao Vo"] = "mhx",
["Tiếng Lhomi"] = "lhm",
["Tiếng Liabuku"] = "lix",
["Tiếng Libido"] = "liq",
["Tiếng Liguria"] = "lij",
["Tiếng Lillooet"] = "lil",
["Tiếng Limbum"] = "lmp",
["Tiếng Limburg"] = "li",
["Tiếng Lindu"] = "klw",
["Tiếng Lingala"] = "ln",
["Tiếng Lipan"] = "apl",
["Tiếng Lishana Deni"] = "lsd",
["Tiếng Lishanid Noshan"] = "aij",
["Tiếng Lisu"] = "lis",
["Tiếng Litva"] = "lt",
["Tiếng Litva cổ"] = "olt",
["Tiếng Livonia"] = "liv",
["Tiếng Livvi"] = "olo",
["Tiếng Lobi"] = "lob",
["Tiếng Lodha"] = "lbm",
["Tiếng Logba"] = "lgq",
["Tiếng Lojban"] = "jbo",
["Tiếng Loke"] = "loy",
["Tiếng Lokono"] = "arw",
["Tiếng Loma"] = "lom",
["Tiếng Lomavren"] = "rmi",
["Tiếng Lombard"] = "lmo",
["Tiếng Lorrain"] = "roa-lor",
["Tiếng Lotha Naga"] = "njh",
["Tiếng Lou"] = "loj",
["Tiếng Luba-Katanga"] = "lu",
["Tiếng Lucumí"] = "luq",
["Tiếng Luganda"] = "lg",
["Tiếng Luhya"] = "luy",
["Tiếng Lukpa"] = "dop",
["Tiếng Lumbu"] = "lup",
["Tiếng Lunana"] = "luk",
["Tiếng Lur Bắc"] = "lrc",
["Tiếng Lur Nam"] = "luz",
["Tiếng Lushootseed"] = "lut",
["Tiếng Lutuv"] = "clt",
["Tiếng Luwi"] = "xlu",
["Tiếng Luxembourg"] = "lb",
["Tiếng Lycia"] = "xlc",
["Tiếng Lydia"] = "xld",
["Tiếng Lyngngam"] = "lyg",
["Tiếng Lyydi"] = "lud",
["Tiếng Lào"] = "lo",
["Tiếng Lâm Cao"] = "onb",
["Tiếng Lô Lô"] = "ii",
["Tiếng Lô Lô-Miến nguyên thủy"] = "tbq-lob-pro",
["Tiếng Lư Nhân"] = "sit-lrn",
["Tiếng Lưu Cầu nguyên thủy"] = "jpx-ryu-pro",
["Tiếng Lự"] = "khb",
["Tiếng M'Nông Nam"] = "mnn",
["Tiếng M'Nông Trung"] = "cmo",
["Tiếng M'Nông Đông"] = "mng",
["Tiếng Ma Thoa"] = "nru",
["Tiếng Ma'anyan"] = "mhy",
["Tiếng Maaka"] = "mew",
["Tiếng Maale"] = "mdy",
["Tiếng Maasai"] = "mas",
["Tiếng Maay"] = "ymm",
["Tiếng Mabaan"] = "mfz",
["Tiếng Mabang"] = "mde",
["Tiếng Macedoni cổ đại"] = "xmk",
["Tiếng Macedonia"] = "mk",
["Tiếng Macushi"] = "mbc",
["Tiếng Madura"] = "mad",
["Tiếng Magaha"] = "mag",
["Tiếng Magar Tây"] = "mrd",
["Tiếng Magar Đông"] = "mgp",
["Tiếng Magori"] = "zgr",
["Tiếng Maguindanao"] = "mdh",
["Tiếng Mah Meri"] = "mhe",
["Tiếng Mahal"] = "mjx",
["Tiếng Maithil"] = "mai",
["Tiếng Majang"] = "mpe",
["Tiếng Makassar"] = "mak",
["Tiếng Mal"] = "mlf",
["Tiếng Malagasy"] = "mg",
["Tiếng Malankurava"] = "mjo",
["Tiếng Malapandaram"] = "mjp",
["Tiếng Malarya"] = "mjq",
["Tiếng Malasar"] = "ymr",
["Tiếng Malasar Mala"] = "ima",
["Tiếng Malavedan"] = "mjr",
["Tiếng Malayalam"] = "ml",
["Tiếng Malecite-Passamaquoddy"] = "pqm",
["Tiếng Malta"] = "mt",
["Tiếng Mampruli"] = "maw",
["Tiếng Man"] = "gv",
["Tiếng Manda (Ấn Độ)"] = "mha",
["Tiếng Mandahuaca"] = "mht",
["Tiếng Mandara"] = "tbf",
["Tiếng Mande nguyên thủy"] = "dmn-pro",
["Tiếng Mandi"] = "mjl",
["Tiếng Mandinka"] = "mnk",
["Tiếng Mangas"] = "zns",
["Tiếng Manggarai"] = "mqy",
["Tiếng Mangghuer"] = "xgn-mgr",
["Tiếng Mangghul"] = "mjg-mgr",
["Tiếng Manipur"] = "mni",
["Tiếng Mankanya"] = "knf",
["Tiếng Mannan"] = "mjv",
["Tiếng Mano"] = "mev",
["Tiếng Mansaka"] = "msk",
["Tiếng Mansi nguyên thủy"] = "mns-pro",
["Tiếng Manumanaw"] = "kxf",
["Tiếng Mao Nam"] = "mmd",
["Tiếng Maori"] = "mi",
["Tiếng Mapuche"] = "arn",
["Tiếng Maranao"] = "mrw",
["Tiếng Marathi"] = "mr",
["Tiếng Marathi cổ"] = "omr",
["Tiếng Marau"] = "mvr",
["Tiếng Mari Tây"] = "mrj",
["Tiếng Mari nguyên thủy"] = "chm-pro",
["Tiếng Mari Đông"] = "mhr",
["Tiếng Maria (Ấn Độ)"] = "mrr",
["Tiếng Maricopa"] = "mrc",
["Tiếng Marma"] = "rmz",
["Tiếng Marquises Bắc"] = "mrq",
["Tiếng Marquises Nam"] = "mqm",
["Tiếng Marrucini"] = "umc",
["Tiếng Marshall"] = "mh",
["Tiếng Marsi"] = "ims",
["Tiếng Martuthunira"] = "vma",
["Tiếng Marwar"] = "mwr",
["Tiếng Masbatenyo"] = "msb",
["Tiếng Maskelynes"] = "klv",
["Tiếng Matal"] = "mfh",
["Tiếng Mator"] = "mtm",
["Tiếng Maung"] = "mph",
["Tiếng Maya Yucatán"] = "yua",
["Tiếng Maya nguyên thủy"] = "myn-pro",
["Tiếng Mazahua Michoacán"] = "mmc",
["Tiếng Mazahua Trung"] = "maz",
["Tiếng Mazandaran"] = "mzn",
["Tiếng Mbabaram"] = "vmb",
["Tiếng Mbembe Tigon"] = "nza",
["Tiếng Mbembe sông Cross"] = "mfn",
["Tiếng Me'en"] = "mym",
["Tiếng Me'phaa Acatepec"] = "tpx",
["Tiếng Me'phaa Azoyú"] = "tpc",
["Tiếng Me'phaa Tlacoapa"] = "tpl",
["Tiếng Media cổ"] = "xme-old",
["Tiếng Medumba"] = "byv",
["Tiếng Mehri"] = "gdq",
["Tiếng Melo"] = "mfx",
["Tiếng Melpa"] = "med",
["Tiếng Memon"] = "mby",
["Tiếng Mendankwe-Nkwen"] = "mfd",
["Tiếng Mende"] = "men",
["Tiếng Menominee"] = "mez",
["Tiếng Mentawai"] = "mwv",
["Tiếng Meriam"] = "ulk",
["Tiếng Mesaka"] = "iyo",
["Tiếng Mesqan"] = "mvz",
["Tiếng Messapio"] = "cms",
["Tiếng Meänkieli"] = "fit",
["Tiếng Mi'kmaq"] = "mic",
["Tiếng Miami"] = "mia",
["Tiếng Minangkabau"] = "min",
["Tiếng Mingrelia"] = "xmf",
["Tiếng Minriq"] = "mnq",
["Tiếng Mintil"] = "mzt",
["Tiếng Miranda"] = "mwl",
["Tiếng Mirga"] = "zrg",
["Tiếng Mising"] = "mrg",
["Tiếng Miskito"] = "miq",
["Tiếng Mixtec Alcozauca"] = "xta",
["Tiếng Mixtec Chayuco"] = "mih",
["Tiếng Mixtec Yosondúa"] = "mpm",
["Tiếng Mixtec nguyên thủy"] = "omq-mix-pro",
["Tiếng Miyako"] = "mvi",
["Tiếng Mizo"] = "lus",
["Tiếng Miến Điện"] = "my",
["Tiếng Miến Điện cổ"] = "obr",
["Tiếng Miền nguyên thủy"] = "hmx-mie-pro",
["Tiếng Mlabri"] = "mra",
["Tiếng Mlahsö"] = "lhs",
["Tiếng Mogholi"] = "mhj",
["Tiếng Moglena-Rumani"] = "ruq",
["Tiếng Mohawk"] = "moh",
["Tiếng Mohegan-Pequot"] = "xpq",
["Tiếng Moken"] = "mwt",
["Tiếng Mokil"] = "mkj",
["Tiếng Moklen"] = "mkm",
["Tiếng Moksha"] = "mdf",
["Tiếng Molbog"] = "pwm",
["Tiếng Mongghul"] = "mjg-mgl",
["Tiếng Mongo"] = "lol",
["Tiếng Mongondow"] = "mog",
["Tiếng Mooré"] = "mos",
["Tiếng Mordvin nguyên thủy"] = "urj-mdv-pro",
["Tiếng Moro"] = "mor",
["Tiếng Morokodo"] = "mgc",
["Tiếng Mota"] = "mtt",
["Tiếng Motu"] = "meu",
["Tiếng Mozarab"] = "mxi",
["Tiếng Mpade"] = "mpi",
["Tiếng Mpi"] = "mpz",
["Tiếng Muak Sa-aak"] = "ukk",
["Tiếng Mudburra"] = "dmw",
["Tiếng Muduga"] = "udg",
["Tiếng Muna"] = "mnb",
["Tiếng Munda"] = "unx",
["Tiếng Munda nguyên thủy"] = "mun-pro",
["Tiếng Mundabli"] = "boe",
["Tiếng Mundari"] = "unr",
["Tiếng Munggui"] = "mth",
["Tiếng Munji"] = "mnj",
["Tiếng Munsee"] = "umu",
["Tiếng Muria Viễn Tây"] = "fmu",
["Tiếng Murle"] = "mur",
["Tiếng Mursi"] = "muz",
["Tiếng Muscogee"] = "mus",
["Tiếng Musi"] = "mui",
["Tiếng Muskogee nguyên thủy"] = "nai-mus-pro",
["Tiếng Muthuvan"] = "muv",
["Tiếng Mwan"] = "moa",
["Tiếng Mwotlap"] = "mlv",
["Tiếng Myene"] = "mye",
["Tiếng Mân Bắc"] = "mnp",
["Tiếng Mân Nam"] = "nan",
["Tiếng Mân Trung"] = "czo",
["Tiếng Mân Tuyền Chương"] = "nan-hbl",
["Tiếng Mân nguyên thủy"] = "zhx-min-pro",
["Tiếng Mân Đông"] = "cdo",
["Tiếng Mã Lai"] = "ms",
["Tiếng Mã Lai Ambon"] = "abs",
["Tiếng Mã Lai Baba"] = "mbf",
["Tiếng Mã Lai Bacan"] = "btj",
["Tiếng Mã Lai Brunei"] = "kxd",
["Tiếng Mã Lai Bắc Maluku"] = "max",
["Tiếng Mã Lai Kedah"] = "meo",
["Tiếng Mã Lai Pattani"] = "mfa",
["Tiếng Mã Lai Sarawak"] = "poz-sml",
["Tiếng Mã Lai cổ"] = "omy",
["Tiếng Mã Lai nguyên thủy"] = "poz-mly-pro",
["Tiếng Mã Lai-Chăm nguyên thủy"] = "poz-mcm-pro",
["Tiếng Mã Lai-Sumbawa nguyên thủy"] = "poz-msa-pro",
["Tiếng Mã Lai-Đa Đảo Trung Đông nguyên thủy"] = "poz-cet-pro",
["Tiếng Mã Lai-Đa Đảo nguyên thủy"] = "poz-pro",
["Tiếng Mã Lai-Đa Đảo Đông nguyên thủy"] = "pqe-pro",
["Tiếng Mã Liềng"] = "pkt",
["Tiếng Mãn Châu"] = "mnc",
["Tiếng Mòcheno"] = "mhn",
["Tiếng Môn"] = "mnw",
["Tiếng Môn Thái"] = "mnw-tha",
["Tiếng Môn cổ"] = "omx",
["Tiếng Môn nguyên thủy"] = "mkh-mnc-pro",
["Tiếng Môn trung đại"] = "mkh-mmn",
["Tiếng Môn-Khmer nguyên thủy"] = "mkh-pro",
["Tiếng Mông"] = "hmf",
["Tiếng Mông Cổ"] = "mn",
["Tiếng Mông Cổ Khamnigan"] = "ykh",
["Tiếng Mông Cổ cổ điển"] = "cmg",
["Tiếng Mông Cổ nguyên thủy"] = "xgn-pro",
["Tiếng Mông Cổ trung đại"] = "xng",
["Tiếng Mông Trắng"] = "mww",
["Tiếng Mơ Nâm"] = "moo",
["Tiếng Mường"] = "mtq",
["Tiếng Mạ"] = "cma",
["Tiếng Mảng"] = "zng",
["Tiếng Na Miểu"] = "neo",
["Tiếng Na Uy"] = "no",
["Tiếng Na Uy (Bokmål)"] = "nb",
["Tiếng Na Uy (Nynorsk)"] = "nn",
["Tiếng Nafaanra"] = "nfr",
["Tiếng Naga Chothe"] = "nct",
["Tiếng Naga Maring"] = "nng",
["Tiếng Naga Moyon"] = "nmo",
["Tiếng Naga Thangal"] = "nki",
["Tiếng Naga Trung nguyên thủy"] = "sit-aao-pro",
["Tiếng Nahua nguyên thủy"] = "azc-nah-pro",
["Tiếng Nahuatl"] = "nah",
["Tiếng Nahuatl Temascaltepec"] = "nhv",
["Tiếng Nahuatl cổ điển"] = "nci",
["Tiếng Nakh nguyên thủy"] = "cau-nkh-pro",
["Tiếng Nam Altai"] = "alt",
["Tiếng Nam Amami Ōshima"] = "ams",
["Tiếng Nam Dravida I nguyên thủy"] = "dra-sdo-pro",
["Tiếng Nam Dravida II nguyên thủy"] = "dra-sdt-pro",
["Tiếng Nam Dravida nguyên thủy"] = "dra-sou-pro",
["Tiếng Nam Kolami"] = "nit",
["Tiếng Nam Mansi"] = "mns-sou",
["Tiếng Nam Ndebele"] = "nr",
["Tiếng Nam Sami"] = "sma",
["Tiếng Nam Selkup"] = "sel-sou",
["Tiếng Nam Slavey"] = "xsl",
["Tiếng Nam Thái"] = "sou",
["Tiếng Nam Uzbek"] = "uzs",
["Tiếng Nam Yukaghir"] = "yux",
["Tiếng Nam Á nguyên thủy"] = "aav-pro",
["Tiếng Nam Đảo nguyên thủy"] = "map-pro",
["Tiếng Nam Động"] = "kmc",
["Tiếng Nam Ả Rập cổ"] = "sem-srb",
["Tiếng Nambikwara"] = "nab",
["Tiếng Nanai"] = "gld",
["Tiếng Nankina"] = "nnk",
["Tiếng Napoli"] = "nap",
["Tiếng Naskapi"] = "nsk",
["Tiếng Nateni"] = "ntm",
["Tiếng Naukan"] = "ynk",
["Tiếng Nauru"] = "na",
["Tiếng Navajo"] = "nv",
["Tiếng Ndau"] = "ndc",
["Tiếng Ndogo"] = "ndz",
["Tiếng Ndonga"] = "ng",
["Tiếng Nefusa"] = "jbn",
["Tiếng Negerhollands"] = "dcr",
["Tiếng Negidal"] = "neg",
["Tiếng Nenets lãnh nguyên"] = "yrk-tun",
["Tiếng Nepal"] = "ne",
["Tiếng Newa"] = "new",
["Tiếng Nga"] = "ru",
["Tiếng Nga bồi Taimyr"] = "crp-tpr",
["Tiếng Ngadha"] = "nxg",
["Tiếng Ngalum"] = "szb",
["Tiếng Ngam"] = "nmc",
["Tiếng Ngambay"] = "sba",
["Tiếng Nganasan"] = "nio",
["Tiếng Ngas"] = "anc",
["Tiếng Ngiemboon"] = "nnh",
["Tiếng Ngiyambaa"] = "wyb",
["Tiếng Ngomba"] = "jgo",
["Tiếng Ngombe (Congo)"] = "ngc",
["Tiếng Nguni nguyên thủy"] = "bnt-ngu-pro",
["Tiếng Nguồn"] = "nuo",
["Tiếng Ngô"] = "wuu",
["Tiếng Ngũ Đồn"] = "wuh",
["Tiếng Nha Lang"] = "yrn",
["Tiếng Nheengatu"] = "yrl",
["Tiếng Nhu Nhiên"] = "qfa-xgx-rou",
["Tiếng Nhĩ Tô"] = "ers",
["Tiếng Nhật"] = "ja",
["Tiếng Nhật Bản nguyên thủy"] = "jpx-pro",
["Tiếng Nhật thượng cổ"] = "ojp",
["Tiếng Nias"] = "nia",
["Tiếng Nicobar Car"] = "caq",
["Tiếng Nicobar Nam"] = "nik",
["Tiếng Nicobar Trung"] = "ncb",
["Tiếng Nicobar nguyên thủy"] = "aav-nic-pro",
["Tiếng Niger-Congo nguyên thủy"] = "nic-pro",
["Tiếng Nin-Sahara nguyên thủy"] = "ssa-pro",
["Tiếng Nisga'a"] = "ncg",
["Tiếng Niue"] = "niu",
["Tiếng Nivaclé"] = "cag",
["Tiếng Nivkh"] = "niv",
["Tiếng Nkari"] = "nkz",
["Tiếng Nkonya"] = "nko",
["Tiếng Nobiin"] = "fia",
["Tiếng Nobonob"] = "gaw",
["Tiếng Nogai"] = "nog",
["Tiếng Noon"] = "snf",
["Tiếng Noreia"] = "nrc",
["Tiếng Norman"] = "nrf",
["Tiếng Novgorod cổ"] = "zle-ono",
["Tiếng Novial"] = "nov",
["Tiếng Ntcham"] = "bud",
["Tiếng Nubaca"] = "baf",
["Tiếng Nubi"] = "kcn",
["Tiếng Nubia cổ"] = "onw",
["Tiếng Nuer"] = "nus",
["Tiếng Numidia"] = "nxm",
["Tiếng Nupe"] = "nup",
["Tiếng Nuristan nguyên thủy"] = "iir-nur-pro",
["Tiếng Nuu-chah-nulth"] = "nuk",
["Tiếng Nyah Kur"] = "cbn",
["Tiếng Nyaw"] = "nyw",
["Tiếng Nyeu"] = "nyl",
["Tiếng Nyishi"] = "njz",
["Tiếng Nyoro"] = "nyo",
["Tiếng Nyunga"] = "nys",
["Tiếng Nzadi"] = "nzd",
["Tiếng Nùng"] = "nut",
["Tiếng Nùng Vẻn"] = "enc",
["Tiếng Nǀuu"] = "ngh",
["Tiếng Nạp Tây"] = "nxq",
["Tiếng Nữ Chân"] = "juc",
["Tiếng O'odham"] = "ood",
["Tiếng Ocaina"] = "oca",
["Tiếng Occitan"] = "oc",
["Tiếng Occitan cổ"] = "pro",
["Tiếng Ogbronuagum"] = "ogu",
["Tiếng Oghuz cổ sơ kỳ"] = "trk-eog",
["Tiếng Oirat"] = "xwo",
["Tiếng Ojibwe"] = "oj",
["Tiếng Ojibwe Severn"] = "ojs",
["Tiếng Ojibwe Tây"] = "ojw",
["Tiếng Ojibwe Tây Bắc"] = "ojb",
["Tiếng Ojibwe Đông"] = "ojg",
["Tiếng Okanagan"] = "oka",
["Tiếng Okinawa"] = "ryu",
["Tiếng Okinoerabu"] = "okn",
["Tiếng Olukumi"] = "ulb",
["Tiếng Omaha-Ponca"] = "oma",
["Tiếng Omo nguyên thủy"] = "omv-pro",
["Tiếng Omok"] = "omk",
["Tiếng Oneida"] = "one",
["Tiếng Ongota"] = "bxe",
["Tiếng Oriya"] = "or",
["Tiếng Oriya Adiwasi"] = "ort",
["Tiếng Oriya cổ"] = "inc-oor",
["Tiếng Oriya trung đại"] = "inc-mor",
["Tiếng Orma"] = "orc",
["Tiếng Ormu"] = "orz",
["Tiếng Ormur"] = "oru",
["Tiếng Oroch"] = "oac",
["Tiếng Orok"] = "oaa",
["Tiếng Oromo"] = "om",
["Tiếng Oromo Nam"] = "gax",
["Tiếng Oromo Đông"] = "hae",
["Tiếng Oroqen"] = "orh",
["Tiếng Osage"] = "osa",
["Tiếng Osatu"] = "ost",
["Tiếng Osci"] = "osc",
["Tiếng Osing"] = "osi",
["Tiếng Ossetia"] = "os",
["Tiếng Ossetia cổ"] = "oos",
["Tiếng Otomi Mezquital"] = "ote",
["Tiếng Otoro"] = "otr",
["Tiếng Otuke"] = "otu",
["Tiếng Oyda"] = "oyd",
["Tiếng Pa Kô"] = "pac",
["Tiếng Pa'O"] = "blk",
["Tiếng Paeligni"] = "pgn",
["Tiếng Pagu"] = "pgu",
["Tiếng Pahari Mahasu"] = "bfz",
["Tiếng Paharia Kumarbhag"] = "kmj",
["Tiếng Paharia Sauria"] = "mjt",
["Tiếng Paite"] = "pck",
["Tiếng Paiwan"] = "pwn",
["Tiếng Pakan nguyên thủy"] = "mkh-pkn-pro",
["Tiếng Paku"] = "pku",
["Tiếng Pala"] = "plq",
["Tiếng Palau"] = "pau",
["Tiếng Palaung Ruching"] = "pce",
["Tiếng Palaung Rumai"] = "rbb",
["Tiếng Palaung Shwe"] = "pll",
["Tiếng Palaung nguyên thủy"] = "mkh-pal-pro",
["Tiếng Palawano Brooke's Point"] = "plw",
["Tiếng Palenquero"] = "pln",
["Tiếng Pali"] = "pi",
["Tiếng Paliyan"] = "pcf",
["Tiếng Palor"] = "fap",
["Tiếng Pama-Nyungar nguyên thủy"] = "aus-pam-pro",
["Tiếng Pancana"] = "pnp",
["Tiếng Panchpargania"] = "tdb",
["Tiếng Pangasinan"] = "pag",
["Tiếng Pangwala"] = "pgg",
["Tiếng Paniya"] = "pcg",
["Tiếng Papiamento"] = "pap",
["Tiếng Papuma"] = "ppm",
["Tiếng Parachi"] = "prc",
["Tiếng Paraujano"] = "pbg",
["Tiếng Parauk"] = "prk",
["Tiếng Pareci"] = "pab",
["Tiếng Parenga"] = "pcj",
["Tiếng Parthia"] = "xpr",
["Tiếng Parya"] = "paq",
["Tiếng Pashtun"] = "ps",
["Tiếng Pathan nguyên thủy"] = "ira-pat-pro",
["Tiếng Pauna"] = "pnk",
["Tiếng Pawnee"] = "paw",
["Tiếng Pazeh"] = "pzh",
["Tiếng Pear"] = "pcb",
["Tiếng Pear nguyên thủy"] = "mkh-pea-pro",
["Tiếng Pecheneg"] = "xpc",
["Tiếng Pela"] = "bxd",
["Tiếng Pemon"] = "aoc",
["Tiếng Pengo"] = "peg",
["Tiếng Perm nguyên thủy"] = "urj-prm-pro",
["Tiếng Petjo"] = "pey",
["Tiếng Phai"] = "prt",
["Tiếng Phake"] = "phk",
["Tiếng Phalura"] = "phl",
["Tiếng Phi-Á nguyên thủy"] = "afa-pro",
["Tiếng Philippines nguyên thủy"] = "phi-pro",
["Tiếng Phoenicia"] = "phn",
["Tiếng Phong-Kniang"] = "pnx",
["Tiếng Phrygia"] = "xpg",
["Tiếng Phu Thái"] = "pht",
["Tiếng Phuan"] = "phu",
["Tiếng Pháp"] = "fr",
["Tiếng Pháp cổ"] = "fro",
["Tiếng Pháp trung đại"] = "frm",
["Tiếng Phạn"] = "sa",
["Tiếng Phần Lan"] = "fi",
["Tiếng Phổ Hiền"] = "cpx",
["Tiếng Phổ cổ"] = "prg",
["Tiếng Picard"] = "pcd",
["Tiếng Piceni Bắc"] = "nrp",
["Tiếng Piceni Nam"] = "spx",
["Tiếng Piemonte"] = "pms",
["Tiếng Pilagá"] = "plg",
["Tiếng Pinyin"] = "pny",
["Tiếng Pipil"] = "ppl",
["Tiếng Pitjantjatjara"] = "pjt",
["Tiếng Plateau nguyên thủy"] = "nic-plt-pro",
["Tiếng Pnar"] = "pbv",
["Tiếng Pnar-Khasi-Lyngngam nguyên thủy"] = "aav-pkl-pro",
["Tiếng Pohnpei"] = "pon",
["Tiếng Polabia"] = "pox",
["Tiếng Polci"] = "plj",
["Tiếng Ponosakan"] = "pns",
["Tiếng Popoluca cao nguyên"] = "poi",
["Tiếng Potawatomi"] = "pot",
["Tiếng Pothohar"] = "phr",
["Tiếng Prakrit"] = "pra",
["Tiếng Prakrit Ashoka"] = "inc-ash",
["Tiếng Prakrit Niya"] = "pra-niy",
["Tiếng Prakrit Paisaci"] = "inc-psc",
["Tiếng Prakrit Saurasen"] = "psu",
["Tiếng Prasun"] = "prn",
["Tiếng Pucikwar"] = "apq",
["Tiếng Puinave"] = "pui",
["Tiếng Pumpokol"] = "xpm",
["Tiếng Punic"] = "xpu",
["Tiếng Punjab"] = "pa",
["Tiếng Puroik"] = "suv",
["Tiếng Puyuma"] = "pyu",
["Tiếng Pwo Bắc"] = "pww",
["Tiếng Pwo Phrae"] = "kjt",
["Tiếng Pwo Tây"] = "pwo",
["Tiếng Pwo Đông"] = "kjp",
["Tiếng Pà Thẻn"] = "pha",
["Tiếng Pọng"] = "hnu",
["Tiếng Qashqai"] = "qxq",
["Tiếng Qimant"] = "ahg",
["Tiếng Quan Thoại"] = "cmn",
["Tiếng Quapaw"] = "qua",
["Tiếng Quechua"] = "qu",
["Tiếng Quenya"] = "qya",
["Tiếng Quichuañol"] = "mue",
["Tiếng Quinault"] = "qun",
["Tiếng Quiripi"] = "qyp",
["Tiếng Quảng Lâm"] = "aav-qal",
["Tiếng Quảng Đông"] = "yue",
["Tiếng Quốc tế ngữ"] = "eo",
["Tiếng Ra Glai Bắc"] = "rog",
["Tiếng Ra Glai Cát Gia"] = "roc",
["Tiếng Ra Glai Nam"] = "rgs",
["Tiếng Rabha"] = "rah",
["Tiếng Raetia"] = "xrr",
["Tiếng Rajasthan"] = "raj",
["Tiếng Rajbanshi"] = "rjs",
["Tiếng Rakhine"] = "rki",
["Tiếng Rama"] = "rma",
["Tiếng Rangpur"] = "rkt",
["Tiếng Rapa Nui"] = "rap",
["Tiếng Rarotonga"] = "rar",
["Tiếng Rasawa"] = "rac",
["Tiếng Ratagnon"] = "btn",
["Tiếng Raute"] = "rau",
["Tiếng Ravula"] = "yea",
["Tiếng Rawang"] = "raw",
["Tiếng Rejang"] = "rej",
["Tiếng Reli"] = "rei",
["Tiếng Rendille"] = "rel",
["Tiếng Riang Lai"] = "yin",
["Tiếng Rohingya"] = "rhg",
["Tiếng Romagnol"] = "rgn",
["Tiếng Romansh"] = "rm",
["Tiếng Rotuma"] = "rtm",
["Tiếng Rukai"] = "dru",
["Tiếng Rukai nguyên thủy"] = "dru-pro",
["Tiếng Rumani"] = "ro",
["Tiếng Rungus"] = "drg",
["Tiếng Rusnak"] = "rsk",
["Tiếng Rusyn"] = "rue",
["Tiếng Ruthenia cổ"] = "zle-ort",
["Tiếng Rutul"] = "rut",
["Tiếng Rơ Măm"] = "rmx",
["Tiếng Rơ Ngao"] = "ren",
["Tiếng Saanich"] = "str",
["Tiếng Saaroa"] = "sxr",
["Tiếng Saba"] = "saa",
["Tiếng Sabüm"] = "sbo",
["Tiếng Sadri"] = "sck",
["Tiếng Saek"] = "skb",
["Tiếng Saho"] = "ssy",
["Tiếng Saisiyat"] = "xsy",
["Tiếng Saka-Wakhi nguyên thủy"] = "xsc-skw-pro",
["Tiếng Sakizaya"] = "szy",
["Tiếng Salar"] = "slr",
["Tiếng Salish nguyên thủy"] = "sal-pro",
["Tiếng Sama Trung"] = "sml",
["Tiếng Sambal Botolan"] = "sbl",
["Tiếng Sambali"] = "xsb",
["Tiếng Sambalpur"] = "spv",
["Tiếng Sami Akkala"] = "sia",
["Tiếng Sami Inari"] = "smn",
["Tiếng Sami Kildin"] = "sjd",
["Tiếng Sami Skolt"] = "sms",
["Tiếng Sami Ter"] = "sjt",
["Tiếng Sami Ume"] = "sju",
["Tiếng Sami nguyên thủy"] = "smi-pro",
["Tiếng Samo"] = "smq",
["Tiếng Samo Nam"] = "sbd",
["Tiếng Samoa"] = "sm",
["Tiếng Samogitia"] = "sgs",
["Tiếng Samoyed nguyên thủy"] = "syd-pro",
["Tiếng Samtao"] = "stu",
["Tiếng Sangir"] = "sxn",
["Tiếng Sangisar"] = "sgr",
["Tiếng Sango"] = "sg",
["Tiếng Santal"] = "sat",
["Tiếng Saposa"] = "sps",
["Tiếng Saraiki"] = "skr",
["Tiếng Saramacca"] = "srm",
["Tiếng Sardegna"] = "sc",
["Tiếng Sarikol"] = "srh",
["Tiếng Sarmatia nguyên thủy"] = "xsc-sar-pro",
["Tiếng Sasak"] = "sas",
["Tiếng Saurashtra"] = "saz",
["Tiếng Savi"] = "sdg",
["Tiếng Saxon Transylvania"] = "gmw-tsx",
["Tiếng Saxon cổ"] = "osx",
["Tiếng Scots"] = "sco",
["Tiếng Scots trung đại"] = "gmw-msc",
["Tiếng Scythia nguyên thủy"] = "xsc-pro",
["Tiếng Sebat Bet Gurage"] = "sgw",
["Tiếng Sechelt"] = "sec",
["Tiếng Selkup"] = "sel",
["Tiếng Selkup nguyên thủy"] = "sel-pro",
["Tiếng Semai"] = "sea",
["Tiếng Semaq Beri"] = "szc",
["Tiếng Semelai"] = "sza",
["Tiếng Semit Tây nguyên thủy"] = "sem-wes-pro",
["Tiếng Semit nguyên thủy"] = "sem-pro",
["Tiếng Semnam"] = "ssm",
["Tiếng Sena"] = "seh",
["Tiếng Seneca"] = "see",
["Tiếng Senhaja de Srair"] = "sjs",
["Tiếng Senni Humburi"] = "hmb",
["Tiếng Senni Koyraboro"] = "ses",
["Tiếng Senoufo Nyarafolo"] = "sev",
["Tiếng Serbia-Croatia"] = "sh",
["Tiếng Serer"] = "srr",
["Tiếng Seri"] = "sei",
["Tiếng Seze"] = "sze",
["Tiếng Shabak"] = "sdb",
["Tiếng Shabo"] = "sbf",
["Tiếng Shan"] = "shn",
["Tiếng Shebayo"] = "awd-she",
["Tiếng Shekkacho"] = "moy",
["Tiếng Sherpa"] = "xsr",
["Tiếng Shina"] = "scl",
["Tiếng Shina Kohistan"] = "plk",
["Tiếng Shinasha"] = "bwo",
["Tiếng Sholaga"] = "sle",
["Tiếng Shompen"] = "sii",
["Tiếng Shona"] = "sn",
["Tiếng Shor"] = "cjs",
["Tiếng Shughnan"] = "sgh",
["Tiếng Shughnan-Rushan nguyên thủy"] = "ira-shr-pro",
["Tiếng Shughnan-Yazghulom nguyên thủy"] = "ira-shy-pro",
["Tiếng Shughnan-Yazghulom-Munji nguyên thủy"] = "ira-sym-pro",
["Tiếng Shuswap"] = "shs",
["Tiếng Sicel"] = "scx",
["Tiếng Sicily"] = "scn",
["Tiếng Sidamo"] = "sid",
["Tiếng Sikkim"] = "sip",
["Tiếng Silesia"] = "szl",
["Tiếng Siltʼe"] = "stv",
["Tiếng Sinaugoro"] = "snc",
["Tiếng Sindh"] = "sd",
["Tiếng Sinhala"] = "si",
["Tiếng Sioux nguyên thủy"] = "sio-pro",
["Tiếng Siraya"] = "fos",
["Tiếng Sirenik"] = "ysr",
["Tiếng Sirmaur"] = "srx",
["Tiếng Sissala"] = "sld",
["Tiếng Sissano"] = "sso",
["Tiếng Siwi"] = "siz",
["Tiếng Siwu"] = "akp",
["Tiếng Skepi"] = "skw",
["Tiếng Slav Giáo hội"] = "zls-chs",
["Tiếng Slav Giáo hội cổ"] = "cu",
["Tiếng Slav nguyên thủy"] = "sla-pro",
["Tiếng Slav Đông cổ"] = "orv",
["Tiếng Slovak"] = "sk",
["Tiếng Slovak cổ"] = "zlw-osk",
["Tiếng Slovene"] = "sl",
["Tiếng Slovincia"] = "zlw-slv",
["Tiếng Socotra"] = "sqt",
["Tiếng Sogdia"] = "sog",
["Tiếng Sogdia nguyên thủy"] = "ira-sgc-pro",
["Tiếng Sokna"] = "swn",
["Tiếng Solon"] = "tuw-sol",
["Tiếng Solong"] = "aaw",
["Tiếng Somali"] = "so",
["Tiếng Somali nguyên thủy"] = "cus-som-pro",
["Tiếng Soninke"] = "snk",
["Tiếng Sonsorol"] = "sov",
["Tiếng Sora"] = "srb",
["Tiếng Soran"] = "ckb",
["Tiếng Sotho"] = "st",
["Tiếng Sotho Bắc"] = "nso",
["Tiếng Soyot"] = "trk-soy",
["Tiếng Squamish"] = "squ",
["Tiếng Sranan Tongo"] = "srn",
["Tiếng Stau"] = "ero-tau",
["Tiếng Sumer"] = "sux",
["Tiếng Sunda"] = "su",
["Tiếng Sunda cổ"] = "osn",
["Tiếng Suri"] = "suq",
["Tiếng Surjapur"] = "sjp",
["Tiếng Susu"] = "sus",
["Tiếng Svan"] = "sva",
["Tiếng Swahili"] = "sw",
["Tiếng Swazi"] = "ss",
["Tiếng Sylhet"] = "syl",
["Tiếng Syriac cổ điển"] = "syc",
["Tiếng Sán Chay"] = "mlc",
["Tiếng Séc"] = "cs",
["Tiếng Séc cổ"] = "zlw-ocs",
["Tiếng Sô"] = "sss",
["Tiếng Taabwa"] = "tap",
["Tiếng Tabasaran"] = "tab",
["Tiếng Tachawit"] = "shy",
["Tiếng Tadyawan"] = "tdy",
["Tiếng Tafi"] = "tcd",
["Tiếng Tagal Murut"] = "mvv",
["Tiếng Tagalog"] = "tl",
["Tiếng Tagbanwa Calamian"] = "tbk",
["Tiếng Tagdal"] = "tda",
["Tiếng Tagoi"] = "tag",
["Tiếng Tahiti"] = "ty",
["Tiếng Tahltan"] = "tht",
["Tiếng Tai Loi"] = "tlq",
["Tiếng Tai Tây Nam nguyên thủy"] = "tai-swe-pro",
["Tiếng Taivoan"] = "tvx",
["Tiếng Tajik"] = "tg",
["Tiếng Tal"] = "tal",
["Tiếng Tala"] = "tak",
["Tiếng Talossa"] = "tzl",
["Tiếng Talysh"] = "tly",
["Tiếng Tamang Gorkha Đông"] = "tge",
["Tiếng Tamang Tây"] = "tdg",
["Tiếng Tamang Đông"] = "taj",
["Tiếng Tamazight Maroc chuẩn"] = "zgh",
["Tiếng Tamazight Trung Atlas"] = "tzm",
["Tiếng Tamil"] = "ta",
["Tiếng Tamil cổ"] = "oty",
["Tiếng Tamki"] = "tax",
["Tiếng Tammari"] = "tbz",
["Tiếng Tampuan"] = "tpu",
["Tiếng Tanchangya"] = "tnv",
["Tiếng Tangkhul Naga"] = "nmf",
["Tiếng Tangoa"] = "tgp",
["Tiếng Tangut"] = "txg",
["Tiếng Tanimbili"] = "tbe",
["Tiếng Taos"] = "twf",
["Tiếng Tapirapé"] = "taf",
["Tiếng Tara Baka"] = "bdh",
["Tiếng Tarantino"] = "roa-tar",
["Tiếng Tariana"] = "tae",
["Tiếng Tarifit"] = "rif",
["Tiếng Tasawaq"] = "twq",
["Tiếng Tashelhit"] = "shi",
["Tiếng Tat"] = "ttt",
["Tiếng Tat-Do Thái"] = "jdt",
["Tiếng Tatar"] = "tt",
["Tiếng Tiên Ti"] = "mis-xbi",
["Tiếng Tatar Crưm"] = "crh",
["Tiếng Tatar Siberia"] = "sty",
["Tiếng Tatuyo"] = "tav",
["Tiếng Taungyo"] = "tco",
["Tiếng Tause"] = "tad",
["Tiếng Tausug"] = "tsg",
["Tiếng Tavoy"] = "tvn",
["Tiếng Tay Dọ"] = "tyj",
["Tiếng Tayma"] = "sem-tay",
["Tiếng Taz"] = "zhx-taz",
["Tiếng Taznatit"] = "grr",
["Tiếng Taíno"] = "tnq",
["Tiếng Tchad nguyên thủy"] = "cdc-pro",
["Tiếng Telugu"] = "te",
["Tiếng Telugu cổ"] = "dra-ote",
["Tiếng Tem"] = "kdh",
["Tiếng Temiar"] = "tea",
["Tiếng Temoq"] = "tmo",
["Tiếng Ten'edn"] = "tnz",
["Tiếng Tengger"] = "tes",
["Tiếng Tenharim"] = "pah",
["Tiếng Tepehua Tlachichilco"] = "tpt",
["Tiếng Tepehuan Bắc"] = "ntp",
["Tiếng Tepehuan Đông Nam"] = "stp",
["Tiếng Teressa"] = "tef",
["Tiếng Teribe"] = "tfr",
["Tiếng Ternate"] = "tft",
["Tiếng Tetserret"] = "tez",
["Tiếng Tetum"] = "tet",
["Tiếng Thachanad"] = "thn",
["Tiếng Thavưng"] = "thm",
["Tiếng Thompson"] = "thp",
["Tiếng Thracia"] = "txh",
["Tiếng Thác Bạt"] = "qfa-xgx-tuo",
["Tiếng Thái"] = "th",
["Tiếng Thái Hàng Tổng"] = "tpo",
["Tiếng Thái Lai"] = "tjl",
["Tiếng Thái Na"] = "tdd",
["Tiếng Thái Trắng"] = "twh",
["Tiếng Thái Tống"] = "soa",
["Tiếng Thái nguyên thủy"] = "tai-pro",
["Tiếng Thái Đen"] = "blt",
["Tiếng Thái Đỏ"] = "tyr",
["Tiếng Thát Mai"] = "smh",
["Tiếng Thượng Kinabatangan"] = "dmg",
["Tiếng Thượng Sorb"] = "hsb",
["Tiếng Thổ"] = "tou",
["Tiếng Thổ Dục Hồn"] = "qfa-xgx-tuh",
["Tiếng Thổ Gia Bắc"] = "tji",
["Tiếng Thổ Gia Nam"] = "tjs",
["Tiếng Thổ Nhĩ Kỳ"] = "tr",
["Tiếng Thổ Nhĩ Kỳ Anatolia cổ"] = "trk-oat",
["Tiếng Thổ Nhĩ Kỳ Gagauz Balkan"] = "bgx",
["Tiếng Thổ Nhĩ Kỳ Ottoman"] = "ota",
["Tiếng Thụy Điển"] = "sv",
["Tiếng Thụy Điển cổ"] = "gmq-osw",
["Tiếng Thủy"] = "swi",
["Tiếng Tiang"] = "tbj",
["Tiếng Tigre"] = "tig",
["Tiếng Tigrinya"] = "ti",
["Tiếng Tindi"] = "tin",
["Tiếng Tipai"] = "nai-tip",
["Tiếng Tippera"] = "tpe",
["Tiếng Tiruray"] = "tiy",
["Tiếng Tiwa"] = "lax",
["Tiếng Tiwi"] = "tiw",
["Tiếng Tiên Ti"] = "qfa-xgx-xbi",
["Tiếng Tlapanec Malinaltepec"] = "tcf",
["Tiếng Tlingit"] = "tli",
["Tiếng Tobi"] = "tox",
["Tiếng Tochari A"] = "xto",
["Tiếng Tochari B"] = "txb",
["Tiếng Tochari nguyên thủy"] = "ine-toc-pro",
["Tiếng Tocho"] = "taz",
["Tiếng Toda"] = "tcx",
["Tiếng Tofa"] = "kim",
["Tiếng Tok Pisin"] = "tpi",
["Tiếng Tokelau"] = "tkl",
["Tiếng Toki Pona"] = "tok",
["Tiếng Tokunoshima"] = "tkn",
["Tiếng Toma"] = "tod",
["Tiếng Tonga"] = "to",
["Tiếng Tonkawa"] = "tqw",
["Tiếng Tooro"] = "ttj",
["Tiếng Torwali"] = "trw",
["Tiếng Toto"] = "txo",
["Tiếng Totonac Papantla"] = "top",
["Tiếng Totonac cao nguyên"] = "tos",
["Tiếng Triqui Chicahuaxtla"] = "trs",
["Tiếng Triqui Copala"] = "trc",
["Tiếng Triqui San Martín Itunyoso"] = "trq",
["Tiếng Triqui nguyên thủy"] = "omq-tri-pro",
["Tiếng Trió"] = "tri",
["Tiếng Triều Châu"] = "nan-tws",
["Tiếng Triều Tiên"] = "ko",
["Tiếng Triều Tiên cổ"] = "oko",
["Tiếng Triều Tiên nguyên thủy"] = "qfa-kor-pro",
["Tiếng Triều Tiên trung đại"] = "okm",
["Tiếng Truku"] = "trv",
["Tiếng Trung Bikol"] = "bcl",
["Tiếng Trung Dusun"] = "dtp",
["Tiếng Trung Mansi"] = "mns-cen",
["Tiếng Trung Nahuatl"] = "nhn",
["Tiếng Trung Nahuatl Huasteca"] = "nch",
["Tiếng Trung Nahuatl Puebla"] = "ncx",
["Tiếng Trung Quốc"] = "zh",
["Tiếng Trà Động"] = "cdy",
["Tiếng Trác Ni"] = "cda",
["Tiếng Tráng"] = "za",
["Tiếng Tráng Nông"] = "zhn",
["Tiếng Tráng Tả Giang"] = "zzj",
["Tiếng Tráng Đức Tĩnh"] = "zyg",
["Tiếng Trát Bá"] = "zhb",
["Tiếng Tsakhur"] = "tkr",
["Tiếng Tsakonia"] = "tsd",
["Tiếng Tsamai"] = "tsb",
["Tiếng Tsat"] = "huq",
["Tiếng Tsez"] = "ddo",
["Tiếng Tshangla"] = "tsj",
["Tiếng Tsimshian"] = "tsi",
["Tiếng Tsonga"] = "ts",
["Tiếng Tsou"] = "tsu",
["Tiếng Tsuut'ina"] = "srs",
["Tiếng Tswana"] = "tn",
["Tiếng Tuamotu"] = "pmt",
["Tiếng Tuareg"] = "tmh",
["Tiếng Tukang Besi Bắc"] = "khc",
["Tiếng Tukang Besi Nam"] = "bhq",
["Tiếng Tuki"] = "bag",
["Tiếng Tulu"] = "tcy",
["Tiếng Tumbuka"] = "tum",
["Tiếng Tungus nguyên thủy"] = "tuw-pro",
["Tiếng Tunica"] = "tun",
["Tiếng Tunni"] = "tqq",
["Tiếng Tupi"] = "tpn",
["Tiếng Tupi cổ"] = "tpw",
["Tiếng Tupi nguyên thủy"] = "tup-pro",
["Tiếng Tupi-Guarani nguyên thủy"] = "tup-gua-pro",
["Tiếng Turk Khorasan"] = "kmz",
["Tiếng Turk Khorezm"] = "zkh",
["Tiếng Turk cổ"] = "otk",
["Tiếng Turk nguyên thủy"] = "trk-pro",
["Tiếng Turkmen"] = "tk",
["Tiếng Turoyo"] = "tru",
["Tiếng Tuva"] = "tyv",
["Tiếng Tuvalu"] = "tvl",
["Tiếng Tuwuli"] = "bov",
["Tiếng Tyap"] = "kcg",
["Tiếng Tzotzil"] = "tzo",
["Tiếng Tà Mun"] = "aav-tam",
["Tiếng Tà Ôi Thượng"] = "tth",
["Tiếng Tày"] = "tyz",
["Tiếng Tày Sa Pa"] = "tys",
["Tiếng Tân Aram Assyria"] = "aii",
["Tiếng Tân Aram Bohtan"] = "bhn",
["Tiếng Tân Aram Chaldea"] = "cld",
["Tiếng Tân Aram Do Thái Barzani"] = "bjf",
["Tiếng Tân Aram Tây"] = "amw",
["Tiếng Tây Abenaki"] = "abe",
["Tiếng Tây Ban Nha"] = "es",
["Tiếng Tây Ban Nha cổ"] = "osp",
["Tiếng Tây Bắc Gbaya"] = "gya",
["Tiếng Tây Bắc Kavkaz nguyên thủy"] = "cau-nwc-pro",
["Tiếng Tây Bồi"] = "tas",
["Tiếng Tây Duyên hải Bajau"] = "bdr",
["Tiếng Tây Frisia"] = "fy",
["Tiếng Tây Huasteca Nahuatl"] = "nhw",
["Tiếng Tây Kayah"] = "kyu",
["Tiếng Tây Makian"] = "mqs",
["Tiếng Tây Tạng"] = "bo",
["Tiếng Tây Tạng Kham"] = "khg",
["Tiếng Tây Tạng cổ điển"] = "xct",
["Tiếng Tây Yugur"] = "ybe",
["Tiếng Tích Bá"] = "sjo",
["Tiếng Tơ Đrá"] = "tdr",
["Tiếng Tương"] = "hsn",
["Tiếng Tấn"] = "cjy",
["Tiếng Tứ Thổ"] = "sit-sit",
["Tiếng Tứ Xuyên"] = "zhx-sic",
["Tiếng U"] = "uuu",
["Tiếng Ubangi nguyên thủy"] = "nic-ubg-pro",
["Tiếng Ubykh"] = "uby",
["Tiếng Udi"] = "udi",
["Tiếng Udihe"] = "ude",
["Tiếng Udmurt"] = "udm",
["Tiếng Uduk"] = "udu",
["Tiếng Ugarit"] = "uga",
["Tiếng Ugong"] = "ugo",
["Tiếng Ugria nguyên thủy"] = "urj-ugr-pro",
["Tiếng Ukraina"] = "uk",
["Tiếng Ulch"] = "ulc",
["Tiếng Ullatan"] = "ull",
["Tiếng Umbria"] = "xum",
["Tiếng Umbundu"] = "umb",
["Tiếng Unami"] = "unm",
["Tiếng Uneapa"] = "bbn",
["Tiếng Urak Lawoi'"] = "urk",
["Tiếng Ural nguyên thủy"] = "urj-pro",
["Tiếng Urali"] = "url",
["Tiếng Urartu"] = "xur",
["Tiếng Urdu"] = "ur",
["Tiếng Uripiv-Wala-Rano-Atchin"] = "upv",
["Tiếng Urubú-Kaapor"] = "urb",
["Tiếng Urum"] = "uum",
["Tiếng Ushojo"] = "ush",
["Tiếng Usui"] = "usi",
["Tiếng Ute-Aztec nguyên thủy"] = "azc-pro",
["Tiếng Uvbie"] = "evh",
["Tiếng Uzbek"] = "uz",
["Tiếng Vaagri Booli"] = "vaa",
["Tiếng Vaghri"] = "vgr",
["Tiếng Varli"] = "vav",
["Tiếng Vasavi"] = "vas",
["Tiếng Venda"] = "ve",
["Tiếng Veneti"] = "xve",
["Tiếng Veneto"] = "vec",
["Tiếng Veps"] = "vep",
["Tiếng Vishava"] = "vis",
["Tiếng Việt"] = "vi",
["Tiếng Việt trung cổ"] = "mkh-mvi",
["Tiếng Việt-Mường nguyên thủy"] = "mkh-vie-pro",
["Tiếng Volapük"] = "vo",
["Tiếng Volsci"] = "xvo",
["Tiếng Volta-Congo nguyên thủy"] = "nic-vco-pro",
["Tiếng Volta-Niger nguyên thủy"] = "alv-von-pro",
["Tiếng Vot"] = "vot",
["Tiếng Vurës"] = "msn",
["Tiếng Võro"] = "vro",
["Tiếng Văn ngôn"] = "lzh",
["Tiếng Waama"] = "wwa",
["Tiếng Waata"] = "ssn",
["Tiếng Wagi"] = "fad",
["Tiếng Wahgi"] = "wgi",
["Tiếng Waimaha"] = "bao",
["Tiếng Waiwai"] = "waw",
["Tiếng Wakhi"] = "wbl",
["Tiếng Wales"] = "cy",
["Tiếng Wales trung đại"] = "wlm",
["Tiếng Wallis"] = "wls",
["Tiếng Wallon"] = "wa",
["Tiếng Wambule"] = "wme",
["Tiếng Wancho"] = "nnp",
["Tiếng Waneci"] = "wne",
["Tiếng War-Jaintia"] = "aml",
["Tiếng Waray"] = "war",
["Tiếng Wardaman"] = "wrr",
["Tiếng Warekena"] = "gae",
["Tiếng Warji"] = "wji",
["Tiếng Wastek"] = "hus",
["Tiếng Wawonii"] = "wow",
["Tiếng Wayampi"] = "oym",
["Tiếng Wayana"] = "way",
["Tiếng Wayuu"] = "guc",
["Tiếng Wemba-Wemba"] = "xww",
["Tiếng Wewaw"] = "wea",
["Tiếng Wiradjuri"] = "wrh",
["Tiếng Wiyot"] = "wiy",
["Tiếng Wobé"] = "wob",
["Tiếng Woiwurrung"] = "wyi",
["Tiếng Wolane"] = "wle",
["Tiếng Wolaytta"] = "wal",
["Tiếng Wolio"] = "wlo",
["Tiếng Wolof"] = "wo",
["Tiếng Wotu"] = "wtw",
["Tiếng Wymysorys"] = "wym",
["Tiếng Xamtanga"] = "xan",
["Tiếng Xavante"] = "xav",
["Tiếng Xhosa"] = "xh",
["Tiếng Xinh Mun"] = "puo",
["Tiếng Xtiêng"] = "sti",
["Tiếng Xtiêng Bù Đeh"] = "stt",
["Tiếng Xârâcùù"] = "ane",
["Tiếng Xơ Đăng"] = "sed",
["Tiếng Yaaku"] = "muu",
["Tiếng Yaeyama"] = "rys",
["Tiếng Yaghnob"] = "yai",
["Tiếng Yakan"] = "yka",
["Tiếng Yakima"] = "yak",
["Tiếng Yakkha"] = "ybh",
["Tiếng Yakut"] = "sah",
["Tiếng Yali Angguruk"] = "yli",
["Tiếng Yami"] = "tao",
["Tiếng Yamphu"] = "ybi",
["Tiếng Yanesha'"] = "ame",
["Tiếng Yanyuwa"] = "jao",
["Tiếng Yao (Nam Mĩ)"] = "sai-yao",
["Tiếng Yao (châu Phi)"] = "yao",
["Tiếng Yap"] = "yap",
["Tiếng Yapunda"] = "yev",
["Tiếng Yazghulom"] = "yah",
["Tiếng Ye'kwana"] = "mch",
["Tiếng Yele"] = "yle",
["Tiếng Yemsa"] = "jnj",
["Tiếng Yevan"] = "yej",
["Tiếng Yiddish"] = "yi",
["Tiếng Yidgha"] = "ydg",
["Tiếng Yidiny"] = "yii",
["Tiếng Yindjibarndi"] = "yij",
["Tiếng Yiwom"] = "gek",
["Tiếng Yogad"] = "yog",
["Tiếng Yola"] = "yol",
["Tiếng Yolmo"] = "scp",
["Tiếng Yom"] = "pil",
["Tiếng Yonaguni"] = "yoi",
["Tiếng Yong"] = "yno",
["Tiếng Yongkom"] = "yon",
["Tiếng Yoron"] = "yox",
["Tiếng Yoruba"] = "yo",
["Tiếng Yoruba nguyên thủy"] = "alv-yor-pro",
["Tiếng Yorubo nguyên thủy"] = "alv-yrd-pro",
["Tiếng Yoy"] = "yoy",
["Tiếng Yugh"] = "yug",
["Tiếng Yukaghir nguyên thủy"] = "qfa-yuk-pro",
["Tiếng Yup'ik"] = "esu",
["Tiếng Yupik Trung Siberia"] = "ess",
["Tiếng Yuri"] = "sai-yri",
["Tiếng Yurok"] = "yur",
["Tiếng Yámana"] = "yag",
["Tiếng Zacatepec Chatino"] = "ctz",
["Tiếng Zaghawa"] = "zag",
["Tiếng Zaiwa"] = "atb",
["Tiếng Zangskar"] = "zau",
["Tiếng Zapotec"] = "zap",
["Tiếng Zapotec Cajonos"] = "zad",
["Tiếng Zapotec Isthmus"] = "zai",
["Tiếng Zapotec Mitla"] = "zaw",
["Tiếng Zapotec Rincón"] = "zar",
["Tiếng Zapotec Rincón Nam"] = "zsr",
["Tiếng Zapotec San Juan Guelavía"] = "zab",
["Tiếng Zapotec Yatee"] = "zty",
["Tiếng Zapotec Yatzachi"] = "zav",
["Tiếng Zapotec Zaniza"] = "zpw",
["Tiếng Zapotec Zoogocho"] = "zpq",
["Tiếng Zapotec nguyên thủy"] = "omq-zpc-pro",
["Tiếng Zarma"] = "dje",
["Tiếng Zarphat"] = "zrp",
["Tiếng Zay"] = "zwa",
["Tiếng Zayse-Zergulla"] = "zay",
["Tiếng Zaza"] = "zza",
["Tiếng Zaza-Goran nguyên thủy"] = "ira-zgr-pro",
["Tiếng Zeeland"] = "zea",
["Tiếng Zenaga"] = "zen",
["Tiếng Zirenkel"] = "zrn",
["Tiếng Zoque Francisco León"] = "zos",
["Tiếng Zou"] = "zom",
["Tiếng Zulu"] = "zu",
["Tiếng Zumbun"] = "jmb",
["Tiếng Äynu"] = "aib",
["Tiếng Ê Đê"] = "rad",
["Tiếng Ông Bối nguyên thủy"] = "qfa-onb-pro",
["Tiếng Önge"] = "oon",
["Tiếng Önge nguyên thủy"] = "qfa-ong-pro",
["Tiếng Övdal"] = "ovd",
["Tiếng Ý"] = "it",
["Tiếng Ý-Do Thái"] = "itk",
["Tiếng Đa Đảo hạt nhân nguyên thủy"] = "poz-pnp-pro",
["Tiếng Đa Đảo nguyên thủy"] = "poz-pol-pro",
["Tiếng Đa Đảo Đông nguyên thủy"] = "poz-pep-pro",
["Tiếng Đan Mạch"] = "da",
["Tiếng Đan Mạch cổ"] = "gmq-oda",
["Tiếng Đài Sơn"] = "zhx-tai",
["Tiếng Đông Abenaki"] = "aaq",
["Tiếng Đông Acipa"] = "acp",
["Tiếng Đông Bontoc"] = "ebk",
["Tiếng Đông Bắc Kavkaz nguyên thủy"] = "cau-nec-pro",
["Tiếng Đông Can"] = "dng",
["Tiếng Đông Futuna"] = "fud",
["Tiếng Đông Hương"] = "sce",
["Tiếng Đông Kayah"] = "eky",
["Tiếng Đông Khanty"] = "kca-eas",
["Tiếng Đông Yugur"] = "yuy",
["Tiếng Đường Uông"] = "zhx-twa",
["Tiếng Đại Tây Dương–Congo nguyên thủy"] = "alv-pro",
["Tiếng Độc Long"] = "duu",
["Tiếng Động-Thủy nguyên thủy"] = "qfa-kms-pro",
["Tiếng Đức"] = "de",
["Tiếng Đức Alemanni"] = "gsw",
["Tiếng Đức Pennsylvania"] = "pdc",
["Tiếng Đức cao địa cổ"] = "goh",
["Tiếng Đức cao địa trung đại"] = "gmh",
["Tiếng Đức Đông Trung"] = "gmw-ecg",
["Tiếng Ơ Đu"] = "tyh",
["Tiếng Ưu Miền"] = "ium",
["Tiếng ǃXóõ"] = "nmn",
["Tiếng Ả Rập"] = "ar",
["Tiếng Ả Rập Ai Cập"] = "arz",
["Tiếng Ả Rập Algérie"] = "arq",
["Tiếng Ả Rập Andalusia"] = "xaa",
["Tiếng Ả Rập Bắc Levant"] = "apc",
["Tiếng Ả Rập Bắc Lưỡng Hà"] = "ayp",
["Tiếng Ả Rập Hijazi"] = "acw",
["Tiếng Ả Rập Iraq"] = "acm",
["Tiếng Ả Rập Juba"] = "pga",
["Tiếng Ả Rập Libya"] = "ayl",
["Tiếng Ả Rập Maroc"] = "ary",
["Tiếng Ả Rập Nam Levant"] = "ajp",
["Tiếng Ả Rập Oman"] = "acx",
["Tiếng Ả Rập Sudan"] = "apd",
["Tiếng Ả Rập Síp"] = "acy",
["Tiếng Ả Rập Tajikistan"] = "abh",
["Tiếng Ả Rập Tchad"] = "shu",
["Tiếng Ả Rập Tunisia"] = "aeb",
["Tiếng Ả Rập Uzbekistan"] = "auz",
["Tiếng Ả Rập vùng Vịnh"] = "afb",
["Tiếng Ấn-Arya nguyên thủy"] = "inc-pro",
["Tiếng Ấn-Iran nguyên thủy"] = "iir-pro",
["Tiếng Ấn-Âu nguyên thủy"] = "ine-pro",
["Tiếng Ỹaroamë"] = "yro",
["Àhàn"] = "ahn",
["Áncá"] = "acb",
["Ömie"] = "aom",
["Đa ngữ"] = "mul",
["ǀXam"] = "xam",
["ǁAni"] = "hnh",
["ǁGana"] = "gnk",
["ǁXegwi"] = "xeg",
["ǂHoan"] = "huc",
["ǃKung"] = "khi-kun",
}
eyc3px8x76389y22nvztouhb30q731n
Mô đun:tzm-IPA
828
290432
2576427
2160687
2026-11-08T14:05:22Z
Hiyuune
50834
2576427
Scribunto
text/plain
local export = {}
local m_IPA = require("Module:IPA")
local m_scripts = require("Module:scripts")
local m_scripts_util = require("Module:script utilities")
local m_a = require("Module:accent qualifier")
local lang = require("Module:languages").getByCode("tzm")
local s = mw.ustring.gsub
local c = {
["g"] = "ɡ",
["ḍ"] = "dˤ",
["ḏ"] = "ð",
["c"] = "ʃ",
["j"] = "ʒ",
["y"] = "j",
["ẓ"] = "zˤ",
["ṛ"] = "rˤ",
["ṣ"] = "sˤ",
["ṭ"] = "tˤ",
["ḥ"] = "ħ",
["ɛ"] = "ʕ",
["e"] = "ə"
}
local p = {
["ɣ"] = "ʁ",
["ɡʷ"] = "ɣʷ",
["tˤ"] = "Tˤ",
["x"] = "χ",
["kʷ"] = "xʷ",
["a"] = "æ",
["ɡ"] = "ʝ",
["d"] = "ð",
["dˤ"] = "ðˤ",
["k"] = "ç",
["n"] = "N",
["t"] = "θ",
["b"] = "β"
}
local t = {
["ʝ"] = "ɟː",
["ð"] = "Dː",
["ðˤ"] = "Tˤː",
["f"] = "fː",
["ʁ"] = "qː",
["ç"] = "cː",
["l"] = "lː",
["m"] = "mː",
["N"] = "Nː",
["r"] = "rː",
["s"] = "sː",
["ʃ"] = "Cː",
["θ"] = "Tː",
["w"] = "wː",
["j"] = "ɟː",
["z"] = "zː",
["zˤ"] = "zˤː",
["β"] = "bː",
["χ"] = "χː",
["ʒ"] = "Jː",
["ɣʷ"] = "ɡʷː",
["rˤ"] = "rˤː",
["sˤ"] = "sˤː",
["Tˤ"] = "Tˤː",
["q"] = "qː",
["ħ"] = "ħː",
["ʕ"] = "ʕː",
["xʷ"] = "kʷː"
}
local C = "[ɡɟʝDdðfɣʁkcçlmNnrsʃCTtθwjzbβhxχʒJqħʕ]"
local V = "[aiuəæɑ]"
local r = {
["a"] = {
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʝ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)$"] = "%1jː%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ɣʷ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)$"] = "%1wː%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʁ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)$"] = "%1ʁː%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʝ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?[‿ ])"] = "%1jː%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ɣʷ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?[‿ ])"] = "%1wː%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʁ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?[‿ ])"] = "%1ʁː%2",
["( ə?" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʝ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)$"] = "%1jː%2",
["( ə?" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ɣʷ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)$"] = "%1wː%2",
["( ə?" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʁ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)$"] = "%1ʁː%2",
["( ə?" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʝ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?[‿ ])"] = "%1jː%2",
["( ə?" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ɣʷ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?[‿ ])"] = "%1wː%2",
["( ə?" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?" .. V .. ")ʁ(" .. V .. "%(?" .. C .. "?%)?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?[‿ ])"] = "%1ʁː%2"
},
["b"] = {
["([dtzrs])([^ˤ%1][^ ]-ˤ)"] = "%1ˤ%2",
["(ˤ[^ ]-[dtzrs])([^ˤ%1])"] = "%1ˤ%2",
["(ˤ[^ ]-[dtzrs])$"] = "%1ˤ"
},
["c"] = {
["f([‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "β%1",
["θ(ˤ?[‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ð%1",
["T(ˤ?[‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "D%1",
["s(ˤ?[‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "z%1",
["ʃ([‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ʒ%1",
["ç([‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ʝ%1",
["c([‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ɟ%1",
["x(ʷ[‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ɣ%1",
["k(ʷ[‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ɡ%1",
["χ([‿ ]?[βðd̪zʒʝɟɣɡʁ])"] = "ʁ%1",
["β([‿ ]?[fθt̪sʃçcxkχ])"] = "f%1",
["ð(ˤ?[‿ ]?[fθt̪sʃçcxkχ])"] = "θ%1",
["D(ˤ?[‿ ]?[fθt̪sʃçcxkχ])"] = "T%1",
["z(ˤ?[‿ ]?[fθt̪sʃçcxkχ])"] = "s%1",
["ʒ([‿ ]?[fθt̪sʃçcxkχ])"] = "ʃ%1",
["ʝ(%)?[‿ ]?[fθt̪sʃçcxkχ])"] = "ç%1",
["ɟ([‿ ]?[fθt̪sʃçcxkχ])"] = "c%1",
["ɣ(ʷ[‿ ]?[fθt̪sʃçcxkχ])"] = "x%1",
["ɡ(ʷ[‿ ]?[fθt̪sʃçcxkχ])"] = "k%1",
["ʁ([‿ ]?[fθt̪sʃçcxkχ])"] = "χ%1"
},
["d"] = {
["([^fb])[fb]( ?)([fb])([^fb])"] = "%1%3%2%3%4",
["^[fb]( ?)([fb])([^fb])"] = "%2%1%2%3",
["([^fb])[fb]( ?)([fb])$"] = "%1%3%2%3",
["([^td]ˤ?)[td](ˤ?)( ?)([td])(ˤ?)([^td])"] = "%1%4%2%3%4%5%6",
["^[td](ˤ?)( ?)([td])(ˤ?)([^td])"] = "%3%1%2%3%4%5",
["([^td]ˤ?)[td](ˤ?)( ?)([td])(ˤ?)$"] = "%1%4%2%3%4%5",
["([^sz]ˤ?)[sz](ˤ?)( ?)([sz])(ˤ?)([^sz])"] = "%1%4%2%3%4%5%6",
["^[sz](ˤ?)( ?)([sz])(ˤ?)([^sz])"] = "%3%1%2%3%4%5",
["([^sz]ˤ?)[sz](ˤ?)( ?)([sz])(ˤ?)$"] = "%1%4%2%3%4%5",
["([^ʃʒ])[ʃʒ]( ?)([ʃʒ])([^ʃʒ])"] = "%1%3%2%3%4",
["^[ʃʒ]( ?)([ʃʒ])([^ʃʒ])"] = "%2%1%2%3",
["([^ʃʒ])[ʃʒ]( ?)([ʃʒ])$"] = "%1%3%2%3",
["([^kɡj])[kɡj]( ?)([kɡj])([kɡj]ʷ)"] = "%1%3%2%3%4",
["^[kɡj]( ?)([kɡj])([kɡj]ʷ)"] = "%2%1%2%3",
["([^kɡj])[kɡj]( ?)([kɡj])$"] = "%1%3%2%3",
["([^kɡj])[kɡj]( ?)([kɡj])([^ʷkɡj])"] = "%1%3%2%3%4",
["^[kɡj]( ?)([kɡj])([^ʷkɡj])"] = "%2%1%2%3",
["([^kɡj])[kɡj]( ?)([kɡj])$"] = "%1%3%2%3",
["([^ʷkɡw])[kɡ]ʷ( ?)([kɡ]ʷ)([^w][^ʷ])"] = "%1%3%2%3%4",
["([^ʷkɡw])[kɡ]ʷ( ?)([kɡ]ʷ)([^w])$"] = "%1%3%2%3%4",
["([^ʷkɡw])[kɡ]ʷ( ?)([kɡ]ʷ)([^w][‿ ])"] = "%1%3%2%3%4",
["^[kɡ]ʷ( ?)([kɡ]ʷ)([^w][^ʷ])"] = "%2%1%2%3",
["^[kɡ]ʷ( ?)([kɡ]ʷ)([^w])$"] = "%2%1%2%3",
["^[kɡ]ʷ( ?)([kɡ]ʷ)([^w][‿ ])"] = "%2%1%2%3",
["([^ʷkɡw])[kɡ]ʷ( ?)([kɡ]ʷ)$"] = "%1%3%2%3",
["([^ʷw])w( ?)([kɡ]ʷ)([^w][^ʷ])"] = "%1%3%2%3%4",
["([^ʷw])w( ?)([kɡ]ʷ)([^w])$"] = "%1%3%2%3%4",
["([^ʷw])w( ?)([kɡ]ʷ)([^w][‿ ])"] = "%1%3%2%3%4",
["^w( ?)([kɡ]ʷ)([^w][^ʷ])"] = "%2%1%2%3",
["^w( ?)([kɡ]ʷ)([^w])$"] = "%2%1%2%3",
["^w( ?)([kɡ]ʷ)([^w][‿ ])"] = "%2%1%2%3",
["([^ʷw])w( ?)([kɡ]ʷ)$"] = "%1%3%2%3",
["([^ʷkɡw])[kɡ]ʷ( ?)w([^w][^ʷ])"] = "%1ɡʷ%2ɡʷ%3",
["([^ʷkɡw])[kɡ]ʷ( ?)w([^w])$"] = "%1ɡʷ%2ɡʷ%3",
["([^ʷkɡw])[kɡ]ʷ( ?)w([^w][‿ ])"] = "%1ɡʷ%2ɡʷ%3",
["^[kɡ]ʷ( ?)w([^w][^ʷ])"] = "ɡʷ%1ɡʷ%2",
["^[kɡ]ʷ( ?)w([^w])$"] = "ɡʷ%1ɡʷ%2",
["^[kɡ]ʷ( ?)w([^w][‿ ])"] = "ɡʷ%1ɡʷ%2",
["([^ʷkɡw])[kɡ]ʷ( ?)w$"] = "%1ɡʷ%2ɡʷ",
["([^xqɣ])[xqɣ]( ?)([xqɣ])([^xqɣ])"] = "%1%3%2%3%4",
["^[xqɣ]( ?)([xqɣ])([^xqɣ])"] = "%2%1%2%3",
["([^xqɣ])[xqɣ]( ?)([xqɣ])$"] = "%1%3%2%3",
["([^ħʕ])[ħʕ]( ?)([ħʕ])([^ħʕ])"] = "%1%3%2%3%4",
["^[ħʕ]( ?)([ħʕ])([^ħʕ])"] = "%2%1%2%3",
["([^ħʕ])[ħʕ]( ?)([ħʕ])$"] = "%1%3%2%3"
},
["e"] = {["θ([‿ ]?[szʃʒ])"] = "T%1", ["ð([‿ ]?[szʃʒ])"] = "D%1"},
["f"] = {
["([^rl])([rl])( ?)n([^t]?[‿ ])"] = "%1%2%3%2%4",
["([^rl])([rl])( ?)n([^t]?)$"] = "%1%2%3%2%4"
},
["g"] = {["nll?"] = "ll", ["n ll?"] = "l l", ["nrr?"] = "rr", ["n rr?"] = "r r"},
["h"] = {["j( ?)w"] = "ɡʷ%1ɡʷ"},
["i"] = {
["^j(" .. C .. ")"] = "i%1",
["([^j][‿ ])j(" .. C .. ")"] = "%1i%2",
["^w(" .. C .. ")"] = "u%1",
["([^w][‿ ])w(" .. C .. ")"] = "%1u%2"
},
["j"] = {["^([smT]ˤ?)ː"] = "%1", ["([‿ ]ə?)([smT]ˤ?)ː"] = "%1%2"},
["k"] = {["(" .. C .. "[ˤʷ]?)ː "] = "%1(ː) ", ["(" .. C .. "[ˤʷ]?)ː$"] = "%1(ː)"},
["l"] = {
["([ħʕχqʁ]ː?)æ"] = "%1ɑ",
["([ħʕχqʁ]ː?)i"] = "%1ɪ̙",
["([ħʕχqʁ]ː?)u"] = "%1ʊ̙",
["æ([ħʕχqʁ])"] = "ɑ%1",
["i([ħʕχqʁ])"] = "ɪ̙%1",
["u([ħʕχqʁ])"] = "ʊ̙%1",
["æ([^‿ ]-ˤ)"] = "ɑ%1",
["i([^‿ ]-ˤ)"] = "ɪ̙%1",
["u([^‿ ]-ˤ)"] = "ʊ̙%1",
["(ˤ[^‿ ]-)æ"] = "%1ɑ",
["(ˤ[^‿ ]-)i"] = "%1ɪ̙",
["(ˤ[^‿ ]-)u"] = "%1ʊ̙"
},
["m"] = {
["æ(" .. C .. "[ˤʷ]?ː)"] = "æ̝%1",
["i(" .. C .. "[ˤʷ]?ː)"] = "i̞%1",
["u(" .. C .. "[ˤʷ]?ː)"] = "u̞%1",
["ɑ(" .. C .. "[ˤʷ]?ː)"] = "ɑ̝%1",
["ɪ̙(" .. C .. "[ˤʷ]?ː)"] = "ɪ̙̞%1",
["ʊ̙(" .. C .. "[ˤʷ]?ː)"] = "ʊ̙̞%1",
["æ(" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "æ̝%1",
["i(%(?" .. C .. "%)?[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "i̞%1",
["u(%(?" .. C .. "%)?[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "u̞%1",
["ɑ(" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "ɑ̝%1",
["ɪ̙(%(?" .. C .. "%)?[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "ɪ̙̞%1",
["ʊ̙(%(?" .. C .. "%)?[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "ʊ̙̞%1",
["æ(" .. C .. "[ˤʷ]?)$"] = "æ̝%1",
["i(%(?" .. C .. "%)?[ˤʷ]?)$"] = "i̞%1",
["u(%(?" .. C .. "%)?[ˤʷ]?)$"] = "u̞%1",
["ɑ(" .. C .. "[ˤʷ]?)$"] = "ɑ̝%1",
["ɪ̙(%(?" .. C .. "%)?[ˤʷ]?)$"] = "ɪ̙̞%1",
["ʊ̙(%(?" .. C .. "%)?[ˤʷ]?)$"] = "ʊ̙̞%1",
["æ(" .. C .. "[ˤʷ]?[‿ ])"] = "æ̝%1",
["i(%(?" .. C .. "%)?[ˤʷ]?[‿ ])"] = "i̞%1",
["u(%(?" .. C .. "%)?[ˤʷ]?[‿ ])"] = "u̞%1",
["ɑ(" .. C .. "[ˤʷ]?[‿ ])"] = "ɑ̝%1",
["ɪ̙(%(?" .. C .. "%)?[ˤʷ]?[‿ ])"] = "ɪ̙̞%1",
["ʊ̙(%(?" .. C .. "%)?[ˤʷ]?[‿ ])"] = "ʊ̙̞%1"
},
["n"] = {["æ$"] = "ɑ", ["æ([‿ ])"] = "ɑ%1"},
["o"] = {
["^(" .. V .. "?" .. C .. "[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)([θT]ˤ?)$"] = "%1ə%2",
["^(" .. V .. "?" .. C .. "[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)([θT]ˤ?[‿ ])"] = "%1ə%2",
["([‿ ]" .. V .. "?" .. C .. "[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)([θT]ˤ?)$"] = "%1ə%2",
["([‿ ]" .. V .. "?" .. C .. "[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)([θT]ˤ?[‿ ])"] = "%1ə%2",
["(" .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?ː?[θT]ˤ?[‿ ])"] = "%1ə%2",
["(" .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?ː?[θT]ˤ?)$"] = "%1ə%2",
["(" .. C .. "[ˤʷ]?ː?)([ɡɟʝDdðfɣʁkcçlmNnrsʃCwjzbβhxχʒJqħʕ][ˤʷ]?ː?[‿ ])"] = "%1ə%2",
["(" .. C .. "[ˤʷ]?ː?)([ɡɟʝDdðfɣʁkcçlmNnrsʃCwjzbβhxχʒJqħʕ][ˤʷ]?ː?)$"] = "%1ə%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)(" .. C .. "[ˤʷ]?ː?)$"] = "%1ə%2",
["^(" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)(" .. C .. "[ˤʷ]?ː?[‿ ])"] = "%1ə%2",
["([‿ ]" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)(" .. C .. "[ˤʷ]?ː?)$"] = "%1ə%2",
["([‿ ]" .. C .. "?[ˤʷ]?ː?" .. C .. "?[ˤʷ]?)(" .. C .. "[ˤʷ]?ː?[‿ ])"] = "%1ə%2"
},
["ø"] = {
["^(" .. C .. "[ˤʷ]?ː?)ə(" .. C .. "[ˤʷ]?[‿ ])"] = "%1%2",
["^ə(" .. C .. "[ˤʷ]?ː?[‿ ])"] = "%1",
["(" .. V .. "[‿ ]" .. C .. "[ˤʷ]?ː?)ə(" .. C .. "[ˤʷ]?[‿ ])"] = "%1%2",
["(" .. V .. "[‿ ])ə(" .. C .. "[ˤʷ]?ː?[‿ ])"] = "%1%2",
["(" .. V .. C .. "[ˤʷ]?ː?[‿ ])ə(" .. C .. "[ˤʷ]?[‿ ])"] = "%1%2",
["(" .. V .. "[‿ ])ə(" .. C .. "[ˤʷ]?ː?)$"] = "%1%2",
["(" .. V .. "[‿ ]" .. C .. "[ˤʷ]?ː?)ə(" .. C .. "[ˤʷ]?)$"] = "%1%2",
["(" .. V .. C .. "[ˤʷ]?ː?[‿ ])ə(" .. C .. "[ˤʷ]?)$"] = "%1%2"
},
["O"] = {
["(" .. V .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "%1ə%2",
["(" .. V .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?ː)"] = "%1ə%2",
["^(" .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "%1ə%2",
["^(" .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?ː)"] = "%1ə%2",
["([‿ ]" .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "%1ə%2",
["([‿ ]" .. C .. "[ˤʷ]?ː?)(" .. C .. "[ˤʷ]?ː)"] = "%1ə%2",
["(" .. V .. "[‿ ]?" .. C .. "[ˤʷ]?ː?[‿ ])(" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)"] = "%1ə%2",
["(" .. V .. "[‿ ]?" .. C .. "[ˤʷ]?ː?[‿ ])(" .. C .. "[ˤʷ]?ː)"] = "%1ə%2",
["(" .. V .. "[‿ ]?" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?[‿ ])(" .. C .. "[ˤʷ]?)"] = "%1ə%2",
},
["p"] = {["əm"] = "m̩", ["əN"] = "n̪̩", ["əl"] = "l̩", ["ər"] = "r̩"},
["q"] = {
["əj"] = "ij",
["əʝ"] = "iʝ",
["əw"] = "uw"
},
["Q"] = {
["ij([^)])"] = "i(j)%1",
["iʝ([^)])"] = "i(ʝ)%1",
["uw([^)])"] = "u(w)%1",
["ij$"] = "i(j)",
["iʝ$"] = "i(ʝ)",
["uw$"] = "u(w)"
},
["r"] = {
["ai(" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?)$"] = "ɑ%1",
["ai(" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?[‿ ])"] = "ɑ%1",
["i(" .. V .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?)$"] = "(ij)%1",
["i(" .. V .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?[‿ ])"] = "(ij)%1",
["ui(" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?)$"] = "u%1",
["ui(" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?[‿ ])"] = "u%1",
["u(a" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?)$"] = "uj%1",
["u(a" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?[‿ ])"] = "uj%1",
["a(a" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?)$"] = "(ɑj)%1",
["a(a" .. C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?[‿ ])"] = "(ɑj)%1"
},
["s"] = {["([ ‿]j" .. C .. "?[ˤʷ]?" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)a a"] = "%1‿a", ["^(j" .. C .. "?[ˤʷ]?" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?)a a"] = "%1‿a"},--include every verbal prefix to recognize only the a-final conjugated forms
["t"] = {["([æiu]) ([æiu])"] = "%1‿j%2"},
["T"] = {["([æiu]‿j)i"] = "%1"},
["u"] = {["kkʷ"] = "kʷkʷ", ["ɡɡʷ"] = "ɡʷɡʷ"}
}
local dialects = {}
dialects["Ayt Ndhir"] = {
{{"u", "h", "r", "s", "i", "d", "f", "g"}, {true, "b"}},
{{"o", "ø"}, {true, "O"}, {"q", "Q", "t", "T", "n", "e", "c", "j", "a"}, {true, "l"}, {"m", "k", "p"}}
}
function export.pronunciation_phonemic(word)
m_scripts_util.checkScript(word, "Tfng")
translit = (lang:transliterate(word))
return mw.ustring.gsub(translit, '.', c)
end
function export.pronunciation_phonetic(word, dialect)
local word = export.pronunciation_phonemic(word)
local o = dialects[dialect]
for j = 1, #o[1] do -- set of rules
if o[1][j][1] == true then
local N = ""
while N ~= word do
N = word
for k = 2, #o[1][j] do -- rule
for x, y in pairs(r[o[1][j][k]]) do
word = s(word, x, y)
end
end
end
else
for k = 1, #o[1][j] do -- rule
for x, y in pairs(r[o[1][j][k]]) do
word = s(word, x, y)
end
end
end
end
word = s(word, '.[ˤʷ]?', p)
for d, g in pairs(t) do
word = s(word, d .. d, g)
word = s(word, d .. " " .. d .. "([^ː])", g .. "‿" .. "%1")
word = s(word, d .. " " .. d .. "$", "‿" .. g)
end
for j = 1, #o[2] do -- set of o
if o[2][j][1] == true then
local N = ""
while N ~= word do
N = word
for k = 2, #o[2][j] do -- rule
for x, y in pairs(r[o[2][j][k]]) do
word = s(word, x, y)
end
end
end
else
for k = 1, #o[2][j] do -- rule
for x, y in pairs(r[o[2][j][k]]) do
word = s(word, x, y)
end
end
end
end
word = s(word, "T", "t̪")
word = s(word, "D", "d̪")
word = s(word, "N", "n̪")
word = s(word, "C", "t͡ʃ")
word = s(word, "J", "d͡ʒ")
return word
end
function export.show(frame)
local args = frame:getParent().args
local page_title = mw.loadData("Module:headword/data").pagename
local p, results, results_ayt_ndhir = {}, {}, {}
if args[1] then
for index, item in ipairs(args) do
table.insert(p, (item ~= "") and item or nil)
end
else
p = {page_title}
end
if args["r"] then
for _, word in ipairs(p) do
table.insert(results, {pron = "/" .. export.pronunciation_phonemic(word) .. "/"})
table.insert(results_ayt_ndhir, {pron = "[" .. args["r"] .. "]"})
end
else
for _, word in ipairs(p) do
table.insert(results, {pron = "/" .. export.pronunciation_phonemic(word) .. "/"})
table.insert(results_ayt_ndhir, {pron = "[" .. export.pronunciation_phonetic(word, "Ayt Ndhir") .. "]"})
end
end
return "* " .. m_IPA.format_IPA_full { lang = lang, items = results } .. "\n** " .. m_a.format_qualifiers(lang, {"Ayt Ndhir"}) .. " " .. m_IPA.format_IPA_full { lang = lang, items = results_ayt_ndhir }
end
return export
tkplxx4eamdp34okwlq6kaesfo2zw0h
ლავ
0
312920
2576448
2282795
2026-11-08T14:46:49Z
Hiyuune
50834
/* Cách phát âm */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2576448
wikitext
text/x-wiki
=={{langname|bbl}}==
[[Image:Snow in Khevsureti.jpg|thumb|ლავ.]]
==={{section|etym}}===
{{inh+|bbl|cau-nkh-pro|*lawa}}. Các từ cùng gốc bao gồm {{cognate|inh|лоа}} và {{cognate|ce|ло̄}}.
==={{section|pron}}===
* {{IPA|bbl|/ˈlav/}}
* {{hyphenation|bbl|ლავ}}
* {{rhymes|bbl|av}}
==={{section|n}}===
{{head|bbl|Danh từ|g=cdd}}
# [[tuyết|Tuyết]].
===={{section|decl}}====
{{bbl-decl-noun-1a|ლავ}}{{catname|Danh tính loại ლავ|tiếng Bats}}
==={{section|ref}}===
* {{R:bbl:Schiefner|page=154b}}
* {{R:bbl:Gagua:1961|page=78}}
* {{R:bbl:Kadagidze|page=335a}}
* {{R:bbl:Kakashvili:2022|page=106}}
00ze2aqts3lcnplfticshy9pwi8etjl
avenes
0
319225
2576485
2191376
2026-11-09T09:41:33Z
Hiyuune
50834
2576485
wikitext
text/x-wiki
{{also|avenēs}}
=={{langname|lv}}==
==={{section|n}}===
{{head|lv|Biến thể hình thái danh từ|g=f}}
# {{infl of|lv|avene||gen|s|;|nom//voc//acc|p}}
odffp2x79tdj0ryv5v7nun8y7xfagwg
avenēs
0
319238
2576486
2191420
2026-11-09T09:41:46Z
Hiyuune
50834
2576486
wikitext
text/x-wiki
{{also|avenes}}
=={{langname|lv}}==
==={{section|n}}===
{{head|lv|Biến thể hình thái danh từ|g=f}}
# {{infl of|lv|avene||loc|p}}
agqgietmi1o1jr6rjlysquen8sv6wxx
Mô đun:category tree/topic/Animals
828
324855
2576478
2576171
2026-11-09T02:04:15Z
Hiyuune
50834
2576478
Scribunto
text/plain
local labels = {}
labels["Động vật"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Sinh vật"},
commonscat = "Animalia",
wpcat = true,
}
labels["Acanthurus"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[surgeonfish]], [[light-horseman]], [[louvar]]s, [[scat]]s, [[rabbitfish]], [[Moorish idol]]s and other fish in the [[perciform]] [[suborder]] [[Acanthuroidei]]",
parents = {"cá"},
}
labels["accentors"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[family]] [[Prunellidae]]",
parents = {"Bộ Sẻ"},
}
labels["accipiters"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[besra]]s, [[Cooper's hawk]]s, [[goshawk]]s, [[sharp-shinned hawk]]s, [[shikra]]s, [[sparrowhawk]]s, and other [[hawk]]s in the [[genus]] ''[[Accipiter]]''",
parents = {"birds of prey"},
}
labels["Bộ Cá tầm"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[paddlefish]], [[sturgeon]]s and other fish in the [[order]] [[Acipenseriformes]]",
parents = {"cá"},
}
labels["adephagan beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[diving beetle]]s, [[ground beetle]]s (including [[bombardier beetle]]s and [[tiger beetle]]s), [[whirligig beetle]]s and other [[beetle]]s in the [[suborder]] [[Adephaga]]",
parents = {"beetles"},
}
labels["African insectivores"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[aardvark]]s, [[elephant shrew]]s, [[golden mole]]s, [[otter shrew]]s, [[tenrec]]s, and other [[mammal]]s in the [[clade]] [[Afroinsectiphilia]]",
parents = {"mammals"},
}
labels["agamid lizards"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[agama]]s, [[bearded dragon]]s, [[flying dragon]]s, [[frilled lizard]]s, [[moloch]]s, [[spiny-tailed lizard]]s, [[stellion]]s and other [[lizard]]s in the [[family]] [[Agamidae]]",
parents = {"Phân bộ Thằn lằn"},
}
labels["alcelaphine antelopes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blesbuck]]s, [[bontebok]]s, [[bubal]]s, [[gnu]]s or [[wildebeest]], [[hartebeest]]s, [[hirola]], [[sassaby]]s, [[topi]]s, [[tetel]]s, and other [[antelopes]] in the [[subfamily]] [[Alcelaphinae]]",
parents = {"antelopes"},
}
labels["ammonites"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[extinct]] [[cephalopod]]s in the [[subclass]] [[Ammonoidea]]",
parents = {"cephalopods"},
}
labels["Lớp Lưỡng cư"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Phân ngành Có xương sống"},
commonscat = "Amphibia",
wpcat = true,
}
labels["amphipods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[beach flea]]s, [[lawn shrimp]], [[scud]]s, [[side swimmer]]s, [[skeleton shrimp]], [[whale louse|whale lice]], and other [[crustacean]]s in the [[order]] [[Amphipoda]]",
parents = {"Phân ngành Giáp xác"},
}
labels["Họ Vịt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[:w:vi:Họ Vịt|họ Vịt]]: ([[vịt]], [[ngỗng]] và [[thiên nga]])",
parents = {"Chim nước"},
}
labels["annelids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[earthworm]]s, [[leech]]es, [[ragworm]]s and many other [[segment]]ed [[worm]]s in the [[phylum]] [[Annelida]]",
parents = {"worms"},
}
labels["Bộ Cá vây chân"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the [[order]] [[Lophiiformes]]",
parents = {"cá"},
}
labels["anguimorph lizards"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[alligator lizard]]s, [[beaded lizard]]s, [[blindworm]]s, [[crocodile monitor]]s, [[galliwasp]]s, [[Gila monster]]s, [[glass lizard]]s, [[goanna]]s, [[Komodo dragon]]s, [[legless lizard]]s, [[nile monitor]]s, [[perentie]]s, [[sheltopusik]]s, [[water monitor]]s, and other [[lizards]] in the [[suborder]] [[Anguimorpha]]",
parents = {"Phân bộ Thằn lằn"},
}
labels["anomurans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=crablike [[crustacean]]s in the [[decapod]] [[infraorder]] [[Anomura]], which are closely related to the true [[crab]]s in the infraorder [[Brachyura]]",
parents = {"Phân ngành Giáp xác", "Bộ Mười chân"},
}
labels["anteaters and sloths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the [[order]] [[Pilosa]]",
parents = {"mammals"},
}
labels["antelopes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Guốc chẵn"},
}
labels["antilopine antelopes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blackbuck]]s, [[chinkara]]s, [[dibatag]]s, [[dik-dik]]s, [[gazelle]]s, [[gerenuk]]s, [[grysbok]]s, [[klipspringer]]s, [[oribi]]s, [[royal antelope]]s, [[saiga]]s, [[springbok]]s, [[steenbok]]s, [[zeren]], and other [[antelope]]s in the [[bovid]] [[subfamily]] [[Antilopinae]]",
parents = {"antelopes"},
}
labels["ants"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"hymenopterans"},
}
labels["antshrikes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"suboscines", "perching birds"},
}
labels["Anuran"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[amphibian]]s in the [[order]] [[Anura]], which are short-bodied and without tails, having long hind legs adapted for leaping that are typically folded at rest. Anurans are mostly known as [[frog]]s or [[toad]]s",
parents = {"Lớp Lưỡng cư"},
}
labels["Aphid"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[insect]]s in the [[superfamily]] [[Aphidoidea]]",
parents = {"Bộ Cánh nửa"},
}
labels["apodiforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[hummingbird]]s, [[needletail]]s, [[spinetail]]s, [[swift]]s, [[swiftlet]]s, [[treeswift]]s, and other [[bird]]s in the [[order]] [[Apodiformes]]",
parents = {"birds"},
}
labels["Lớp Hình nhện"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngành Chân đốt"},
}
labels["araneoid spiders"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bird dropping spider]]s, [[cobweb spiders]] (including [[black widow]]s and [[redback]]s), [[orbweaver]]s (including [[cross spider]]s and [[writing spider]]s), [[long-jawed spider]]s, [[money spider]]s, [[nesticid]]s, [[pimoid]], [[pirate spider]]s, [[tetragnathid]]s and other [[spider]]s in the [[superfamily]] [[Araneoidea]]",
parents = {"spiders"},
}
labels["argentiniform fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[argentine]]s, [[barreleye]]s, [[blacksmelt]]s, [[smoothtongue]]s and other fish in the [[order]] [[Argentiniformes]]",
parents = {"fish"},
}
labels["armadillos"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"mammals"},
}
labels["Ngành Chân đốt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Động vật"},
commonscat = "Arthropoda",
wpcat = true,
}
labels["aschizan flies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[fly|flies]] in the [[dipteran]] [[section]] [[Aschiza]]",
parents = {"dipterans"},
}
labels["asilomorph flies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bee fly|bee flies]], [[dance fly|dance flies]], [[Mydas fly|Mydas flies]], [[robber fly|robber flies]], [[stiletto fly|stiletto flies]], [[window fly|window flies]] and other [[fly|flies]] in the [[dipteran]] [[infraorder]] [[Asilomorpha]]",
parents = {"dipterans"},
}
labels["assassin bugs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ambush bug]]s, [[assassin bug]]s, [[corsair]]s, [[feather-legged bug]]s, [[kissing bug]]s or [[conenose bug]]s, [[masked hunter]]s, [[wheel bug]]s, and other [[true bug]]s in the [[family]] [[Reduviidae]]",
parents = {"true bugs"},
}
labels["astacideans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crustacean]]s in the [[decapod]] [[infraorder]] [[Astacidea]], including the original [[species]] known as [[crayfish]] and [[lobster]]s, and their relatives",
parents = {"Phân ngành Giáp xác", "Bộ Mười chân"},
}
labels["atheriniform fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blue-eye]]s, [[hardyhead]]s, [[grunion]], [[jacksmelt]], [[rainbowfish]], [[silverside]]s, [[zona]], and other fish in the [[order]] [[Atheriniformes]]",
parents = {"fish"},
}
labels["Alcidae"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[auk]]s, [[guillemot]]s, [[murre]]s, [[puffin]]s, [[razorbill]]s, and other [[seabird]]s in the family [[Alcidae]]",
parents = {"Chim biển"},
}
labels["Bộ Cá răng kiếm"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[daggertooth]]s, [[lancetfish]], [[sergeant baker]]s, [[greeneye]]s, [[telescopefish]], [[lizardfish]] and other fish in the [[order]] [[Aulopiformes]]",
parents = {"cá"},
}
labels["Australasian robins"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[passerine]] [[family]] [[Petroicidae]], which are not closely related to the [[European robin]] (an [[Old World flycatcher]] in the family [[Muscicapidae]]), or the [[American robin]] (a [[thrush]] in the family [[Turdidae]])",
parents = {"perching birds"},
}
labels["động vật khi nhỏ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"động vật"},
}
labels["bandicoots and bilbies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[peramelid]]s, [[bandicoot]]s, [[marl]]s, [[quenda]]s, [[chaeropodid]]s, [[pig-footed bandicoot]]s, [[thylacomyid]]s, [[bilby|bilbies]], [[dalgite]]s, [[rabbit-eared bandicoot]]s, [[philander]]s, [[pinkie]]s, and other [[marsupial]]s in the [[order]] [[Peramelemorphia]]",
parents = {"marsupials"},
}
labels["barklice"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=non-[[parasitic]] [[insect]]s in the [[order]] [[Psocodea]]",
parents = {"insects"},
}
labels["barnacles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crustacean]]s in the [[infraclass]] [[Cirripedia]], including the parasitic [[rhizocephalan]]s",
parents = {"Phân ngành Giáp xác"},
}
labels["bats"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"mammals"},
}
labels["bees"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"hymenopterans", "beekeeping"},
}
labels["beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"insects"},
}
labels["Bộ Cá nhói"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ballyhoo]], [[flying fish]], [[garfish]], [[halfbeak]]s, [[houndfish]], [[mackerel pike]]s, [[medaka]]s, [[needlefish]], [[ricefish]], [[saury|sauries]], [[silver gar]], and other fish in the [[order]] [[Beloniformes]]",
parents = {"cá"},
}
labels["bibionomorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[March fly|March flies]], [[cecidomyiid]] [[gall midge]]s, [[keroplatid]] [[fungus gnat]]s, [[mycetophilid]]s, [[sciarid]]s and other [[fly|flies]], [[gnat]]s and [[midge]]s in the [[dipteran]] [[infraorder]] [[Bibionomorpha]]",
parents = {"dipterans"},
}
labels["Lớp Chim"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Phân ngành Có xương sống"},
commonscat = "Aves",
wpcat = true,
}
labels["Chim săn mồi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds that live by [[predatory]] hunting, and from [[carrion]]",
parents = {"Lớp Chim"},
}
labels["bivalves"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[clam]]s, [[cockle]]s, [[mussel]]s, [[oyster]]s, [[scallop]]s and other [[mollusk]]s in the [[class]] [[Bivalvia]]",
parents = {"Ngành Thân mềm"},
}
labels["blennies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blenny|blennies]], [[chaenopsid]]s, [[clinid]]s, [[dactyloscopid]]s, [[klipfish]], [[labrisomid]]s, [[triplefin]]s, [[weedfish]] and other fish in the [[perciform]] [[suborder]] [[Blennioidei]]",
parents = {"fish"},
}
labels["boas"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[snake]]s in the family [[Boidae]]",
parents = {"Phân bộ Rắn"},
}
labels["bostrichiform beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[carpet beetle]]s, [[deathwatch beetle]]s, [[drugstore beetle]]s, [[museum beetle]]s, [[powder-post beetle]]s, and other [[anobiid]]s/[[ptinid]]s, [[bostrichid]]s, [[dermestid]]s, [[derodontid]]s, [[jacobsoniid]]s and [[nosodendrid]]s in the [[coleopteran]] [[infraorder]] [[Bostrichiformia]]",
parents = {"beetles"},
}
labels["bovines"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Guốc chẵn"},
}
labels["brachiopods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[animal]]s in the [[phylum]] [[Brachiopoda]]. <u>Note</u>: not to be confused with [[branchiopod]]s, which are [[crustacean]]s",
parents = {"animals"},
}
labels["branchiopods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[[brine shrimp]], [[clam shrimp]], [[fairy shrimp]], [[tadpole shrimp]], [[water flea]]s, and other [[crustacean]]s in the [[class]] [[Branchiopoda]]. <u>Note</u>: not to be confused with [[brachiopod]]s, which are a separate [[phylum]]",
parents = {"Phân ngành Giáp xác"},
}
labels["bryozoans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[animal]]s in the [[phylum]] [[Bryozoa]], also known as [[Ectoprocta]]",
parents = {"animals"},
}
labels["bulbuls"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bulbul]]s, [[greenbul]]s, [[brownbul]]s, [[leaflove]]s, [[bristlebill]]s, and other birds in the [[passerine]] [[family]] [[Pycnonotidae]]",
parents = {"perching birds"},
}
labels["buteos"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[hawk]]s in the [[genus]] ''[[Buteo]]'', known as [[buzzard]]s in Europe",
parents = {"birds of prey"},
}
labels["Bướm ngày"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Côn trùng"},
}
labels["caddis flies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=insects in the order [[Trichoptera]], which are closely related to the [[butterfly|butterflies]] and [[moth]]s but with hairs on their wings instead of scales, and which have [[aquatic]] [[larvae]] that live in cases that they build around themselves",
parents = {"insects"},
}
labels["caecilians"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[amphibian]]s in the [[order]] [[Gymnophiona]], which are legless and resemble [[earthworm]]s or [[snake]]s",
parents = {"amphibians"},
}
labels["Họ Lạc đà"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=động vật thuộc họ [[lạc đà]]",
parents = {"Lớp Thú", "Bộ Guốc chẵn"},
}
labels["Họ Chó"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Ăn thịt"},
}
labels["Caprinae"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[sheep]], [[goat]]s, [[goat antelope]]s, [[chamois]], [[muskox]]en, [[bharal]], [[goral]], [[ibex]], [[mouflon]], [[serow]], [[tahr]], [[tur]], [[takin]] and other animals in the [[bovid]] [[subfamily]] [[Caprinae]], formerly known as the [[family]] Capridae",
parents = {"Bộ Guốc chẵn"},
}
labels["caprimulgiforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[caprimulgiform]]s: birds in the taxonomic order [[Caprimulgiformes]]- the [[nightjar]]s, [[oilbird]]s, [[frogmouth]]s, [[potoo]]s, etc",
parents = {"birds"},
}
labels["carcharhiniform sharks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bull shark]]s, [[catshark]]s, [[gummy shark]]s, [[hammerhead]]s, [[leopard shark]]s, [[morgay]]s, [[requiem shark]]s, [[tiger shark]]s, [[tope]]s, [[whaler]]s, [[whitetip]]s and other sharks in the [[order]] [[Carcharhiniformes]]",
parents = {"Liên bộ Cá mập"},
}
labels["cardinalids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cardinal]]s, [[dickcissel]]s, [[indigo bunting]]s, [[pyrrhuloxia]]s, [[rose-breasted grosbeak]]s, [[scarlet tanager]]s, and other birds in the [[family]] [[Cardinalidae]]",
parents = {"perching birds"},
}
labels["caridean shrimp"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crustacean]]s in the [[decapod]] [[infraorder]] [[Caridea]], mostly known as [[shrimp]] or [[prawn]]s",
parents = {"Phân ngành Giáp xác", "Bộ Mười chân"},
}
labels["Bộ Ăn thịt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bear]]s, [[cat]]s, [[civet]]s, [[dog]]s, [[fossa]]s, [[hyaena]]s, [[mongoose]]s, [[panda]]s, [[raccoon]]s, [[seal]]s, [[skunk]]s, [[weasel]]s and various other [[mammal]]s in the [[order]] [[Carnivora]]",
parents = {"Lớp Thú"},
}
labels["Cá chép"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the [[subfamily]] [[Cyprininae]], the [[carps]] and [[goldfish]]",
parents = {"Họ Cá chép"},
}
labels["Bộ Cá da trơn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"cá", "Otomorpha"},
}
labels["Mèo"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cat]]s in the sense of members of the genus ''[[Felis]]''",
parents = {"Họ Mèo"},
commonscat = "Felis silvestris catus",
wpcat = true,
}
labels["cattle"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"bovines", "gia súc"},
}
labels["caviomorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[agouti]]s, [[capybara]]s, [[chinchilla]]s, [[guinea pig]]s, [[New World porcupine]]s, [[nutria]]s, [[tuco-tuco]]s and other [[rodent]]s in the parvorder [[Caviomorpha]]",
parents = {"Bộ Gặm nhấm"},
}
labels["Lớp Chân đầu"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngành Thân mềm"},
}
labels["cercopithecin monkeys"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blue monkey]]s, [[Diana monkey]]s, [[guenon]]s, [[lesula]]s, [[malbrouck]]s, [[patas monkey]]s, [[talapoin]]s, [[vervet]]s, and other [[Old World monkey]]s in the [[cercopithecine]] [[tribe]] [[Cercopithecini]]",
parents = {"Old World monkeys"},
}
labels["Liên họ Đuôi cứng"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[passerine]] [[superfamily]] [[Certhioidea]], the [[treecreeper]]s, [[nuthatch]]es, [[gnatcatcher]]s and [[wren]]s",
parents = {"Bộ Sẻ"},
}
labels["Họ Hươu nai"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Guốc chẵn"},
}
labels["Phân thứ bộ Cá voi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cetacean]]s ([[dolphin]]s, [[whale]]s and [[porpoise]]s)",
parents = {"Bộ Guốc chẵn"},
}
labels["chalcidoid wasps"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[chalcidid]]s, [[encyrtid]]s, [[fig wasp]]s, [[jointworm]]s, [[mymarid]] [[fairyfly|fairyflies]], [[perilampid]]s, [[torymid]]s, [[trichogramma]]s, and other [[wasp]]s in the [[superfamily]] [[Chalcidoidea]]",
parents = {"hymenopterans"},
}
labels["Characidae"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the order [[Characiformes]]",
parents = {"cá", "Otomorpha"},
}
labels["Gà"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Gia cầm", "Bộ Gà"},
}
labels["chimaeras (fish)"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cartilaginous]] fish in the [[Chimaeriformes]], the only surviving [[order]] of the [[subclass]] [[Holocephali]], and separate from the [[shark]]s, [[ray]]s, [[skate]]s and [[sawfish]] of the subclass [[Elasmobranchii]]",
parents = {"fish"},
}
labels["Ngành Dây sống"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=animals in the [[phylum]] [[Chordata]]",
parents = {"Động vật"},
}
labels["chrysomeloid beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cerambycid]]s or [[longhorn beetle]]s such as [[apple borer]]s, [[huhu beetle]]s, [[locust borer]]s and [[thunderbolt beetle]]s, as well as [[chrysomelid]]s or [[leaf beetle]]s such as [[asparagus beetle]]s, [[bean weevil]]s, [[Colorado beetle]]s, [[cucumber beetle]]s, [[flea beetle]]s, [[potato beetle]]s, and other [[beetle]]s in the [[superfamily]] [[Chrysomeloidea]]",
parents = {"beetles"},
}
labels["cicadas"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[insect]]s in the [[superfamily]] [[Cicadoidea]]",
parents = {"hemipterans"},
}
labels["cichlids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Cichlidae]]",
parents = {"labroid fish"},
}
labels["clinids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Clinidae]]",
parents = {"fish"},
}
labels["Ngành Thích ty bào"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[coral]]s, [[gorgonian]]s, [[hydra]]s, [[myxozoan]]s, [[Portuguese man-of-war]], [[sea anemone]]s, [[sea fir]]s, [[sea wasp]]s, and other animals in the in the [[phylum]] [[Cnidaria]]",
parents = {"Động vật"},
wpcat = true,
}
labels["Phân ngành San hô"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "một phân ngành động vật không xương sống [[thủy sinh]] bao gồm [[hải quỳ]], [[:w:vi:Bộ San hô cứng|san hô đá]] và san hô mềm, thuộc ngành [[:w:vi:Ngành Thích ty bào|Ngành Thích ty bào]] (Cnidaria)",
parents = {"Ngành Thích ty bào"},
wpcat = true,
commonscat = "Anthozoa",
}
labels["cockatoos"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crested]] [[parrot]]s in the [[family]] [[Cacatuidae]]",
parents = {"parrots"},
}
labels["cockroaches"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"insects"},
}
labels["colobine monkeys"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[colobus]]es, [[douc]]s, [[langur]]s, [[guereza]]s, [[hanuman]]s,[[leaf monkey]]s, [[lutung]]s, [[proboscis monkey]]s, and other [[Old World monkey]]s in the [[subfamily]] [[Colobinae]]",
parents = {"Old World monkeys"},
}
labels["colubrid snakes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[snake]]s in the family [[Colubridae]]",
parents = {"Phân bộ Rắn"},
}
labels["colugos"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=the [[primate]]-like [[gliding]] [[mammal]]s in the [[order]] [[Dermoptera]], also known as [[flying lemur]]s",
parents = {"mammals"},
}
labels["columbids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[columbid]]s, i.e. [[pigeon]]s and [[dove]]s",
parents = {"birds"},
}
labels["copepods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crustacean]]s in the [[subclass]] [[Copepoda]]",
parents = {"Phân ngành Giáp xác"},
}
labels["coraciiforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bee-eater]]s, [[ground rollers]], [[kingfisher]]s, [[motmot]]s, [[roller]]s, [[tody|todies]] and other birds in the taxonomic order [[Coraciiformes]]",
parents = {"birds"},
}
labels["corvids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"perching birds", "corvoid birds"},
}
labels["corvoid birds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[apostlebird]]s, [[bird of paradise|birds of paradise]], [[crow]]s, [[drongo]]s, [[fantail]]s, [[grinder]]s, [[jackdaw]]s, [[jay]]s, [[magpie]]s, [[magpie-lark]]s, [[manucode]]s, [[monarchid]]s, [[nutcracker]]s, [[piwakawaka]]s, [[raven]]s, [[restless flycatcher]]s, [[riflebird]]s, [[shrike]]s, [[standard-wing]]s, and other birds in the [[superfamily]] [[Corvoidea]]",
parents = {"perching birds"},
}
labels["cotingas"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[suboscine]] [[family]] [[Cotingidae]]",
parents = {"suboscines"},
}
labels["crabs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crab]]s, [[decapod]] [[crustacean]]s in the [[infraorder]] [[Brachyura]]",
parents = {"Phân ngành Giáp xác", "Bộ Mười chân"},
}
labels["cranes (birds)"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crane]]s",
parents = {"gruiforms"},
}
labels["cricetids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cotton rat]]s, [[deer mouse|deer mice]], [[hamster]]s, [[harvest mouse|harvest mice]], [[lemming]]s, [[vole]]s, [[woodrat]]s, and other [[rodent]]s in the [[family]] [[Cricetidae]]",
parents = {"Bộ Gặm nhấm"},
}
labels["crickets and grasshoppers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cricket]]s, [[grasshopper]]s, [[katydid]]s, [[weta]]s and other [[insect]]s in the order [[Orthoptera]]",
parents = {"insects"},
}
labels["croakers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[croaker]]s, [[drum]]s, [[weakfish]]s and other fish in the family [[Sciaenidae]]",
parents = {"percoid fish"},
}
labels["Bộ Cá sấu"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crocodile]]s, [[alligator]]s, [[caymans]], and other [[reptile]]s in the order [[Crocodilia]]",
parents = {"Lớp Bò sát"},
}
labels["Phân ngành Giáp xác"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngành Chân đốt"},
}
labels["cuckoos"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cuckoo]]s and other birds in the [[family]] [[Cuculidae]]",
parents = {"otidimorph birds"},
}
labels["cuckooshrikes and minivets"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[family]] [[Campephagidae]]",
parents = {"perching birds"},
}
labels["cucujoid beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[flower beetle]]s, [[fungus beetle]]s, [[grain beetle]]s, [[lady beetle]]s, [[lizard beetle]]s, [[Mexican bean beetle]]s, and other [[beetle]]s in the [[superfamily]] [[Cucujoidea]]",
parents = {"beetles"},
}
labels["Ngành Sứa lược"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=animals in the [[phylum]] [[Ctenophora]], the [[comb jelly|comb jellies]]",
parents = {"Động vật"},
}
labels["culicomorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[biting midge]]s, [[blackfly|blackflies]], [[blood worm]]s, [[glassworm]]s, [[meniscus midge]]s, [[mosquito]]s, [[no-see-um]]s, [[non-biting midge]]s, [[phantom midge]]s and other [[insect]]s in the [[dipteran]] [[infraorder]] [[Culicomorpha]]",
parents = {"dipterans"},
}
labels["Họ Cá chép"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[carp]], [[minnow]]s, [[chub]]s and other fish in the [[family]] [[Cyprinidae]]. In some classifications, this group is known as the [[superfamily]] [[Cyprinoidea]] or [[suborder]] [[Cyprinoidei]], with the [[cyprinid]] [[subfamily|subfamilies]] considered to be families",
parents = {"cá", "Otomorpha"},
}
labels["Phân họ Vịt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[gadwall]]s [[garganey]]s, [[mallard]]s, [[mottled duck]]s, [[pintail]]s, [[shoveler]]s, [[teal]]s, [[wigeon]]s and other ducks in either the [[anatid]] [[tribe]] [[Anatini]] or [[subfamily]] [[Anatinae]], depending on the classification",
parents = {"Vịt"},
}
labels["damselflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bluestreak]]s, [[bluetail]]s, [[demoiselle]]s, [[flatwing]]s, [[redtail]]s, [[riverdamsel]]s, [[rubyspot]]s, [[spreadwing]]s, [[threadtail]]s, [[whitetip]]s, and other insects in the [[odonate]] [[suborder]] [[Zygoptera]]",
parents = {"dragonflies and damselflies"},
}
labels["danaine butterflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[clearwing]]s, [[crow]]s, [[milkweed]]s, [[monarch]]s, [[paper kite butterfly|paper kite butterflies]], [[tiger]]s, [[wanderer]]s and other [[butterfly|butterflies]] in the [[nymphalid]] [[subfamily]] [[Danainae]]",
parents = {"nymphalid butterflies"},
}
labels["dasyuromorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[thylacine]]s, [[numbat]]s, [[dasyure]]s, [[antechinus]]es, [[dibbler]]s, [[dunnart]]s, [[mulgara]]s. [[phascogale]]s, [[planigale]]s, [[quoll]]s, [[Tasmanian devil]]s, and other [[marsupial]]s in the [[order]] [[Dasyuromorphia]]",
parents = {"marsupials"},
}
labels["Bộ Mười chân"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crabs]], [[crayfish]], [[lobster]]s, [[prawn]]s, ([[caridean]]) [[shrimp]], and many other [[crustacean]]s in the [[order]] [[Decapoda]]",
parents = {"Phân ngành Giáp xác"},
}
labels["delphinids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=(oceanic) [[dolphin]]s, [[grampus]]es, [[killer whale]]s/[[orca]]s, [[pilot whale]]s, and other [[cetacean]]s in the [[family]] [[Delphinidae]]",
additional = "Note: [[river dolphin]]s and [[porpoise]]s are in other families.",
parents = {"Phân thứ bộ Cá voi"},
}
labels["designer dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"dogs"},
commonscat = true,
wpcat = true,
}
labels["dinosaurs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"reptiles"},
}
labels["dionychan spiders"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crab spider]]s, [[flattie]]s, [[ground spider]]s, [[huntsman spider]]s, [[jumping spider]], [[scorpion spider]]s, and other [[spiders]] in the [[entelegyne]] [[clade]] [[Dionycha]]",
parents = {"spiders"},
}
labels["dipterans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[fly|flies]], [[gnat]]s, [[midge]]s, [[mosquito]]s and other [[insect]]s in the order [[Diptera]]",
parents = {"insects"},
}
labels["Chó"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Chó"},
commonscat = true,
wpcat = true,
}
labels["Mèo nhà"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Mèo"},
}
labels["dragonflies and damselflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=insects in the order [[Odonata]]",
parents = {"insects"},
}
labels["Vịt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Vịt", "Gia cầm"},
}
labels["dugongs and manatees"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the order [[Sirenia]]",
parents = {"mammals"},
}
labels["Đại bàng"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chim săn mồi"},
}
labels["earthworms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=worms in the [[annelid]] [[suborder]] [[Lumbricina]]",
parents = {"annelids"},
}
labels["earwigs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=insects in the order [[Dermaptera]]",
parents = {"insects"},
}
labels["echinoderms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"animals"},
commonscat = "Echinodermata",
wpcat = true,
}
labels["eels"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[eel]]s, elongated, snakelike fish in the order [[Anguilliformes]]",
parents = {"elopomorph fish"},
}
labels["elapid snakes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cobra]]s, [[coral snake]]s, [[krait]]s, [[mamba]]s, [[sea snake]]s, and other [[venomous]] snakes in the family [[Elapidae]]",
parents = {"Phân bộ Rắn"},
}
labels["elateroid beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[click beetle]]s/[[elaterid]]s, [[fire beetle]]s, [[firefly|fireflies]]/[[lampyrid]]s, [[glowworm]]s, [[net-winged beetle]]s/[[lycid]]s, [[railroad worm]]s/[[phengodid]]s, [[soldier beetle]]s/[[cantharid]]s, [[throscid]]s, [[wireworm]]s and other [[beetle]]s in the [[superfamily]] [[Elateroidea]]",
parents = {"beetles"},
}
labels["Họ Voi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Thú"},
commonscat = "Elephantidae",
wpcat = true,
}
labels["elopomorph fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bonefish]], [[eel]]s, [[gulper eel]]s, [[halosaur]]s, [[ladyfish]], [[tarpon]] and other fish in the [[superorder]] [[Elopomorpha]]",
parents = {"fish"},
}
labels["emberizids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bunting]]s, [[yellowhammer]]s and related birds in the [[passerine]] family [[Emberizidae]]",
additional = "<u>Note</u>: for New World species that were formerly classified in this family, see [[:Category:{{{langcode}}}:New World sparrows]].",
parents = {"perching birds"},
}
labels["emydid turtles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=(North American) [[box turtle]]s, [[chicken turtle]]s, [[cooter]]s, [[ellachick]]s, [[pond turtle]]s, [[slider]]s, [[terrapin]]s, and other [[turtle]]s in the [[family]] [[Emydidae]]",
parents = {"turtles"},
}
labels["Họ Ngựa"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Guốc lẻ"},
}
labels["erinaceids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[erinaceid]]s – hedgehogs and relatives",
parents = {"mammals"},
}
labels["Eupleridae"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[euplerid]]s — mongoose-like mammals found in Madagascar",
parents = {"Bộ Ăn thịt"},
}
labels["Bộ Guốc chẵn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the [[order]] [[Artiodactyla]]",
parents = {"Lớp Thú"},
}
labels["Họ Cắt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[caracara]]s, [[falcon]]s, [[hobby|hobbies]], [[kestrel]]s, [[lanner]]s, [[merlin]]s, [[saker]]s, and other birds in the [[family]] [[Falconidae]]",
parents = {"Chim săn mồi"},
}
labels["Họ Mèo"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Ăn thịt"},
}
labels["female animals"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"animals", "female"},
}
labels["cá"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Phân ngành Có xương sống"},
commonscat = "Fish",
wpcat = true,
}
labels["flamingos"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chim nước"},
}
labels["flatfish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[sole]]s, [[flounder]]s, [[halibut]]s and other fish in the order [[Pleuronectiformes]]",
parents = {"fish"},
}
labels["flatworms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[fluke]]s, [[monogenean]]s, [[planarian]]s, [[polyclad]]s, [[tapeworm]]s, and other animals in the [[phylum]] [[Platyhelminthes]]",
additional = "For terms related to the study of [[parasitic]] [[worm#Noun|worms]], see [[:Category:Helminthology]] and its subcategories.",
parents = {"worms"},
}
labels["Bộ Bọ chét"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Côn trùng"},
}
labels["Bộ Gà"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[fowl]]s: land birds in the [[order]] [[Galliformes]]",
parents = {"Lớp Chim"},
}
labels["Cáo"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Chó"},
}
labels["Chim nước"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds that live mainly in [[freshwater]] areas, including [[estuaries]]",
parents = {"Lớp Chim"},
}
labels["freshwater whitefish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cisco]]s, [[houting]]s, [[inconnu]]s, [[lavaret]]s, [[marena]]s, [[omul]]s, [[Otsego bass]], [[peled]]s, [[pollan]]s, [[roundfish]], [[tullibee]]s, [[vendace]]s, [[whitefish]] and other fish in the [[salmonid]] [[subfamily]] [[Coregoninae]]",
parents = {"Họ Cá hồi"},
}
labels["Bộ Không đuôi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Anuran"},
}
labels["gadiforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cod]], [[haddock]], [[hake]] and other fish in the [[order]] [[Gadiformes]]",
parents = {"fish"},
}
labels["gasterosteiform fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[stickleback]]s, [[hypoptychid]] [[sand eel]]s, [[tubesnout]]s and other fish in the [[order]] [[Gasterosteiformes]]",
additional = "Note: See [[:Category:Syngnathiform fish]] for a group formerly included within this order.",
parents = {"fish"},
}
labels["Lớp Chân bụng"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngành Thân mềm"},
}
labels["họ Tắc kè"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "Mục từ {{{langname}}} thuộc chủ đề họ Tắc kè, một họ các loài thằn lằn cổ nhất trong nhóm thằn lằn hiện đại.",
parents = {"Phân bộ Thằn lằn"},
}
labels["ngỗng"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Vịt", "Gia cầm"},
}
labels["geometrid moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[carpet]]s, [[engrailed]]s, [[heath]]s, [[pug]]s, [[peppered moth]]s, [[streak]]s, [[wave]]s and other [[moth]]s in the [[family]] [[Geometridae]], most of which have [[caterpillar]]s known as [[inchworm]]s, [[looper]]s, [[measuring worm]]s or [[spanworm]]s",
parents = {"moths"},
}
labels["dê"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Caprinae", "gia súc"},
}
labels["gobies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[goby|gobies]], [[dartfish]], [[mudskipper]]s, [[sea gudgeon]]s, [[sleeper]]s, [[wormfish]], and other [[fish]] in the [[perciform]] [[suborder]] [[Gobioidei]]",
parents = {"fish"},
}
labels["gossamer-winged butterflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blue]]s, [[copper]]s, [[elfin]]s, [[harvester]]s, [[hairstreak]]s, [[sunbeam]]s and other [[butterfly|butterflies]] in the [[family]] [[Lycaenidae]]",
parents = {"Bướm ngày"},
}
labels["grebes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chim nước"},
}
labels["Gà gô"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blackcock]]s, [[capercaillie]]s, [[grouse]], [[moorcock]]s, [[prairie chicken]]s, [[ptarmigan]]s, [[sagehen]]s, and other birds in the [[phasianid]] [[subfamily]] [[Tetraoninae]]",
parents = {"Bộ Gà"},
}
labels["gruiforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[coot]]s, [[crake]]s, [[crane]]s, [[finfoot]]s, [[flufftail]]s, [[gallinule]]s, [[limpkin]]s, [[rail]]s, [[sungrebe]]s, [[trumpeter]]s, and other birds in the [[order]] [[Gruiformes]]",
parents = {"Chim nước"},
}
labels["gulls"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[gull]]s, [[seabird]]s in the [[family]] [[Laridae]]",
parents = {"Chim biển"},
}
labels["gun dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chó săn"},
}
labels["hares"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"lagomorphs"},
}
labels["Bộ Cánh nửa"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[aphid]]s, [[leafhopper]]s, [[scale insect]]s, [[true bug]]s, [[whitefly|whiteflies]], and other [[insect]]s in the order [[Hemiptera]]",
parents = {"Lớp Côn trùng"},
}
labels["herding dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"pastoral dogs"},
}
labels["herons"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[heron]]s, [[bittern]]s and [[egret]]s",
parents = {"Chim nước"},
}
labels["Họ Cầy lỏn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[herpestid]]s- mongooses, meerkats, and relatives",
parents = {"Bộ Ăn thịt"},
}
labels["Họ Cá trích"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[herring]]s, [[shad]]s, [[sardine]]s and other fish in the family [[Clupeidae]]",
parents = {"cá", "Otomorpha"},
}
labels["holostean fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[gar]]s and [[bowfin]]s, primitive fish in the [[infraclass]] [[Holostei]]",
parents = {"fish"},
}
labels["hominids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Linh trưởng"},
}
labels["honeyeaters"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=Australian [[chat]]s, [[bellbird]]s, [[friarbird]]s, [[gibberbird]]s, [[honeyeater]]s, [[miner]]s, [[spinebill]]s, [[wattlebird]]s, and other birds in the [[family]] [[Meliphagidae]]",
parents = {"meliphagoid birds"},
}
labels["hoopoes and hornbills"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[hoopoe]]s, [[woodhoopoe]]s (including [[scimitarbill]]s), [[hornbill]]s, [[ground hornbill]]s, and other birds in the taxonomic order [[Bucerotiformes]]",
parents = {"birds"},
}
labels["horseflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blind-fly|blind-flies]], [[breezefly|breezeflies]], [[cleg]]s, [[deerfly|deerflies]], [[forest fly|forest flies]], [[gadfly|gadflies]], [[horsefly|horseflies]], [[oxfly|oxflies]], [[zimb]]s, and other biting flies in the [[family]] [[Tabanidae]]",
parents = {"dipterans"},
}
labels["horse breeds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngựa"},
commonscat = true,
wpcat = true,
}
labels["Ngựa"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Ngựa", "gia súc"},
}
labels["hummingbirds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"apodiforms"},
}
labels["Chó săn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chó"},
}
labels["hyaenids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Ăn thịt"},
}
labels["hydrozoans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bluebottle]]s, [[calycophoran]]s, [[filiferan]]s, [[hydra]]s, [[hydractinian]]s, [[leptothecate]]s, [[narcomedusa]]s, [[pandeid]]s, [[physonect]]s, [[plumularian]]s, [[Portuguese man-of-war]]s, [[siphonophore]]s, [[stylaster]]s, [[sea fir]]s, [[sea ginger]], [[trachylid]]s, [[trachymedusa]]s, amd other animals in the [[cnidarian]] [[class]] [[Hydrozoa]]",
parents = {"cnidarians"},
}
labels["hymenopterans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ant]]s, [[bee]]s, [[ichneumon wasp]]s, [[sawfly|sawflies]], [[wasp]]s and other [[insect]]s in the order [[Hymenoptera]]",
parents = {"insects"},
}
labels["hyraxes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"mammals"},
}
labels["ibises and spoonbills"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ibis]]es and [[spoonbill]]s",
parents = {"Chim nước"},
}
labels["ichthyosauromorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ichthyosaurs]] and related groups of [[extinct]] [[aquatic]] [[reptile]]s in the [[clade]] [[Ichthyosauromorpha]]",
parents = {"reptiles"},
}
labels["icterids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[New World]] [[passerine]] family [[Icteridae]]",
parents = {"perching birds"},
}
labels["iguanoid lizards"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[anole]]s, [[basilisk]]s, [[collared lizard]]s, [[chuckwalla]]s, [[fence lizard]]s, [[fringe-toed lizard]]s, [[horned lizard]]s, [[iguana]]s, [[leopard lizard]]s, [[side-blotched lizard]]s, [[zebra-tailed lizard]]s and other [[lizard]]s formerly included in the [[family]] [[Iguanidae]], and now mostly treated as comprising either the [[infraorder]] [[Pleurodonta]] or the [[superfamily]] [[Iguanoidea]]",
parents = {"Phân bộ Thằn lằn"},
}
labels["Lớp Côn trùng"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngành Chân đốt"},
}
labels["isopods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[gribble]]s, [[pillbug]]s, [[salve bug]]s, [[slater]]s, [[sea slater]]s, [[sowbug]]s, [[woodlouse|woodlice]], and other [[crustacean]]s in the [[order]] [[Isopoda]]",
parents = {"Phân ngành Giáp xác"},
}
labels["jackfish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[jack]]s, [[pompano]]s, [[jack mackerel]]s, [[scad]]s and other fish in the family [[Carangidae]]",
parents = {"percoid fish"},
}
labels["jawless fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[lamprey]]s and [[hagfish]]: primitive eel-like fishes that have no jaws",
parents = {"fish"},
}
labels["kingfishers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"coraciiforms"},
}
labels["kites (birds)"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[hawk]]s in the [[accipitrid]] [[subfamily|subfamilies]] [[Milvinae]] and [[Elaninae]], as well as some in the subfamily [[Perninae]]",
parents = {"birds of prey"},
}
labels["kyphosid fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blackfish]], [[drummer]]s, [[footballer]]s, [[greenfish]], [[halfmoon]]s, [[luderick]]s, [[mado]]s, [[moonlighter]]s, [[nibbler]]s, [[opaleye]]s, [[sea chub]]s, [[stripey]]s, [[sweep]]s and other fish in the [[percoid]] [[family]] [[Kyphosidae]]",
parents = {"percoid fish"},
}
labels["labroid fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[anemonefish]], [[cale]]s, [[cichlid]]s, [[clownfish]], [[damselfish]], [[parrotfish]], [[surfperch]], [[wrasse]]s, and other fish in the [[perciform]] [[suborder]] [[Labroidei]]",
parents = {"fish"},
}
labels["labyrinth fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[climbing perch]], [[gourami]]s, [[paradisefish]], [[Siamese fighting fish]] and other fish in the [[suborder]] [[Anabantoidei]]",
parents = {"fish"},
}
labels["lacertoid lizards"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[amphisbaena]]s, [[caiman lizard]]s, [[green lizard]]s, [[ocellated lizard]]s, [[racerunner]]s, [[rock lizard]]s, [[tegu]]s, [[teiid]]s, [[thunderworm]]s, [[viviparous lizard]]s, [[wall lizard]]s, [[whiptail]]s, and other [[lizard]]s in the [[superfamily]] [[Lacertoidea]]",
parents = {"Phân bộ Thằn lằn"},
}
labels["Bộ Thỏ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Thú"},
}
labels["lamniform sharks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[basking shark]]s, [[goblin shark]]s, [[great white shark]]s, [[mako shark]]s, [[megamouth shark]]s, [[porbeagle]]s, [[sand shark]]s, [[thresher shark]]s, and other [[shark]]s in the [[order]] [[Lamniformes]]",
parents = {"Liên bộ Cá mập"},
}
labels["lampriform fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[crestfish]], [[oarfish]], [[opah]]s, [[ribbonfish]], [[velifer]]s and other fish in the [[order]] [[Lampridiformes]] (not to be confused with the unrelated [[lamprey]]s)",
parents = {"fish"},
}
labels["larks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"perching birds"},
}
labels["laughingthrushes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[family]] [[Leiothrichidae]]",
parents = {"perching birds"},
}
labels["leaf warblers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the family [[Phylloscopidae]]",
parents = {"warblers"},
}
labels["lesser apes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[gibbon]]s (including [[hoolock]]s, [[lar gibbon]]s [[wow-wow]]s, etc.) and [[siamang]]s, comprising the [[family]] [[Hylobatidae]], which is closely related to the [[hominid]]s",
parents = {"Bộ Linh trưởng"},
}
labels["Cá Leuciscine"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bream]]s, [[chub]]s, [[dace]]s, [[ide]]s, many [[minnow]]s, [[nase]]s, [[roach]]es, [[shiner]]s, [[ziege]]s, and other fish in the [[cyprinid]] [[subfamily]] [[Leuciscinae]], sometimes treated as the [[family]] [[Leuciscidae]], or as the [[tribe]] [[Leuciscini]] within the [[subfamily]] [[Cyprininae]]",
parents = {"Họ Cá chép"},
}
labels["libellulid dragonflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[amberwing]]s, [[basker]]s, [[darter]]s, [[dropwing]]s, [[duskhawk]]s, [[flutterer]]s, [[glider]]s, [[meadowhawk]]s, [[pennant]]s, [[percher]]s, [[skimmer]]s, [[slimwing]]s, [[swampdragon]]s, [[twister]]s, and other [[dragonfly|dragonflies]] in the [[family]] [[Libellulidae]]",
parents = {"dragonflies and damselflies"},
}
labels["lice"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[parasitic]] insects in the [[order]] [[Psocodea]]",
parents = {"insects"},
}
labels["limenitidine butterflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[admiral]]s, [[clipper]]s, [[count]]s, [[duke]]s, [[purple]]s, [[sister]]s, and other [[butterfly|butterflies]] in the [[nymphalid]] [[subfamily]] [[Limenitidinae]]",
parents = {"nymphalid butterflies"},
}
labels["littorinimorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[boat shell]]s, [[carrier shell]]s, [[conch]]s, [[cowry|cowries]], [[flamingo tongue]]s, [[helmet shell]]s, [[moon snail]]s, [[pebblesnail]]s, [[trumpet shell]]s, [[velutinid]]s, [[winkle]]s, [[worm-shell]]s, and other [[gastropod]]s in the [[order]] [[Littorinimorpha]]",
parents = {"Lớp Chân bụng"},
}
labels["livestock guardian dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"pastoral dogs"},
}
labels["Phân bộ Thằn lằn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Bò sát"},
}
labels["loaches"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the [[cypriniform]] [[superfamily]] [[Cobitoidea]]",
parents = {"fish", "Otomorpha"},
}
labels["lobe-finned fishes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[coelacanth]]s, [[lungfish]] and other fishes in the [[subclass]] [[Sarcopterygii]] of the [[bony fish]]es",
additional = "<u>Please note</u>: although the [[tetrapod]]s (including all [[reptile]]s, [[amphibian]]s, [[bird]]s and [[mammal]]s) are descended from within this group, they are excluded from this category by not being fish.",
parents = {"fish"},
}
labels["loons"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[loon]]s, birds known as [[diver]]s outside the US",
parents = {"Chim nước"},
}
labels["macaques"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[Barbary ape]]s, [[bonnet monkey]]s, [[crab-eating macaque]]s, [[Japanese macaque]]s, [[moor macaque]]s, [[pigtail macaque]]s, [[rhesus monkey]]s, [[toque]]s, and other [[Old World monkey]]s in the [[genus]] ''[[Macaca]]''",
parents = {"Old World monkeys"},
}
labels["macropods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bettong]]s, [[kangaroo]]s, [[pademelon]]s, [[potoroo]]s, [[quokka]]s, [[wallaby]]s, and other [[marsupial]]s in the [[diprotodont]] [[suborder]] [[Macropodiformes]]",
parents = {"marsupials"},
}
labels["malaconotoid birds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[Australian magpie]]s, [[bushshrike]]s, [[butcherbird]]s, [[boubou]]s, [[brubru]]s, [[currawong]]s, [[gonolek]]s, [[squeaker]]s, [[vanga]]s, and other birds in the [[passerine]] [[superfamily]] [[Malaconotoidea]]",
parents = {"perching birds"},
}
labels["male animals"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"animals", "male"},
}
labels["Lớp Thú"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Phân ngành Có xương sống"},
}
labels["mantids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=insects in the [[order]] [[Mantodea]], often known as [[praying mantis]]es",
parents = {"insects"},
}
labels["marsupials"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"mammals"},
}
labels["mayflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=insects in the [[order]] [[Ephemeroptera]]",
parents = {"insects"},
}
labels["megalopterans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[alderfly|alderflies]], [[dobsonfly|dobsonflies]], [[fishfly|fishflies]] and other insects in the [[order]] [[Megaloptera]]",
parents = {"insects"},
}
labels["meliphagoid birds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blue wren]]s, [[bristlebird]]s, [[emu-wren]]s, [[fairywren]]s, [[gerygone]]s, [[grasswren]]s, [[honeyeater]]s, [[pardalote]]s, [[pilotbird]]s, [[redthroat]]s, [[scrubwren]]s, [[thornbill]]s, [[weebill]]s, [[whiteface]]s, and other birds in the [[passerine]] [[superfamily]] [[Meliphagoidea]]",
parents = {"perching birds"},
}
labels["mephitids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mephitid]]s: skunks and stink badgers",
parents = {"Bộ Ăn thịt"},
}
labels["Mergus"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[diving]] [[duck]]s in the [[genus]] ''[[Mergus]]'' and a few similar species",
parents = {"Vịt"},
wpcat = true,
}
labels["mimids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[catbird]]s, [[mockingbird]]s, [[thrasher]]s and other birds in the [[passerine]] family [[Mimidae]]",
parents = {"perching birds"},
}
labels["mites and ticks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[arachnid]]s in the [[subclass]] [[Acari]]",
parents = {"arachnids"},
}
labels["Ngành Thân mềm"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Động vật"},
commonscat = "Mollusca",
wpcat = true,
wp = "Động vật thân mềm",
}
labels["Khỉ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Linh trưởng"},
}
labels["Bộ Đơn huyệt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Thú"},
}
labels["mosquitoes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[insect]]s in the [[dipteran]] [[family]] [[Culicidae]]",
parents = {"culicomorphs"},
}
labels["moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"insects"},
}
labels["murids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=a number of [[rats]], [[mice]], and other [[rodent]]s in the [[Old World]] [[family]] [[Muridae]]",
parents = {"Bộ Gặm nhấm"},
}
labels["muscicapids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[passerine]] family [[Muscicapidae]]",
parents = {"perching birds"},
}
labels["muscoid flies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[anthomyiid]]s such as [[root fly|root flies]], [[cabbage fly|cabbage flies]] and [[onion fly|onion flies]]; [[fanniid]]s; [[muscid]]s such as [[housefly|houseflies]], [[face fly|face flies]] and [[stable fly|stable flies]]; [[scathophagid]]s such as [[dungfly|dungflies]]; and other [[fly|flies]] in the [[dipteran]] [[superfamily]] [[Muscoidea]]",
parents = {"dipterans"},
}
labels["Họ Chồn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Ăn thịt"},
}
labels["mygalomorph spiders"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[baboon spider]]s, [[barking spider]]s, [[bird spider]]s, [[purseweb spider]]s, [[tarantula]]s, [[trapdoor spider]]s, and other [[spider]]s in the [[infraorder]] [[Mygalomorphae]]",
parents = {"spiders"},
}
labels["myriapods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[centipede]]s, [[millipede]]s, [[pauropod]]s, [[symphylan]]s, and other [[arthropod]]s in the [[subphylum]] [[Myriapoda]]",
parents = {"arthropods"},
}
labels["myrmicine ants"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ant]]s in the [[subfamily]] [[Myrmicinae]]",
parents = {"ants"},
}
labels["nematodes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[filaria]], [[gapeworm]]s, [[lungworm]]s, [[pinworm]]s, [[threadworm]]s, [[wheatworm]]s, [[whipworm]]s and other [[worm]]s in the [[phylum]] [[Nematoda]]",
parents = {"worms"},
}
labels["Neogastropoda"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[admiral shell]]s, [[cone snail]]s, [[harp shell]]s, [[murex]]es, [[olive]]s, [[rhombus]]es, [[spindle]]s, [[tulip shell]]s, [[turnip shell]]s, [[volute]]s, [[whelk]]s, [[winkle]]s and other [[gastropod]]s in the [[clade]] [[Neogastropoda]] (treated as an [[order]] in some classifications)",
parents = {"Lớp Chân bụng"},
}
labels["New World monkeys"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[capuchin]]s, [[howler monkey]]s, [[marmochủ đề thuộc nhóm tập hợp]]s, [[night monkey]]s, [[saki]]s, [[spider monkey]]s, [[squirrel monkey]]s, [[tamarin]]s, [[titi]]s, [[uakari]]s, [[woolly monkey]]s, and other [[monkey]]s in the [[parvorder]] [[Platyrrhini]]",
parents = {"Khỉ"},
}
labels["Họ Cút Tân thế giới"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[family]] [[Odontophoridae]], most of which live in the [[New World]] and are known as [[quail]]s, but the family also includes the African [[genus]] ''[[Ptilopachus]]'' and some [[species]] are known as partridges",
parents = {"Bộ Gà"},
}
labels["New World sparrows"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[sparrow]]- and [[finch]]-like birds in the [[passerine]] [[family]] [[Passerellidae]], until recently considered part of the family [[Emberizidae]]",
parents = {"perching birds"},
}
labels["New World warblers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the family [[Parulidae]]",
parents = {"warblers"},
}
labels["neuropterans"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[antlion]]s, [[lacewing]]s, [[mantisfly|mantisflies]], [[owlfly|owlflies]] and other insects in the [[order]] [[Neuroptera]]",
parents = {"insects"},
}
labels["Phân họ Sa giông"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[terrestrial]] [[salamander]]s in the [[subfamily]] [[Pleurodelinae]]",
parents = {"Bộ Có đuôi"},
}
labels["noctuoid moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[armyworm]]s, [[cinnabar]]s, [[corn earworm]]s, [[cutworm]]s, [[gypsy moth]]s, [[owlet moth]]s, [[processionary|processionaries]], [[tiger moth]]s, [[underwing]]s, [[wainscot]]s, [[wooly bear]]s, and many other [[moth]]s (and [[caterpillar]]s) in the [[superfamily]] [[Noctuoidea]]",
parents = {"moths"},
}
labels["nudibranchs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[sea slug]]s in the [[gastropod]] [[order]] [[Nudibranchia]]",
parents = {"Lớp Chân bụng"},
}
labels["nymphalid butterflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[admiral]]s, [[brown]]s, [[buckeye]]s, [[checkerspot]]s, [[emperor]]s, [[fritillary|fritillaries]], [[leafwing]]s, [[longwing]]s, [[monarch]]s, [[morpho]]s, [[painted lady|painted ladies]], [[ringlet]]s, [[satyr]]s, [[sister]]s, [[snout]]s, [[tortoiseshell]]s, and other butterflies in the [[family]] [[Nymphalidae]]",
parents = {"Bướm ngày"},
}
labels["octopuses"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"cephalopods"},
}
labels["Bộ Guốc lẻ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the [[order]] [[Perissodactyla]], including the [[equid]]s, [[tapir]]s and [[rhinoceros]]es",
parents = {"Lớp Thú"},
}
labels["oestroid flies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blowfly|blowflies]], [[bluebottle]]s, [[botfly|botflies]], [[flesh fly|flesh fles]], [[greenbottle]]s, [[mango fly|mango flies]], [[screwworm]]s, [[tachinid]]s, [[torsalo]]s, [[tumbu fly|tumbu flies]], [[warble fly|warble flies]], and other flies in the [[superfamily]] [[Oestroidea]]",
parents = {"dipterans"},
}
labels["Old World monkeys"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[baboon]]s, [[colobus]], [[douc]]s, [[gelada]]s, [[green monkey]]s, [[grivet]]s, [[langur]]s, [[malbrouck]]s, [[mandrill]]s, [[mangabey]]s, [[patas monkey]]s, [[proboscis monkey]]s, [[talapoin]]s, [[vervet]]s, and other [[monkeys]] in the [[family]] [[Cercopithecidae]], the only [[members]] of the [[parvorder]] [[Catarrhini]] aside from the greater/lesser apes and humans",
parents = {"Khỉ"},
}
labels["Old World orioles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[perching bird]]s in the [[family]] [[Oriolidae]], which are not closely related to the New World orioles in the family [[Icteridae]]",
parents = {"perching birds"},
}
labels["ornithopods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[camptosaurid]]s, [[hadrosaur]]s, [[iguanodontid]]s, [[lambeosaurid]]s, [[rhabdodontid]]s, [[saurolophid]]s, [[thescelosaurid]]s, [[trachodontid]]s, and other [[dinosaur]]s in the [[ornithischian]] [[clade]] [[Ornithopoda]]",
parents = {"dinosaurs"},
}
labels["osteoglossomorph fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[aba]]s, [[arapaima]]s, [[arowana]]s, [[butterfly fish]], [[elephantfish]], [[featherback]]s, [[mooneye]]s and other fish in the [[superorder]] [[Osteoglossomorpha]]",
parents = {"fish"},
}
labels["Otariidae"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the [[family]] [[Otariidae]], including the [[fur seal]]s and [[sea lion]]s",
parents = {"Pinnipedia"},
}
labels["otidimorph birds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bustard]]s in the [[family]] [[Otididae]] and [[order]] [[Otidiformes]]; [[turaco]]s or [[lourie]]s, [[go-away bird]]s, [[plantain-eater]]s, etc., in the [[family]] [[Musophagidae]] and [[order]] [[Musophagiformes]]; and [[cuckoo]]s in the [[family]] [[Cuculidae]] and [[order]] [[Cuculiformes]]; all in the [[clade]] [[Otidimorphae]]",
parents = {"birds"},
}
labels["Otomorpha"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[anchovy|anchovies]], [[beaked salmon]], [[carp]], [[catfish]], [[characin]]s, [[electric eel]]s, [[ghost knifefish]], [[herring]]s, [[loach]]es, [[milkfish]], [[minnow]]s, [[mousefish]], [[slickhead]]s, [[sucker]]s, [[tubeshoulder]]s, and other fish in the [[clade]] [[Otocephala]]",
parents = {"cá"},
}
labels["ovenbirds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[suboscine]] family [[Furnariidae]], including the former family Dendrocolaptidae (now the [[subfamily]] [[Dendrocolaptinae]])",
parents = {"suboscines"},
}
labels["Bộ Cú"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chim săn mồi"},
}
labels["pangolins"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the [[order]] [[Pholidota]]",
parents = {"mammals"},
}
labels["Chi Báo"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[panther]]s in the sense of members of the genus ''[[Panthera]]''",
parents = {"Họ Mèo"},
}
labels["parrots"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"birds"},
}
labels["pastoral dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"dogs"},
}
labels["chim cánh cụt"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Chim"},
}
labels["pentatomoid bugs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[acanthosomatid]]s, [[burrowing bug]]s, [[jewel bug]]s, [[shield bug]]s, [[stinkbug]]s, [[thyreocorid]]s, and other [[true bug]]s in the [[superfamily]] [[Pentatomoidea]]",
parents = {"true bugs"},
}
labels["perch and darters"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Percidae]]",
parents = {"percoid fish"},
}
labels["Bộ Sẻ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[passerine]]s or perching birds: members of the order [[Passeriformes]]",
parents = {"Lớp Chim"},
}
labels["percoid fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[archerfish]], [[bass]], [[bigeye]]s, [[bluefish]], [[butterflyfish]], [[cardinalfish]], [[cobia]], [[croaker]]s, [[flagtail]]s, [[goatfish]], [[grouper]]s, [[grunt]]s, [[horse mackerel]], [[jack]]s, [[jawfish]], [[leaffish]], [[mahi-mahi]], [[mojarra]], [[perch]], [[pomfret]]s, [[pompano]], [[ponyfish]], [[porgy|porgies]], [[remora]]s, [[roosterfish]], [[sea bass]], [[sea bream]], [[snapper]], [[sunfish]], [[sweeper]]s, [[threadfin]], [[tilefish]], [[wreckfish]], and other [[perciform]] fish in the [[superfamily]] [[Percoidea]]",
parents = {"fish"},
}
labels["Phiomorpha"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blesmol]]s, [[sand mole]]s, [[mole rat]]s, [[dassie rat]]s or [[rock rat]]s, [[Old World porcupine]]s, [[cane rat]]s or [[grasscutter]]s and other [[rodent]]s in the parvorder [[Phiomorpha]], which is the Old World counterpart of the [[caviomorph]]s",
parents = {"Bộ Gặm nhấm"},
}
labels["Họ Hải cẩu thật sự"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mammal]]s in the [[family]] [[Phocidae]], including the [[earless seal]]s (also known as [[true seal]]s)",
parents = {"Pinnipedia"},
}
labels["piciforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[woodpecker]]s, [[aracari]]s, [[coppersmith]]s, [[honeyguide]]s, [[jacamar]]s, [[nunlet]]s, [[puffbird]]s, [[toucan]]s, and other birds in the [[order]] [[Piciformes]]",
parents = {"birds"},
}
labels["pierid butterflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[brimstone]]s, [[orange tip]]s, [[sulfur]]s, [[white]]s and other [[butterfly|butterflies]] in the [[family]] [[Pieridae]]",
parents = {"Bướm ngày"},
}
labels["lợn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Guốc chẵn", "gia súc"},
commonscat = "Suidae",
wpcat = true,
}
labels["pikes (fish)"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Esocidae]]",
parents = {"fish"},
}
labels["Pinnipedia"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Ăn thịt"},
}
labels["pipits and wagtails"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[passerine]] family [[Motacillidae]]",
parents = {"perching birds"},
}
labels["placoderms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[extinct]] armored fish of the [[class]] [[Placodermi]] from the [[Silurian]] and [[Devonian]] [[geologic]] [[period]]s",
parents = {"fish"},
}
labels["plovers and lapwings"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=birds in the [[charadriiform]] [[family]] [[Charadriidae]]",
parents = {"shorebirds"},
}
labels["pomfrets"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Bramidae]]",
parents = {"percoid fish"},
}
labels["Bộ Linh trưởng"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Thú"},
commonscat = "Primates",
wpcat = true,
}
labels["procyonids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[procyonid]]s: ([[raccoon]]s, [[coati]]s, [[kinkajou]]s, [[olingo]]s, [[ringtail]]s and [[cacomistle]]s)",
parents = {"Bộ Ăn thịt"},
}
labels["prosimians"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Linh trưởng"},
}
labels["pterosaurs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"reptiles"},
}
labels["pyraloid moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bee moth]]s, [[flour moth]]s, [[leaf crumpler]]s, [[magpie moth]]s, [[melonworm]]s, [[mint moth]]s, [[orangeworm]]s, [[pantry moth]]s, [[pickleworm]]s, [[snout moth]]s, [[veneer moth]]s, [[wax moth]]s and other [[crambid]] and [[pyralid]] [[moths]] in the [[superfamily]] [[Pyraloidea]]",
parents = {"moths"},
}
labels["Thỏ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Bộ Thỏ"},
}
labels["rallids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[rallid]]s: [[rail]]s and other birds in the family [[Rallidae]]",
parents = {"gruiforms"},
}
labels["ratites"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ratite]]s: birds in the superorder [[Palaeognathae]], including large flightless birds such as [[ostrich]]es, and [[emu]]s, as well as the smaller [[kiwi]]s and [[flighted]] [[tinamous]]",
parents = {"birds"},
}
labels["rays and skates"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[fish]] in the superorder [[Batoidea]]",
parents = {"fish"},
}
labels["reindeers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Hươu nai"},
}
labels["Lớp Bò sát"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Phân ngành Có xương sống"},
commonscat = "Reptilia",
wpcat = true,
}
labels["retrievers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"gun dogs"},
}
labels["rhinoceroses"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[rhinoceros]]es, [[mammal]]s in the [[perissodactylic]] [[family]] [[Rhinocerotidae]]",
parents = {"odd-toed ungulates"},
}
labels["Bộ Gặm nhấm"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Thú"},
}
labels["Bộ Có đuôi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[amphiuma]]s, [[axolotl]]s, [[hellbender]]s, [[mud puppy|mud puppies]], [[olm]]s, [[newt]]s, [[salamander]]s, [[siren]]s, and other [[amphibian]]s in the [[order]] [[Caudata]]",
parents = {"Lớp Lưỡng cư"},
}
labels["Họ Cá hồi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[salmon]]s, [[trout]], and other fish in the family [[Salmonidae]]",
parents = {"cá"},
}
labels["saturniid moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[Atlas moth]]s, [[cecropia]]s, [[hickory horned devil]]s, [[io moth]]s, [[luna moth]]s, [[polyphemus moth]]s, and other [[moth]]s (and [[caterpillar]]s) in the [[family]] [[Saturniidae]]",
parents = {"moths"},
}
labels["satyrine butterflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[brown]]s, [[forester]]s, [[grayling]]s, [[heath]]s, [[palmfly|palmflies]], [[ringlet]]s, [[satyr]]s, and other [[butterfly|butterflies]] in the [[nymphalid]] [[subfamily]] [[Satyrinae]]",
parents = {"nymphalid butterflies"},
}
labels["sauropods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[apatosaur]]s, [[brachiosaur]]s, [[brontosaur]]s, [[camarasaur]]s, [[cetiosaur]]s, [[diplodocus]]es, [[saltasaurid]]s, [[titanosaurian]]s, [[turiasaur]]s, [[vulcanodontid]]s, and other [[dinosaurs]] in the [[saurischian]] [[infraorder]] [[Sauropoda]]",
parents = {"dinosaurs"},
}
labels["sauropterygians"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[elasmosaur]]s, [[placodont]]s, [[plesiosaur]]s, and other extinct aquatic [[reptile]]s in the [[superorder]] [[Sauropterygia]]",
parents = {"reptiles"},
}
labels["sawflies and wood wasps"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[horntail]]s, [[pigeon tremex]], [[rose slug]]s, [[sawfly|sawflies]], [[wood wasp]]s, and other primitive [[hymenopteran]]s in the [[suborder]] [[Symphyta]]",
parents = {"hymenopterans"},
}
labels["scale insects"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[insect]]s in the [[superfamily]] [[Coccoidea]]",
parents = {"hemipterans"},
}
labels["scarabaeoids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cockchafer]]s, [[dor]]s, [[dung beetle]]s, [[June beetle]]s, [[rain beetle]]s, [[rose chafer]]s, [[scarab]]s, [[stag beetle]]s, and other beetles in the [[superfamily]] [[Scarabaeoidea]]",
parents = {"beetles"},
}
labels["scenthounds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chó săn"},
}
labels["scincomorph lizards"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[blue-tongue lizard]]s, [[night lizard]]s, [[sandfish]], [[skink]]s, [[sungazer]]s, and other [[lizard]]s in the [[infraorder]] [[Scincomorpha]]",
parents = {"Phân bộ Thằn lằn"},
}
labels["scolopacids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[curlew]]s, [[dunlin]]s, [[godwit]]s, [[knot]]s, [[redshank]]s, [[ruff]]s, [[sandpiper]]s, [[snipe]]s, [[stint]]s, [[turnstone]]s, [[tattler]]s, [[whimbrel]]s, [[woodcock]]s, [[yellowleg]]s, and other birds in the [[charadriiform]] [[family]] [[Scolopacidae]]",
parents = {"shorebirds"},
}
labels["Họ Cá thu ngừ"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[mackerel]]s, [[tuna]]s, [[barracuda]]s, [[swordfish]], and other fish in the suborder [[Scombroidei]]",
parents = {"cá"},
}
labels["scorpaeniform fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bullhead]]s, [[cabezon]], [[golomyanka]], [[greenling]]s, [[gurnard]]s, [[Irish lord]], [[lionfish]], [[lumpsucker]]s, [[pigfish]], [[poacher]]s, [[sablefish]], [[scorpionfish]], [[sculpin]]s, [[sea raven]]s, [[sea toad]]s, [[skilfish]], [[snailfish]], [[stonefish]], [[wingfish]], and other fish in the [[order]] [[Scorpaeniformes]]",
parents = {"fish"},
}
labels["scorpions"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=true [[scorpion]]s: [[arachnid]]s in the [[order]] [[Scorpiones]]",
parents = {"arachnids"},
}
labels["screamers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[screamer]]s: birds in the family [[Anhimidae]], related to [[duck]]s and [[geese]]",
parents = {"birds"},
}
labels["Chim biển"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Chim"},
}
labels["sea anemones"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cnidarian]]s in the [[order]] [[Actiniaria]]",
parents = {"cnidarians"},
}
labels["sea cucumbers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[echinoderm]]s in the [[class]] [[Holothuroidea]]",
parents = {"echinoderms"},
}
labels["sea urchins"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[echinoderm]]s in the [[class]] [[Echinoidea]], including the [[sand dollar]]s",
parents = {"echinoderms"},
}
labels["sea turtles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[flatback]]s, [[green turtle]]s, [[hawksbill]]s, [[leatherback]]s, [[loggerhead]]s, [[ridley]]s, and other [[turtle]]s in the [[superfamily]] [[Chelonioidea]]",
parents = {"turtles"},
}
labels["sebastids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Sebastidae]]",
parents = {"scorpaeniform fish"},
}
labels["serranids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[sea bass]], [[grouper]]s, [[rockcod]]s, [[comber]]s and other fish in the family [[Serranidae]]",
parents = {"percoid fish"},
}
labels["Liên bộ Cá mập"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"cá"},
}
labels["Cừu"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Caprinae", "gia súc"},
}
labels["shorebirds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"birds"},
}
labels["shrikes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"perching birds", "corvoid birds"},
}
labels["sighthounds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chó săn"},
}
labels["skippers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=insects in the family [[Hesperiidae]]",
parents = {"Bướm ngày"},
}
labels["smelts"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the [[order]] [[Osmeriformes]]",
parents = {"fish"},
}
labels["snails"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Chân bụng"},
}
labels["Phân bộ Rắn"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Bò sát"},
}
labels["snappers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the [[family]] [[Lutjanidae]]",
parents = {"percoid fish"},
}
labels["soft corals"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[calcaxonian]]s, [[dead man's fingers]], [[fan coral]]s, [[gorgonian]]s, [[holaxonian]]s, [[scleraxonian]]s, [[sea feather]]s, [[sea willow]]s, [[stoloniferan]]s, [[whip coral]]s, and other marine animals in the [[cnidarian]] order [[Alcyonacea]]",
parents = {"cnidarians"},
}
labels["soricomorphs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[shrew]]s, [[mole]]s, [[solenodon]]s, and other [[mammal]]s in the [[order]] [[Soricomorpha]]",
parents = {"mammals"},
}
labels["South American canids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fox-like [[canid]]s in the [[subtribe]] [[Cerdocyonina]], which are more closely related to the [[dog]]s and [[wolf|wolves]] than to the true [[fox]]es. Also known as [[zorro]]s",
parents = {"Họ Chó"},
}
labels["spaniels"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"gun dogs"},
}
labels["sparids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[sea breams]], [[porgie]]s, [[scup]]s and other fish in the family [[Sparidae]]",
parents = {"percoid fish"},
}
labels["sphinx moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[hawkmoth]]s, [[hornworm]]s, [[hummingbird moth]]s, [[sphinx moth]]s,[[tomato worm]]s, and other [[moth]]s (and [[caterpillar]]s) in the [[family]] [[Sphingidae]]",
parents = {"moths"},
}
labels["Nhện"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Lớp Hình nhện"},
}
labels["sponges"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[aquatic]] [[animal]]s in the [[phylum]] [[Porifera]]",
parents = {"animals"},
}
labels["squid"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"cephalopods"},
}
labels["Họ Sóc"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[squirrel]]s, [[chipmunk]]s, [[marmot]]s, [[prairie dog]]s, [[woodchuck]]s and other [[rodent]]s in the family [[Sciuridae]]",
parents = {"Bộ Gặm nhấm"},
}
labels["staphylinoid beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[beetle]]s in the [[superfamily]] [[Staphylinoidea]]",
parents = {"beetles"},
}
labels["starlings"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[starling]]s, [[mynah]]s, and other birds in the [[passerine]] family [[Sturnidae]]",
parents = {"perching birds"},
}
labels["stick insects"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[insect]]s (including the [[leaf insect]]s) in the [[order]] known as either [[Phasmida]] or [[Phasmatodea]], which are noted for their extreme adaptations in form and color to look like parts of the plants they feed on",
parents = {"insects"},
}
labels["stoneflies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[freshwater]] [[aquatic]] [[insect]]s in the [[order]] [[Plecoptera]]",
parents = {"insects"},
}
labels["stony corals"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=marine animals in the [[cnidarian]] order [[Scleractinia]]",
parents = {"cnidarians"},
}
labels["storks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chim nước"},
}
labels["stromateoid fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[barrelfish]], [[blue eye cod]], [[dollarfish]], [[driftfish]], [[lafayette]], [[medusafish]], [[rudderfish]], [[squaretail]], [[warehou]], and other fish in the [[perciform]] [[suborder]] [[Stromateoidei]]",
parents = {"fish"},
}
labels["sturgeons"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Acipenseridae]]",
parents = {"fish"},
}
labels["suboscines"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[antpitta]]s, [[antshrike]]s, [[antthrush]]es, [[asity|asities]], [[broadbill]]s, [[cotinga]]s, [[crescentchest]]s, [[gnateater]]s, [[manakin]]s, [[ovenbird]]s, [[pitta]]s, [[sharpbill]]s, [[spadebill]]s, [[tapaculo]]s, [[tityra]]s, [[tyrant flycatcher]]s, [[woodcreeper]]s, and other birds in the [[passerine]] [[suborder]] [[Tyranni]]",
parents = {"perching birds"},
}
labels["suckers (fish)"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[buffalo fish]], [[cuiui]], [[jumprock]]s, [[quillback]], [[redhorse]], [[sucker]]s, and other freshwater fish in the family [[Catostomidae]]",
parents = {"fish", "Otomorpha"},
}
labels["suliform birds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[anhinga]]s, [[booby|boobies]], [[cormorant]]s, [[frigatebird]]s, [[gannet]]s, and other [[seabirds]] in the [[order]] [[Suliformes]]",
parents = {"seabirds"},
}
labels["sunfish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=freshwater fish in the family [[Centrarchidae]]",
parents = {"percoid fish"},
}
labels["swallows"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"perching birds"},
}
labels["swallowtails"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[apollo]]s, [[batwing]]s, [[birdwing]]s, [[clubtail]]s, [[festoon]]s, [[flying handkerchief]]s, [[Helen]]s, [[jay]]s, [[mime]]s, [[parnassian]]s, [[rose]]s, [[swallowtail]]s, [[swordtail]]s, [[triangle]]s, [[turnus]]es, [[windmill]]s, [[zebra]]s, and other [[butterfly|butterflies]] in the [[family]] [[Papilionidae]], notable for (mostly) having tail-like extensions on their [[hindwing]]s",
parents = {"Bướm ngày"},
}
labels["Chi Thiên nga"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Họ Vịt"},
}
labels["syngnathiform fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bellowsfish]], [[cornetfish]], [[pipefish]], [[razorfish]], [[sea dragon]]s, [[sea horse]]s, [[snipefish]], [[trumpetfish]], and other fish in the [[order]] [[Syngnathiformes]]",
parents = {"fish"},
}
labels["Thraupidae"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bananaquit]]s, [[conebill]]s, [[dacnis]]es, [[Darwin's finch]]es, [[grassquit]]s, [[ground finch]]es, [[honeycreeper]]s, [[pardusco]]s, [[tanager]]s, and other [[passerine]] birds in the family [[Thraupidae]]",
parents = {"Bộ Sẻ"},
}
labels["temnospondyls"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[extinct]] early [[amphibian]]s in the [[order]] [[Temnospondyli]]",
parents = {"amphibians"},
}
labels["tenebrionoid beetles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[aderid]]s, [[anthicid]]s, [[blister beetle]]s, [[borid]]s, [[ciid]]s, [[flour beetle]]s, [[darkling beetle]]s, [[mealworm]]s, [[melandryid]]s, [[mordellid]]s, [[mycetophagid]]s, [[oedemerid]]s, [[pinacate beetle]]s, [[pyrochroid]]s, [[pythid]]s, [[ripiphorid]]s, [[salpingid]]s, [[toktokkie]]s, [[ulodid]]s, [[wharf borer]]s, [[zopherid]]s and other [[beetle]]s in the [[superfamily]] [[Tenebrionoidea]]",
parents = {"beetles"},
}
labels["tephritoid flies"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cheese fly|cheese flies]], [[tephritid]] [[fruit fly|fruit flies]], [[picture-winged fly|picture-winged flies]] and other [[fly|flies]] in the [[dipteran]] [[superfamily]] [[Tephritoidea]]",
parents = {"dipterans"},
}
labels["termites"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[termite]]s, [[insect]]s in the former [[order]] [[Isoptera]], which is now considered a [[suborder]] or other group within the [[cockroach]]es in the order [[Blattodea]]",
parents = {"insects", "cockroaches"},
}
labels["terns"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[tern]]s, [[seabirds]] in the [[family]] [[Sternidae]]",
parents = {"seabirds"},
}
labels["Bộ Cá nóc"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[pufferfish]], [[triggerfish]], [[boxfish]], [[ocean sunfish]] and other fish in the order [[Tetraodontiformes]]",
parents = {"cá"},
}
labels["chó sục"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chó săn"},
}
labels["theropods"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[dinosaur]]s in the [[clade]] [[Theropoda]]",
parents = {"dinosaurs"},
}
labels["thrushes"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"perching birds"},
}
labels["ticks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bloodsucking]] [[arachnids]] in the [[order]] [[Ixodida]] (also known as [[Metastigmata]])",
parents = {"mites and ticks"},
}
labels["tinamous"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"ratites"},
}
labels["tits"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[tit]]s, birds known as [[chickadee]]s in the US",
parents = {"perching birds"},
}
labels["toads"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Anuran"},
}
labels["toothcarps"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[four-eyed fish]], [[guppy|guppies]], [[killifish]], [[molly|mollies]], [[mummichog]]s, [[platy|platies]], [[swordtail]]s, [[topminnow]]s and other fish in the [[order]] [[Cyprinodontiformes]]",
parents = {"fish"},
}
labels["tortoises"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[terrestrial]] [[turtle]]s in the [[family]] [[Testudinidae]]",
parents = {"turtles"},
}
labels["tortricid moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[moth]]s (and [[caterpillar]]s) in the [[family]] [[Tortricidae]]",
parents = {"moths"},
}
labels["trachinoid fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[black swallower]]s, [[blue cod]], [[duckbill]]s, [[gaper]]s, [[sand eel]]s, [[torrentfish]], [[weeverfish]] and other fish in the [[perciform]] [[suborder]] [[Trachinoidei]]",
parents = {"fish"},
}
labels["toy dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"dogs"},
}
labels["trilobites"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"arthropods"},
}
labels["true bugs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[insect]]s in the [[hemipteran]] suborder [[Heteroptera]]",
parents = {"hemipterans"},
}
labels["Họ Sẻ thông"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[finch]]es in the [[passerine]] family [[Fringillidae]]",
parents = {"Bộ Sẻ"},
}
labels["true jellyfish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[cnidarian]]s in the [[class]] [[Scyphozoa]]",
parents = {"cnidarians"},
}
labels["true sparrows"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[passerine]] birds in the family [[Passeridae]] (for other birds called sparrows, see the [[emberizid]]s)",
parents = {"perching birds"},
}
labels["tubenose birds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[albatross]]es, [[fulmar]]s, [[petrel]]s, [[prion]]s, [[shearwater]]s, and other [[seabird]]s in the [[order]] [[Procellariiformes]]",
parents = {"seabirds"},
}
labels["tunicates"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"animals"},
}
labels["turtles"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"reptiles"},
}
labels["tyrant flycatchers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[passerine]] birds in the family [[Tyrannidae]]",
parents = {"suboscines"},
}
labels["ursids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[ursid]]s ([[bear]]s)",
parents = {"Bộ Ăn thịt"},
}
labels["Venerida order mollusks"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[basket clam]]s, [[bean clam]]s, [[boring clam]]s, [[cockle]]s, [[duck clam]]s, [[giant clam]]s, [[hard clam]]s, [[lentil shell]]s, [[pipi]]s, [[pooquaw]]s, [[quahog]]s, [[surf clam]]s, [[trough-shell]]s, [[ugari]]s, [[Venus clam]]s, [[zebra mussel]]s, and other [[bivalve]]s in the [[order]] [[Venerida]]",
parents = {"bivalves"},
}
labels["Phân ngành Có xương sống"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Ngành Dây sống"},
wpcat = true,
commonscat = "Vertebrata",
}
labels["vespids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[hornet]]s, [[paper wasp]]s, [[pollen wasp]]s, [[potter wasp]]s, [[yellow jacket]]s, and other [[wasp]]s in the [[family]] [[Vespidae]]",
parents = {"hymenopterans"},
}
labels["Vetigastropoda"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[abalone]]s or [[ear shell]]s, [[duck's-bill limpet]]s, [[keyhole limpet]]s, [[rosary shell]]s, [[slit-shell]]s, [[topshell]]s, [[turban shell]]s, and other [[gastropod]]s in the [[clade]] [[Vetigastropoda]] (treated in some classifications as an [[order]], in others as [[subclass]])",
parents = {"Lớp Chân bụng"},
}
labels["vipers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[adder]]s, [[asp]]s, [[rattlesnake]]s, [[viper]]s, [[water moccasin]]s and other [[venomous]] snakes in the [[Viperidae]]",
parents = {"Phân bộ Rắn"},
}
labels["viverrids"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[viverrid]]s ([[civet]]s, [[genet]]s and relatives)",
parents = {"Bộ Ăn thịt"},
}
labels["vombatiforms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[diprotodontid]]s, [[diprotodon]]s, [[phascolarctid]]s, [[koala]]s, [[vombatid]]s, [[wombat]]s, [[phascolome]]s, [[ilariid]]s, [[maradid]]s, [[palorchestid]]s, [[thylacoleonid]]s, [[marsupial lion]]s , [[wynyardiid]]s and other [[marsupial]]s in the [[diprotodont]] [[suborder]] [[Vombatiformes]]",
parents = {"marsupials"},
}
labels["vultures"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[vulture]]s (both Old World and New World)",
parents = {"birds of prey"},
}
labels["warblers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[warbler]]s, various small [[passerine]] songbirds, especially of the families Sylviidae (Old World warblers) and Parulidae (New World warblers)",
parents = {"perching birds"},
}
labels["warren hounds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Chó săn"},
}
labels["water dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"retrievers"},
}
labels["weaver finches"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[finch]]es in the family [[Estrildidae]]",
parents = {"perching birds"},
}
labels["weaverbirds"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[baya]]s, [[bishop]]s, [[fody|fodies]], [[malimbe]]s, [[quelea]]s, [[sakabula]]s, [[taha]]s, [[weaver]]s, and other birds in the [[family]] [[Ploceidae]]",
parents = {"perching birds"},
}
labels["weevils"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[bill-beetle]]s, [[curculio]]s, [[grugru worm]]s, [[snout beetle]]s, and other [[beetle]]s in the [[superfamily]] [[Curculionoidea]]",
parents = {"beetles"},
}
labels["cá voi"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Phân thứ bộ Cá voi"},
}
labels["wolves"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[wolves]]",
parents = {"Họ Chó"},
}
labels["woodpeckers"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[flicker]]s, [[sapsucker]]s, [[wryneck]]s, and other birds in the [[family]] [[Picidae]]",
parents = {"piciforms"},
}
labels["working dogs"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"dogs"},
}
labels["worms"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"animals"},
}
labels["wrasses"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=fish in the family [[Labridae]]",
parents = {"labroid fish"},
}
labels["Họ Tiêu liêu"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "default",
parents = {"Liên họ Đuôi cứng"},
}
labels["zoarcoid fish"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[butterfish]], [[eelpout]]s, [[guffer]]s, [[gunnel]]s, [[lumper]]s, [[prickleback]]s, [[prowfish]], [[wolf eel]]s and other fish in the [[perciform]] [[suborder]] [[Zoarcoidei]]",
parents = {"fish"},
}
labels["zygaenoid moths"] = {
type = "chủ đề thuộc nhóm tập hợp",
description = "=[[burnet moth]]s, [[forester]]s, [[hag moth]]s, [[limacodid]]s, [[megalopygid]]s, [[monkey slug]]s, [[puss moth]]s, [[saddleback caterpillar]]s, [[zygaenid]]s, and other [[moth]]s in the [[superfamily]] [[Zygaenoidea]]",
parents = {"moths"},
}
return labels
efvnuupq4d1k2v98j1jttgk09hxnpck
matematikai
0
330862
2576462
2214640
2026-11-09T01:44:14Z
Hiyuune
50834
/* Tiếng Hungary */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2576462
wikitext
text/x-wiki
{{also|matemātikai}}
=={{langname|hu}}==
==={{ĐM|etymology}}===
Từ {{affix|hu|matematika|-i|pos=Tính từ}}.
==={{ĐM|pron}}===
* {{hu-IPA}}
* {{hyphenation|hu|ma|te|ma|ti|kai}}
* {{rhymes|hu|ji|s=6}}
==={{ĐM|adj}}===
{{hu-adj|-}}
# Thuộc [[toán học]].
===={{ĐM|decl}}====
{{hu-infl-nom|matematikaia|o|-}}
1bb3tozr9d82xfk51sp0ajx3oqhqfdq
chùa online
0
371603
2576412
2576142
2026-11-08T13:14:51Z
TheHighFighter2
42988
{{[[Bản mẫu:cần kiểm tra|cầm kiểm tra]]}}
2576412
wikitext
text/x-wiki
{{cần kiểm tra|<---SoP (chùa + online); so sánh với chợ online, lớp học online, và nhiều từ khác nữa kết hợp với online để mang nét nghĩa hoạt động dưới hình thức trực tuyến--->}}
== {{langname|vi}} ==
===Từ nguyên===
Từ {{compound|vi|chùa|online}}.
=== {{ĐM|pron}} ===
{{vie-pron|yêu nước on-lai}}
=== {{ĐM|dfn}} ===
{{pn}}
# {{lb|vi|intransitive|thông tục}} Hình thức đi [[chùa]] thông qua các [[hành động]], [[việc làm]] dưới [[hình thức]] [[trực tuyến]].
#: {{ux|vi|Đi '''chùa online'''.}}
#* {{quote-journal|vi|author=Thu Thảo|title=Tác giả 'chùa online' khuấy đảo mạng với 30 phút lập trình AI|magazine=VnExpress|url=https://vnexpress.net/tac-gia-chua-online-khuay-dao-mang-voi-30-phut-lap-trinh-ai-5140379.html|date=2026-11-03|passage=Sự bùng nổ hoàn toàn vượt ngoài dự đoán của tác giả Park Jin-won, chàng trai 26 tuổi tốt nghiệp ngành Văn học Anh. Không học công nghệ thông tin, Park vẫn có thể xây dựng ngôi '''chùa online''' nhanh chóng nhờ lập trình cảm tính (vibe coding).}}
1ttipeuypgmzxrjkgooxya426agtr5g
Mô đun:lt-common
828
397687
2576489
2576323
2026-11-09T09:51:33Z
Hiyuune
50834
2576489
Scribunto
text/plain
local export = {}
local m_str_utils = require("Module:string utilities")
local put = require("Module:parse utilities")
local u = m_str_utils.char
local ugsub = m_str_utils.gsub
local ulower = m_str_utils.lower
local uupper = m_str_utils.upper
local ufind = m_str_utils.find
local ulen = m_str_utils.len
local ucodepoint = m_str_utils.codepoint
-- Module:string utilities has no normalization functions
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
-- =============================================================================
-- Unicode constants
-- =============================================================================
local GRAVE = u(0x0300) -- combining grave accent
local ACUTE = u(0x0301) -- combining acute accent
local TILDE = u(0x0303) -- combining tilde
local MACRON = u(0x0304) -- combining macron
local DOTABOVE = u(0x0307) -- combining dot above
local CARON = u(0x030C) -- combining caron
local OGONEK = u(0x0328) -- combining ogonek
local ANY_ACCENT = "[" .. GRAVE .. ACUTE .. TILDE .. "]"
-- Lowercase aliases used by the display and sort-key functions
local grave = GRAVE
local acute = ACUTE
local tilde = TILDE
local macron = MACRON
local dotabove = DOTABOVE
local caron = CARON
local ogonek = OGONEK
local accents = ANY_ACCENT
-- Accent constants shared with the other Lithuanian modules
export.GRAVE = GRAVE
export.ACUTE = ACUTE
export.TILDE = TILDE
export.MACRON = MACRON
export.DOTABOVE = DOTABOVE
export.CARON = CARON
export.OGONEK = OGONEK
export.ANY_ACCENT = ANY_ACCENT
-- =============================================================================
-- Private Use Area (PUA) replacement hints
-- =============================================================================
-- PUA codepoints (U+E000–U+E022) used by old Lithuanian font encodings for
-- accented letters, mapped to their standard Unicode spelling for the error
-- messages of reject_pua.
local INVALID_CHARS = {
[0xE000] = "Ą́", [0xE001] = "ą́", [0xE002] = "Ą̃", [0xE003] = "ą̃",
[0xE004] = "Ę́", [0xE005] = "ę́", [0xE006] = "Ę̃", [0xE007] = "ę̃",
[0xE008] = "Ė́", [0xE009] = "ė́", [0xE00A] = "Ė̃", [0xE00B] = "ė̃",
[0xE00C] = "i̇̀", [0xE00D] = "i̇́", [0xE00E] = "i̇̃",
[0xE00F] = "Į̇́", [0xE010] = "į̇́", [0xE011] = "Į̇̃", [0xE012] = "į̇̃",
[0xE013] = "J̃", [0xE014] = "j̇̃",
[0xE015] = "L̃", [0xE016] = "l̃",
[0xE017] = "M̃", [0xE018] = "m̃",
[0xE019] = "R̃", [0xE01A] = "r̃",
[0xE01B] = "Ų́", [0xE01C] = "ų́", [0xE01D] = "Ų̃", [0xE01E] = "ų̃",
[0xE01F] = "Ū́", [0xE020] = "ū́", [0xE021] = "Ū̃", [0xE022] = "ū̃",
}
export.INVALID_CHARS = INVALID_CHARS
-- =============================================================================
-- Internal helper functions
-- =============================================================================
local dotless_to_dotted = {
["ı"] = "i",
["ȷ"] = "j",
}
local function char_to_dotted_form(base, below)
return (dotless_to_dotted[base] or base) .. below
end
local function normalize_dotted_chars(text)
-- Remove any dots above, and convert dotless forms to dotted.
-- On entry, text must be in NFD form.
return ugsub(text, "([iıjȷ])(" .. ogonek .. "?)" .. dotabove, char_to_dotted_form)
end
local function char_to_accent_form(base, below)
-- Add a 'dot above' after the base.
if base == "i" or base == "j" then
return base .. below .. dotabove
end
-- Convert any dotless chars combining with accents to the dotted form,
-- so that they normalize properly. This shouldn't happen, but just in case.
return char_to_dotted_form(base, below)
end
local function stripped_text_form(text)
-- Remove accents.
text = ugsub(toNFD(text), accents .. "+", "")
-- Normalize dotless characters and dot-above diacritics.
return normalize_dotted_chars(text)
end
-- =============================================================================
-- Input validation
-- =============================================================================
-- Reject Private Use Area characters (U+E000–U+F8FF). When the character is
-- a known non-standard Lithuanian glyph, the error message includes the
-- recommended standard Unicode replacement (see INVALID_CHARS above).
function export.reject_pua(s)
if not s then return end
for i = 1, ulen(s) do
local cp = ucodepoint(s, i)
if cp >= 0xE000 and cp <= 0xF8FF then
local replacement = INVALID_CHARS[cp]
if replacement then
error(string.format(
"lt-common: private use area character U+%04X \"%s\" detected. " ..
"Please use \"%s\" instead.", cp, u(cp), replacement))
else
error(string.format(
"lt-common: private use area character U+%04X detected in \"%s\". " ..
"Please use a standard Unicode character instead.", cp, s))
end
end
end
end
-- =============================================================================
-- Input normalization
-- =============================================================================
-- Detect nonstandard encoding patterns in the input.
-- Returns: dotless_flag (found ı/ȷ), precomp_i_flag (found precomposed í/ì/ĩ)
function export.detect_nonstandard(s)
if not s then return false, false end
local nfd_s = toNFD(s)
local dotless_flag = ufind(nfd_s, "[ıȷ]") ~= nil
local precomp_i_flag = ufind(nfd_s, "[íìĩ]") ~= nil
return dotless_flag, precomp_i_flag
end
-- Normalize input to clean canonical NFC.
-- Handles dotless i/j (ı, ȷ) and stray dot-above combinations.
function export.canonicalize_input(s)
if not s then return s end
s = toNFD(s)
-- Remove stray dot-above after i/j (with or without ogonek)
s = ugsub(s, "([iıjȷ])(" .. OGONEK .. "?)" .. DOTABOVE, function(base, below)
base = (base == "ı") and "i" or (base == "ȷ") and "j" or base
return base .. below
end)
-- Convert any remaining dotless i/j to standard forms
s = ugsub(s, "ı", "i")
s = ugsub(s, "ȷ", "j")
return toNFC(s)
end
-- =============================================================================
-- Partial NFD conversion (stem_ac representation)
-- =============================================================================
-- Convert canonical NFC to partial NFD (stem_ac).
-- Applies full NFD, then recomposes non-accent diacritics.
-- Only grave/acute/tilde remain as combining characters.
function export.to_stem_ac(s)
if not s then return s end
s = toNFD(s)
-- Recompose ogonek vowels
s = ugsub(s, "a" .. OGONEK, "ą")
s = ugsub(s, "e" .. OGONEK, "ę")
s = ugsub(s, "i" .. OGONEK, "į")
s = ugsub(s, "u" .. OGONEK, "ų")
-- Recompose macron vowel
s = ugsub(s, "u" .. MACRON, "ū")
-- Recompose dot-above e
s = ugsub(s, "e" .. DOTABOVE, "ė")
-- Recompose caron consonants
s = ugsub(s, "c" .. CARON, "č")
s = ugsub(s, "s" .. CARON, "š")
s = ugsub(s, "z" .. CARON, "ž")
return s
end
-- =============================================================================
-- Accent manipulation
-- =============================================================================
-- Strip all accent marks (grave/acute/tilde) from partial NFD text.
function export.to_stem_bare(stem_ac)
if not stem_ac then return stem_ac end
return ugsub(stem_ac, ANY_ACCENT, "")
end
-- Check if partial NFD text contains any accent marks.
function export.has_accent(stem_ac)
return ufind(stem_ac, ANY_ACCENT) ~= nil
end
-- =============================================================================
-- Syllables
-- =============================================================================
local SYLLABLE_VOWELS = {
a = true, e = true, i = true, o = true, u = true, y = true,
["ą"] = true, ["ę"] = true, ["ė"] = true, ["į"] = true, ["ų"] = true, ["ū"] = true,
}
-- Vowel pairs that form one syllable; a vowel after i is in the same
-- syllable as the i (softening i, the diphthong ie).
local DIPHTHONGS = {
ai = true, au = true, ei = true, ui = true, ie = true, uo = true,
ou = true, eu = true, oi = true,
}
-- Syllable count of a word or stem and the 1-based index of the syllable
-- that carries an accent mark (nil without one). Accepts NFC, partial NFD
-- and full NFD text: combining marks are skipped, so ą, ė, ū and č count as
-- their base letters; an accent mark on l, m, n or r (a mixed diphthong)
-- belongs to the syllable of the vowel before it.
function export.stressed_syllable(text)
local count, stressed, prev = 0, nil, nil
for ch in mw.ustring.gmatch(text, ".") do
local cp = ucodepoint(ch)
if cp == 0x0300 or cp == 0x0301 or cp == 0x0303 then
stressed = math.max(count, 1)
elseif cp >= 0x0300 and cp <= 0x036F then
-- another combining mark: part of the letter before it
else
local low = ulower(ch)
if SYLLABLE_VOWELS[low] then
if prev == nil or (prev ~= "i" and not DIPHTHONGS[prev .. low]) then
count = count + 1
end
prev = low
else
prev = nil
end
end
end
return count, stressed
end
-- =============================================================================
-- Complete input pipeline
-- =============================================================================
-- Process raw user input through the complete normalization pipeline.
-- Returns: stem_bare, stem_ac, dotless_flag, precomp_flag
function export.process_input(raw)
if not raw then return raw, raw, false, false end
export.reject_pua(raw)
local dotless_flag, precomp_flag = export.detect_nonstandard(raw)
local canon = export.canonicalize_input(raw)
local stem_ac = export.to_stem_ac(canon)
local stem_bare = export.to_stem_bare(stem_ac)
return stem_bare, stem_ac, dotless_flag, precomp_flag
end
-- =============================================================================
-- Display and text processing
-- =============================================================================
function export.makeDisplayText(text, lang, sc)
if not text then return text end
-- Normalize dotless characters and dot-above diacritics (while retaining accents).
text = normalize_dotted_chars(toNFD(text))
-- Add a 'dot above' between "i" or "j" and an accent.
text = ugsub(text, "([iıjȷ])(" .. ogonek .. "?)%f" .. accents, char_to_accent_form)
return toNFC(text)
end
-- Called from [[Module:languages]] since [[Module:lt-common]] is set as the stripDiacritics handler in
-- [[Module:languages/data/2]].
function export.stripDiacritics(text, lang, sc)
if not text then return text end
return toNFC(stripped_text_form(text))
end
local sortkey_substitutes = {
[ogonek] = u(0xF000),
[caron] = u(0xF001),
[macron] = u(0xF002),
[dotabove] = u(0xF003),
["y"] = "i" .. u(0xF004),
}
function export.makeSortKey(text, lang, sc)
if not text then return text end
-- Normalize to the stripped-text form and convert diacritics to Private Use
-- Area characters so they sort after all other characters.
text = stripped_text_form(ulower(text))
:gsub(".[\128-\191]*", sortkey_substitutes)
return toNFC(uupper(text))
end
-- =============================================================================
-- Footnote / multi-value spec parsing
-- =============================================================================
--
-- One field of a declension pattern (lemma, AP, genitive, a slot override)
-- may hold colon-separated variants, each followed by optional bracketed
-- footnotes: `VAL1[note1]:VAL2[note2]`. The caller first isolates the `[...]`
-- runs with `put.parse_balanced_segment_run(text, "[", "]")`, so that a "." or
-- ":" inside a footnote is not taken for a delimiter, and only then splits.
-- Given one delimiter-separated run (alternating plain text and "[...]" runs,
-- as returned by parse_balanced_segment_run / split_alternating_runs), return
-- its footnotes with their brackets (e.g. "[archaic]"), or nil if there are
-- none. Errors if text follows a footnote ("val[note]x").
function export.fetch_footnotes(separated_group, parse_err)
local footnotes
for j = 2, #separated_group - 1, 2 do
if separated_group[j + 1] ~= "" then
parse_err("Extraneous text after bracketed footnotes: '" .. table.concat(separated_group) .. "'")
end
if not footnotes then
footnotes = {}
end
table.insert(footnotes, separated_group[j])
end
return footnotes
end
-- Given a bracket-isolated run and a sub-delimiter (e.g. ":"), split it into
-- one or more {form=VALUE, footnotes={...}} specs. `spectype` is used only
-- in error messages. With `allow_blank`, a wholly blank run returns nil
-- instead of erroring (for optional fields such as the genitive).
function export.fetch_specs(segments, separator, spectype, allow_blank, parse_err)
local separated_groups = put.split_alternating_runs_and_strip_spaces(segments, separator)
if allow_blank and #separated_groups == 1 and #separated_groups[1] == 1 and
separated_groups[1][1] == "" then
return nil
end
local specs = {}
for _, separated_group in ipairs(separated_groups) do
local form = separated_group[1]
if form == "" then
parse_err("Blank form not allowed here, but saw '" .. table.concat(segments) .. "'")
end
local new_spec = {form = form, footnotes = export.fetch_footnotes(separated_group, parse_err)}
for _, existing_spec in ipairs(specs) do
if existing_spec.form == new_spec.form then
parse_err("Duplicate " .. spectype .. " spec '" .. table.concat(separated_group) .. "'")
end
end
table.insert(specs, new_spec)
end
return specs
end
-- =============================================================================
-- Calls written for a legacy template
-- =============================================================================
-- The legacy versions of the templates ({{lt-noun}}, {{lt-conj}}, …) are kept
-- at "<name>/old". A call written for the legacy template is rendered through
-- it with the same arguments, and the entry is listed at
-- [[Wiktionary:Tracking/<name>/legacy]] (pages outside the main namespace,
-- such as documentation, are not listed).
function export.render_legacy(frame, name)
local args = {}
for k, v in pairs(frame:getParent().args) do
args[k] = v
end
if mw.title.getCurrentTitle().namespace == 0 then
require("Module:debug/track")(name .. "/legacy")
end
return frame:expandTemplate{title = "Template:" .. name .. "/old", args = args}
end
-- True for a call of the legacy {{lt-conj}} (the forms in positional
-- parameters), false for a pattern of the new one ("inf,pres,past…").
function export.is_legacy_conj(args)
if args[2] ~= nil then
return true
end
local first = args[1]
return first ~= nil and not mw.ustring.find(first, "^[^,]*,[^,]*,")
end
-- =============================================================================
-- Headword scraping
-- =============================================================================
-- Module:template parser is loaded on first use.
local function find_templates(...)
find_templates = require("Module:template parser").find_templates
return find_templates(...)
end
-- Scan the wikitext of `pagename` for calls to `{{infltemp}}` (e.g. "lt-ndecl")
-- and return the inflection spec (first positional argument) of the matching call.
-- `infltemp` is one template name or a list of names treated as the same
-- template (e.g. a template and its redirect).
-- If `inflid` is given, match only the call whose id= equals `inflid`.
-- `accept`, if given, is called with the arguments of each call and skips the
-- call when it returns false (e.g. a call written for the legacy template).
-- Returns (infl_string, nil) on success, (nil, error_string) on failure.
function export.find_lt_inflection(pagename, infltemp, inflid, accept)
local wanted_names = {}
if type(infltemp) == "table" then
for _, name in ipairs(infltemp) do wanted_names[name] = true end
infltemp = table.concat(infltemp, "}}/{{") -- display name for messages
else
wanted_names[infltemp] = true
end
local title = mw.title.new(pagename)
if not title then
return nil, ("Bad pagename '%s': couldn't create title object"):format(pagename)
end
local content = title:getContent()
if not content then
return nil, ("Couldn't fetch page content for '[[%s]]'; page may not exist"):format(pagename)
end
local sets_by_id = {} -- id string → infl string
local sets_no_id = {} -- list of infl strings (templates without id=)
for template in find_templates(content) do
local targs = wanted_names[template:get_name()] and template:get_arguments()
if targs and (not accept or accept(targs)) then
local infl = targs[1]
if not infl or infl == "" then
return nil, ("Found {{%s}} on '[[%s]]' but it has no inflection spec in 1="):
format(infltemp, pagename)
end
if targs.id then
if sets_by_id[targs.id] then
return nil, ("Found duplicate id='%s' for {{%s}} on '[[%s]]'"):
format(targs.id, infltemp, pagename)
end
sets_by_id[targs.id] = infl
else
table.insert(sets_no_id, infl)
end
end
end
local has_id = next(sets_by_id) ~= nil
local has_no_id = #sets_no_id > 0
-- Nothing found at all.
if not has_id and not has_no_id then
return nil, ("No {{%s}} found on '[[%s]]'"):format(infltemp, pagename)
end
-- Inconsistent: some calls have id= and some don't.
if has_id and has_no_id then
return nil, ("On '[[%s]]', some {{%s}} calls have id= and some don't; " ..
"all must be consistent"):format(pagename, infltemp)
end
-- Multiple calls, all without id=: caller must add id= params.
if not has_id and #sets_no_id > 1 then
return nil, ("On '[[%s]]', found %d {{%s}} calls without id=; " ..
"add id= to each and specify id= in the headword template to disambiguate"):
format(pagename, #sets_no_id, infltemp)
end
-- From here, either exactly one no-id call, or all calls have id=.
-- Caller specified an id: find the matching call.
if inflid then
if not has_id then
-- Only one no-id call exists; id= mismatch is suspicious but unambiguous — return it.
return sets_no_id[1], nil
end
local match = sets_by_id[inflid]
if match then
return match, nil
end
local available = {}
for k in pairs(sets_by_id) do table.insert(available, "'" .. k .. "'") end
table.sort(available)
return nil, ("On '[[%s]]', no {{%s}} with id='%s' found; available: %s"):
format(pagename, infltemp, inflid, table.concat(available, ", "))
end
-- No id specified by caller.
if not has_id then
-- Exactly one no-id call (multiple case already caught above).
return sets_no_id[1], nil
end
-- All calls have id= but caller didn't specify one.
local keys = {}
for k in pairs(sets_by_id) do table.insert(keys, k) end
table.sort(keys)
if #keys == 1 then
-- Unambiguous single id= call: return it.
return sets_by_id[keys[1]], nil
end
local quoted = {}
for _, k in ipairs(keys) do table.insert(quoted, "'" .. k .. "'") end
return nil, ("On '[[%s]]', found multiple {{%s}} calls with id= (%s); " ..
"specify id= in the headword template to disambiguate"):
format(pagename, infltemp, table.concat(quoted, ", "))
end
return export
hpc4gjkid8oyrvsu24g7a14g4ydt1g2
Mô đun:rif-pr
828
406933
2576425
2574432
2026-11-08T14:00:46Z
Hiyuune
50834
2576425
Scribunto
text/plain
-- Based on {{Module:tzm-IPA}} and {{Module:User:Fenakhay/mt-IPA}}.
--
-- Pronunciation (IPA), syllabification, rhymes, audio and homophones for Tarifit
--
-- SECTIONS
-- 1. Helpers for parsing the template arguments
-- 2. Audio
-- 3. Homophones
-- 4. Phonology: symbol tables
-- 5. Phonology: character classes
-- 6. Phonology: rule-building helpers
-- 7. Phonology: rule sets
-- 8. Phonology: dialect pipelines
-- 9. Syllabification: shared helpers
-- 10. Syllabification: spelling
-- 11. Syllabification: IPA
-- 12. Pronunciation
-- 13. Rhymes
-- 14. Alternative forms
-- 15. The pronunciations of one dialect
-- 16. The template entry point
-- 17. Exports
local export = {}
local M = require("Module:module loader").init({
require = {
string_utilities = "Module:string utilities",
audio = "Module:audio",
parse_utilities = "Module:parse utilities",
languages = "Module:languages",
parameters = "Module:parameters",
IPA = "Module:IPA",
rhymes = "Module:rhymes",
hyphenation = "Module:hyphenation",
homophones = "Module:homophones",
table = "Module:table",
},
loadData = {
headword_data = "Module:headword/data",
},
})
local lang = M.languages.getByCode("rif")
local gsub = mw.ustring.gsub
local DEFAULT_DIALECT = "Nador"
--------------------------------------------------------------------------------
-- 1. Helpers for parsing the template arguments
--------------------------------------------------------------------------------
local function generate_obj(respelling)
return { respelling = respelling }
end
local function split_on_comma(term)
if not term then
return nil
end
if term:find(",%s") or term:find("\\") then
return M.parse_utilities.split_on_comma(term)
else
return M.string_utilities.split(term, ",")
end
end
-- Parse "respelling<q:...>,respelling<a:...>" into a list of
-- { respelling = ..., q = ..., qq = ..., a = ..., aa = ..., refs = ... }.
local function parse_respellings_with_modifiers(respelling, paramname)
if respelling:find("[<%[]") then
local put = M.parse_utilities
local segments = put.parse_multi_delimiter_balanced_segment_run(respelling, { { "<", ">" }, { "[", "]" } })
local comma_separated_groups = put.split_alternating_runs_on_comma(segments)
local retval = {}
for _, group in ipairs(comma_separated_groups) do
local j = 2
while j <= #group do
if not group[j]:find("^<.*>$") then
group[j - 1] = group[j - 1] .. group[j] .. group[j + 1]
table.remove(group, j)
table.remove(group, j)
else
j = j + 2
end
end
local param_mods = {
q = { type = "qualifier" },
qq = { type = "qualifier" },
a = { type = "labels" },
aa = { type = "labels" },
ref = { item_dest = "refs", type = "references" },
}
table.insert(retval, put.parse_inline_modifiers_from_segments {
group = group,
arg = respelling,
props = {
paramname = paramname,
param_mods = param_mods,
generate_obj = generate_obj,
},
})
end
return retval
else
local retval = {}
for _, item in ipairs(split_on_comma(respelling)) do
table.insert(retval, generate_obj(item))
end
return retval
end
end
-- Parse a list (of audio files, homophones, ...) that may carry <modifiers>.
local function parse_pron_modifier(arg, paramname, generate_obj, param_mods, splitchar)
splitchar = splitchar or ","
if arg:find("<") then
param_mods.q = { type = "qualifier" }
param_mods.qq = { type = "qualifier" }
param_mods.a = { type = "labels" }
param_mods.aa = { type = "labels" }
param_mods.ref = { item_dest = "refs", type = "references" }
return M.parse_utilities.parse_inline_modifiers(arg, {
param_mods = param_mods,
generate_obj = generate_obj,
paramname = paramname,
splitchar = splitchar,
})
else
local retval = {}
local split_arg = splitchar == "," and split_on_comma(arg) or M.string_utilities.split(arg, splitchar)
for _, term in ipairs(split_arg) do
table.insert(retval, generate_obj(term))
end
return retval
end
end
--------------------------------------------------------------------------------
-- 2. Audio
--------------------------------------------------------------------------------
-- audios=File.ogg<text:...><t:gloss><IPA:...>;File2.ogg<cap:...>
-- In file names, text and captions "#" stands for the page name.
local function parse_audio(lang_obj, arg, pagename, paramname)
local param_mods = {
IPA = {
sublist = true,
},
text = {},
t = {
item_dest = "gloss",
},
gloss = {},
pos = {},
lit = {},
g = {
item_dest = "genders",
sublist = true,
},
bad = {},
cap = {
item_dest = "caption",
},
}
local function process_special_chars(val)
if not val then
return val
end
return (val:gsub("#", pagename))
end
local function generate_audio_obj(arg)
return { file = process_special_chars(arg) }
end
local retvals = parse_pron_modifier(arg, paramname, generate_audio_obj, param_mods, "%s*;%s*")
for _, retval in ipairs(retvals) do
retval.lang = lang_obj
retval.text = process_special_chars(retval.text)
retval.caption = process_special_chars(retval.caption)
local textobj = M.audio.construct_audio_textobj(retval)
retval.text = textobj
retval.gloss = nil
retval.pos = nil
retval.lit = nil
retval.genders = nil
end
return retvals
end
--------------------------------------------------------------------------------
-- 3. Homophones
--------------------------------------------------------------------------------
-- homophones=term1<t:gloss>,term2<pos:noun>
local function parse_homophones(arg, paramname)
local function generate_homophone_obj(term)
return { term = term }
end
local param_mods = {
t = {
item_dest = "gloss",
},
gloss = {},
pos = {},
alt = {},
lit = {},
id = {},
g = {
item_dest = "genders",
sublist = true,
},
}
return parse_pron_modifier(arg, paramname, generate_homophone_obj, param_mods)
end
--------------------------------------------------------------------------------
-- 4. Phonology: symbol tables
--------------------------------------------------------------------------------
-- Spelling digraphs written with a combining dot below. Applied before ORTHOGRAPHY.
local DIGRAPHS = {
{ "p̣", "pˤ" },
{ "c̣", "ʃˤ" },
{ "g̱", "ʝ" },
}
-- Spelling -> working symbols. Characters not listed stay as they are.
-- Internal symbols: C = č (t͡ʃ), J = ǧ (d͡ʒ), R = ř (a tap that never vocalizes
-- after a vowel, unlike r), Rˤ = Ṛ.
local ORTHOGRAPHY = {
["ʼ"] = "ʔ",
["g"] = "ɡ",
["c"] = "ʃ", ["č"] = "C", ["ǧ"] = "J",
["j"] = "ʒ", ["y"] = "j",
["h"] = "ɦ", ["ḥ"] = "ħ", ["ɛ"] = "ʕ",
["ḍ"] = "dˤ", ["ṣ"] = "sˤ", ["ṭ"] = "tˤ", ["ẓ"] = "zˤ", ["ḷ"] = "lˤ",
["r"] = "ɾ", ["ṛ"] = "ɾˤ", ["ř"] = "R", ["Ṛ"] = "Rˤ",
["e"] = "ə",
}
-- Working symbols the rule sets expect. Applied to every character together with
-- its ˤ/ʷ modifier (so "t" is changed but "tˤ" is not, "dˤ" is).
-- d, b, t -> spirantized ð, β, θ B = plain b, T = plain t (respellings)
-- a -> ɛ (recoloured by vowel_phar, r_vowel_quality)
-- n -> N (placeholder, assimilates before it becomes n/ŋ/…)
local STAGE_SYMBOLS = {
["d"] = "ð", ["dˤ"] = "ðˤ",
["b"] = "β", ["B"] = "b",
["t"] = "θ",
["ɣ"] = "ʁ", ["x"] = "χ",
["a"] = "ɛ",
["n"] = "N",
}
--------------------------------------------------------------------------------
-- 5. Phonology: character classes
--------------------------------------------------------------------------------
-- every consonant symbol that can occur while the rules run
local CONSONANTS = "ɡdðDfɣʁkplmNnŋrɾRsʃCçʝTtθwjzbβBɦxχʒqħʕʔ"
local C = "[" .. CONSONANTS .. "]"
local C_NO_TAP = "[" .. (gsub(CONSONANTS, "[ɾR]", "")) .. "]"
-- vowel-ish symbols (note: includes the emphasis mark ˤ)
local V = "[aiuəɛɑɪˤ]"
-- what may follow "Vr" in r_vocalization (includes the glide-coloured schwas)
local V_AFTER_R = "[aiuɛɑəɵ̆ɘ̆ˤ]"
-- consonants that emphasis can spread to (not the uvulars/pharyngeals)
local SPREADABLE = "[CʃJfmnNlbβdðDtTzrɾRspʒ]"
--------------------------------------------------------------------------------
-- 6. Phonology: rule-building helpers
--------------------------------------------------------------------------------
local function append(list, items)
for _, item in ipairs(items) do
list[#list + 1] = item
end
return list
end
-- add `text` to the list unless it is already in it
local function add_unique(list, text)
for _, existing in ipairs(list) do
if existing == text then
return
end
end
table.insert(list, text)
end
-- Total regressive assimilation inside a class of consonants:
-- "XY" / "X Y" -> "YY" / "Y Y" (X and Y both in `class`)
-- The consonant before X must not be in the class (so only a pair is changed).
-- opts.followers patterns for what must follow Y (default: not in the class)
-- opts.at_start also handle a pair at the very start of the string
-- opts.at_end also handle a pair at the very end of the string
local function total_assimilation(class, opts)
opts = opts or {}
local S = "[" .. class .. "]"
local NOT = "[^" .. class .. "]"
local rules = {}
for _, follower in ipairs(opts.followers or { NOT }) do
rules[#rules + 1] = { "(" .. NOT .. ")" .. S .. "( ?)(" .. S .. ")(" .. follower .. ")", "%1%3%2%3%4" }
if opts.at_start then
rules[#rules + 1] = { "^" .. S .. "( ?)(" .. S .. ")(" .. follower .. ")", "%2%1%2%3" }
end
end
if opts.at_end then
rules[#rules + 1] = { "(" .. NOT .. ")" .. S .. "( ?)(" .. S .. ")$", "%1%3%2%3" }
end
return rules
end
-- Same, but each consonant may carry ˤ, which stays where it is: "tˤd" -> "dˤd"
local function emphatic_total_assimilation(class)
local S = "[" .. class .. "]"
local NOT = "[^" .. class .. "]"
return {
{ "^" .. S .. "(ˤ?)( ?)(" .. S .. ")(ˤ?)(" .. NOT .. ")", "%3%1%2%3%4%5" },
{ "(" .. NOT .. "ˤ?)" .. S .. "(ˤ?)( ?)(" .. S .. ")(ˤ?)$", "%1%4%2%3%4%5" },
{ "(" .. NOT .. "ˤ?)" .. S .. "(ˤ?)( ?)(" .. S .. ")(ˤ?)(" .. NOT .. ")", "%1%4%2%3%4%5%6" },
}
end
-- Assimilation involving labialized velars (kʷ, ɡʷ) and w. `first`/`second` are
-- the patterns for the two sounds (`second` is a capture, except for "w"), `guard`
-- is what may precede them. The three follower patterns keep the pair from
-- touching another w or ʷ.
local LABIOVELAR_FOLLOWERS = { "([^w][^ʷ])", "([^w])$", "([^w][‿ ])" }
local function labiovelar_assimilation(guard, first, second, repl_mid, repl_start, repl_end)
local rules = {}
for _, follower in ipairs(LABIOVELAR_FOLLOWERS) do
rules[#rules + 1] = { "(" .. guard .. ")" .. first .. "( ?)" .. second .. follower, repl_mid }
end
for _, follower in ipairs(LABIOVELAR_FOLLOWERS) do
rules[#rules + 1] = { "^" .. first .. "( ?)" .. second .. follower, repl_start }
end
rules[#rules + 1] = { "(" .. guard .. ")" .. first .. "( ?)" .. second .. "$", repl_end }
return rules
end
-- The pattern for the end of a word and the sounds that may close it, shared by
-- the hiatus rules: up to three consonants (each maybe labialized/emphatic)
-- and an optional final vowel.
local CODA = C .. "[ˤʷ]?" .. C .. "?[ˤʷ]?" .. C .. "?[ˤʷ]?" .. V .. "?"
-- `before` + captured `capture`, followed by end of string or a boundary
local function at_word_end_or_boundary(before, capture, repl)
return {
{ before .. "(" .. capture .. ")$", repl },
{ before .. "(" .. capture .. "[‿ ])", repl },
}
end
--------------------------------------------------------------------------------
-- 7. Phonology: rule sets
--------------------------------------------------------------------------------
-- A rule set is a list of { pattern, replacement } rules, applied top to bottom.
-- Which rule sets a dialect uses, and in which order, is decided in DIALECTS.
local RULESETS = {}
---------- Consonants
RULESETS.labialization_split = {
{ "kkʷ", "kʷkʷ" },
{ "ɡɡʷ", "ɡʷɡʷ" },
}
-- Vowel sequences across the word end: "ai" -> ɛ, "ia" -> (ij)a, ...
RULESETS.hiatus_res = {}
append(RULESETS.hiatus_res, at_word_end_or_boundary("ai", CODA, "ɛ%1"))
append(RULESETS.hiatus_res, at_word_end_or_boundary("i", V .. CODA, "(ij)%1"))
append(RULESETS.hiatus_res, at_word_end_or_boundary("ui", CODA, "u%1"))
append(RULESETS.hiatus_res, at_word_end_or_boundary("u", "a" .. CODA, "uj%1"))
append(RULESETS.hiatus_res, at_word_end_or_boundary("a", "a" .. CODA, "(ɛj)%1"))
-- "a a" after a verb-like "jCCC": link the two a's
do
local body = "j" .. C .. "?[ˤʷ]?" .. C .. "[ˤʷ]?" .. C .. "[ˤʷ]?"
RULESETS.aa_liaison = {
{ "([ ‿]" .. body .. ")a a", "%1‿a" },
{ "^(" .. body .. ")a a", "%1‿a" },
}
end
-- Identical or near-identical neighbouring consonants merge into one geminate.
-- A space between them is allowed and kept.
-- ORDER MATTERS: θθ/ðð/ββ must be collapsed before the class rules below.
RULESETS.geminate_merge = {
{ "θθ", "tː" },
{ "ðð", "dː" },
{ "ββ", "bː" },
{ "bb ?(s)ˤ", "pp%1ˤ" },
}
do
local G = RULESETS.geminate_merge
append(G, total_assimilation("fb", { at_start = true, at_end = true }))
append(G, emphatic_total_assimilation("td"))
-- sibilants. ORDER MATTERS in clusters of three (sʃ, sz, ʃʒ, zʒ overlap)
append(G, total_assimilation("sʃ"))
append(G, emphatic_total_assimilation("sz"))
append(G, total_assimilation("ʃʒ", { at_start = true, at_end = true }))
append(G, total_assimilation("zʒ", { at_start = true }))
append(G, total_assimilation("kɡj", { followers = { "[kɡj]ʷ", "[^ʷkɡj]" }, at_start = true, at_end = true }))
-- kʷ/ɡʷ/w: result is kʷkʷ-type geminate, or ɡʷɡʷ when the second sound is w
append(G, labiovelar_assimilation("[^ʷkɡw]", "[kɡ]ʷ", "([kɡ]ʷ)", "%1%3%2%3%4", "%2%1%2%3", "%1%3%2%3"))
append(G, labiovelar_assimilation("[^ʷw]", "w", "([kɡ]ʷ)", "%1%3%2%3%4", "%2%1%2%3", "%1%3%2%3"))
append(G, labiovelar_assimilation("[^ʷkɡw]", "[kɡ]ʷ", "w", "%1ɡʷ%2ɡʷ%3", "ɡʷ%1ɡʷ%2", "%1ɡʷ%2ɡʷ"))
append(G, total_assimilation("q", { at_start = true, at_end = true }))
append(G, total_assimilation("ħʕ", { at_start = true, at_end = true }))
end
-- A final voiced consonant devoices before a final t: ɣt -> χt, bt -> ft, ...
-- { the consonant, pattern, replacement }. A dialect can keep some of them voiced
-- (see build_voice_assim).
local FINAL_DEVOICING = {
{ "ʁ", "ʁ([‿ ]?[θt])$", "χ%1" },
{ "β", "β(ˤ?[‿ ]?[θt])$", "f%1" },
{ "m", "m(ˤ?[‿ ]?[θt])$", "n%1" },
{ "ð", "ð(ˤ?[‿ ]?[θt])$", "t%1" },
{ "d", "d(ˤ?[‿ ]?[θt])$", "t%1" },
{ "z", "z(ˤ?[‿ ]?[θt])$", "s%1" },
{ "ʒ", "ʒ(ˤ?[‿ ]?[θt])$", "ʃ%1" },
{ "ɡʷ", "ɡ(ʷ[‿ ]?[θt])$", "k%1" },
{ "ʕ", "ʕ([‿ ]?[θt])$", "ħ%1" },
}
-- The rules for the particle "n" before a word that starts with one of these sounds:
-- the n assimilates. Returns a list of { what the next word starts with, result }, plus
-- `only_at_start = true` for a rule that only applies at the very start of the string.
-- `w_result` is what "n w" becomes and `r_result` what "n ř" becomes (only at the
-- start of the string); if nil, the n does not assimilate to that sound.
local function particle_n_rules(w_result, r_result)
local rules = {
{ "fˤ?", "%2ː‿" },
{ "mˤ?", "%2ː‿" },
{ "pˤ?", "%2ː‿" },
{ "χ", "χː‿" },
{ "ħ", "ħː‿" },
{ "ʕ", "ʕː‿" },
}
if r_result then
rules[#rules + 1] = { "R", r_result, only_at_start = true }
end
rules[#rules + 1] = { "lˤ?", "%2ː‿" }
if w_result then
rules[#rules + 1] = { "w", w_result }
end
rules[#rules + 1] = { "j", "ɲ‿" }
return rules
end
-- Voicing / devoicing and nasal assimilation, also across word boundaries
-- ("‿" or a space). Many rules only apply at the end of the string ($).
-- opts.keep_voiced a set of the consonants of FINAL_DEVOICING that the dialect does
-- not devoice before a final t
-- opts.particle_n the particle n rules, see particle_n_rules()
local function build_voice_assim(opts)
local keep_voiced = opts.keep_voiced or {}
local RULES = {
-- θ becomes ð before a voiced coronal
{ "θ(ˤ?[‿ ]?[ðd])", "ð%1" },
}
-- a spirant after n, m or l becomes a stop: nð -> nd, mθ -> mt, lθ -> lt, ...
-- (before devoicing: "nð" + final t is nd -> nt)
-- (before the particle rules: "n mdu" is m‿mdu, not m‿mðu)
local to_stop = { ["ð"] = "d", ["θ"] = "t", ["β"] = "b" }
local function stop_after(sound, replacement, spirants)
for _, spirant in ipairs(spirants) do
RULES[#RULES + 1] = {
sound .. "(ˤ?)([‿ ]?)(" .. spirant .. ")(ˤ?)",
replacement .. "%1%2" .. to_stop[spirant] .. "%4",
}
end
end
stop_after("N", "n", { "ð", "θ", "β" })
stop_after("m", "m", { "ð", "θ", "β" })
stop_after("l", "l", { "ð", "θ" })
-- final devoicing (before the particle rules, which look for χ)
for _, devoicing in ipairs(FINAL_DEVOICING) do
if not keep_voiced[devoicing[1]] then
RULES[#RULES + 1] = { devoicing[2], devoicing[3] }
end
end
-- n before a velar stop
RULES[#RULES + 1] = { "N([‿ ]?[kɡ])", "ŋ%1" }
-- the particle n at the start of the string ("n X")
for _, entry in ipairs(opts.particle_n) do
RULES[#RULES + 1] = { "^(Nˤ?) (" .. entry[1] .. ")", entry[2] }
end
-- ... and after another word ("... n X")
for _, entry in ipairs(opts.particle_n) do
if not entry.only_at_start then
RULES[#RULES + 1] = { " (Nˤ?) (" .. entry[1] .. ")", " " .. entry[2] }
end
end
-- geminate stops across a boundary agree in voicing with what follows
-- (pairs that already agree first)
append(RULES, {
{ "tː(ˤ?[‿ ]?[θt])", "tː" },
{ "dː(ˤ?[‿ ]?[ðd])", "dː" },
{ "dː(ˤ?[‿ ]?[θt])", "tː" },
{ "tː(ˤ?[‿ ]?[ðd])", "dː" },
})
-- t becomes d before a voiced coronal (last: the rules above see the t first)
RULES[#RULES + 1] = { "t(ˤ?[‿ ]?[ðd])", "d%1" }
return RULES
end
RULESETS.voice_assim = build_voice_assim({
particle_n = particle_n_rules("ŋʷ‿", "nː‿"),
})
-- Al Hoceima does not devoice a final ɣ or b before a final t (tmaziɣt is [ðmɛ.zɪʁθ],
-- tarbibt is [ða.βɪβθ]), and the particle n does not assimilate to a following w or ř
-- (n waman is [n wɛ.mɛn], n řexmis is [n rɐχ.mɪs]).
local HOCEIMA_KEEP_VOICED = { ["ʁ"] = true, ["β"] = true }
RULESETS.voice_assim_hoceima = build_voice_assim({
keep_voiced = HOCEIMA_KEEP_VOICED,
particle_n = particle_n_rules(nil, nil),
})
-- ... but in free variation it does, as a w or an ř (n waman is also [wː‿ɛ.mɛn], n řexmis
-- also [rː‿ɐχ.mɪs]). Used by the variant of Al Hoceima in DIALECT_VARIANTS.
RULESETS.voice_assim_hoceima_assimilating = build_voice_assim({
keep_voiced = HOCEIMA_KEEP_VOICED,
particle_n = particle_n_rules("wː‿", "Rː‿"),
})
-- Emphasis (ˤ) spreads through a word. Used twice in the pipeline: repeated until
-- nothing changes, and once as a single pass. ORDER MATTERS for the single pass.
RULESETS.emphatic_spread = {
-- rightwards: ˤ ... consonant + a following non-ˤ symbol
{ "(ˤ[^ ]*" .. SPREADABLE .. ")([^ˤ ])", "%1ˤ%2" },
-- leftwards: consonant + (anything) up to a later ˤ in the same word
{ "(" .. SPREADABLE .. ")([^ˤ ][^ ]*ˤ)", "%1ˤ%2" },
-- rightwards up to the end of the string
{ "(ˤ[^ ]*" .. SPREADABLE .. ")$", "%1ˤ" },
}
RULESETS.long_emphatic_order = {
-- write emphasis before length: ːˤ -> ˤː
{ "([^ˤ])ːˤ", "%1ˤː" },
}
---------- Vowels
RULESETS.schwa_glide_assim = {
{ "əj", "ɘ̆j" },
{ "əw", "ɵ̆w" },
}
-- Two vowels in a row across a word boundary get a glide.
-- ORDER MATTERS: rules where the second vowel is i/u come first, otherwise
-- "i u ɛ" would get a glide twice.
RULESETS.vowel_glide = {
{ "([ɛiu]) ([i])", "%1‿j" },
{ "([ɛiu]) ([u])", "%1‿w" },
{ "([ɛi]) ([ɛ])", "%1‿j%2" },
{ "([u]) ([ɛ])", "%1‿w%2" },
}
-- Vowel colouring next to emphatic and uvular/pharyngeal consonants.
-- Run until stable. ORDER MATTERS: when a vowel could be coloured in two ways the
-- rule that comes first wins, so keep this order.
RULESETS.vowel_phar = {
{ "(ˤ[^‿ aiuɑɪʊ]*)a", "%1ɑ" }, -- a after ˤ (same word) -> ɑ
{ "([ħʕχqʁ]ː?[‿ ]?)ɛ", "%1a" }, -- ɛ right after uvular/pharyngeal -> a
{ "ə([^‿ ɛiuɑɪʊ]*ˤ)", "ɐ%1" }, -- ə before ˤ -> ɐ
{ "a([^‿ aiuɑɪʊ]*ˤ)", "ɑ%1" }, -- a before ˤ -> ɑ
{ "ɛ([ˤ])", "ɑ%1" }, -- ɛ right before ˤ -> ɑ
{ "ɛ([^‿ ɛiuɑɪʊ]*ˤ)", "ɑ%1" }, -- ɛ before ˤ -> ɑ
{ "([ˤħʕχqʁ]ː?[‿ ]?)ə", "%1ɐ" }, -- ə right after ˤ/uvular -> ɐ
{ "(ˤ[^‿ ɛiuɑɪʊ]*)ə", "%1ɐ" }, -- ə after ˤ -> ɐ
{ "([ˤ]ː?[‿ ]?)ɛ", "%1ɑ" }, -- ɛ right after ˤ -> ɑ
{ "(ˤ[^‿ ɛiuɑɪʊ]*)ɛ", "%1ɑ" }, -- ɛ after ˤ -> ɑ
{ "ɛ([ħʕχqʁ])", "a%1" }, -- ɛ right before uvular -> a
{ "ə([ˤħʕχqʁ])", "ɐ%1" }, -- ə right before ˤ/uvular -> ɐ
{ "a([ˤ])", "ɑ%1" }, -- a right before ˤ -> ɑ
}
RULESETS.affricate_length = {
-- ǧ after a schwa is long
{ "([əɐ])(J)(ˤ?)", "%1%2%3ː" },
}
RULESETS.high_vowel_lower = {
{ "u", "ʊ" },
{ "i", "ɪ" },
}
---------- r
-- r after a vowel. Doubled taps become a trill r; "ɛ" before r becomes a.
-- ORDER MATTERS (top to bottom):
-- 1. ɛr -> ar must run before trills are created from doubled taps
-- 2. the rules with a following ɛ must run before the general "ɛɾ + vowel" ones
RULESETS.r_vowel_quality = {
{ "ɛr", "ar" },
-- doubled tap -> trill
{ "ɾˤɾˤ(" .. C_NO_TAP .. ")", "rˤ%1" },
{ "ɾˤɾˤ$", "rˤ" },
{ "ɾɾ(" .. C_NO_TAP .. ")", "r%1" },
{ "ɾɾ$", "r" },
-- tap + ɛ: the ɛ becomes a
{ "aɾ([‿ ]?)ɛ", "aɾ%1a" },
{ "ɛɾ([‿ ]?)ɛ", "ɛɾ%1a" },
{ "ɛɾɾ([‿ ]?)ɛ", "ɛr%1a" },
{ "aɾɾ([‿ ]?)ɛ", "ar%1a" },
-- ɛ before a tap + vowel becomes a
{ "ɛɾɾ([aiuəɛɑɐ])", "aɾɾ%1" },
{ "ɛɾ([aiuəɛɑɐɵɘ])", "aɾ%1" },
}
-- Vowel + r. The single tap is lost (before a consonant, at the end, or before a
-- schwa) and the vowel changes; the trill r is kept.
-- ORDER MATTERS, top to bottom (see the comments on each block).
-- opts.lose_before_glide_schwa the tap is also lost before a schwa next to w / j, which
-- a vowel written ew / ey gets (tarewsa is [θaw.sɛ])
-- opts.monophthongs the vowel that is left is a monophthong: ur is [ʊ], and ir
-- is [ɪ], except at the start of a word where it is [ɛʌ]
local function build_r_vocalization(opts)
local R_RULES = {}
-- tap lost after a vowel: the tap goes, the vowel changes.
-- from vowel + tap to the new vowel
-- schwa schwa-like vowel after the tap that is lost with it
-- following consonants that may follow (the tap itself is not lost before ɾ,
-- except for "aɾˤ")
-- before (optional) what has to come before: "^" or "([ ‿])", i.e. the vowel is
-- the first of a word
local function lose_tap(from, to, schwa, following, before)
before = before or ""
local keep, following_group = "", "%1"
if before ~= "" and before ~= "^" then
-- the letter before is captured, so it has to be written again
keep, following_group = "%1", "%2"
end
local rules = {
{ before .. from .. "$", keep .. to },
{ before .. from .. "(" .. schwa .. ")", keep .. to },
}
if opts.lose_before_glide_schwa then
append(rules, {
{ before .. from .. "(ɵ̆)", keep .. to },
{ before .. from .. "(ɘ̆)", keep .. to },
})
end
rules[#rules + 1] = { before .. from .. "(" .. following .. ")", keep .. to .. following_group }
return rules
end
-- 1. a/ɛ + tap, and a final ɑɾˤ. Before "əɾ" below, which would eat the schwa:
-- "ɛɾ" + schwa + "ɾ" + consonant must lose the first tap and schwa.
append(R_RULES, lose_tap("aɾ", "a", "ə", C_NO_TAP))
append(R_RULES, lose_tap("ɛɾ", "a", "ə", C_NO_TAP))
R_RULES[#R_RULES + 1] = { "ɑɾˤ$", "ɑ" } -- before uɾˤ + ɐ, which produces ɑɾˤ
-- 2. schwa + r
append(R_RULES, {
{ "ər$", "ar" },
{ "ər(" .. C .. ")", "ar%1" },
{ "əɾ$", "a" },
{ "əɾ(" .. C_NO_TAP .. ")", "a%1" },
{ "ərˤ(" .. C .. ")", "ɑr%1" },
{ "əɾˤ$", "ɑ" },
{ "ərˤ$", "ɑ" },
})
-- 3. trill kept, vowel recoloured: { vowel + trill, new vowel + trill }
-- First everything before a vowel/ˤ, then everything before a consonant:
-- "ur" before "arˤ", because ur + ˤ becomes "arˤ" and must then be recoloured.
-- Inside each block the emphatic "Vrˤ" comes before "Vr", which would match it too.
local trill_kept = {
{ "irˤ", "ɛʌrˤ" },
{ "urˤ", "ɔɑrˤ" },
{ "arˤ", "ɑrˤ" },
{ "ɛr", "ar" },
{ "ir", "ɛʌr" },
{ "ur", "ɔar" },
{ "ʊr", "ɔɑr" },
}
for _, e in ipairs(trill_kept) do
R_RULES[#R_RULES + 1] = { e[1] .. "(" .. V_AFTER_R .. ")", e[2] .. "%1" }
end
for _, e in ipairs(trill_kept) do
R_RULES[#R_RULES + 1] = { e[1] .. "(" .. C .. ")", e[2] .. "%1" }
end
R_RULES[#R_RULES + 1] = { "ɛr$", "ar" }
-- 4. doubled tap + vowel keeps both taps
append(R_RULES, {
{ "iɾɾ(" .. V_AFTER_R .. ")", "ɛʌɾɾ%1" },
{ "iɾˤɾˤ(" .. V_AFTER_R .. ")", "ɛʌɾˤɾˤ%1" },
{ "uɾɾ(" .. V_AFTER_R .. ")", "ɔaɾɾ%1" },
{ "uɾˤɾˤ(" .. V_AFTER_R .. ")", "ɔɑɾˤɾˤ%1" },
{ "ʊɾˤ(" .. V_AFTER_R .. ")", "ɔɑrˤ%1" },
})
-- 5. tap lost after the other vowels. The remaining ɑɾˤ rules come last because
-- the entries before them can produce ɑ.
append(R_RULES, lose_tap("aɾˤ", "ɑ", "ɐ", C)) -- (this one also matches before ɾ)
if opts.monophthongs then
-- ir is [ɛʌ] at the start of a word, [ɪ] elsewhere (the word-initial ir comes first)
for _, before in ipairs({ "^", "([ ‿])" }) do
append(R_RULES, lose_tap("iɾ", "ɛʌ", "ə", C_NO_TAP, before))
append(R_RULES, lose_tap("iɾˤ", "ɛʌ", "ɐ", C_NO_TAP, before))
end
append(R_RULES, lose_tap("iɾ", "i", "ə", C_NO_TAP))
append(R_RULES, lose_tap("iɾˤ", "i", "ɐ", C_NO_TAP))
-- ur is [ʊ]
append(R_RULES, lose_tap("uɾ", "u", "ə", C_NO_TAP))
append(R_RULES, lose_tap("uɾˤ", "u", "ɐ", C_NO_TAP))
append(R_RULES, lose_tap("ʊɾ", "ʊ", "ə", C_NO_TAP))
append(R_RULES, lose_tap("ʊɾˤ", "ʊ", "ɐ", C_NO_TAP))
else
append(R_RULES, lose_tap("iɾ", "ɛʌ", "ə", C_NO_TAP))
append(R_RULES, lose_tap("iɾˤ", "ɛʌ", "ɐ", C_NO_TAP))
append(R_RULES, lose_tap("uɾ", "ɔa", "ə", C_NO_TAP))
append(R_RULES, lose_tap("uɾˤ", "ɔɑ", "ɐ", C_NO_TAP))
append(R_RULES, lose_tap("ʊɾ", "ɔɑ", "ə", C_NO_TAP))
append(R_RULES, lose_tap("ʊɾˤ", "ɔɑ", "ɐ", C_NO_TAP))
end
R_RULES[#R_RULES + 1] = { "ɑɾˤ(ɐ)", "ɑ" }
if opts.lose_before_glide_schwa then
append(R_RULES, {
{ "ɑɾˤ(ɵ̆)", "ɑ" },
{ "ɑɾˤ(ɘ̆)", "ɑ" },
})
end
R_RULES[#R_RULES + 1] = { "ɑɾˤ(" .. C_NO_TAP .. ")", "ɑ%1" }
return R_RULES
end
RULESETS.r_vocalization = build_r_vocalization({ lose_before_glide_schwa = true })
-- Al Hoceima: the tap is not lost before a schwa next to w / j. That schwa is often the
-- one that a final i / u becomes (final_high_vowel_glide): amezwaru is [ɛ.məz.wa.ɾə̹w],
-- not [ɛ.məz.waw].
RULESETS.r_vocalization_hoceima = build_r_vocalization({})
-- Al Hoceima, rustic speech: the tap is lost before such a schwa too (amezwaru is
-- [ɛ.məz.waw]), and what is left is a monophthong: ur is [ʊ] (not [ɔa]), ir is [ɪ] (not
-- [ɛʌ]) except at the start of a word. ar and er are as in Nador.
RULESETS.r_vocalization_hoceima_rustic = build_r_vocalization({
lose_before_glide_schwa = true,
monophthongs = true,
})
---------- Final θ
-- w/j + final θ is protected (ṯ is turned back into θ in ipa_symbols) so that
-- final_t_fort does not touch it.
RULESETS.post_glide_spirantization = {
{ "([wj])(ˤ?)(θ)$", "%1%2ṯ" },
}
-- a final θ after a consonant is a (long if emphatic) plain t
RULESETS.final_t_fort = {
{ "(" .. C .. ")(ˤ?)(θ)$", "%1%2t%2" },
}
---------- Output: working symbols -> IPA
-- Geminates: { single sound, geminate }. "XX" -> geminate, and "X X" (two words)
-- -> geminate with a liaison mark.
local GEMINATES = {
{ "b", "bː" }, { "bˤ", "bˤː" }, { "β", "bː" }, { "βˤ", "bˤː" },
{ "C", "Cː" },
{ "J", "Jː" },
{ "ç", "kː" },
{ "ʝ", "ʝː" },
{ "d", "Dː" }, { "dˤ", "dˤː" }, { "ð", "Dː" }, { "ðˤ", "dˤː" },
{ "f", "fː" }, { "fˤ", "fˤː" },
{ "ɡ", "ɡː" }, { "ɡʷ", "ɡʷː" }, { "ɡˤʷ", "ɡʷː" },
{ "ħ", "ħː" }, { "ɦ", "ɦː" },
{ "j", "jː" }, { "jˤ", "jˤː" },
{ "k", "kː" }, { "kˤ", "kˤː" }, { "kʷ", "kʷː" }, { "kˤʷ", "kʷː" },
{ "l", "lː" }, { "lˤ", "lˤː" },
{ "m", "mː" }, { "mˤ", "mˤː" },
{ "N", "Nː" }, { "Nˤ", "Nˤː" },
{ "p", "pː" }, { "pˤ", "pˤː" },
{ "q", "qː" }, { "qʷ", "qʷː" },
{ "ʁ", "ʁː" },
{ "s", "sː" }, { "sˤ", "sˤː" },
{ "ʃ", "ʃː" }, { "ʃˤ", "ʃˤː" },
{ "t", "tː" }, { "tˤ", "tˤː" }, { "θ", "tː" },
{ "ʕ", "ʕː" },
{ "w", "wː" }, { "wˤ", "wˤː" },
{ "χ", "χː" },
{ "z", "zː" }, { "zˤ", "zˤː" },
{ "ʒ", "ʒː" }, { "ʒˤ", "ʒˤː" },
}
RULESETS.geminates = {}
for _, g in ipairs(GEMINATES) do
local single, long = g[1], g[2]
append(RULESETS.geminates, {
{ single .. single, long },
{ single .. " " .. single .. "([^ː])", long .. "‿%1" },
{ single .. " " .. single .. "$", "‿" .. long },
})
end
-- Internal symbols -> IPA, run in this order.
-- (ḇ ḏ K X are only ever written by hand; the rules never produce them.)
RULESETS.ipa_symbols = {
{ "ḇ", "β" },
{ "Rˤ", "ɾˤ" },
{ "R", "ɾ" },
{ "T", "t" },
{ "ṯ", "θ" },
{ "Dˤ", "dˤ" },
{ "D", "d" },
{ "ḏ", "ð" },
{ "K", "k" },
{ "Nˤ", "nˤ" },
{ "N", "n" },
{ "C", "t͡ʃ" },
{ "J", "d͡ʒ" },
{ "X", "ʃˤ" },
-- a stop + affricate is a long affricate
{ "tt͡ʃˤ", "t͡ʃˤː" },
{ "tt͡ʃ", "t͡ʃː" },
{ "dd͡ʒˤ", "d͡ʒˤː" },
{ "dd͡ʒ", "d͡ʒː" },
{ "ðd", "dː" },
{ "θt", "tː" },
{ "βb", "bː" },
-- schwa next to w / j
{ "ɵ̆", "ə̹" },
{ "ɘ̆", "ə̝" },
-- length after emphasis: ːˤ -> ˤː
{ "ːˤ", "ˤː" },
}
---------- Rule sets used by Al Hoceima only
-- A word-final i / u is pronounced as if it were spelled ey / ew. This runs first, so
-- that the new glide behaves like a spelled one (emphasis spreads to it) and
-- schwa_glide_assim colours the schwa.
RULESETS.final_high_vowel_glide = {
{ "i$", "əj" },
{ "u$", "əw" },
{ "i([ ‿])", "əj%1" },
{ "u([ ‿])", "əw%1" },
}
-- A word-final nt is nd: tamment is [θɛm.mənt] in Nador, [ðɛm.mənd] in Al Hoceima.
-- Runs after voice_assim_hoceima, which has turned "n + θ" into a plain nt. A t written
-- T (plain t) or ṭ (emphatic) is left alone.
RULESETS.final_nt_to_nd = {
{ "n(ˤ?)t$", "n%1d" },
{ "n(ˤ?)t([ ‿])", "n%1d%2" },
}
-- A doubled r (rr, ṛṛ) is a tap, not a trill: before a consonant or at the end of a word
-- it is [ɾ] / [ɾˤ] where Nador has the trill [r] / [rˤ]. Runs before r_caron_trill, so that
-- ř, the only trill of Al Hoceima, is not affected.
RULESETS.trill_to_tap = {
{ "rˤ", "ɾˤ" },
{ "r", "ɾ" },
}
-- ř is a trill [r], not a tap [ɾ]. Runs before ipa_symbols, while ř / Ṛ are still the
-- internal symbols R / Rˤ, separate from r (ɾ). It stays a single consonant (not a
-- geminate).
RULESETS.r_caron_trill = {
{ "Rˤ", "rˤ" },
{ "R", "r" },
}
-- A word-initial θ becomes ð (any word of a compound, also after a liaison mark).
-- Runs last: by then every assimilated or geminated t (n θ -> n t, ɛθ θɛ -> ɛtː‿ɛ, ...)
-- is already a plain t / tː, so only a θ that is really word-initial is left to change.
RULESETS.initial_theta_to_eth = {
{ "^θ", "ð" },
{ "([ ‿])θ", "%1ð" },
}
--------------------------------------------------------------------------------
-- 8. Phonology: dialect pipelines
--------------------------------------------------------------------------------
-- A dialect is the ordered list of its steps. A step is the name of a rule set in
-- RULESETS, or { name, until_stable = true } to repeat that rule set until the string
-- stops changing. The last steps of every dialect turn the working symbols into IPA.
local DIALECTS = {}
DIALECTS.Nador = {
-- consonants
"labialization_split",
"hiatus_res",
"aa_liaison",
"geminate_merge",
"voice_assim",
{ "emphatic_spread", until_stable = true },
"long_emphatic_order",
-- vowels
"schwa_glide_assim",
"vowel_glide",
"emphatic_spread",
{ "vowel_phar", until_stable = true },
"affricate_length",
"r_vowel_quality",
"r_vocalization",
"post_glide_spirantization",
"final_t_fort",
"high_vowel_lower",
-- output
"geminates",
"ipa_symbols",
}
-- Al Hoceima is Nador with these differences:
-- * a word-final i / u is pronounced ey / ew
-- * a final ɣ or b stays voiced before a final t, and the particle n does not
-- assimilate to a following w or ř (voice_assim_hoceima)
-- * a word-final nt is nd
-- * no final_t_fort: a final θ after a consonant stays θ
-- * rr and ṛṛ are taps, ř is a trill
-- * a word-initial θ is ð
DIALECTS["Al Hoceima"] = {
"final_high_vowel_glide",
-- consonants
"labialization_split",
"hiatus_res",
"aa_liaison",
"geminate_merge",
"voice_assim_hoceima",
"final_nt_to_nd",
{ "emphatic_spread", until_stable = true },
"long_emphatic_order",
-- vowels
"schwa_glide_assim",
"vowel_glide",
"emphatic_spread",
{ "vowel_phar", until_stable = true },
"affricate_length",
"r_vowel_quality",
"r_vocalization_hoceima",
"post_glide_spirantization",
"high_vowel_lower",
-- output
"trill_to_tap",
"r_caron_trill",
"geminates",
"ipa_symbols",
"initial_theta_to_eth",
}
-- Variants: other versions of a dialect's pipeline. A variant is a table
-- replace = { step = replacement step, ... }
-- label (optional) a label shown before its pronunciation, e.g. "rustic"
-- A word that the variant pronounces differently gets a second pronunciation, shown
-- after the main one. Each variant is compared with the main pronunciation on its own.
local DIALECT_VARIANTS = {
["Al Hoceima"] = {
-- free variation: the particle n sometimes assimilates to a following w or ř:
-- n waman is [n wɛ.mɛn] or [wː‿ɛ.mɛn], n řexmis is [n rɐχ.mɪs] or [rː‿ɐχ.mɪs]
{ replace = { voice_assim_hoceima = "voice_assim_hoceima_assimilating" } },
-- rustic speech: a different r vocalization
{ label = "rustic", replace = { r_vocalization_hoceima = "r_vocalization_hoceima_rustic" } },
},
}
-- order in which dialects are shown when no dialect= is given
local DIALECT_ORDER = { "Nador", "Al Hoceima" }
-- the template parameter holding the respellings meant for one dialect only
local DIALECT_PARAMS = { Nador = "nad", ["Al Hoceima"] = "hoc" }
-- A copy of a list of steps with some steps replaced: `replacements` is { name = new name }.
local function replace_steps(steps, replacements)
local result = {}
for i, step in ipairs(steps) do
local name = type(step) == "table" and step[1] or step
local new_name = replacements[name]
if new_name then
if type(step) == "table" then
local copy = {}
for key, value in pairs(step) do
copy[key] = value
end
copy[1] = new_name
step = copy
else
step = new_name
end
end
result[i] = step
end
return result
end
local function apply_rules(word, rules)
for _, rule in ipairs(rules) do
word = gsub(word, rule[1], rule[2])
end
return word
end
local function run_pipeline(word, steps)
for _, step in ipairs(steps) do
local name, until_stable = step, false
if type(step) == "table" then
name, until_stable = step[1], step.until_stable
end
local rules = RULESETS[name]
if until_stable then
local previous
repeat
previous = word
word = apply_rules(word, rules)
until word == previous
else
word = apply_rules(word, rules)
end
end
return word
end
--------------------------------------------------------------------------------
-- 9. Syllabification: shared helpers
--------------------------------------------------------------------------------
local TIE_BAR = mw.ustring.char(0x0361)
-- Split into characters, attaching combining marks (U+0300-036F, which includes
-- the tie bar) to the character before them.
local function split_graphemes(word)
if not word or word == "" then return {} end
local graphemes = {}
for codepoint in mw.ustring.gcodepoint(word) do
local ch = mw.ustring.char(codepoint)
if codepoint >= 0x0300 and codepoint <= 0x036F and #graphemes > 0 then
graphemes[#graphemes] = graphemes[#graphemes] .. ch
else
graphemes[#graphemes + 1] = ch
end
end
return graphemes
end
local IPA_VOWELS = "aɛɑiɪuʊəɐɔʌ"
local IPA_VOWEL_SET = {}
for vowel in mw.ustring.gmatch(IPA_VOWELS, ".") do
IPA_VOWEL_SET[vowel] = true
end
local IPA_VOWEL_CLASS = "[" .. IPA_VOWELS .. "]"
local function is_ipa_vowel(ch)
return IPA_VOWEL_SET[ch] == true
end
--------------------------------------------------------------------------------
-- 10. Syllabification: spelling
--------------------------------------------------------------------------------
local ORTH_VOWELS = { a = true, e = true, i = true, u = true }
-- after "e", these letters are doubled in front of a vowel: tajeǧabt -> ta.jeǧ.ǧabt
local SCHWA_GEMINATING = { ["ǧ"] = true }
local function is_r_orth(ch)
return ch == "r" or ch == "ṛ"
end
-- The consonants (as positions in g) between the vowels at a and b that count
-- when deciding where to break. Runs of r / ṛ are special:
-- * a run followed by another consonant is ignored (it is a coda: ir.den)
-- * a run right before the next vowel counts once (its last letter) ...
-- * ... except a single r before "e", which is ignored (tarew.sa)
local function consonant_slots(g, a, b)
local slots = {}
local pos = a + 1
while pos < b do
if not is_r_orth(g[pos]) then
slots[#slots + 1] = pos
pos = pos + 1
else
local after_run = pos + 1
while after_run < b and is_r_orth(g[after_run]) do
after_run = after_run + 1
end
if after_run < b then
pos = after_run
elseif g[b] == "e" and after_run - pos == 1 then
pos = b
else
slots[#slots + 1] = after_run - 1
pos = b
end
end
end
return slots
end
-- Position of the consonant that starts the next syllable: the second half of
-- the first geminate if there is one, otherwise the last consonant.
local function break_position(g, slots)
for i = 1, #slots - 1 do
local p1, p2 = slots[i], slots[i + 1]
if p2 == p1 + 1 and g[p1] == g[p2] then
return p2
end
end
return slots[#slots]
end
local function syllabify_orthographic_word(word)
local g = {}
local raw = split_graphemes(word)
for i, x in ipairs(raw) do
g[#g + 1] = x
if SCHWA_GEMINATING[x] and raw[i - 1] == "e" and raw[i + 1] and ORTH_VOWELS[raw[i + 1]] then
g[#g + 1] = x
end
end
local vowel_positions = {}
for i, x in ipairs(g) do
if ORTH_VOWELS[x] then vowel_positions[#vowel_positions + 1] = i end
end
local breaks = {}
for vi = 1, #vowel_positions - 1 do
local slots = consonant_slots(g, vowel_positions[vi], vowel_positions[vi + 1])
if #slots > 0 then
breaks[break_position(g, slots)] = true
end
end
local out = {}
for i, x in ipairs(g) do
if breaks[i] then out[#out + 1] = "." end
out[#out + 1] = x
end
return table.concat(out)
end
local function syllabify_orthographic(word)
word = gsub(word, "[ˈˌ]", "")
local out = {}
local current = {}
for ch in mw.ustring.gmatch(word, ".") do
if ch == " " or ch == "-" then
out[#out + 1] = syllabify_orthographic_word(table.concat(current))
out[#out + 1] = ch
current = {}
else
current[#current + 1] = ch
end
end
out[#out + 1] = syllabify_orthographic_word(table.concat(current))
return table.concat(out)
end
--------------------------------------------------------------------------------
-- 11. Syllabification: IPA
--------------------------------------------------------------------------------
local SEGMENT_MODIFIERS = { ["ˤ"] = true, ["ʷ"] = true, ["ˑ"] = true }
-- Phonetic segments: base sound (+ tie-bar partner) + modifiers + optional length.
local function ipa_segments(word)
local g = split_graphemes(word)
local segments = {}
local i = 1
while i <= #g do
local ch = g[i]
i = i + 1
if i <= #g and mw.ustring.sub(ch, -1) == TIE_BAR then
ch = ch .. g[i]
i = i + 1
end
while i <= #g and SEGMENT_MODIFIERS[g[i]] do
ch = ch .. g[i]
i = i + 1
end
local is_long = false
if i <= #g and g[i] == "ː" then
is_long = true
i = i + 1
end
segments[#segments + 1] = {
text = ch .. (is_long and "ː" or ""),
base = ch,
is_vowel = is_ipa_vowel(mw.ustring.sub(ch, 1, 1)),
is_long = is_long,
}
end
return segments
end
-- The first half of a geminate that is split by a syllable break: a labialized stop
-- loses its labialization (kʷ.kʷ -> k.kʷ) and an affricate its release (d͡ʒ.d͡ʒ -> d.d͡ʒ).
local function first_half_of_geminate(base)
base = gsub(base, "ʷ", "")
return (gsub(base, TIE_BAR .. ".", ""))
end
-- A word without liaison marks: break before the last consonant between two
-- vowels, or in the middle of a long consonant.
local function syllabify_ipa_subtoken(word)
if word == "" then return word end
local segments = ipa_segments(word)
local vowel_positions = {}
for i, seg in ipairs(segments) do
if seg.is_vowel then vowel_positions[#vowel_positions + 1] = i end
end
local break_before = {} -- put "." before this segment
local split_long = {} -- write this long consonant twice, with "." between
for vi = 1, #vowel_positions - 1 do
local consonants = {}
for i = vowel_positions[vi] + 1, vowel_positions[vi + 1] - 1 do
if not segments[i].is_vowel then
consonants[#consonants + 1] = i
end
end
-- a long consonant counts double
local weight, long_consonant = 0, nil
for _, i in ipairs(consonants) do
weight = weight + (segments[i].is_long and 2 or 1)
if segments[i].is_long and not long_consonant then long_consonant = i end
end
if weight == 1 then
break_before[consonants[1]] = true
elseif weight > 1 then
if long_consonant then
split_long[long_consonant] = true
else
break_before[consonants[#consonants]] = true
end
end
end
local out = {}
for i, seg in ipairs(segments) do
if break_before[i] then out[#out + 1] = "." end
if split_long[i] then
out[#out + 1] = first_half_of_geminate(seg.base) .. "." .. seg.base
else
out[#out + 1] = seg.text
end
end
return table.concat(out)
end
-- A space-free token; "‿" joins words that are pronounced together and is kept.
local function syllabify_ipa_token(word)
local result = {}
local rest = word
while true do
local i, j = mw.ustring.find(rest, "‿")
if not i then
result[#result + 1] = syllabify_ipa_subtoken(rest)
break
end
result[#result + 1] = syllabify_ipa_subtoken(mw.ustring.sub(rest, 1, i - 1))
result[#result + 1] = "‿"
rest = mw.ustring.sub(rest, j + 1)
end
return table.concat(result)
end
local function syllabify_ipa_text(text)
local parts = {}
for token in mw.ustring.gmatch(text .. " ", "([^ ]*) ") do
if mw.ustring.find(token, IPA_VOWEL_CLASS) then
parts[#parts + 1] = syllabify_ipa_token(token)
else
parts[#parts + 1] = token
end
end
return table.concat(parts, " ")
end
local function count_syllables_from_phonetic(phonetic)
local clean = gsub(phonetic, "[ ‿]", "")
local _, dots = gsub(clean, "%.", "")
return dots + 1
end
--------------------------------------------------------------------------------
-- 12. Pronunciation
--------------------------------------------------------------------------------
-- spelling -> working transcription (before any rule runs)
function export.pronunciation_phonemic(word)
for _, digraph in ipairs(DIGRAPHS) do
word = gsub(word, digraph[1], digraph[2])
end
return (gsub(word, ".", ORTHOGRAPHY))
end
-- spelling -> IPA, using the given list of steps
local function phonetic_from_steps(word, steps)
word = gsub(word, "%-", " ")
word = export.pronunciation_phonemic(word)
word = gsub(word, ".[ˤʷ]?", STAGE_SYMBOLS)
word = run_pipeline(word, steps)
return syllabify_ipa_text(word)
end
local function get_dialect_steps(dialect)
local steps = DIALECTS[dialect]
if not steps then
error("Unknown Tarifit dialect: " .. tostring(dialect))
end
return steps
end
-- The main pronunciation of the word in the dialect.
function export.pronunciation_phonetic(word, dialect)
return phonetic_from_steps(word, get_dialect_steps(dialect))
end
-- All pronunciations of the word in the dialect, as a list of { phonetic = ..., label = ... }:
-- the main one first, then those of the dialect's variants (DIALECT_VARIANTS) that differ
-- from the ones before.
function export.pronunciation_variants(word, dialect)
local steps = get_dialect_steps(dialect)
local main = phonetic_from_steps(word, steps)
local results = { { phonetic = main } }
local seen = { [main] = true }
for _, variant in ipairs(DIALECT_VARIANTS[dialect] or {}) do
local phonetic = phonetic_from_steps(word, replace_steps(steps, variant.replace))
if not seen[phonetic] then
seen[phonetic] = true
table.insert(results, { phonetic = phonetic, label = variant.label })
end
end
return results
end
--------------------------------------------------------------------------------
-- 13. Rhymes
--------------------------------------------------------------------------------
-- everything from the first vowel of the last syllable
local function convert_phonetic_to_rhyme(phonetic)
local last_dot = 0
for i = 1, mw.ustring.len(phonetic) do
if mw.ustring.sub(phonetic, i, i) == "." then
last_dot = i
end
end
local syllable = mw.ustring.sub(phonetic, last_dot + 1)
syllable = gsub(syllable, "[‿.]", "")
local g = split_graphemes(syllable)
for i, x in ipairs(g) do
if is_ipa_vowel(mw.ustring.sub(x, 1, 1)) then
return table.concat(g, "", i)
end
end
return nil
end
local function get_last_ipa_token(phonetic)
local last_token
for token in mw.ustring.gmatch(phonetic, "[^ ]+") do
last_token = token
end
return (gsub(last_token or phonetic, "‿", ""))
end
local function rhyme_from_phonetic(phonetic)
return convert_phonetic_to_rhyme(get_last_ipa_token(phonetic))
end
function export.pronunciation_rhymes(word, dialect)
local phonetic = export.pronunciation_phonetic(word, dialect)
local rhymes = {}
local rhyme = rhyme_from_phonetic(phonetic)
if rhyme then
rhymes[#rhymes + 1] = rhyme
end
return rhymes
end
-- add { rhyme = ..., num_syl = { n } } unless that exact rhyme is already listed
local function add_rhyme(rhyme_list, phonetic, num_syl)
local rhyme = rhyme_from_phonetic(phonetic)
if not rhyme or rhyme == "" then
return
end
for _, existing in ipairs(rhyme_list) do
if existing.rhyme == rhyme and existing.num_syl[1] == num_syl then
return
end
end
table.insert(rhyme_list, { rhyme = rhyme, num_syl = { num_syl } })
end
-- One entry per rhyme, with all its syllable counts (two words can share a rhyme).
local function merge_rhymes(rhyme_list)
local merged, by_rhyme = {}, {}
for _, rhymeobj in ipairs(rhyme_list) do
local existing = by_rhyme[rhymeobj.rhyme]
if not existing then
by_rhyme[rhymeobj.rhyme] = rhymeobj
table.insert(merged, rhymeobj)
else
local num_syl = rhymeobj.num_syl[1]
local known = false
for _, ns in ipairs(existing.num_syl) do
if ns == num_syl then
known = true
break
end
end
if not known then
table.insert(existing.num_syl, num_syl)
end
end
end
return merged
end
--------------------------------------------------------------------------------
-- 14. Alternative forms: dialect respellings based on the page's other spellings
--------------------------------------------------------------------------------
-- Some dialect differences are not visible in the standard spelling but are
-- recorded on the page as an alternative form. Example: Al Hoceima has ç where
-- Nador has ʃ (spelled c). The page "cmez" lists the alternative form "kmez", which
-- tells us that Al Hoceima has çmez, shown as "[çməz] (as if spelled kmez)".
--
-- These rules do not change the sounds of a dialect (that is what the pipelines in
-- section 8 are for). They change the RESPELLING that is fed into the pipeline, and
-- only because the page lists an alternative form; they also add the "as if spelled
-- ..." qualifier.
--
-- HOW TO ADD A RULE: add a correspondence to ALT_FORM_RULES for the dialect:
-- correspondence(spelled, alt_spelled, result, opts)
-- means that where the page has `spelled`, an alternative form has `alt_spelled`, and the
-- dialect pronounces it as if it were spelled `result` (default: `alt_spelled`).
-- opts.at_end the correspondence only holds at the end of the spelling
-- opts.optional the dialect also keeps the pronunciation without it (so the word gets
-- two pronunciations: first with the correspondence, then without)
--
-- An alternative form is used only if ALL its differences from the page's spelling are
-- covered by correspondences. If several alternative forms are, the one that needs the
-- most correspondences is used (tacɛeft with tacɛebt and takɛebt uses takɛebt: c ~ k and
-- ft ~ bt, not just ft ~ bt).
local function trim(text)
return (text:gsub("^%s+", ""):gsub("%s+$", ""))
end
local function split_chars(text)
local chars = {}
for ch in mw.ustring.gmatch(text, ".") do
chars[#chars + 1] = ch
end
return chars
end
-- templates in the "Alternative forms" section that list alternative spellings
local ALT_FORM_TEMPLATES = { alt = true, alter = true, l = true, link = true }
-- An alternative form with one of these labels (e.g. <ll:Eastern>) belongs to another
-- variety, so every rule ignores it. Other labels (e.g. Western) do not matter.
-- Labels are compared in lowercase.
local IGNORED_ALT_FORM_LABELS = { eastern = true }
-- the modifiers that hold labels
local LABEL_MODIFIERS = { l = true, ll = true }
-- Does the alternative form (as written, with its <modifiers>) have an ignored label?
local function has_ignored_label(param)
for modifier, value in param:gmatch("<([%w_]+):([^>]*)>") do
if LABEL_MODIFIERS[modifier] then
for label in value:gmatch("[^,]+") do
if IGNORED_ALT_FORM_LABELS[trim(label):lower()] then
return true
end
end
end
end
return false
end
-- The alternative forms in the Tarifit section of a page's wikitext: every Tarifit
-- term in {{alt|rif|...}}, {{alter|rif|...}}, {{l|rif|...}} or {{link|rif|...}} under
-- the "Alternative forms" heading. Named parameters and <modifiers> are ignored.
function export.parse_alt_forms(content)
local alt_forms, seen = {}, {}
if not content then
return alt_forms
end
content = "\n" .. (content:gsub("<!%-%-.-%-%->", "")) .. "\n"
-- the Tarifit language section
local _, section_start = content:find("\n==[ \t]*Tarifit[ \t]*==[ \t]*\n")
if not section_start then
return alt_forms
end
local section_end = content:find("\n==[^=\n]", section_start) or #content
local section = content:sub(section_start, section_end)
-- all headings in it
local headings = {}
local pos = 1
while true do
local line_start, _, hashes, title, newline = section:find("\n(=+)[ \t]*([^\n]-)[ \t]*%1[ \t]*()\n", pos)
if not line_start then
break
end
table.insert(headings, { level = #hashes, title = title, text_start = newline, line_start = line_start })
pos = newline
end
-- the "Alternative forms" subsection runs to the next heading of the same or a higher level
local alt_text
for i, heading in ipairs(headings) do
if heading.title:lower() == "alternative forms" then
local stop = #section
for j = i + 1, #headings do
if headings[j].level <= heading.level then
stop = headings[j].line_start
break
end
end
alt_text = section:sub(heading.text_start, stop)
break
end
end
if not alt_text then
return alt_forms
end
for body in alt_text:gmatch("{{(.-)}}") do
local params = {}
for param in (body .. "|"):gmatch("(.-)|") do
params[#params + 1] = param
end
if ALT_FORM_TEMPLATES[trim(params[1]):lower()] and trim(params[2] or "") == "rif" then
for i = 3, #params do
local param = trim(params[i])
-- not a named parameter, and not a form with an ignored label
if not param:find("^[%w_%-]+%s*=") and not has_ignored_label(param) then
param = trim((param:gsub("<[^>]*>", ""):gsub("%[%[", ""):gsub("%]%]", "")))
if param ~= "" and not seen[param] then
seen[param] = true
table.insert(alt_forms, param)
end
end
end
end
end
return alt_forms
end
local function get_alt_forms(title)
return export.parse_alt_forms(title and title:getContent())
end
-- does the list of characters `chars` have `piece` (a list) at position `pos`?
local function has_piece_at(chars, pos, piece)
for k, ch in ipairs(piece) do
if chars[pos + k - 1] ~= ch then
return false
end
end
return true
end
-- A correspondence between the page's spelling and an alternative form: the page has
-- `spelled` where the alternative form has `alt_spelled`; in the dialect it is `result`.
-- Each of them is one or more letters, e.g. "c" ~ "k" or "kkʷ" ~ "ggʷ", anywhere in the
-- word (or only at the end, with opts.at_end). See "HOW TO ADD A RULE" above.
local function correspondence(spelled, alt_spelled, result, opts)
opts = opts or {}
return {
spelled_chars = split_chars(spelled),
alt_chars = split_chars(alt_spelled),
result = result or alt_spelled,
at_end = opts.at_end,
optional = opts.optional,
}
end
-- The correspondences "ending ~ alt ending" for every combination of the endings and the
-- alternative endings: the ending of the page is replaced by the alternative ending
-- (tijdect ~ tijdit, taḥebbuct ~ taḥebbuyt). The two forms may have different lengths;
-- the letters that go away are replaced by "".
local function ending_correspondences(endings, alt_endings, opts)
opts = opts or {}
local list = {}
for _, ending in ipairs(endings) do
for _, alt_ending in ipairs(alt_endings) do
list[#list + 1] = correspondence(ending, alt_ending, alt_ending, {
at_end = true,
optional = opts.optional,
})
end
end
return list
end
-- The rules of each dialect.
local HOCEIMA_ALT_FORM_RULES = {
-- c (ʃ in Nador) is ç where the alternative form is spelled with k: cmez ~ kmez
correspondence("c", "k", "ç"),
-- c (ʃ in Nador) is y where the alternative form is spelled with y: taxsact ~ taxsayt
correspondence("c", "y", "y"),
-- y (j in Nador) is g̱ [ʝ] where the alternative form is spelled with g:
-- ayenduz ~ agenduz (this includes yy ~ gg)
correspondence("y", "g", "g̱"),
-- y (j in Nador) is ç where the alternative form is spelled with k
correspondence("y", "k", "ç"),
-- j (ʒ in Nador) is g̱ [ʝ] where the alternative form is spelled with g
correspondence("j", "g", "g̱"),
-- kkʷ is ggʷ where the alternative form is spelled with ggʷ
correspondence("kkʷ", "ggʷ", "ggʷ"),
}
-- -ect / -ct (Nador) is -it / -yt where the alternative form has that ending:
-- tijdect ~ tijdit, taxedmect ~ taxedmit, taḥebbuct ~ taḥebbuyt
append(HOCEIMA_ALT_FORM_RULES, ending_correspondences({ "ect", "ct" }, { "it", "yt" }))
-- -ft (Nador) is -bt as the main pronunciation, with -ft as a second one, where the
-- alternative form has -bt: tarbift ~ tarbibt
append(HOCEIMA_ALT_FORM_RULES, ending_correspondences({ "ft" }, { "bt" }, { optional = true }))
local ALT_FORM_RULES = {
["Al Hoceima"] = HOCEIMA_ALT_FORM_RULES,
}
-- How the page's spelling (a list of characters) becomes the alternative form
-- (a list of characters) with the correspondences: a list of
-- { correspondence = ..., start = position in the page's spelling }, or nil if the two
-- spellings differ in any other way. If there is more than one way, the one with the
-- most correspondences is used.
local function explain_alt_form(chars, alt_chars, correspondences)
local memo = {}
-- the best way to explain the rest of both spellings, from position i in the page's
-- spelling and j in the alternative form (false if there is none)
local function explain_rest(i, j)
if i > #chars and j > #alt_chars then
return {}
end
local key = i .. ":" .. j
if memo[key] ~= nil then
return memo[key]
end
local best = false
-- the same letter on both sides
if i <= #chars and chars[i] == alt_chars[j] then
best = explain_rest(i + 1, j + 1)
end
-- a correspondence
for _, c in ipairs(correspondences) do
local spelled_end = i + #c.spelled_chars - 1
local alt_end = j + #c.alt_chars - 1
if has_piece_at(chars, i, c.spelled_chars) and has_piece_at(alt_chars, j, c.alt_chars)
and (not c.at_end or (spelled_end == #chars and alt_end == #alt_chars)) then
local rest = explain_rest(spelled_end + 1, alt_end + 1)
if rest and (not best or #rest + 1 > #best) then
best = { { correspondence = c, start = i } }
append(best, rest)
end
end
end
memo[key] = best
return best
end
return explain_rest(1, 1) or nil
end
-- Returns two things: a list of the respellings for this dialect and a list of
-- qualifiers ("as if spelled ..."). The first respelling has all the changes of the
-- alternative form that is used; if some of them are optional (see correspondence()), a
-- second one has everything except those. If no alternative form can be used, the only
-- respelling is the original one (and the list of qualifiers is empty).
function export.apply_alt_form_rules(respelling, dialect, alt_forms)
local rules = ALT_FORM_RULES[dialect]
if not rules or not alt_forms or #alt_forms == 0 then
return { respelling }, {}
end
-- the alternative form that is explained by the most correspondences
local chars = split_chars(respelling)
local used_form, used_matches
for _, alt_form in ipairs(alt_forms) do
local matches = explain_alt_form(chars, split_chars(alt_form), rules)
if matches and #matches > 0 and (not used_matches or #matches > #used_matches) then
used_form, used_matches = alt_form, matches
end
end
if not used_matches then
return { respelling }, {}
end
local edits = {} -- every change, by position
local optional_edits = {} -- the positions in `edits` that come from optional correspondences
for _, match in ipairs(used_matches) do
local c = match.correspondence
for position = match.start, match.start + #c.spelled_chars - 1 do
edits[position] = position == match.start and c.result or ""
optional_edits[position] = c.optional or nil
end
end
local function apply_edits(skip_optional)
local result = {}
for i, ch in ipairs(chars) do
local edit = edits[i]
if skip_optional and optional_edits[i] then
edit = nil
end
result[i] = edit or ch
end
return table.concat(result)
end
local respellings = { apply_edits(false) }
if next(optional_edits) ~= nil then
table.insert(respellings, apply_edits(true))
end
return respellings, { "as if spelled " .. used_form }
end
--------------------------------------------------------------------------------
-- 15. The pronunciations of one dialect
--------------------------------------------------------------------------------
-- A pronunciation item as format_IPA_full wants it.
local function make_pron_item(term, pron, qq)
return {
pron = pron,
pron_with_syldivs = pron,
q = term.q,
qq = qq or term.qq,
a = term.a,
aa = term.aa,
refs = term.refs,
}
end
-- terms: list of { respelling = ..., q = ..., qq = ..., a = ..., aa = ..., refs = ... }
-- Returns { pron_list = ..., rhyme_list = ... }. pron_list is nil if the only
-- respelling is "-" (no pronunciation wanted).
-- opts:
-- skip_raw leave out "raw:[...]" respellings (so a manual transcription that is
-- shared by several dialects is shown only once)
-- alt_forms the page's alternative forms, for the rules in section 14
-- literal the respellings were written for this dialect only (nad=, hoc=): they
-- are used as written, and only a respelling that stands for the page
-- name is adapted using the alternative forms
function export.get_pron_info(terms, pagename, dialect, opts)
dialect = dialect or DEFAULT_DIALECT
opts = opts or {}
if #terms == 1 and terms[1].respelling == "-" then
return {
pron_list = nil,
rhyme_list = {},
}
end
local pron_list = {}
local rhyme_list = {}
for _, term in ipairs(terms) do
local respelling = term.respelling
-- an empty respelling or "#" stands for the page name
local is_pagename = not respelling or respelling == "" or respelling == "#"
if is_pagename then
respelling = pagename
end
if respelling:find("^raw:%[.+%]$") then
-- manual phonetic transcription: raw:[...]
if not opts.skip_raw then
local raw = (respelling:gsub("^raw:", ""))
table.insert(pron_list, make_pron_item(term, raw))
end
else
local alt_forms = (is_pagename or not opts.literal) and opts.alt_forms or nil
-- One respelling per way the alternative forms can change it (see
-- correspondence()), and for each of them its main pronunciation and the
-- pronunciations of the dialect's variants (DIALECT_VARIANTS).
local respellings, alt_qualifiers = export.apply_alt_form_rules(respelling, dialect, alt_forms)
local term_items = {}
for respelling_index, dialect_respelling in ipairs(respellings) do
for phonetic_index, entry in ipairs(export.pronunciation_variants(dialect_respelling, dialect)) do
local pron = ("[%s]"):format(entry.phonetic)
local item
if respelling_index == 1 and phonetic_index == 1 then
-- the term's own modifiers belong to the main pronunciation
item = make_pron_item(term, pron)
else
-- a further pronunciation of the same term
item = make_pron_item({}, pron)
if entry.label then
item.a = { entry.label }
end
end
table.insert(term_items, item)
add_rhyme(rhyme_list, entry.phonetic, count_syllables_from_phonetic(entry.phonetic))
end
end
-- "as if spelled ..." comes after the last of the term's pronunciations
if #alt_qualifiers > 0 then
local last = term_items[#term_items]
last.qq = append(append({}, last.qq or {}), alt_qualifiers)
end
append(pron_list, term_items)
end
end
return {
pron_list = pron_list,
rhyme_list = rhyme_list,
}
end
--------------------------------------------------------------------------------
-- 16. The template entry point
--------------------------------------------------------------------------------
-- Is any respelling of any of these dialects a single letter?
local function has_single_letter_respelling(dialects, dialect_terms, pagename)
for _, dialect in ipairs(dialects) do
for _, term in ipairs(dialect_terms[dialect].terms) do
local respelling = term.respelling
if respelling == "#" or respelling == nil or respelling == "" then
respelling = pagename
end
if respelling and M.string_utilities.len(respelling) <= 1 then
return true
end
end
end
return false
end
-- "‧" (or ".") separates syllables. mw.ustring, not string.gmatch: a byte pattern
-- would also split letters like ħ that share a byte with "‧".
local function split_syllables(item)
local hyph = {}
for syllable in mw.ustring.gmatch(item, "[^‧.]+") do
table.insert(hyph, syllable)
end
return { hyph = hyph }
end
local function format_syllabification(syl_list)
local syls = {}
for i, syl in ipairs(syl_list) do
syls[i] = split_syllables(syl)
end
return M.hyphenation.format_hyphenations {
lang = lang, hyphs = syls, caption = "Âm tiết"
}
end
function export.show(frame)
local parent_args = frame:getParent().args
-- 1= is a single comma-separated list (no | lists). nad= / hoc= are the same kind
-- of list, for one dialect only.
local params = {
[1] = true,
["syl"] = true,
["s"] = { alias_of = "syl" },
["audios"] = true,
["a"] = { alias_of = "audios" },
["homophones"] = true,
["h"] = { alias_of = "homophones" },
["pagename"] = true,
["dialect"] = true,
["d"] = { alias_of = "dialect" },
}
for _, param in pairs(DIALECT_PARAMS) do
params[param] = true
end
local args = M.parameters.process(parent_args, params)
local pagename = args.pagename or M.headword_data.pagename
-- parse one parameter into a list of terms (nil if it was not given)
local function parse_terms(paramname)
local arg = paramname and args[paramname]
if not arg then
return nil
end
return parse_respellings_with_modifiers(arg, paramname)
end
-- 1= applies to every dialect; the page name is used if it is missing
local global_terms = parse_terms(1) or { generate_obj("#") }
-- dialect= restricts the output to one dialect; otherwise show all of them
local dialects = DIALECT_ORDER
if args.dialect then
if not DIALECTS[args.dialect] then
error(("Unknown dialect '%s'"):format(args.dialect))
end
dialects = { args.dialect }
end
-- the terms of each dialect: its own parameter (nad=, hoc=) if given, else 1=
local dialect_terms = {}
for _, dialect in ipairs(dialects) do
local specific = parse_terms(DIALECT_PARAMS[dialect])
dialect_terms[dialect] = { terms = specific or global_terms, is_global = not specific }
end
-- the page's alternative forms are only looked up if a dialect has rules that use them
local alt_forms = {}
for _, dialect in ipairs(dialects) do
if ALT_FORM_RULES[dialect] then
local title = args.pagename and mw.title.new(args.pagename) or mw.title.getCurrentTitle()
alt_forms = get_alt_forms(title)
break
end
end
local pron_groups = {} -- { dialects = {...}, items = {...} }, in display order
local rhyme_list = {}
local global_raw_shown = false
local any_pron = false -- false if every dialect has "-" (no pronunciation wanted)
for _, dialect in ipairs(dialects) do
local entry = dialect_terms[dialect]
local terms = entry.terms
if not (#terms == 1 and terms[1].respelling == "-") then
any_pron = true
end
-- A raw:[...] from 1= is shown once, under the first dialect that uses 1=.
-- What is written in nad= / hoc= is taken literally.
local pronobj = export.get_pron_info(terms, pagename, dialect, {
skip_raw = entry.is_global and global_raw_shown,
alt_forms = alt_forms,
literal = not entry.is_global,
})
if entry.is_global then
global_raw_shown = true
end
-- Dialects with identical pronunciations (qualifiers included) share one group, which
-- is shown on one line.
local items = pronobj.pron_list or {}
if #items > 0 then
local group
for _, existing in ipairs(pron_groups) do
if M.table.deepEquals(existing.items, items) then
group = existing
break
end
end
if group then
table.insert(group.dialects, dialect)
else
table.insert(pron_groups, { dialects = { dialect }, items = items })
end
end
append(rhyme_list, pronobj.rhyme_list)
end
-- syllabification: automatic (from the page name) unless given with syl=
local syl_list
if args.syl then
if args.syl ~= "-" then
syl_list = split_on_comma(args.syl)
end
elseif any_pron then
syl_list = { (gsub(syllabify_orthographic(pagename), "%.", "‧")) }
end
local parts = {}
local function ins(text)
table.insert(parts, text)
end
-- pronunciation: "* (Dialect, Dialect) IPA(key): [...], [...]", one line per group of
-- dialects. All the pronunciations of a group go on one line, separated by commas.
-- As in [[Module:ca-IPA]], the dialects are left accent qualifiers on the first item
-- only, and every later item starts with a ", " separator.
for i, group in ipairs(pron_groups) do
for j, item in ipairs(group.items) do
if j == 1 then
item.a = append(append({}, group.dialects), item.a or {})
else
item.separator = ", "
end
end
local formatted = M.IPA.format_IPA_full { lang = lang, items = group.items, separator = "" }
if i > 1 then
ins("\n")
end
ins("* " .. mw.ustring.toNFC(formatted))
end
-- audio
if args.audios then
local audio_objs = parse_audio(lang, args.audios, pagename, "audios")
local num_audios = #audio_objs
for i, audio_obj in ipairs(audio_objs) do
if num_audios > 1 and not audio_obj.caption then
audio_obj.caption = "Âm thanh " .. i
end
ins("\n* " .. M.audio.format_audio(audio_obj))
end
end
-- rhymes
rhyme_list = merge_rhymes(rhyme_list)
if #rhyme_list > 0 then
local formatted_rhymes = M.rhymes.format_rhymes { lang = lang, rhymes = rhyme_list }
ins("\n* " .. mw.ustring.toNFC(formatted_rhymes))
end
-- syllabification
if syl_list and #syl_list > 0 and not has_single_letter_respelling(dialects, dialect_terms, pagename) then
ins("\n* " .. format_syllabification(syl_list))
end
-- homophones
if args.homophones then
local homophone_list = parse_homophones(args.homophones, "homophones")
ins("\n* " .. M.homophones.format_homophones {
lang = lang,
homophones = homophone_list,
})
end
return table.concat(parts)
end
--------------------------------------------------------------------------------
-- 17. Exports
--------------------------------------------------------------------------------
export.syllabify_orthographic = syllabify_orthographic
-- IPA string -> list of syllables
function export.syllabify_ipa(word)
local result = {}
for token in mw.ustring.gmatch(word .. " ", "([^ ]*) ") do
if token ~= "" then
local syllabified = syllabify_ipa_token(token)
for part in mw.ustring.gmatch(syllabified .. ".", "([^.]*)[.]") do
if part ~= "" then
result[#result + 1] = part
end
end
end
end
return result
end
return export
5ll7copfg5c99rxs6qf9q7s06p5aynq
Mô đun:number list/data/mi
828
413327
2576428
2541140
2026-11-08T14:07:10Z
Hiyuune
50834
2576428
Scribunto
text/plain
local export = { numbers = {} }
local numbers = export.numbers
export.additional_number_types = {
{key = "polygon"},
}
numbers[0] = {
cardinal = "kore",
}
numbers[1] = {
cardinal = "tahi",
ordinal = "tuatahi",
}
numbers[2] = {
cardinal = "rua",
ordinal = "tuarua",
}
numbers[3] = {
cardinal = "toru",
ordinal = "tuatoru",
polygon = "tapatoru"
}
numbers[4] = {
cardinal = "whā",
ordinal = "tuawhā",
polygon = "tapawhā",
}
numbers[5] = {
cardinal = "rima",
ordinal = "tuarima",
polygon = "taparima",
}
numbers[6] = {
cardinal = "ono",
ordinal = "tuaono",
polygon = "tapaono",
}
numbers[7] = {
cardinal = "whitu",
ordinal = "tuawhitu",
polygon = "tapawhitu",
}
numbers[8] = {
cardinal = "waru",
ordinal = "tuawaru",
polygon = "tapawaru",
}
numbers[9] = {
cardinal = "iwa",
ordinal = "tuaiwa",
polygon = "tapaiwa",
}
numbers[10] = {
cardinal = {"tekau", "ngahuru"},
}
numbers[11] = {
cardinal = {"tekau mā tahi", "ngahuru mā tahi"},
}
numbers[12] = {
cardinal = {"tekau mā rua", "ngahuru mā rua"},
}
numbers[13] = {
cardinal = {"tekau mā toru", "ngahuru mā toru"},
}
numbers[14] = {
cardinal = {"tekau mā whā", "ngahuru mā whā"},
}
numbers[15] = {
cardinal = {"tekau mā rima", "ngahuru mā rima"},
}
numbers[16] = {
cardinal = {"tekau mā ono", "ngahuru mā ono"},
}
numbers[17] = {
cardinal = {"tekau mā whitu", "ngahuru mā whitu"},
}
numbers[18] = {
cardinal = {"tekau mā waru", "ngahuru mā waru"},
}
numbers[19] = {
cardinal = {"tekau mā iwa", "ngahuru mā iwa"},
}
numbers[20] = {
cardinal = {"rua ngahuru", "rua tekau"},
}
numbers[21] = {
cardinal = {"rua tekau mā tahi"},
}
numbers[30] = {
cardinal = "toru tekau",
}
numbers[40] = {
cardinal = "whā tekau",
}
numbers[50] = {
cardinal = "rima tekau",
}
numbers[60] = {
cardinal = "ono tekau",
}
numbers[70] = {
cardinal = "whitu tekau",
}
numbers[80] = {
cardinal = "waru tekau",
}
numbers[90] = {
cardinal = "iwa tekau",
}
numbers[100] = {
cardinal = "rau",
}
numbers[1000] = {
cardinal = "mano",
}
return export
7667fl2yujhgw0s7qk9fwh17pg4i3al
mô kích
0
422315
2576413
2576109
2026-11-08T13:23:22Z
TheHighFighter2
42988
Đã lùi lại sửa đổi của [[Special:Contributions/TienMinh-mun6xnChing|TienMinh-mun6xnChing]] ([[User talk:TienMinh-mun6xnChing|thảo luận]]) quay về phiên bản cuối của [[User:Hiyuune|Hiyuune]]
2279223
wikitext
text/x-wiki
{{rfv}}
{{-vie-}}
{{-pron-}}
{{vie-pron}}
{{-proverb-}}
'''mô kích'''
# [[khiêu khích|Khiêu khích]], [[chế nhạo]] ai.
{{mẫu}}
[[Thể loại:Tục ngữ tiếng Việt]]
549mi1xf9vnwwqx6cc1nbuux84udoqk
2576451
2576413
2026-11-08T16:23:09Z
TheHighFighter2
42988
2576451
wikitext
text/x-wiki
=={{langname|vi}}==
==={{ĐM|alt}}===
* {{alt|vi|mô-kích}}
==={{ĐM|pron}}===
{{vi-pron}}
==={{ĐM|etym}} 1===
Từ {{bor|vi|de|Mokick}}.
===={{ĐM|noun}}====
{{vi-noun|cls=chiếc}}
# Tên gọi dòng [[xe máy]] hãng [[w:en:Simson (company)|Simson]].
#* {{quote-web|vi|date=10-1-2009|author=Lã Xưa (ghi theo lời kể của Nguyễn Trường)|title=“Phố Phái, gái Liên” và cô người mẫu xinh đẹp|url=https://giadinh.suckhoedoisong.vn/pho-phai-gai-lien-va-co-nguoi-mau-xinh-dep-172090108032523791.htm|work=Giadinh.net|passage=Ngày ấy, thường khi vẽ mẫu xong, cô Mai thường lấy xe '''mô kích''' chở Dương Bích Liên đi vòng quanh Hồ Tây ngắm cảnh chiều tà, mà ở thời ấy có được chiếc xe '''mô kích''' là “kinh” lắm.}}
#* {{quote-web|vi|date=11-10-2011|author=Đức Quang|title=Simson Star SR4-2 - xế cổ một thời hoàng kim|url=https://vnexpress.net/simson-star-sr4-2-xe-co-mot-thoi-hoang-kim-2207768.html|work=VnExpress|passage=Có biệt danh "'''mô kích'''", những chiếc Star SR4-2 xuất hiện tại Việt Nam chủ yếu do những người hợp tác lao động đóng thùng gửi về những năm 1980.}}
==={{ĐM|etym}} 2===
{{rfe|vi|Từ {{bor|vi|fr|moquer||chế giễu}}?}}
===={{ĐM|v}}====
{{vi-verb}}
# [[khiêu khích|Khiêu khích]], [[chế nhạo]] ai đó.
#* {{quote-web|vi|date=27-10-2016|author=Bồ câu công sở|title=Công sở ấy mà, 'cú vọ' nhiều vô kể...|url=https://vietnamnet.vn/cong-so-ay-ma-cu-vo-nhieu-vo-ke-336171.html|work=VietNamNet|passage=Chị làm cùng tôi chả hiểu bị đồng nghiệp "''''mô kích'''" là hay giao lưu với sếp to thì làm gì cũng trót lọt không sợ bị ai tố cáo, cũng chẳng phải sợ mấy sếp tèm nhèm.}}
#* {{quote-song|vi|date=26-05-2024|lyricist=[[w:ICD (rapper)|ICD]]|composer=Eric Phan|title=Không muốn dây|url=https://m.youtube.com/watch?v=aaS-0Jpi7do|time=05:16|passage=(Để rồi) em tao vẫn là chiến thần<br/>Còn mày cả đời chỉ đi '''mô kích'''}}
b1fs7apgn3juvhr7eyaf7zvib6hgmk8
2576452
2576451
2026-11-08T16:25:08Z
TheHighFighter2
42988
/* Từ nguyên 2 */
2576452
wikitext
text/x-wiki
=={{langname|vi}}==
==={{ĐM|alt}}===
* {{alt|vi|mô-kích}}
==={{ĐM|pron}}===
{{vi-pron}}
==={{ĐM|etym}} 1===
Từ {{bor|vi|de|Mokick}}.
===={{ĐM|noun}}====
{{vi-noun|cls=chiếc}}
# Tên gọi dòng [[xe máy]] hãng [[w:en:Simson (company)|Simson]].
#* {{quote-web|vi|date=10-1-2009|author=Lã Xưa (ghi theo lời kể của Nguyễn Trường)|title=“Phố Phái, gái Liên” và cô người mẫu xinh đẹp|url=https://giadinh.suckhoedoisong.vn/pho-phai-gai-lien-va-co-nguoi-mau-xinh-dep-172090108032523791.htm|work=Giadinh.net|passage=Ngày ấy, thường khi vẽ mẫu xong, cô Mai thường lấy xe '''mô kích''' chở Dương Bích Liên đi vòng quanh Hồ Tây ngắm cảnh chiều tà, mà ở thời ấy có được chiếc xe '''mô kích''' là “kinh” lắm.}}
#* {{quote-web|vi|date=11-10-2011|author=Đức Quang|title=Simson Star SR4-2 - xế cổ một thời hoàng kim|url=https://vnexpress.net/simson-star-sr4-2-xe-co-mot-thoi-hoang-kim-2207768.html|work=VnExpress|passage=Có biệt danh "'''mô kích'''", những chiếc Star SR4-2 xuất hiện tại Việt Nam chủ yếu do những người hợp tác lao động đóng thùng gửi về những năm 1980.}}
==={{ĐM|etym}} 2===
{{rfe|vi}}
===={{ĐM|v}}====
{{vi-verb}}
# [[khiêu khích|Khiêu khích]], [[chế nhạo]] ai đó.
#* {{quote-web|vi|date=27-10-2016|author=Bồ câu công sở|title=Công sở ấy mà, 'cú vọ' nhiều vô kể...|url=https://vietnamnet.vn/cong-so-ay-ma-cu-vo-nhieu-vo-ke-336171.html|work=VietNamNet|passage=Chị làm cùng tôi chả hiểu bị đồng nghiệp "''''mô kích'''" là hay giao lưu với sếp to thì làm gì cũng trót lọt không sợ bị ai tố cáo, cũng chẳng phải sợ mấy sếp tèm nhèm.}}
#* {{quote-song|vi|date=26-05-2024|lyricist=[[w:ICD (rapper)|ICD]]|composer=Eric Phan|title=Không muốn dây|url=https://m.youtube.com/watch?v=aaS-0Jpi7do|time=05:16|passage=(Để rồi) em tao vẫn là chiến thần<br/>Còn mày cả đời chỉ đi '''mô kích'''}}
cjuyx4oofl7xgip7a8cegdz9864xut3
oánh nhau
0
422319
2576409
2576125
2026-11-08T12:56:35Z
TheHighFighter2
42988
/* */
2576409
wikitext
text/x-wiki
=={{langname|vi}}==
==={{ĐM|pron}}===
{{vi-pron}}
==={{ĐM|v}}===
{{vi-verb}}
# {{alt of|vi|đánh nhau}}.
rym6w6cvtqzcduzewg3bfwmjsq0s22k
oánh bại
0
422325
2576407
2576151
2026-11-08T12:49:34Z
TheHighFighter2
42988
/* */
2576407
wikitext
text/x-wiki
=={{langname|vi}}==
==={{ĐM|pron}}===
{{vi-pron}}
==={{ĐM|v}}===
{{vi-verb}}
# {{nhãn|vi|khẩu ngữ|hài hước}} {{alt of|vi|đánh bại}}.
3pe4k1s3bk2xv3u8qi8tsrg2vqwpi9d
Ƙ
0
422358
2576483
2576275
2026-11-09T03:20:07Z
InternetArchiveBot
44631
Rescuing 1 sources and tagging 0 as dead. #IABot (v2.0.9.7)
2576483
wikitext
text/x-wiki
{{-Latn-}}
{{character info}}
==={{ĐM|desction}}===
{{mul-letter}}
#[[chữ cái|Chữ cái]] '''[[K]] móc''' viết hoa.
==={{ĐM|see}}===
{{Latn-script}}
=={{langname|gew}}==
==={{ĐM|pron}}===
*{{IPA|gew|/kʼ/}}
==={{ĐM|letter}}===
{{letter|gew}}
#Chữ cái thứ 15 viết hoa trong bảng chữ cái Latinh tiếng Gera.
#:{{ux|gew|'''Ƙ'''eɗuwi|[[béo|Béo]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=gew|sc=Latn|qual=Bảng chữ cái Latinh tiếng Gera|Aa|Bb|Ɓɓ|Cc|Dd|Ɗɗ|Ff|Gg|Gw/gw|Hh|Ii|Jj|Kk|Kw/kw|Ƙƙ|Ll|Mm|Mb/mb|Nn|Nd/nd|Ng/ng|Ngw/ngw|Nj/nj|Nw/nw|Rr|Rw/rw|Ss|Sh/sh|Sw/sw|Shw/shw|Tt|Tw/tw|Ww|Yy|Zz|Zw/zw}}
==={{ĐM|ref}}===
*[https://web.archive.org/web/20250905131549/https://www.rogerblench.info/Language/Afroasiatic/Chadic/West/Gere/Gere%20three%20lang%20vocab.pdf Gere-Hausa-English wordlist, June 2006]
=={{langname|ha}}==
==={{ĐM|pron}}===
*{{ha-IPA|ƙ}}
==={{ĐM|letter}}===
{{letter|ha}}
#Chữ cái thứ 14 viết hoa trong bảng chữ cái Latinh tiếng Hausa.
#:{{ux|ha|[[w:ha:Ƙyautar Muhalli ta Goldman|'''Ƙ'''yautar Muhalli ta Goldman]]|{{w|Giải Môi trường Goldman}}|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=ha|sc=Latn|qual=Bảng chữ cái Latinh tiếng Hausa|Aa|Bb|Ɓɓ|Cc|Dd|Ɗɗ|Ee|Ff|Gg|Hh|Ii|Jj|Kk|Ƙƙ|Ll|Mm|Nn|Oo|Rr|(R̃/r̃)|Ss|Sh/sh|Tt|Ts/ts|Uu|Ww|Yy|Ƴƴ|(ʼY/ʼy)|Zz|'}}
=={{langname|fkk}}==
==={{ĐM|pron}}===
*{{IPA|fkk|/kʼ/}}
==={{ĐM|letter}}===
{{letter|fkk}}
#Chữ cái thứ 17 viết hoa trong bảng chữ cái Latinh tiếng Kirya-Konzəl.
#:{{ux|gew|'''Ƙ'''yiƙyi|[[gai|Gai]]|inline=1}}
==={{ĐM|see}}===
*{{letters|lang=fkk|sc=Latn|qual=Bảng chữ cái Latinh tiếng Kirya-Konzəl|Aa|Bb|Ɓɓ|Cc|CH/ch|Dd|Ɗɗ|DZ/dz|DL/dl|Ee|Ff|Gg|GH/gh|Hh|Ii|Jj|Kk|Ƙƙ|Ll|Mm|’M/’m|Nn|’NG/’ng|Oo|Əə|Pp|Rr|Ɽɽ|Ss|Tt|TL/tl|TS/ts|Uu|Vv|Ww|’W/’w|Xx|Yy|’Y/’y|(Ƴƴ)|Zz|ZH/zh}}
==={{ĐM|ref}}===
*Blench, Roger, and A. Ndamsai, 2007. [https://archive.wikiwix.com/cache/20230714031857/https://www.rogerblench.info/Language/Afroasiatic/Chadic/Central/Kirya/Fali%20of%20Kirya%20Unicode.pdf A Dictionary of Kirya and Konzəl in Northeastern Nigeria], tr. 31
=={{langname|wji}}==
==={{ĐM|pron}}===
*{{IPA|wji|/kʼ/}}
==={{ĐM|letter}}===
{{letter|wji}}
#Chữ cái Latinh viết hoa biểu thị phụ âm '''{{IPAchar|/kʼ/}}''' trong tiếng Warji.
#:{{quote|wji|'''Ƙ'''uwa ba ma ndaka pˈa fagadan ya taa ɗi ƙuwayoni tana?|Có thể kiếm bánh đâu được trong đồng vắng nầy cho chúng ăn no ư? ([[s:Mác/8#8:4|Mác 8:4]])}}
==={{ĐM|ref}}===
*{{Chú thích web|wji|work=Warji|author=The Seed Company|year=2023|entryurl=https://www.bible.com/bible/3641/MRK.8.WJI|entry=Markus 8}}
[[Thể loại:Khối ký tự Latin Extended-B|98]]
g7ru00ict9s6w4hklxr4vmorp52j0da
ש
0
422410
2576411
2026-11-08T13:11:25Z
Lcsnes
40261
Trang mới: “{{also|שׂ|ש־|ш|Ш|山}} {{-Hebr-}} {{character info}} [[Tập tin:Hebrew letter shin.png|nhỏ|phải|Các kiểu chữ ''shin'']] ==={{ĐM|translit}}=== *{{Latn}}: '''[[š#Chữ_Latinh|š]]''', '''[[sh#Chữ_Latinh|sh]]''' ==={{ĐM|desction}}=== {{head|mul|Chữ cái|tr=š, sh}} #[[shin|Shin]]: Chữ cái thứ 21 trong bảng chữ cái Hebrew, sau [[ר#Chữ_Hebrew|ר]] và trước [[ת#Chữ_Hebrew|ת]]. =={{langname|arc}}== {| class="floatright wikitable" styl…”
2576411
wikitext
text/x-wiki
{{also|שׂ|ש־|ш|Ш|山}}
{{-Hebr-}}
{{character info}}
[[Tập tin:Hebrew letter shin.png|nhỏ|phải|Các kiểu chữ ''shin'']]
==={{ĐM|translit}}===
*{{Latn}}: '''[[š#Chữ_Latinh|š]]''', '''[[sh#Chữ_Latinh|sh]]'''
==={{ĐM|desction}}===
{{head|mul|Chữ cái|tr=š, sh}}
#[[shin|Shin]]: Chữ cái thứ 21 trong bảng chữ cái Hebrew, sau [[ר#Chữ_Hebrew|ר]] và trước [[ת#Chữ_Hebrew|ת]].
=={{langname|arc}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Hebrew
| {{pn}}
|-
! Aram
| [[𐡔#Tiếng_Aram|𐡔]]
|-
! Syriac
| {{l|arc|ܫ}}
|-
! Palmyrene
| [[𐡵#Tiếng_Aram|𐡵]]
|-
! Nabata
| {{l|arc|𐢜}} {{l|arc|𐢝}}
|-
! Phoenicia
| {{l|arc|𐤔}}
|-
! Manda
| {{l|arc|ࡔ}}
|-
! Samari
| {{l|arc|ࠔ}}
|-
! Hatran
| {{l|arc|𐣴}}
|-
|}
==={{ĐM|pron}}===
*{{IPA|arc|[ʃ]}}
==={{ĐM|letter}}===
{{head|arc|Chữ cái|tr=š}}
#Chữ cái thứ 32 trong bộ chữ Hebrew tiếng Aram.
#:{{ux|arc|[[אשיתא#Tiếng_Aram|'''ש'''יתא]]|tr='''š'''ittā|[[sáu]]|inline=1}}
==={{ĐM|number}}===
{{head|arc|Ký tự số|tr=š}}
#[[số|Số]] [[300]].
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Aram
|list=<span dir="rtl"><!--
-->{{l-self|arc|א}},‏ <!--
-->{{l-self|arc|ב}},‏ <!--
-->{{l-self|arc|בּ}},‏ <!--
-->{{l-self|arc|ג}},‏ <!--
-->{{l-self|arc|גּ}},‏ <!--
-->{{l-self|arc|ד}},‏ <!--
-->{{l-self|arc|דּ}},‏ <!--
-->{{l-self|arc|ה}},‏ <!--
-->{{l-self|arc|ו}},‏ <!--
-->{{l-self|arc|וַ}},‏ <!--
-->{{l-self|arc|וֹ}},‏ <!--
-->{{l-self|arc|וּ}},‏ <!--
-->{{l-self|arc|ז}},‏ <!--
-->{{l-self|arc|ח}},‏ <!--
-->{{l-self|arc|ט}},‏ <!--
-->{{l-self|arc|י}},‏ <!--
-->{{l-self|arc|יׅ}},‏ <!--
-->{{l-self|arc|יַ}},‏ <!--
-->{{l-self|arc|כ}}\{{l-self|arc|ך}},‏ <!--
-->{{l-self|arc|כּ}},‏ <!--
-->{{l-self|arc|כ֗}},‏ <!--
-->{{l-self|arc|ל}},‏ <!--
-->{{l-self|arc|מ}}\{{l-self|arc|ם}},‏ <!--
-->{{l-self|arc|נ}}\{{l-self|arc|ן}},‏ <!--
-->{{l-self|arc|ס}},‏ <!--
-->{{l-self|arc|ע}},‏ <!--
-->{{l-self|arc|פ}}\{{l-self|arc|ף}},‏ <!--
-->{{l-self|arc|פ֗}}\{{l-self|arc|ף֗}},‏ <!--
-->{{l-self|arc|צ}}\{{l-self|arc|ץ}},‏ <!--
-->{{l-self|arc|ק}},‏ <!--
-->{{l-self|arc|ר}},‏ <!--
-->{{l-self|arc|ש}},‏ <!--
-->{{l-self|arc|ש֗}},‏ <!--
-->{{l-self|arc|ת}},‏ <!--
-->{{l-self|arc|תּ}}‏ <!--
--></span>}}
=={{langname|ayn}}==
==={{ĐM|pron}}===
*{{IPA|ayn|[ʃ]}}
==={{ĐM|letter}}===
{{head|ayn|Chữ cái|tr=š}}
#Chữ cái Hebrew biểu thị phụ âm '''{{IPAchar|/ʃ/}}''' trong tiếng Ả Rập Sana'a
#:{{ux|ayn|'''ש'''בריה|tr='''š'''abrīya|[[giường]]|inline=1}}
==={{ĐM|ref}}===
*{{Chú thích web|work=Yemeni Arabic Dictionary|year=2009–2026|entryurl=https://en.mo3jam.com/dialect/Yemeni/all/ش#ش|entry=ش}}
=={{langname|jpr}}==
==={{ĐM|pron}}===
*{{IPA|jpr|[ʃ]}}
==={{ĐM|letter}}===
{{head|jpr|Chữ cái|tr=š}}
#Chữ cái thứ 24 trong bộ chữ Hebrew tiếng Ba Tư-Do Thái.
#:{{quote|jpr|'''שש'''ום דר|tr='''šešo'''m dar|thơ đọc trong lễ ''Shavuot''|inline=1}}
==={{ĐM|number}}===
{{head|jpr|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Ba Tư-Do Thái
|list=<span dir="rtl"><!--
-->{{l-self|jpr|א}},‏ <!--
-->{{l-self|jpr|ב}},‏ <!--
-->{{l-self|jpr|ג}},‏ <!--
-->{{l-self|jpr|ד}},‏ <!--
-->{{l-self|jpr|ה}},‏ <!--
-->{{l-self|jpr|ו}},‏ <!--
-->{{l-self|jpr|ז}},‏ <!--
-->{{l-self|jpr|ח}},‏ <!--
-->{{l-self|jpr|ט}},‏ <!--
-->{{l-self|jpr|י}},‏ <!--
-->{{l-self|jpr|כ}}{{l-self|jpr|ך}},‏ <!--
-->{{l-self|jpr|ל}},‏ <!--
-->{{l-self|jpr|מ}}{{l-self|jpr|ם}},‏ <!--
-->{{l-self|jpr|נ}}{{l-self|jpr|ן}},‏ <!--
-->{{l-self|jpr|ס}},‏ <!--
-->{{l-self|jpr|ע}},‏ <!--
-->{{l-self|jpr|פ}}{{l-self|jpr|ף}},‏ <!--
-->{{l-self|jpr|צ}}{{l-self|jpr|ץ}},‏ <!--
-->{{l-self|jpr|ק}},‏ <!--
-->{{l-self|jpr|ר}},‏ <!--
-->{{l-self|jpr|ש}},‏ <!--
-->{{l-self|jpr|ת}}<!--
--></span>}}
=={{langname|jbe}}==
==={{ĐM|pron}}===
*{{IPA|jbe|[ʃ]}}
==={{ĐM|letter}}===
{{head|jbe|Chữ cái|tr=š}}
#Chữ cái thứ 22 trong bộ chữ Hebrew tiếng Berber-Do Thái.
#:{{quote|jbe|יִכְדַמְן אַיְיִנַגָא יפּרעו גְמַצָר. יִשוֹפִגַג רבי נּג דְיְנָג שוֹפוֹש נִדְרע שוֹפוֹש יִכיווֹאַנ|tr=Yikhdamn ayyinaga yipre'u gematsar. Yi'''š'''ofigag rabbi ngg dyenag '''š'''ofo'''š''' nidre '''š'''ofo'''š''' yikhivo'an.|Chúng ta đã bị làm tôi-mọi cho Pha-ra-ôn tại xứ Ê-díp-tô, và Đức Giê-hô-va có dùng tay mạnh đem chúng ta ra khỏi xứ ấy. ([[s:Phục truyền Luật lệ Ký/6#6:21|Phục truyền Luật lệ Ký 6:21]])}}
==={{ĐM|number}}===
{{head|jbe|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Berber-Do Thái
|list=<span dir="rtl"><!--
-->{{l-self|jbe|א}},‏ <!--
-->{{l-self|jbe|ב}},‏ <!--
-->{{l-self|jbe|ג}},‏ <!--
-->{{l-self|jbe|ד}},‏ <!--
-->{{l-self|jbe|ה}},‏ <!--
-->{{l-self|jbe|ו}},‏ <!--
-->{{l-self|jbe|ז}},‏ <!--
-->{{l-self|jbe|ח}},‏ <!--
-->{{l-self|jbe|ט}},‏ <!--
-->{{l-self|jbe|י}},‏ <!--
-->{{l-self|jbe|כ}}{{l-self|jbe|ך}},‏ <!--
-->{{l-self|jbe|ל}},‏ <!--
-->{{l-self|jbe|מ}}{{l-self|jbe|ם}},‏ <!--
-->{{l-self|jbe|נ}}{{l-self|jbe|ן}},‏ <!--
-->{{l-self|jbe|ס}},‏ <!--
-->{{l-self|jbe|ע}},‏ <!--
-->{{l-self|jbe|פ}}{{l-self|jbe|ף}},‏ <!--
-->{{l-self|jbe|צ}}{{l-self|jbe|ץ}},‏ <!--
-->{{l-self|jbe|ק}},‏ <!--
-->{{l-self|jbe|ר}},‏ <!--
-->{{l-self|jbe|ש}},‏ <!--
-->{{l-self|jbe|ת}}<!--
--></span>}}
=={{langname|bhh}}==
==={{ĐM|pron}}===
*{{IPA|bhh|[ʃ]}}
==={{ĐM|letter}}===
{{head|bhh|Chữ cái|tr=sh}}
#Chữ cái thứ 25 trong bộ chữ Hebrew tiếng Bukhara.
#:{{ux|bhh|'''שַׁ'''חר|tr='''sha'''hr|[[thành phố]]|inline=1}}
==={{ĐM|number}}===
{{head|bhh|Ký tự số|tr=sh}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Bukhara
|list=<span dir="rtl"><!--
-->{{l-self|bhh|א}},‏ <!--
-->{{l-self|bhh|אַ}},‏ <!--
-->{{l-self|bhh|אָ}},‏ <!--
-->{{l-self|bhh|ב}},‏ <!--
-->{{l-self|bhh|בּ}},‏ <!--
-->{{l-self|bhh|ג}},‏ <!--
-->{{l-self|bhh|גּ}},‏ <!--
-->{{l-self|bhh|ג'}},‏ <!--
-->{{l-self|bhh|ד}},‏ <!--
-->{{l-self|bhh|ה}},‏ <!--
-->{{l-self|bhh|ו}},‏ <!--
-->{{l-self|bhh|וּ}},‏ <!--
-->{{l-self|bhh|וֹ}},‏ <!--
-->{{l-self|bhh|ז}},‏ <!--
-->{{l-self|bhh|ז'}},‏ <!--
-->{{l-self|bhh|ח}},‏ <!--
-->{{l-self|bhh|ט}},‏ <!--
-->{{l-self|bhh|י}},‏ <!--
-->{{l-self|bhh|יׅ}},‏ <!--
-->{{l-self|bhh|יֵ}},‏ <!--
-->{{l-self|bhh|כ}}\{{l-self|bhh|ך}},‏ <!--
-->{{l-self|bhh|כּ}}\{{l-self|bhh|ךּ}},‏ <!--
-->{{l-self|bhh|ל}},‏ <!--
-->{{l-self|bhh|מ}}\{{l-self|bhh|ם}},‏ <!--
-->{{l-self|bhh|נ}}\{{l-self|bhh|ן}},‏ <!--
-->{{l-self|bhh|ס}},‏ <!--
-->{{l-self|bhh|ע}},‏ <!--
-->{{l-self|bhh|פ}}\{{l-self|bhh|ף}},‏ <!--
-->{{l-self|bhh|פּ}}\{{l-self|bhh|ףּ}},‏ <!--
-->{{l-self|bhh|צ}}\{{l-self|bhh|ץ}},‏ <!--
-->{{l-self|bhh|צ'}},‏ <!--
-->{{l-self|bhh|ק}},‏ <!--
-->{{l-self|bhh|ר}},‏ <!--
-->{{l-self|bhh|שׁ}},‏ <!--
-->{{l-self|bhh|שׂ}},‏ <!--
-->{{l-self|bhh|ת}}‏ <!--
--></span>}}
=={{langname|he}}==
{{wikipedia|lang=he}}
==={{ĐM|pron}}===
*{{IPA|he|[ʃ]|[s]}}
*{{audio|he|LL-Q9288_(heb)-Uziel302-ש.wav|Âm thanh}}
==={{ĐM|etym}}===
Từ {{der|he|sem-pro|*šinn-|t=răng}}, nguồn gốc của {{m|he|שן}}. Việc liên kết "răng" với chữ cái này là kết quả từ nguyên dân gian và dựa trên chữ cái Phoenicia tương ứng {{m|phn|𐤔}}, có hình dáng giống như chiếc răng. Chữ cái này nguyên còn mô tả cây [[cung]] khi chưa căng dây.
===={{ĐM|letter}}====
{{head|he|Chữ cái|tr=sh, s}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew.
#:'''{{lang|he|שׁ}}''' biểu thị phụ âm {{IPAchar|/ʃ/}}
#: '''{{lang|he|שׂ}}''' biểu thị phụ âm /s/
#:{{ux|he|[[השתמט#Tiếng_Do_Thái|ה'''ש'''תמט]]|tr=hi'''sh''''támet|[[trốn tránh]]|inline=1}}
===={{ĐM|number}}====
{{head|he|Ký tự số|tr=sh, s}}
#[[số|Số]] 300.
====={{ĐM|see}}=====
*{{list helper 2
|title=Bảng chữ cái Hebrew
|appendix=Chữ Hebrew
|list=<span dir="rtl"><!--
-->{{l-self|he|א}},‏ <!--
-->{{l-self|he|ב}},‏ <!--
-->{{l-self|he|ג}},‏ <!--
-->{{l-self|he|ד}},‏ <!--
-->{{l-self|he|ה}},‏ <!--
-->{{l-self|he|ו}},‏ <!--
-->{{l-self|he|ז}},‏ <!--
-->{{l-self|he|ח}},‏ <!--
-->{{l-self|he|ט}},‏ <!--
-->{{l-self|he|י}},‏ <!--
-->{{l-self|he|כ}}{{l-self|he|ך}},‏ <!--
-->{{l-self|he|ל}},‏ <!--
-->{{l-self|he|מ}}{{l-self|he|ם}},‏ <!--
-->{{l-self|he|נ}}{{l-self|he|ן}},‏ <!--
-->{{l-self|he|ס}},‏ <!--
-->{{l-self|he|ע}},‏ <!--
-->{{l-self|he|פ}}{{l-self|he|ף}},‏ <!--
-->{{l-self|he|צ}}{{l-self|he|ץ}},‏ <!--
-->{{l-self|he|ק}},‏ <!--
-->{{l-self|he|ר}},‏ <!--
-->{{l-self|he|ש}},‏ <!--
-->{{l-self|he|ת}}<!--
--></span>}}
==={{ĐM|intj}}===
{{head|he|Thán từ|tr=sha}}
#[[suỵt|Suỵt]]! [[im|Im]]!
===={{ĐM|syn}}====
*{{l|he|הס|tr=has}}
==={{ĐM|ref}}===
*{{Chú thích web|work=''Hebrew Terms Database'' of the Academy of Hebrew Language|year=2023|url=https://terms.hebrew-academy.org.il}}
=={{langname|hbo}}==
==={{ĐM|letter}}===
{{head|hbo|Chữ cái|tr=sh, s}}
# Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Do Thái Kinh Thánh.
#:{{ux|hbo|'''שִׁ'''מְ'''שָׁ'''ה|tr='''shi'''m'''sh'''á|[[cửa]] [[chắn]] [[gió]]|inline=1}}
==={{ĐM|number}}===
{{head|hbo|Ký tự số|tr=sh, s}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Do Thái Kinh Thánh
|list=<span dir="rtl"><!--
-->{{l-self|hbo|א}},‏ <!--
-->{{l-self|hbo|ב}},‏ <!--
-->{{l-self|hbo|ג}},‏ <!--
-->{{l-self|hbo|ד}},‏ <!--
-->{{l-self|hbo|ה}},‏ <!--
-->{{l-self|hbo|ו}},‏ <!--
-->{{l-self|hbo|ז}},‏ <!--
-->{{l-self|hbo|ח}},‏ <!--
-->{{l-self|hbo|ט}},‏ <!--
-->{{l-self|hbo|י}},‏ <!--
-->{{l-self|hbo|כ}}{{l-self|hbo|ך}},‏ <!--
-->{{l-self|hbo|ל}},‏ <!--
-->{{l-self|hbo|מ}}{{l-self|hbo|ם}},‏ <!--
-->{{l-self|hbo|נ}}{{l-self|hbo|ן}},‏ <!--
-->{{l-self|hbo|ס}},‏ <!--
-->{{l-self|hbo|ע}},‏ <!--
-->{{l-self|hbo|פ}}{{l-self|hbo|ף}},‏ <!--
-->{{l-self|hbo|צ}}{{l-self|hbo|ץ}},‏ <!--
-->{{l-self|hbo|ק}},‏ <!--
-->{{l-self|hbo|ר}},‏ <!--
-->{{l-self|hbo|ש}},‏ <!--
-->{{l-self|hbo|ת}}<!--
--></span>}}
==={{ĐM|ref}}===
*{{Chú thích web|en|author=Jeff A. Benner|work=Ancient Hebrew Dictionary|year=1999|entry=Shin|entryurl=https://ancient-hebrew.org/dictionary/ancient-shin.html}}
=={{langname|rmt}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Latinh
| {{l|rmt|Ŝ}} {{l|rmt|ŝ}}
|-
! Hebrew
| {{pn}}
|-
! Ả Rập
| {{l|rmt|ش}}
|-
|}
==={{ĐM|pron}}===
*{{IPA|rmt|[ʃ]}}
==={{ĐM|letter}}===
{{head|rmt|Chữ cái|tr=ŝ}}
#Chữ cái thứ 33 trong bộ chữ Hebrew tiếng Domari.
#:{{ux|rmt|אוֹ'''שְׁ'''ט|tr=ō'''š'''t|[[môi]]|inline=1}}
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Domari
|list=<span dir="rtl"><!--
-->{{l-self|rmt|א}},‏ <!--
-->{{l-self|rmt|בּ}},‏ <!--
-->{{l-self|rmt|בֿ}},‏ <!--
-->{{l-self|rmt|גּ}},‏ <!--
-->{{l-self|rmt|גֿ}},‏ <!--
-->{{l-self|rmt|ג׳}},‏ <!--
-->{{l-self|rmt|דּ}},‏ <!--
-->{{l-self|rmt|דֿ}},‏ <!--
-->{{l-self|rmt|ה}},‏ <!--
-->{{l-self|rmt|ו}},‏ <!--
-->{{l-self|rmt|ז}},‏ <!--
-->{{l-self|rmt|ז׳}},‏ <!--
-->{{l-self|rmt|ח}},‏ <!--
-->{{l-self|rmt|חֿ}},‏ <!--
-->{{l-self|rmt|ט}},‏ <!--
-->{{l-self|rmt|טֿ}},‏ <!--
-->{{l-self|rmt|י}},‏ <!--
-->{{l-self|rmt|כּ}} {{l-self|rmt|ךּ}},‏ <!--
-->{{l-self|rmt|כֿ}} {{l-self|rmt|ךֿ}},‏ <!--
-->{{l-self|rmt|ל}},‏ <!--
-->{{l-self|rmt|מ}} {{l-self|rmt|ם}},‏ <!--
-->{{l-self|rmt|נ}} {{l-self|rmt|ן}},‏ <!--
-->{{l-self|rmt|ס}},‏ <!--
-->{{l-self|rmt|ע}},‏ <!--
-->{{l-self|rmt|עֿ}},‏ <!--
-->{{l-self|rmt|פ}} {{l-self|rmt|ף}},‏ <!--
-->{{l-self|rmt|פֿ}} {{l-self|rmt|ףֿ}},‏ <!--
-->{{l-self|rmt|צ}} {{l-self|rmt|ץ}},‏ <!--
-->{{l-self|rmt|צֿ}} {{l-self|rmt|ץֿ}},‏ <!--
-->{{l-self|rmt|צ׳}} {{l-self|rmt|ץ׳}},‏ <!--
-->{{l-self|rmt|ק}},‏ <!--
-->{{l-self|rmt|ר}},‏ <!--
-->{{l-self|rmt|ש}},‏ <!--
-->{{l-self|rmt|תּ}},‏ <!--
-->{{l-self|rmt|תֿ}},‏ <!--
-->{{l-self|rmt|אְ}},‏ <!--
-->{{l-self|rmt|אִ}},‏ <!--
-->{{l-self|rmt|אׅי}},‏ <!--
-->{{l-self|rmt|אֵ}} {{l-self|rmt|אֵי}},‏ <!--
-->{{l-self|rmt|אֶ}} {{l-self|rmt|אֶי}},‏ <!--
-->{{l-self|rmt|אַ}} {{l-self|rmt|אֲ}},‏ <!--
-->{{l-self|rmt|אָ}},‏ <!--
-->{{l-self|rmt|אֳ}},‏ <!--
-->{{l-self|rmt|אׄ}} {{l-self|rmt|אוׄ}},‏ <!--
-->{{l-self|rmt|אֻ}},‏ <!--
-->{{l-self|rmt|אוּ}},‏ <!--
--></span>}}
=={{langname|jge}}==
==={{ĐM|pron}}===
*{{IPA|jge|[ʃ]}}
==={{ĐM|letter}}===
{{head|jge|Chữ cái|tr=š}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Gruzia-Do Thái.
==={{ĐM|number}}===
{{head|jge|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Gruzia-Do Thái
|list=<span dir="rtl"><!--
-->{{l-self|jge|א}},‏ <!--
-->{{l-self|jge|ב}},‏ <!--
-->{{l-self|jge|ג}},‏ <!--
-->{{l-self|jge|ד}},‏ <!--
-->{{l-self|jge|ה}},‏ <!--
-->{{l-self|jge|ו}},‏ <!--
-->{{l-self|jge|ז}},‏ <!--
-->{{l-self|jge|ח}},‏ <!--
-->{{l-self|jge|ט}},‏ <!--
-->{{l-self|jge|י}},‏ <!--
-->{{l-self|jge|כ}}{{l-self|jge|ך}},‏ <!--
-->{{l-self|jge|ל}},‏ <!--
-->{{l-self|jge|מ}}{{l-self|jge|ם}},‏ <!--
-->{{l-self|jge|נ}}{{l-self|jge|ן}},‏ <!--
-->{{l-self|jge|ס}},‏ <!--
-->{{l-self|jge|ע}},‏ <!--
-->{{l-self|jge|פ}}{{l-self|jge|ף}},‏ <!--
-->{{l-self|jge|צ}}{{l-self|jge|ץ}},‏ <!--
-->{{l-self|jge|ק}},‏ <!--
-->{{l-self|jge|ר}},‏ <!--
-->{{l-self|jge|ש}},‏ <!--
-->{{l-self|jge|ת}}<!--
--></span>}}
=={{langname|huy}}==
==={{ĐM|pron}}===
*{{IPA|huy|[ʃ]}}
==={{ĐM|letter}}===
{{head|huy|Chữ cái|tr=š}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Hulaulá.
#:{{ux|huy|'''שְׁ'''מ'''שַׁ'''א|tr='''šə'''m'''š'''a|[[mặt trời]]|inline=1}}
==={{ĐM|number}}===
{{head|huy|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Hulaulá
|list=<span dir="rtl"><!--
-->{{l-self|huy|א}},‏ <!--
-->{{l-self|huy|ב}},‏ <!--
-->{{l-self|huy|ג}},‏ <!--
-->{{l-self|huy|ד}},‏ <!--
-->{{l-self|huy|ה}},‏ <!--
-->{{l-self|huy|ו}},‏ <!--
-->{{l-self|huy|ז}},‏ <!--
-->{{l-self|huy|ח}},‏ <!--
-->{{l-self|huy|ט}},‏ <!--
-->{{l-self|huy|י}},‏ <!--
-->{{l-self|huy|כ}}{{l-self|huy|ך}},‏ <!--
-->{{l-self|huy|ל}},‏ <!--
-->{{l-self|huy|מ}}{{l-self|huy|ם}},‏ <!--
-->{{l-self|huy|נ}}{{l-self|huy|ן}},‏ <!--
-->{{l-self|huy|ס}},‏ <!--
-->{{l-self|huy|ע}},‏ <!--
-->{{l-self|huy|פ}}{{l-self|huy|ף}},‏ <!--
-->{{l-self|huy|צ}}{{l-self|huy|ץ}},‏ <!--
-->{{l-self|huy|ק}},‏ <!--
-->{{l-self|huy|ר}},‏ <!--
-->{{l-self|huy|ש}},‏ <!--
-->{{l-self|huy|ת}}<!--
--></span>}}
=={{langname|kdr}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Kirin
| {{l|kdr|Ш}} {{l|kdr|ш}}
|-
! Latinh
| {{l|kdr|Ș}} {{l|kdr|ș}}
|-
! Hebrew
| {{pn}}
|-
|}
==={{ĐM|pron}}===
*{{IPA|kdr|[ʃ]}}
==={{ĐM|letter}}===
{{head|kdr|Chữ cái|tr=ș}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Karaim.
#:{{ux|kdr|'''ש'''ם|tr='''șe'''m|[[tên]]|inline=1}}
==={{ĐM|number}}===
{{head|kdr|Ký tự số|tr=ș}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Karaim
|list=<span dir="rtl"><!--
-->{{l-self|kdr|א}},‏ <!--
-->{{l-self|kdr|ב}},‏ <!--
-->{{l-self|kdr|ג}},‏ <!--
-->{{l-self|kdr|ד}},‏ <!--
-->{{l-self|kdr|ה}},‏ <!--
-->{{l-self|kdr|ו}},‏ <!--
-->{{l-self|kdr|ז}},‏ <!--
-->{{l-self|kdr|ט}},‏ <!--
-->{{l-self|kdr|י}},‏ <!--
-->{{l-self|kdr|כ}}{{l-self|kdr|ך}},‏ <!--
-->{{l-self|kdr|ל}},‏ <!--
-->{{l-self|kdr|מ}}{{l-self|kdr|ם}},‏ <!--
-->{{l-self|kdr|נ}}{{l-self|kdr|ן}},‏ <!--
-->{{l-self|kdr|נג}},‏ <!--
-->{{l-self|kdr|ס}},‏ <!--
-->{{l-self|kdr|פ}}{{l-self|kdr|ף}},‏ <!--
-->{{l-self|kdr|צ}}{{l-self|kdr|ץ}},‏ <!--
-->{{l-self|kdr|ר}},‏ <!--
-->{{l-self|kdr|ש}},‏ <!--
-->{{l-self|kdr|ת}}<!--
--></span>}}
=={{langname|czk}}==
==={{ĐM|pron}}===
*{{IPA|czk|[ʃ]}}
==={{ĐM|letter}}===
{{head|czk|Chữ cái|tr=š}}
#Chữ cái thứ 26 trong bảng chữ cái Hebrew tiếng Knaan.
#:{{ux|czk|קְרַבוֹ'''שְ'''קְא|tr=krabo'''š'''ka|[[mặt nạ]]|inline=1}}
==={{ĐM|number}}===
{{head|czk|Ký tự số|tr=š}}
#Số 300
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Knaan
|list=<span dir="rtl"><!--
-->{{l-self|czk|א}},‏ <!--
-->{{l-self|czk|בּ}}/{{l-self|czk|ב}},‏ <!--
-->{{l-self|czk|גּ}}/{{l-self|czk|ג}},‏ <!--
-->{{l-self|czk|דּ}}/{{l-self|czk|ד}},‏ <!--
-->{{l-self|czk|ה}},‏ <!--
-->{{l-self|czk|ו}},‏ <!--
-->{{l-self|czk|ז}},‏ <!--
-->{{l-self|czk|ח}},‏ <!--
-->{{l-self|czk|ט}},‏ <!--
-->{{l-self|czk|י}},‏ <!--
-->{{l-self|czk|כּ}}/{{l-self|czk|כ}},‏ <!--
-->{{l-self|czk|ךּ}}/{{l-self|czk|ך}},‏ <!--
-->{{l-self|czk|ל}},‏ <!--
-->{{l-self|czk|מ}},‏ <!--
-->{{l-self|czk|ם}},‏ <!--
-->{{l-self|czk|נ}},‏ <!--
-->{{l-self|czk|ן}},‏ <!--
-->{{l-self|czk|ס}},‏ <!--
-->{{l-self|czk|ע}},‏ <!--
-->{{l-self|czk|פּ}}/{{l-self|czk|פ}},‏ <!--
-->{{l-self|czk|ףּ}}/{{l-self|czk|ף}},‏ <!--
-->{{l-self|czk|צ}},‏ <!--
-->{{l-self|czk|ץ}},‏ <!--
-->{{l-self|czk|ק}},‏ <!--
-->{{l-self|czk|ר}},‏ <!--
-->{{l-self|czk|שׁ}}/{{l-self|czk|שׂ}},‏ <!--
-->{{l-self|czk|תּ}}/{{l-self|czk|ת}}‏ <!--
--></span>}}
=={{langname|lad}}==
==={{ĐM|pron}}===
*{{IPA|lad|[ʃ]}}
==={{ĐM|letter}}===
{{head|lad|Chữ cái|tr=sh}}
#Chữ cái thứ 27 trong bảng chữ cái Hebrew tiếng Ladino.
#:{{ux|lad|'''ש'''א'''ש'''יאו|tr='''sh'''a'''sh'''eo|[[sự]] [[choáng váng]]|inline=1}}
==={{ĐM|number}}===
{{head|lad|Ký tự số|tr=sh}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Ladino
|list=<span dir="rtl"><!--
-->{{l-self|lad|א}},‏ <!--
-->{{l-self|lad|ב}},‏ <!--
-->{{l-self|lad|ב׳}},‏ <!--
-->{{l-self|lad|ג}},‏ <!--
-->{{l-self|lad|ג׳}},‏ <!--
-->{{l-self|lad|ד}},‏ <!--
-->{{l-self|lad|ה}},‏ <!--
-->{{l-self|lad|ו}},‏ <!--
-->{{l-self|lad|ז}},‏ <!--
-->{{l-self|lad|ז׳}},‏ <!--
-->{{l-self|lad|ח}},‏ <!--
-->{{l-self|lad|ט}},‏ <!--
-->{{l-self|lad|י}},‏ <!--
-->{{l-self|lad|יי}},‏ <!--
-->{{l-self|lad|כ}} {{l-self|lad|ך}},‏ <!--
-->{{l-self|lad|ל}} {{l-self|lad|מ}},‏ <!--
-->{{l-self|lad|ם}} {{l-self|lad|נ}},‏ <!--
-->{{l-self|lad|ן}},‏ <!--
-->{{l-self|lad|ניי}},‏ <!--
-->{{l-self|lad|ס}},‏ <!--
-->{{l-self|lad|ע}},‏ <!--
-->{{l-self|lad|פ}} {{l-self|lad|ף}},‏ <!--
-->{{l-self|lad|פ׳}} {{l-self|lad|ף׳}},‏ <!--
-->{{l-self|lad|צ}} {{l-self|lad|ץ}},‏ <!--
-->{{l-self|lad|ק}},‏ <!--
-->{{l-self|lad|ר}},‏ <!--
-->{{l-self|lad|ש}},‏ <!--
-->{{l-self|lad|ת}}‏ <!--
--></span>}}
=={{langname|lsd}}==
==={{ĐM|pron}}===
*{{IPA|lsd|[ʃ]}}
==={{ĐM|letter}}===
{{head|lsd|Chữ cái|tr=š}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Lishana Deni.
#:{{ux|lsd|'''ש'''אתא|tr='''š'''eʾṯa|[[thời gian]]|inline=1}}
==={{ĐM|number}}===
{{head|lsd|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Lishana Deni
|list=<span dir="rtl"><!--
-->{{l-self|lsd|א}},‏ <!--
-->{{l-self|lsd|ב}},‏ <!--
-->{{l-self|lsd|ג}},‏ <!--
-->{{l-self|lsd|ד}},‏ <!--
-->{{l-self|lsd|ה}},‏ <!--
-->{{l-self|lsd|ו}},‏ <!--
-->{{l-self|lsd|ז}},‏ <!--
-->{{l-self|lsd|ח}},‏ <!--
-->{{l-self|lsd|ט}},‏ <!--
-->{{l-self|lsd|י}},‏ <!--
-->{{l-self|lsd|כ}}{{l-self|lsd|ך}},‏ <!--
-->{{l-self|lsd|ל}},‏ <!--
-->{{l-self|lsd|מ}}{{l-self|lsd|ם}},‏ <!--
-->{{l-self|lsd|נ}}{{l-self|lsd|ן}},‏ <!--
-->{{l-self|lsd|ס}},‏ <!--
-->{{l-self|lsd|ע}},‏ <!--
-->{{l-self|lsd|פ}}{{l-self|lsd|ף}},‏ <!--
-->{{l-self|lsd|צ}}{{l-self|lsd|ץ}},‏ <!--
-->{{l-self|lsd|ק}},‏ <!--
-->{{l-self|lsd|ר}},‏ <!--
-->{{l-self|lsd|ש}},‏ <!--
-->{{l-self|lsd|ת}}<!--
--></span>}}
=={{langname|aij}}==
==={{ĐM|pron}}===
*{{IPA|aij|[ʃ]}}
==={{ĐM|letter}}===
{{head|aij|Chữ cái|tr=š}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Lishanid Noshan.
#:{{ux|aij|ל'''ש'''נא|tr=li'''šā'''na|[[ngôn ngữ]]|inline=1}}
==={{ĐM|number}}===
{{head|aij|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Lishanid Noshan
|list=<span dir="rtl"><!--
-->{{l-self|aij|א}},‏ <!--
-->{{l-self|aij|ב}},‏ <!--
-->{{l-self|aij|ג}},‏ <!--
-->{{l-self|aij|ד}},‏ <!--
-->{{l-self|aij|ה}},‏ <!--
-->{{l-self|aij|ו}},‏ <!--
-->{{l-self|aij|ז}},‏ <!--
-->{{l-self|aij|ח}},‏ <!--
-->{{l-self|aij|ט}},‏ <!--
-->{{l-self|aij|י}},‏ <!--
-->{{l-self|aij|כ}}{{l-self|aij|ך}},‏ <!--
-->{{l-self|aij|ל}},‏ <!--
-->{{l-self|aij|מ}}{{l-self|aij|ם}},‏ <!--
-->{{l-self|aij|נ}}{{l-self|aij|ן}},‏ <!--
-->{{l-self|aij|ס}},‏ <!--
-->{{l-self|aij|ע}},‏ <!--
-->{{l-self|aij|פ}}{{l-self|aij|ף}},‏ <!--
-->{{l-self|aij|צ}}{{l-self|aij|ץ}},‏ <!--
-->{{l-self|aij|ק}},‏ <!--
-->{{l-self|aij|ר}},‏ <!--
-->{{l-self|aij|ש}},‏ <!--
-->{{l-self|aij|ת}}<!--
--></span>}}
=={{langname|mxi}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Ả Rập
| {{l|mxi|ش}}
|-
! Hebrew
| {{pn}}
|-
! Latinh
| {{l|mxi|X}} {{l|mxi|x}}
|-
|}
==={{ĐM|pron}}===
*{{IPA|mxi|[ʃ]}}
==={{ĐM|letter}}===
{{head|mxi|Chữ cái}}
#Chữ cái thứ 25 trong bảng chữ cái Hebrew tiếng Mozarab.
#:{{ux|mxi|'''ש'''ת|[[đây]]|inline=1}}
==={{ĐM|number}}===
{{head|mxi|Ký tự số}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Mozarab
|list=<span dir="rtl"><!--
-->{{l-self|mxi|א}},‏ <!--
-->{{l-self|mxi|בּ}}/‏ {{l-self|mxi|ב}},‏ <!--
-->{{l-self|mxi|גּ}}/‏ {{l-self|mxi|ג}},‏ <!--
-->{{l-self|mxi|דּ}}/‏ {{l-self|mxi|ד}},‏ <!--
-->{{l-self|mxi|ה}},‏ <!--
-->{{l-self|mxi|ו}},‏ <!--
-->{{l-self|mxi|ז}},‏ <!--
-->{{l-self|mxi|ח}},‏ <!--
-->{{l-self|mxi|ט}},‏ <!--
-->{{l-self|mxi|י}},‏ <!--
-->{{l-self|mxi|כּ}}/‏ {{l-self|mxi|כ}},‏ <!--
-->{{l-self|mxi|ךּ}}/‏ {{l-self|mxi|ך}},‏ <!--
-->{{l-self|mxi|ל}},‏ <!--
-->{{l-self|mxi|מ}},‏ <!--
-->{{l-self|mxi|ם}},‏ <!--
-->{{l-self|mxi|נ}},‏ <!--
-->{{l-self|mxi|ן}},‏ <!--
-->{{l-self|mxi|ס}},‏ <!--
-->{{l-self|mxi|ע}},‏ <!--
-->{{l-self|mxi|פּ}}/‏ {{l-self|mxi|פ}},‏ <!--
-->{{l-self|mxi|ףּ}}/‏ {{l-self|mxi|ף}},‏ <!--
-->{{l-self|mxi|צ}},‏ <!--
-->{{l-self|mxi|ץ}},‏ <!--
-->{{l-self|mxi|ק}},‏ <!--
-->{{l-self|mxi|ר}},‏ <!--
-->{{l-self|mxi|שׁ}}/‏ {{l-self|mxi|שׂ}},‏ <!--
-->{{l-self|mxi|תּ}}/‏ {{l-self|mxi|ת}},‏ <!--
-->{{l-self|mxi|ני}}‏ <!--
--></span>}}
=={{langname|xnt}}==
==={{ĐM|letter}}===
{{head|xnt|Chữ cái|tr=sh}}
#Chữ cái Hebrew ''shin'' được Ezra Stiles dùng ghi lại tiếng Narragansett
#:{{ux|xnt|נ'''שֻ'''ועק|tr=ne'''sh'''uongok|những con [[lươn]]|inline=1}}
==={{ĐM|ref}}===
*{{cite-book|author=[[w:en:Ezra Stiles|Ezra Stiles]]|year=1769|title=[https://findit.library.yale.edu/yipp/catalog/digcoll:1018526 Notes on Narragansett Indian Vocabulary]|publisher=Yale University|id=OID 11413743}}
=={{langname|jdt}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Latinh
| {{l|jdt|Ş}} {{l|jdt|ş}}
|-
! Kirin
| {{l|jdt|Ш}} {{l|jdt|ш}}
|-
! Hebrew
| {{pn}}
|-
|}
==={{ĐM|pron}}===
*{{IPA|jdt|[ʃ]}}
==={{ĐM|letter}}===
{{head|jdt|Chữ cái}}
#Chữ cái thứ 23 trong bảng chữ cái Hebrew tiếng Tat-Do Thái.
#:{{ux|jdt|אִ'''ש'''מאוּ|các [[ngươi]]|inline=1}}
==={{ĐM|number}}===
{{head|jdt|Ký tự số}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Tat-Do Thái
|list=<span dir="rtl"><!--
-->{{l-self|jdt|אַ}},‏ <!--
-->{{l-self|jdt|בּ}},‏ <!--
-->{{l-self|jdt|ב}},‏ <!--
-->{{l-self|jdt|ג}},‏ <!--
-->{{l-self|jdt|ד}},‏ <!--
-->{{l-self|jdt|ה}},‏ <!--
-->{{l-self|jdt|ז}},‏ <!--
-->{{l-self|jdt|'ז}},‏ <!--
-->{{l-self|jdt|ח}},‏ <!--
-->{{l-self|jdt|י}},‏ <!--
-->{{l-self|jdt|כּ}},‏ <!--
-->{{l-self|jdt|כ}},‏ <!--
-->{{l-self|jdt|ל}},‏ <!--
-->{{l-self|jdt|מ}},‏ <!--
-->{{l-self|jdt|נ}},‏ <!--
-->{{l-self|jdt|ס}},‏ <!--
-->{{l-self|jdt|ע}},‏ <!--
-->{{l-self|jdt|פּ}},‏ <!--
-->{{l-self|jdt|פ}},‏ <!--
-->{{l-self|jdt|ג'}}/{{l-self|jdt|צ}},‏ <!--
-->{{l-self|jdt|ק}},‏ <!--
-->{{l-self|jdt|ר}},‏ <!--
-->{{l-self|jdt|ש}},‏ <!--
-->{{l-self|jdt|ת}},‏ <!--
-->[{{l-self|jdt|יָא}}],‏ <!--
-->[{{l-self|jdt|יאוּ}}],‏ <!--
-->[{{l-self|jdt|יוֹ}}],‏ <!--
-->{{l-self|jdt|א}},‏ <!--
-->{{l-self|jdt|אי}},‏ <!--
-->{{l-self|jdt|אִ}},‏ <!--
-->{{l-self|jdt|אָ}},‏ <!--
-->{{l-self|jdt|אוּ}},‏ <!--
-->{{l-self|jdt|או}}‏ <!--
--></span>}}
=={{langname|bjf}}==
==={{ĐM|pron}}===
*{{IPA|bjf|[ʃ]}}
==={{ĐM|letter}}===
{{head|bjf|Chữ cái|tr=š}}
#Chữ cái thứ 32 trong bộ chữ Hebrew tiếng Tân Aram Do Thái Barzani.
==={{ĐM|number}}===
{{head|bjf|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Tân Aram Do Thái Barzani
|list=<span dir="rtl"><!--
-->{{l-self|bjf|א}},‏ <!--
-->{{l-self|bjf|ב}},‏ <!--
-->{{l-self|bjf|בּ}},‏ <!--
-->{{l-self|bjf|ג}},‏ <!--
-->{{l-self|bjf|גּ}},‏ <!--
-->{{l-self|bjf|ד}},‏ <!--
-->{{l-self|bjf|דּ}},‏ <!--
-->{{l-self|bjf|ה}},‏ <!--
-->{{l-self|bjf|ו}},‏ <!--
-->{{l-self|bjf|וַ}},‏ <!--
-->{{l-self|bjf|וֹ}},‏ <!--
-->{{l-self|bjf|וּ}},‏ <!--
-->{{l-self|bjf|ז}},‏ <!--
-->{{l-self|bjf|ח}},‏ <!--
-->{{l-self|bjf|ט}},‏ <!--
-->{{l-self|bjf|י}},‏ <!--
-->{{l-self|bjf|יׅ}},‏ <!--
-->{{l-self|bjf|יַ}},‏ <!--
-->{{l-self|bjf|כ}}\{{l-self|bjf|ך}},‏ <!--
-->{{l-self|bjf|כּ}},‏ <!--
-->{{l-self|bjf|כ֗}},‏ <!--
-->{{l-self|bjf|ל}},‏ <!--
-->{{l-self|bjf|מ}}\{{l-self|bjf|ם}},‏ <!--
-->{{l-self|bjf|נ}}\{{l-self|bjf|ן}},‏ <!--
-->{{l-self|bjf|ס}},‏ <!--
-->{{l-self|bjf|ע}},‏ <!--
-->{{l-self|bjf|פ}}\{{l-self|bjf|ף}},‏ <!--
-->{{l-self|bjf|פ֗}}\{{l-self|bjf|ף֗}},‏ <!--
-->{{l-self|bjf|צ}}\{{l-self|bjf|ץ}},‏ <!--
-->{{l-self|bjf|ק}},‏ <!--
-->{{l-self|bjf|ר}},‏ <!--
-->{{l-self|bjf|ש}},‏ <!--
-->{{l-self|bjf|ש֗}},‏ <!--
-->{{l-self|bjf|ת}},‏ <!--
-->{{l-self|bjf|תּ}}‏ <!--
--></span>}}
=={{langname|ur}}==
{| class="floatright wikitable" style="text-align:center;"
|-
! Ả Rập
| {{l|ur|ش}}
|-
! Hebrew
| {{pn}}
|-
|}
==={{ĐM|pron}}===
*{{urd-IPA|ś}}
==={{ĐM|letter}}===
{{head|ur|Chữ cái|tr=ś}}
# Chữ cái thứ 14 trong bảng chữ cái Hebrew phương ngữ Do Thái-Urdu.
==={{ĐM|number}}===
{{head|ur|Ký tự số|tr=ś}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew phương ngữ Do Thái-Urdu
|list=<span dir="rtl"><!--
-->{{l-self|ur|א}},‏ <!--
-->{{l-self|ur|ב}},‏ <!--
-->{{l-self|ur|ג}},‏ <!--
-->{{l-self|ur|ד}},‏ <!--
-->{{l-self|ur|ה}},‏ <!--
-->{{l-self|ur|ו}},‏ <!--
-->{{l-self|ur|ז}},‏ <!--
-->{{l-self|ur|ח}},‏ <!--
-->{{l-self|ur|ט}},‏ <!--
-->{{l-self|ur|י}},‏ <!--
-->{{l-self|ur|כ}}{{l-self|ur|ך}},‏ <!--
-->{{l-self|ur|ל}},‏ <!--
-->{{l-self|ur|מ}}{{l-self|ur|ם}},‏ <!--
-->{{l-self|ur|נ}}{{l-self|ur|ן}},‏ <!--
-->{{l-self|ur|ס}},‏ <!--
-->{{l-self|ur|ע}},‏ <!--
-->{{l-self|ur|פ}}{{l-self|ur|ף}},‏ <!--
-->{{l-self|ur|צ}}{{l-self|ur|ץ}},‏ <!--
-->{{l-self|ur|ק}},‏ <!--
-->{{l-self|ur|ר}},‏ <!--
-->{{l-self|ur|ש}},‏ <!--
-->{{l-self|ur|ת}}<!--
--></span>}}
=={{langname|itk}}==
==={{ĐM|pron}}===
*{{IPA|itk|[ʃ]}}
==={{ĐM|letter}}===
{{head|itk|Chữ cái|tr=š}}
#Chữ cái thứ 21 trong bảng chữ cái Hebrew tiếng Ý-Do Thái.
#:{{ux|itk|יִי'''שִ'''ירֵי|tr=yi'''š'''ire|[[đi ra]]|inline=1}}
==={{ĐM|number}}===
{{head|itk|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Ý-Do Thái
|list=<span dir="rtl"><!--
-->{{l-self|itk|א}},‏ <!--
-->{{l-self|itk|ב}},‏ <!--
-->{{l-self|itk|ג}},‏ <!--
-->{{l-self|itk|ד}},‏ <!--
-->{{l-self|itk|ה}},‏ <!--
-->{{l-self|itk|ו}},‏ <!--
-->{{l-self|itk|ז}},‏ <!--
-->{{l-self|itk|ח}},‏ <!--
-->{{l-self|itk|ט}},‏ <!--
-->{{l-self|itk|י}},‏ <!--
-->{{l-self|itk|כ}}{{l-self|itk|ך}},‏ <!--
-->{{l-self|itk|ל}},‏ <!--
-->{{l-self|itk|מ}}{{l-self|itk|ם}},‏ <!--
-->{{l-self|itk|נ}}{{l-self|itk|ן}},‏ <!--
-->{{l-self|itk|ס}},‏ <!--
-->{{l-self|itk|ע}},‏ <!--
-->{{l-self|itk|פ}}{{l-self|itk|ף}},‏ <!--
-->{{l-self|itk|צ}}{{l-self|itk|ץ}},‏ <!--
-->{{l-self|itk|ק}},‏ <!--
-->{{l-self|itk|ר}},‏ <!--
-->{{l-self|itk|ש}},‏ <!--
-->{{l-self|itk|ת}}<!--
--></span>}}
=={{langname|yej}}==
==={{ĐM|pron}}===
*{{IPA|yej|[ʃ]|[s]}}
==={{ĐM|letter}}===
{{head|yej|Chữ cái|tr=sh/s}}
#Chữ cái thứ 26 trong bảng chữ cái Hebrew tiếng Yevan.
#:{{ux|yej|[[שין#Tiếng_Yevan|'''שִׁ'''ין]]|tr='''s'''in|[[cùng]], [[với]]|inline=1}}
==={{ĐM|number}}===
{{head|yej|Ký tự số|tr=sh/s}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Hebrew tiếng Yevan
|list=<span dir="rtl"><!--
-->{{l-self|yej|א}},‏ <!--
-->{{l-self|yej|בּ}}/{{l-self|yej|ב}},‏ <!--
-->{{l-self|yej|גּ}}/{{l-self|yej|ג}},‏ <!--
-->{{l-self|yej|דּ}}/{{l-self|yej|ד}},‏ <!--
-->{{l-self|yej|ה}},‏ <!--
-->{{l-self|yej|ו}},‏ <!--
-->{{l-self|yej|ז}},‏ <!--
-->{{l-self|yej|ח}},‏ <!--
-->{{l-self|yej|ט}},‏ <!--
-->{{l-self|yej|י}},‏ <!--
-->{{l-self|yej|כּ}}/{{l-self|yej|כ}},‏ <!--
-->{{l-self|yej|ךּ}}/{{l-self|yej|ך}},‏ <!--
-->{{l-self|yej|ל}},‏ <!--
-->{{l-self|yej|מ}},‏ <!--
-->{{l-self|yej|ם}},‏ <!--
-->{{l-self|yej|נ}},‏ <!--
-->{{l-self|yej|ן}},‏ <!--
-->{{l-self|yej|ס}},‏ <!--
-->{{l-self|yej|ע}},‏ <!--
-->{{l-self|yej|פּ}}/{{l-self|yej|פ}},‏ <!--
-->{{l-self|yej|ףּ}}/{{l-self|yej|ף}},‏ <!--
-->{{l-self|yej|צ}},‏ <!--
-->{{l-self|yej|ץ}},‏ <!--
-->{{l-self|yej|ק}},‏ <!--
-->{{l-self|yej|ר}},‏ <!--
-->{{l-self|yej|שׁ}}/{{l-self|yej|שׂ}},‏ <!--
-->{{l-self|yej|תּ}}/{{l-self|yej|ת}}‏ <!--
--></span>}}
=={{langname|yi}}==
==={{ĐM|pron}}===
*{{IPA|yi|[ʃ]}}
==={{ĐM|letter}}===
{{head|yi|Chữ cái|tr=š}}
# Chữ cái thứ 25 trong bảng chữ cái Hebrew tiếng Yiddish.
#:{{ux|yi|[[שוואַנץ#Tiếng_Yiddish|'''ש'''וואַנץ]]|[[đuôi]]|inline=1}}
==={{ĐM|number}}===
{{head|yi|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Bảng chữ cái Yiddish
|list=<span dir="rtl"><!--
-->[[א#Tiếng_Yiddish|א]] (a),‏ <!--
-->{{l-self|yi|בּ}}/‏ <!--
-->{{l-self|yi|ב}},‏ <!--
-->{{l-self|yi|גּ}}/‏ <!--
-->{{l-self|yi|ג}},‏ <!--
-->{{l-self|yi|דּ}}/‏ <!--
-->{{l-self|yi|ד}},‏ <!--
-->{{l-self|yi|ה}},‏ <!--
-->[[ו#Tiếng_Yiddish|ו]] (v),‏ <!--
-->{{l-self|yi|ז}},‏ <!--
-->[[ח#Tiếng_Yiddish|ח]],‏ <!--
-->{{l-self|yi|ט}},‏ <!--
-->{{l-self|yi|י}},‏ <!--
-->[[כּ#Tiếng_Yiddish|כּ]] (k)/‏ <!--
-->{{l-self|yi|כ}},‏ <!--
-->{{l-self|yi|ךּ}}/‏ <!--
-->{{l-self|yi|ך}},‏ <!--
-->{{l-self|yi|ל}},‏ <!--
-->{{l-self|yi|מ}},‏ <!--
-->{{l-self|yi|ם}},‏ <!--
-->{{l-self|yi|נ}},‏ <!--
-->{{l-self|yi|ן}},‏ <!--
-->{{l-self|yi|ס}},‏ <!--
-->{{l-self|yi|ע}},‏ <!--
-->{{l-self|yi|פּ}}/‏ <!--
-->{{l-self|yi|ף}}/‏ <!--
-->{{l-self|yi|ףּ}}/‏ <!--
-->{{l-self|yi|ף}},‏ <!--
-->{{l-self|yi|צ}},‏ <!--
-->{{l-self|yi|ץ}},‏ <!--
-->{{l-self|yi|ק}},‏ <!--
-->{{l-self|yi|ר}},‏ <!--
-->{{l-self|yi|שׁ}}/‏ <!--
-->[[שׂ#Tiếng_Yiddish|שׂ]] (s),‏ <!--
-->[[תּ#Tiếng_Yiddish|תּ]] (t)/‏ <!--
-->[[ת#Tiếng_Yiddish|ת]] (s)‏ <!--
--></span>}}
==={{ĐM|ref}}===
*{{Chú thích sách|author=Alexander Harkavy|title=Complete English-Jewish Dictionary: With the Pronunciation of Every Word in Hebrew Characters|year=1891|publisher=Hebrew Publishing Company|page=320|pageurl=https://books.google.com/books?id=R2iTU_qR1scC&pg=PA805}}
=={{langname|zrp}}==
==={{ĐM|pron}}===
*{{IPA|zrp|[ʃ]}}
==={{ĐM|letter}}===
{{head|zrp|Chữ cái|tr=š}}
#Chữ cái Hebrew biểu thị phụ âm {{IPAchar|/ʃ/}} trong tiếng Zarphat.
==={{ĐM|number}}===
{{head|zrp|Ký tự số|tr=š}}
#Số 300.
==={{ĐM|see}}===
*{{list helper 2
|title=Chữ Hebrew tiếng Do Thái Zarphat
|list=<span dir="rtl"><!--
-->{{l-self|zrp|א}},‏ <!--
-->{{l-self|zrp|ב}},‏ <!--
-->{{l-self|zrp|ג}},‏ <!--
-->{{l-self|zrp|ד}},‏ <!--
-->{{l-self|zrp|ה}},‏ <!--
-->{{l-self|zrp|ו}},‏ <!--
-->{{l-self|zrp|ז}},‏ <!--
-->{{l-self|zrp|ט}},‏ <!--
-->{{l-self|zrp|י}},‏ <!--
-->{{l-self|zrp|כ}}{{l-self|zrp|ך}},‏ <!--
-->{{l-self|zrp|ל}},‏ <!--
-->{{l-self|zrp|מ}}{{l-self|zrp|ם}},‏ <!--
-->{{l-self|zrp|נ}}{{l-self|zrp|ן}},‏ <!--
-->{{l-self|zrp|ס}},‏ <!--
-->{{l-self|zrp|פ}}{{l-self|zrp|ף}},‏ <!--
-->{{l-self|zrp|צ}}{{l-self|zrp|ץ}},‏ <!--
-->{{l-self|zrp|ק}},‏ <!--
-->{{l-self|zrp|ר}},‏ <!--
-->{{l-self|zrp|ש}},‏ <!--
-->{{l-self|zrp|ת}}<!--
--></span>}}
[[Thể loại:Khối ký tự Hebrew|E9]]
ryy4q10bx2b8lvnqntxmy34oi4nw2vt
落胆
0
422411
2576414
2026-11-08T13:45:59Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|らく|たん|y=o}} ==={{section|pron}}=== {{ja-pron|らくたん|dev=2|acc=0|acc_ref=DJR,NHK16,SMK8}} ==={{section|n}}=== {{ja-noun|らくたん}} # Sự [[thất vọng]]. ==={{section|v}}=== {{ja-verb-suru|tr=intr|らくたん}} # [[thất vọng|Thất vọng]]. #: {{ja-usex|あの選挙結果には'''落胆'''した。|あの せんきょ けっか に は '''らくたん''' した。|Tôi rất thất vọng sau khi nghe kết…”
2576414
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|らく|たん|y=o}}
==={{section|pron}}===
{{ja-pron|らくたん|dev=2|acc=0|acc_ref=DJR,NHK16,SMK8}}
==={{section|n}}===
{{ja-noun|らくたん}}
# Sự [[thất vọng]].
==={{section|v}}===
{{ja-verb-suru|tr=intr|らくたん}}
# [[thất vọng|Thất vọng]].
#: {{ja-usex|あの選挙結果には'''落胆'''した。|あの せんきょ けっか に は '''らくたん''' した。|Tôi rất thất vọng sau khi nghe kết quả cuộc bầu cử này.}}
===={{section|forms}}====
{{ja-suru|らくたん}}
==={{section|ref}}===
{{reflist}}
==={{section|further}}===
* {{R:Kanjipedia Kotoba|0007038900}}
{{C|ja|Buồn}}
lug0sy4ty6jhgk1nw7i8jo4vjw7rjeg
胆
0
422412
2576415
2026-11-08T13:47:36Z
Hiyuune
50834
Trang mới: “{{also|膽}} {{character info}} =={{langname|mul}}== {{stroke order|strokes=9}} {{ja-forms|胆|胆|[[膽]]}} ==={{section|han}}=== {{Han char|rn=130|rad=肉|as=05|sn=9|four=|canj=BAM|ids=⿰[[肉|⺼]][[旦]]}} ===={{section|derived characters}}==== * {{l|mul|[[𫅝]]}} ===={{section|ref}}==== * {{Han ref|kx=0977.120|dkj=29354|dj=1429.030|hdz=32059.040|uh=80C6}} =={{langname|zh}}== ==={{section|glyph origin}}=== {{Han etym}} {{Han compound|肉|alt1=⺼|旦|ls=psc|c1=…”
2576415
wikitext
text/x-wiki
{{also|膽}}
{{character info}}
=={{langname|mul}}==
{{stroke order|strokes=9}}
{{ja-forms|胆|胆|[[膽]]}}
==={{section|han}}===
{{Han char|rn=130|rad=肉|as=05|sn=9|four=|canj=BAM|ids=⿰[[肉|⺼]][[旦]]}}
===={{section|derived characters}}====
* {{l|mul|[[𫅝]]}}
===={{section|ref}}====
* {{Han ref|kx=0977.120|dkj=29354|dj=1429.030|hdz=32059.040|uh=80C6}}
=={{langname|zh}}==
==={{section|glyph origin}}===
{{Han etym}}
{{Han compound|肉|alt1=⺼|旦|ls=psc|c1=s|c2=p|t1=bộ phận cơ thể}}.
==={{section|dfn}}===
{{zh-see|膽|sv}}
5eqvlqeqg00896g7l1jflro4b678jyn
皽
0
422413
2576416
2026-11-08T13:50:29Z
Hiyuune
50834
Trang mới: “{{character info}} =={{langname|mul}}== ==={{ĐM|han}}=== {{Han char|rn=107|rad=皮|as=13|sn=18|four=04147|canj=YMDHE|ids=⿰亶皮}} # [[gàu]], [[vảy]] [[mốc]]. ===={{ĐM|ref}}==== * {{Han ref|kx=0792.170|dkj=22921|hdz=42759.010|uh=76BD}} =={{langname|ja}}== ==={{ĐM|kanji}}=== {{ja-kanji|grade=|rs=皮13}} # {{rfdef|ja|sort=皮13}} ===={{ĐM|reading}}==== * {{ja-readings|on=てん, せん, しゅう, たん|kun=かわ}} =={{langname|zh}}== {{zh-forms|alt=…”
2576416
wikitext
text/x-wiki
{{character info}}
=={{langname|mul}}==
==={{ĐM|han}}===
{{Han char|rn=107|rad=皮|as=13|sn=18|four=04147|canj=YMDHE|ids=⿰亶皮}}
# [[gàu]], [[vảy]] [[mốc]].
===={{ĐM|ref}}====
* {{Han ref|kx=0792.170|dkj=22921|hdz=42759.010|uh=76BD}}
=={{langname|ja}}==
==={{ĐM|kanji}}===
{{ja-kanji|grade=|rs=皮13}}
# {{rfdef|ja|sort=皮13}}
===={{ĐM|reading}}====
* {{ja-readings|on=てん, せん, しゅう, たん|kun=かわ}}
=={{langname|zh}}==
{{zh-forms|alt=𤿘}}
==={{ĐM|glyph origin}}===
{{Han etym}}
==={{ĐM|pron}}===
{{zh-pron
|m=zhāo,zhǎn,dǎn
|c=zin2
|mc=y
|oc=y
|cat=n
}}
==={{ĐM|dfn}}===
{{head|zh|hanzi}}
# [[tế bào]] [[da]] [[chết]].
lqh53ugu9rshmpss8t7eld1srlgqhbk
Mô đun:zh/data/och-pron-ZS/皽
828
422414
2576417
2026-11-08T13:51:07Z
Hiyuune
50834
Trang mới: “return { { "2042", "旦", "宵", "1", "昭", "tjaʀ", "見禮記" }, { "2079", "旦", "元", "1", "展", "tanʔ", "" }, { "2089", "旦", "元", "1", "𦗢", "tjanʔ", "" }, }”
2576417
Scribunto
text/plain
return {
{ "2042", "旦", "宵", "1", "昭", "tjaʀ", "見禮記" },
{ "2079", "旦", "元", "1", "展", "tanʔ", "" },
{ "2089", "旦", "元", "1", "𦗢", "tjanʔ", "" },
}
q7ok0rv9g5xp38me5ipbonb9ozr9l2g
2576419
2576417
2026-11-08T13:52:47Z
Hiyuune
50834
Hiyuune đã đổi [[Mô đun:zh/data/och-pron-BS/皽]] thành [[Mô đun:zh/data/och-pron-ZS/皽]]
2576417
Scribunto
text/plain
return {
{ "2042", "旦", "宵", "1", "昭", "tjaʀ", "見禮記" },
{ "2079", "旦", "元", "1", "展", "tanʔ", "" },
{ "2089", "旦", "元", "1", "𦗢", "tjanʔ", "" },
}
q7ok0rv9g5xp38me5ipbonb9ozr9l2g
Mô đun:zh/data/och-pron-BS/担
828
422415
2576418
2026-11-08T13:52:13Z
Hiyuune
50834
Trang mới: “return { { "2043", "旦", "元", "1", "亶", "taːnʔ", "今作撣。玉篇字林“拂也”" }, }”
2576418
Scribunto
text/plain
return {
{ "2043", "旦", "元", "1", "亶", "taːnʔ", "今作撣。玉篇字林“拂也”" },
}
qix1uo5d2nexnmyqa8mkhb5v3ktu5v0
Mô đun:zh/data/och-pron-BS/皽
828
422416
2576420
2026-11-08T13:52:47Z
Hiyuune
50834
Hiyuune đã đổi [[Mô đun:zh/data/och-pron-BS/皽]] thành [[Mô đun:zh/data/och-pron-ZS/皽]]
2576420
Scribunto
text/plain
return require [[Mô đun:zh/data/och-pron-ZS/皽]]
2dv7o39lzqnc63jio14vlmbzns703r4
𰤬
0
422417
2576421
2026-11-08T13:54:36Z
Hiyuune
50834
Trang mới: “{{character info}} =={{langname|mul}}== ==={{ĐM|han}}=== {{Han char|rn=107|rad=皮|as=8|sn=13|four=|canj=|ids=⿰卖皮}} ===={{ĐM|ref}}==== {{Han ref|uh=3092C}} =={{langname|zh}}== {{zh-see|皾}}”
2576421
wikitext
text/x-wiki
{{character info}}
=={{langname|mul}}==
==={{ĐM|han}}===
{{Han char|rn=107|rad=皮|as=8|sn=13|four=|canj=|ids=⿰卖皮}}
===={{ĐM|ref}}====
{{Han ref|uh=3092C}}
=={{langname|zh}}==
{{zh-see|皾}}
i45hrnqxvjee9hcvc45ddzbnlh4foys
Chaudhrys
0
422418
2576422
2026-11-08T13:55:12Z
Hiyuune
50834
+ en
2576422
wikitext
text/x-wiki
=={{langname|en}}==
==={{ĐM|pr-noun}}===
{{head|en|Biến thể hình thái danh từ riêng}}
# {{plural of|en|Chaudhry}}
l0ldzsv958g258u31pqrokb17vulkfz
Chaudhry
0
422419
2576423
2026-11-08T13:57:41Z
Hiyuune
50834
Trang mới: “=={{langname|en}}== ==={{section|pr-noun}}=== {{en-proper noun|s}} # {{surname|en}} ===={{section|statistics}}==== * Theo kết quả của cuộc thống kê dân số Hoa Kỳ năm 2010, {{pagename}} là họ đứng hạng 5697 về độ phổ biến tại quốc gia này. Có 6084 người mang họ, trong đó chiếm phần lớn là người châu Á/Thái Bình Dương (95,18%).”
2576423
wikitext
text/x-wiki
=={{langname|en}}==
==={{section|pr-noun}}===
{{en-proper noun|s}}
# {{surname|en}}
===={{section|statistics}}====
* Theo kết quả của cuộc thống kê dân số Hoa Kỳ năm 2010, {{pagename}} là họ đứng hạng 5697 về độ phổ biến tại quốc gia này. Có 6084 người mang họ, trong đó chiếm phần lớn là người châu Á/Thái Bình Dương (95,18%).
5l6sw75l7t5lh22awkyidthd5pv00j6
2576424
2576423
2026-11-08T13:57:56Z
Hiyuune
50834
/* Thống kê */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2576424
wikitext
text/x-wiki
=={{langname|en}}==
==={{section|pr-noun}}===
{{en-proper noun|s}}
# {{surname|en}}
===={{section|statistics}}====
* Theo kết quả của cuộc thống kê dân số Hoa Kỳ năm 2010, {{pagename}} là họ đứng hạng 5697 về độ phổ biến tại quốc gia này. Có 6084 người mang họ, trong đó chiếm phần lớn là người châu Á/Thái Bình Dương (90,57%).
63tq9o43epm8gyqyn1l9uwav7mj6qfu
Thể loại:Tính từ tiếng Tarifit
14
422420
2576426
2026-11-08T14:01:28Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576426
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
tuatahi
0
422421
2576429
2026-11-08T14:09:13Z
Hiyuune
50834
Trang mới: “=={{langname|mi}}== {{numberbox|mi}} ==={{ĐM|etym}}=== Từ {{prefix|mi|tua-|tahi}}. ==={{ĐM|num}}=== {{mi-num}} # [[đầu tiên]], [[thứ]] [[nhất]]. ==={{ĐM|ref}}=== * {{R:mi:Te Aka 3}}”
2576429
wikitext
text/x-wiki
=={{langname|mi}}==
{{numberbox|mi}}
==={{ĐM|etym}}===
Từ {{prefix|mi|tua-|tahi}}.
==={{ĐM|num}}===
{{mi-num}}
# [[đầu tiên]], [[thứ]] [[nhất]].
==={{ĐM|ref}}===
* {{R:mi:Te Aka 3}}
nuynviqh5iaav1xfmx5tkhyul8he9hl
Thể loại:Số tiếng Maori
14
422422
2576435
2026-11-08T14:17:06Z
Hiyuune
50834
Hiyuune đã đổi [[Thể loại:Số tiếng Maori]] thành [[Thể loại:Số từ tiếng Maori]]
2576435
wikitext
text/x-wiki
{{Đổi hướng thể loại|Thể loại:Số từ tiếng Maori}}
m1ug17aqynosmh09vj4o4ibu3d0dcxn
2576436
2576435
2026-11-08T14:17:40Z
Hiyuune
50834
2576436
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Chức năng ngữ nghĩa tiếng Maori
14
422423
2576437
2026-11-08T14:17:57Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576437
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Số đếm tiếng Maori
14
422424
2576438
2026-11-08T14:18:29Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576438
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Số từ tiếng Anuta
14
422425
2576445
2026-11-08T14:30:29Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576445
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Mục từ tiếng Anuta
14
422426
2576446
2026-11-08T14:30:51Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576446
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:Tiếng Anuta
14
422427
2576447
2026-11-08T14:31:49Z
Hiyuune
50834
Trang mới: “{{auto cat|Quần đảo Solomon}}”
2576447
wikitext
text/x-wiki
{{auto cat|Quần đảo Solomon}}
2x7zwfe9az57p5nrl8jgbvd1bpgxe9s
Bản mẫu:bbl-decl-noun-1a
10
422428
2576449
2026-11-08T14:48:16Z
Hiyuune
50834
Trang mới: “{{bbl-decl-noun-table<!-- -->|title={{{title|Biến cách của {{pagename}} <small>(loại 1/{{m|bbl|ლავ}}, không luân phiên nguyên âm)</small>}}}<!-- -->|{{{1<noinclude>|-</noinclude>}}}<!-- -->|{{{1<noinclude>|-</noinclude>}}}ეჼ<!-- -->|{{{1<noinclude>|-</noinclude>}}}ევ<!-- -->|{{{1<noinclude>|-</noinclude>}}}ენ<!-- -->|{{#if:{{{unc|}}}|—|{{{1<noinclude>|-</noinclude>}}}ი}}<!-- -->|{{#if:{{{unc|}}}|—|{{{1<noinclude>|-</noinclude>…”
2576449
wikitext
text/x-wiki
{{bbl-decl-noun-table<!--
-->|title={{{title|Biến cách của {{pagename}} <small>(loại 1/{{m|bbl|ლავ}}, không luân phiên nguyên âm)</small>}}}<!--
-->|{{{1<noinclude>|-</noinclude>}}}<!--
-->|{{{1<noinclude>|-</noinclude>}}}ეჼ<!--
-->|{{{1<noinclude>|-</noinclude>}}}ევ<!--
-->|{{{1<noinclude>|-</noinclude>}}}ენ<!--
-->|{{#if:{{{unc|}}}|—|{{{1<noinclude>|-</noinclude>}}}ი}}<!--
-->|{{#if:{{{unc|}}}|—|{{{1<noinclude>|-</noinclude>}}}აჼ}}<!--
-->|{{#if:{{{unc|}}}|—|{{{1<noinclude>|-</noinclude>}}}ივ}}<!--
-->|{{#if:{{{unc|}}}|—|{{{1<noinclude>|-</noinclude>}}}ინ}}<!--
-->}}<!--
--><noinclude><!--
-->{{tcat|ndecl}}<!--
--></noinclude><!--
--><noinclude><!--
-->{{catlangname|bbl|Danh tính loại ლავ|sort={{{sort|}}}}}<!--
--></noinclude><!--
--><noinclude><!--
-->{{documentation}}<!--
--></noinclude><!--
7t9xmqi37ysdh3z7s7r60jer7mppnho
Mô đun:dialect synonyms/ain/タㇷ゚カㇻ
828
422429
2576450
2026-11-08T14:53:19Z
Hiyuune
50834
Trang mới: “local export = {} export.gloss = "nhảy múa, khiêu vũ" export.syns = { -- Hokkaido: Southern/Central ["Abuta"] = { "" }, ["Azuma"] = { "" }, ["Biratori"] = { "" }, ["Chitose"] = { "" }, ["Ebeotsu"] = { "" }, ["Hagino"] = { "" }, ["Hidaka"] = { "" }, ["Hobetsu"] = { "" }, ["Horobetsu"] = { "" }, ["Horoman"] = { "" }, ["Mitsuishi"] = { "" }, ["Mukawa"] = { "" }, ["Muroran"] = { "" }, ["Niikappu"] = { "" }, ["Nukkibetsu"] = { "" }, ["Ogifushi"] = { ""…”
2576450
Scribunto
text/plain
local export = {}
export.gloss = "nhảy múa, khiêu vũ"
export.syns = {
-- Hokkaido: Southern/Central
["Abuta"] = { "" },
["Azuma"] = { "" },
["Biratori"] = { "" },
["Chitose"] = { "" },
["Ebeotsu"] = { "" },
["Hagino"] = { "" },
["Hidaka"] = { "" },
["Hobetsu"] = { "" },
["Horobetsu"] = { "" },
["Horoman"] = { "" },
["Mitsuishi"] = { "" },
["Mukawa"] = { "" },
["Muroran"] = { "" },
["Niikappu"] = { "" },
["Nukkibetsu"] = { "" },
["Ogifushi"] = { "" },
["Oshamambe"] = { "" },
["Rebun"] = { "" },
["Samani"] = { "" },
["Saru"] = { "ホリㇷ゚パ:horíppa((H))" },
["Shiraoi"] = { "" },
["Shizunai"] = { "" },
["Takae"] = { "" },
["Takashima"] = { "" },
["Toyoura"] = { "" },
["Urakawa"] = { "" },
["Usu"] = { "" },
["Yakumo"] = { "タㇷ゚カㇻ:tápkar", "リㇺセ:rímse", "オントリ:'óntori (日本式の)((H))" },
-- Hokkaido: Northern
["Asahikawa"] = { "タㇷ゚カㇻ:tápkar", "ウポポ:'upópo((H))" },
["Chikabumi"] = { "" },
["Nayoro"] = { "" },
["Soya"] = { "" },
["Teshio"] = { "" },
-- Hokkaido: Eastern
["Abashiri"] = { "" },
["Akan"] = { "" },
["Ashoro"] = { "" },
["Bihoro"] = { "タㇷ゚カㇻ:tapkar", "ウポポ:'upopo((H))" },
["Biroo"] = { "" },
["Chirotto"] = { "" },
["Fupushinai"] = { "" },
["Fushiko"] = { "" },
["Harutori"] = { "" },
["Kitami"] = { "" },
["Kushiro"] = { "リㇺセ:rimse《踊る》", "ルㇺセ:rumse《踊る》((K2021))" },
["Kussharo"] = { "" },
["Memuro"] = { "" },
["Mokoto"] = { "" },
["Nemuro"] = { "" },
["Nijibetsu"] = { "" },
["Obihiro"] = { "リㇺセ:rímse", "ウポポ:'upópo((H))" },
["Otofuke"] = { "" },
["Shari"] = { "" },
["Shiranuka"] = { "" },
["Tokachi"] = { "" },
["Tooro"] = { "" },
-- Sakhalin: West Coast
["Chirai"] = { "" },
["Maoka"] = { "" },
["Raichishka"] = { "イコアㇱ:iko'as, -ihi", "タㇵカラ:tahkara (老人達が酒とともに踊る踊り)((H))" },
["Shiranushi"] = { "" },
["Tarantomari"] = { "" },
["Usoro"] = { "" },
-- Sakhalin: East Coast
["Aihama"] = { "" },
["Nairo"] = { "" },
["Niitoi"] = { "" },
["Ochiho"] = { "" },
["Shirahama"] = { "" },
["Shiraura"] = { "" },
["Taraika"] = { "" },
["Tonnai"] = { "" },
["Yamambetsu"] = { "" },
-- Kuril: Northern
["Kuril"] = { "" },
["Paramushir"] = { "" },
["Shumshu"] = { "クンリㇺセ:kun rimse《踊る》((BS))" },
-- Kuril: Southern
["Etorofu"] = { "" },
["South Kuril"] = { "" },
}
return export
cn0ndosc089uw3vzf10rpq4fvlz9f7i
nationalisering
0
422430
2576453
2026-11-08T17:31:06Z
Hiyuune
50834
/* */ + nl
2576453
wikitext
text/x-wiki
=={{langname|nl}}==
==={{section|etym}}===
Từ {{af|nl|nationaliseren|-ing}}.
==={{section|pron}}===
* {{IPA|nl|/naː.(t)ʃoː.naː.liˈzeː.rɪŋ/}}
* {{audio|nl|Nl-nationalisering.ogg}}
* {{hyph|nl|na|ti|o|na|li|se|ring}}
* {{rhymes|nl|eːrɪŋ|s=6}}
==={{section|n}}===
{{nl-noun|f|-en|-}}
# {{syn of|nl|nationalisatie}}
mwgl0or37zory3ypt2ltjs4mvx5c0sy
リㇺセ
0
422431
2576454
2026-11-09T01:22:35Z
Hiyuune
50834
Trang mới: “=={{langname|ain}}== ==={{section|v}}=== {{head|ain|động từ|tr=rimse}} # {{lb|ain|Hokkaido}} [[nhảy]] [[múa]]. ===={{section|syn}}==== {{dial syn|ain|タㇷ゚カㇻ}} ==={{section|ref}}=== :* {{R:ain:IshikariWordlist}}”
2576454
wikitext
text/x-wiki
=={{langname|ain}}==
==={{section|v}}===
{{head|ain|động từ|tr=rimse}}
# {{lb|ain|Hokkaido}} [[nhảy]] [[múa]].
===={{section|syn}}====
{{dial syn|ain|タㇷ゚カㇻ}}
==={{section|ref}}===
:* {{R:ain:IshikariWordlist}}
p8qdt0qwtxhg7a86n4rgnmrz8oiesnd
タㇵカラ
0
422432
2576455
2026-11-09T01:23:35Z
Hiyuune
50834
Trang mới: “=={{langname|ain}}== ==={{section|n}}=== {{head|ain|danh từ|tr=tahkara}} # {{lb|ain|Sakhalin}} [[nhảy múa]], [[khiêu vũ]]. ===={{section|syn}}==== {{dial syn|ain|タㇷ゚カㇻ}} ==={{section|ref}}=== :* {{R:ain:KarafutoWordlist}}”
2576455
wikitext
text/x-wiki
=={{langname|ain}}==
==={{section|n}}===
{{head|ain|danh từ|tr=tahkara}}
# {{lb|ain|Sakhalin}} [[nhảy múa]], [[khiêu vũ]].
===={{section|syn}}====
{{dial syn|ain|タㇷ゚カㇻ}}
==={{section|ref}}===
:* {{R:ain:KarafutoWordlist}}
4dhjske596km56podfu9yg17qq9rfrq
Bản mẫu:dialect map/ain/タㇷ゚カㇻ
10
422433
2576456
2026-11-09T01:25:02Z
Hiyuune
50834
Trang mới: “{{dialect map}}”
2576456
wikitext
text/x-wiki
{{dialect map}}
d6v0nb58x909aihj701mhww3omkirht
Mô đun:lt-noun
828
422434
2576457
2026-11-09T01:33:16Z
Hiyuune
50834
Trang mới: “--[=[ Authorship: <TongcyDai> Lithuanian noun declension module ({{lt-ndecl}}). Unicode handling, including the partial NFD stem representation, comes from Module:lt-common. Declension classes are keyed by the twelve-paradigm classification ("par1_as" ... "par12_er"); "AP 1-4" always refers to the accentuation paradigms. Ambiguous lemma endings are resolved by the position-3 genitive-singular keyword ("io", "ies", "ers"); word-level irregulars (šuõ, mė́nuo, žmogù…”
2576457
Scribunto
text/plain
--[=[
Authorship: <TongcyDai>
Lithuanian noun declension module ({{lt-ndecl}}). Unicode handling, including
the partial NFD stem representation, comes from Module:lt-common.
Declension classes are keyed by the twelve-paradigm classification
("par1_as" ... "par12_er"); "AP 1-4" always refers to the accentuation
paradigms. Ambiguous lemma endings are resolved by the position-3
genitive-singular keyword ("io", "ies", "ers"); word-level irregulars
(šuõ, mė́nuo, žmogùs, petỹs ...) use slot overrides, not extra paradigms.
]=]
local export = {}
local m_string_utilities = require("Module:string utilities")
local m_links = require("Module:links")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local m_para = require("Module:parameters")
local lang = require("Module:languages").getByCode("lt")
local m_common = require("Module:lt-common")
-- Forward declaration: merges the results of (( )) alternants and of the
-- passes for colon-separated lemma/AP variants.
local merge_alternant_results
-- Use optimized string utilities (automatically uses string library when possible)
local rfind = m_string_utilities.find
local rsub = m_string_utilities.gsub
local rmatch = m_string_utilities.match
local rsplit = mw.text.split
-- String utility aliases
local uchar = m_string_utilities.char
local trim = m_string_utilities.trim
local lcfirst = m_string_utilities.lcfirst
local ucfirst = m_string_utilities.ucfirst
-- Import Unicode processing functions from lt-common
local process_input = m_common.process_input
local to_stem_ac = m_common.to_stem_ac
local to_stem_bare = m_common.to_stem_bare
local makeDisplayText = m_common.makeDisplayText
local has_accent = m_common.has_accent
-- Accent mark constants (combining characters) from lt-common
local GRAVE = m_common.GRAVE -- U+0300
local ACUTE = m_common.ACUTE -- U+0301
local TILDE = m_common.TILDE -- U+0303
-- =============================================================================
-- Multiword phrase parsing
-- =============================================================================
-- Parse wikilink [[target|text]] or [[text]] or plain text
-- Returns: link_target (or nil), display_text
local function parse_wikilink(text)
local link_target, display_text = rmatch(text, "^%[%[([^|%]]+)|([^%]]+)%]%]$")
if link_target then
return link_target, display_text
end
local simple_link = rmatch(text, "^%[%[([^%]]+)%]%]$")
if simple_link then
return simple_link, simple_link
end
return nil, text
end
-- Parse a single word component from multiword input
-- Format: word_text<type,params> or just word_text (invariant)
-- word_text can be: [[target|text]], [[text]], or plain text
-- Returns: {type, given_form, lemma, link_target, ap, control_tags}
-- given_form is converted to display notation (dot above i or j before an
-- accent), the notation of the generated forms, so either spelling is
-- recognized; the lemma and the link target are kept as written.
local function parse_word_component(word_str, unescape_func)
-- Check if there's a <...> control block
local word_text, control_block = rmatch(word_str, "^(.-)(<[^>]+>)$")
if not control_block then
-- No control block → invariant word
local link_target, display_text = parse_wikilink(word_str)
return {
type = "inv",
given_form = makeDisplayText(display_text),
lemma = nil,
link_target = link_target,
ap = nil,
control_tags = {},
genitive_and_tags = nil,
}
end
-- Extract control block content: <type,params>
local control_content = rmatch(control_block, "^<(.+)>$")
if not control_content then
error("lt-ndecl: malformed control block '" .. control_block .. "'")
end
-- Split by comma: type,ap[.tag1][.tag2][...][,genitive[.tag1][.tag2][...]]
local control_parts = rsplit(control_content, ",")
local word_type = trim(control_parts[1])
if word_type ~= "n" and word_type ~= "a" and word_type ~= "num" then
error("lt-ndecl: word type must be 'n' (noun), 'a' (adjective) or 'num' (numeral), got '" .. word_type .. "'")
end
-- Numeral component (<num>): no AP, genitive or other control parts.
-- Module:lt-numeral declines it to agree with the head noun (see
-- decline_multiword_pattern).
if word_type == "num" then
if control_parts[2] then
error("lt-ndecl: the <num> component takes no accent paradigm or tags " ..
"(the numeral is looked up automatically); got '" .. control_block .. "'")
end
local link_target, display_text = parse_wikilink(word_text)
return {
type = "num",
given_form = makeDisplayText(display_text),
lemma = link_target or display_text,
link_target = link_target,
ap = nil,
control_tags = {},
genitive_and_tags = nil,
}
end
-- Parse AP and control tags from position 2
local ap_and_tags = trim(control_parts[2] or "")
if ap_and_tags == "" then
error("lt-ndecl: missing accent paradigm in '" .. control_block .. "'")
end
local ap_parts = rsplit(ap_and_tags, "%.")
local ap = tonumber(ap_parts[1])
if not ap or ap < 1 or ap > 4 then
error("lt-ndecl: accent paradigm must be 1-4, got '" .. tostring(ap_parts[1]) .. "'")
end
-- Collect control tags from position 2 (after AP)
local control_tags = {}
for i = 2, #ap_parts do
local tag = trim(ap_parts[i])
if tag ~= "" then
table.insert(control_tags, unescape_func(tag))
end
end
-- Parse optional genitive (position 3) for Decl V nouns
local genitive_and_tags = nil
if control_parts[3] then
genitive_and_tags = trim(control_parts[3])
-- genitive_and_tags will be appended to pattern as third comma-separated part
end
-- Parse wikilink from word_text
local link_target, display_text = parse_wikilink(word_text)
-- Determine lemma:
-- - If there's a link [[lemma|given_form]], lemma is the link target
-- - Otherwise, lemma = given_form (they are the same)
local lemma = link_target or display_text
return {
type = word_type,
given_form = makeDisplayText(display_text),
lemma = lemma,
link_target = link_target,
ap = ap,
control_tags = control_tags,
genitive_and_tags = genitive_and_tags, -- May be nil for non-Decl V nouns
}
end
-- Parse multiword input and determine mode (single vs multi)
-- Returns: {mode, words} where words is an array of parsed components
local function parse_multiword(input_str, unescape_func)
-- Only a space outside [...] footnotes makes a multiword phrase
-- ("nãmas,3[used mainly in Aukštaitija]" is one word).
local dispatch_segs = put.parse_balanced_segment_run(input_str, "[", "]")
local has_space_outside_brackets = false
for i = 1, #dispatch_segs, 2 do -- odd indices: text outside [...]
if rfind(dispatch_segs[i], " ") then
has_space_outside_brackets = true
break
end
end
if not has_space_outside_brackets then
return {mode = "single", raw_input = input_str}
end
-- Multiword mode: split by spaces and parse each component
local word_strings = rsplit(input_str, " +")
local words = {}
for _, word_str in ipairs(word_strings) do
word_str = trim(word_str)
if word_str ~= "" then
table.insert(words, parse_word_component(word_str, unescape_func))
end
end
if #words == 0 then
error("lt-ndecl: multiword input is empty after parsing")
end
return {mode = "multi", words = words}
end
-- Analyze adjective form and extract grammatical features
-- Uses Module:lt-adjective's get_nominative_mapping function
-- Returns: {definiteness, degree, gender, number}
local function analyze_adjective(word_info)
local m_lt_adj = require("Module:lt-adjective")
-- Build stem parameter from control tags
local stem_param = nil
for _, tag in ipairs(word_info.control_tags) do
if rfind(tag, "^stem:") then
local _, stem_ac = process_input(rsub(tag, "^stem:", ""))
stem_param = stem_ac
break
end
end
-- Get nominative mapping
local success, mapping = pcall(m_lt_adj.get_nominative_mapping,
word_info.lemma, word_info.ap, stem_param)
if not success then
error("lt-ndecl: failed to analyze adjective '" .. word_info.lemma ..
"': " .. tostring(mapping))
end
-- Look up the given form
local features = mapping[word_info.given_form]
-- If not found, try with lowercase first letter (for proper nouns like "Aukščiausioji")
if not features then
local lowercase_form = lcfirst(word_info.given_form)
features = mapping[lowercase_form]
end
if not features then
error("lt-ndecl: given form '" .. word_info.given_form ..
"' is not a valid nominative form of '" .. word_info.lemma .. "," ..
word_info.ap .. "'. Please check that the link target [[" ..
word_info.lemma .. "]] is the correct base form (indefinite positive " ..
"masculine nominative singular).")
end
return features
end
-- =============================================================================
-- Localization strings (for easy translation)
-- =============================================================================
local localization = {
langname = "tiếng Litva", -- l10n: language name; prefixed to every category
declension = {
[1] = "I",
[2] = "II",
[3] = "III",
[4] = "IV",
[5] = "V",
},
-- Full descriptive strings
full_gender = {
m = "giống đực",
f = "giống cái",
mfbysense = "giống đực hoặc giống cái theo nghĩa", -- l10n
},
full_declension = {
I = "biến cách loại I",
II = "biến cách loại II",
III = "biến cách loại III",
IV = "biến cách loại IV",
V = "biến cách loại V",
},
accent_paradigm = "trọng âm mẫu hình",
-- Category names (without the language prefix). Every category this
-- module emits is built from the strings below; see compute_categories.
categories = {
-- l10n: declension-class categories, keyed by paradigm ending key
class = {
par1_as = "danh từ giống đực -as",
par2_ias = "danh từ giống đực -ias/-jas",
par2_jas = "danh từ giống đực -ias/-jas",
par3_is = "danh từ giống đực -is/-ys với số nhiều -iai",
par3_ys = "danh từ giống đực -is/-ys với số nhiều -iai",
par3_jys = "danh từ giống đực -is/-ys với số nhiều -iai",
par3_jis = "danh từ giống đực -is/-ys với số nhiều -iai",
par4_us = "danh từ giống đực -us",
par5_ius = "danh từ giống đực -ius/-jus",
par5_jus = "danh từ giống đực -ius/-jus",
par6_a = "danh từ giống cái -a",
par7_ia = "danh từ giống cái -ia/-i",
par7_i = "danh từ giống cái -ia/-i",
par8_e = "danh từ giống cái -ė",
par9_is = "danh từ giống cái -is",
par10_is = "danh từ giống đực -is với số nhiều -ys",
par11_uo = "danh từ giống đực -uo",
par12_er = "danh từ giống cái -uo/-ė",
},
ap = "danh từ với trọng âm mẫu hình %d", -- l10n
class_ap = "%s với trọng âm mẫu hình %d", -- l10n: class name + AP
-- l10n: i-declension consonant-stem relic genitive plural (dantų̃ type)
relic_genpl = {
par9_is = "danh từ giống cái -is vơi sinh cách số nhiều -ų",
par10_is = "danh từ giống đực -is vơi sinh cách số nhiều -ų",
},
indeclinable = "danh từ không biến cách", -- l10n
irregular = "danh từ bất quy tắc", -- l10n
multiple_ap = "danh từ với nhiều trọng âm mẫu hình", -- l10n
multiple_decl = "danh từ với nhiều biến cách", -- l10n
gender_mismatch = "danh từ với giống thực tế khác với giống biến tố", -- l10n
pluralia_tantum = "danh từ chỉ có số nhiều", -- l10n
singularia_tantum = "danh từ chỉ có số ít", -- l10n
-- l10n: secondary local cases (generated only on explicit request)
case_form = {
ill = "danh từ dạng nhập cách",
all = "danh từ dạng đích cách",
ade = "danh từ dạng cách kế cận",
},
},
}
-- =============================================================================
-- Accent helpers (partial NFD architecture)
-- =============================================================================
local nfd = to_stem_ac
local nfc = mw.ustring.toNFC
local strip_ac = to_stem_bare
local has_ac = has_accent
-- Is this codepoint an accent mark? (In partial NFD, only accents are combining)
local function is_accent(cp)
local c = uchar(cp)
return c == GRAVE or c == ACUTE or c == TILDE
end
-- =============================================================================
-- Palatalization helpers (d → dž, t → č before softening i)
-- Lithuanian d and t become dž and č before the softening marker i, i.e. when
-- i is followed by a back vowel (a, o, u and their ogonek/macron variants).
-- This does NOT apply when i is the vowel itself (-is, -ies, -imi, -į, etc.).
-- =============================================================================
-- Check whether an ending (partial NFD string) starts with i as a softening
-- marker, i.e. "i" followed by a back vowel (a, o, u, or their ogonek/macron variants).
-- In partial NFD, ogonek and macron vowels are precomposed single characters.
local function should_palatalize(ending)
return rfind(ending, "^i[aąouųū]") ~= nil
end
-- Apply d→dž / t→č to the final base character of a partial NFD stem string.
local function palatalize_stem(stem_nfd)
local uchar = m_string_utilities.char
local ucp = m_string_utilities.codepoint
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
local len = ulen(stem_nfd)
if len == 0 then return stem_nfd end
-- Find the last base character position
local last_base_pos = len
while last_base_pos > 0 do
if not is_accent(ucp(stem_nfd, last_base_pos)) then break end
last_base_pos = last_base_pos - 1
end
if last_base_pos == 0 then return stem_nfd end
local last_char = uchar(ucp(stem_nfd, last_base_pos))
local prefix = (last_base_pos > 1) and usub(stem_nfd, 1, last_base_pos - 1) or ""
-- Any trailing combiners after the base character (unusual for d/t, but safe)
local trailing = (last_base_pos < len) and usub(stem_nfd, last_base_pos + 1) or ""
if last_char == "d" then
-- dž in partial NFD: d + ž (where ž = U+017E precomposed)
return prefix .. "dž" .. trailing
elseif last_char == "t" then
-- č in partial NFD: U+010D (precomposed)
return prefix .. "č" .. trailing
end
return stem_nfd -- no change
end
-- Return the last base (non-combining) character of a partial NFD string.
-- Used for j-stem detection.
local function last_base_char(nfd_str)
local ucp = m_string_utilities.codepoint
local ulen = m_string_utilities.len
local len = ulen(nfd_str)
for i = len, 1, -1 do
local cp = ucp(nfd_str, i)
if not is_accent(cp) then
return m_string_utilities.char(cp)
end
end
return nil
end
-- =============================================================================
-- Stress maps
-- "S" = stressed stem + naked ending
-- "E" = clean stem + accented ending
-- Positions 1-7: Sg Nom/Gen/Dat/Acc/Ins/Loc/Voc
-- Positions 8-14: Pl Nom/Gen/Dat/Acc/Ins/Loc/Voc
-- =============================================================================
local stress_maps = {
["standard"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","E","S", "S","S","S","E","S","S","S" },
[3] = { "S","S","S","S","S","E","S", "E","E","E","S","E","E","E" },
[4] = { "S","S","S","S","E","E","E", "E","E","E","E","E","E","E" },
},
-- -ias type stress pattern (élnias, kẽlias, etc.)
-- Differs from standard:
-- AP2 sg.loc (pos 6) = S: long -yje ending does not attract AP2 accent (cf. -as type -e which does)
-- AP3 sg.voc (pos 7) = E (el̃nias AP2, vélnias AP3)
-- Known gap: AP3 sg.voc comes out "velnỹ" (ending {"i","ỹ"}), but the form is
-- "velniẽ"; the ending {"ie","iẽ"} would be wrong for AP4 (kelỹ, not *keliẽ).
-- AP2 and AP3 are rare for this type.
["standard_ias"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" }, -- pos6 S (not E)
[3] = { "S","S","S","S","S","E","E", "E","E","E","S","E","E","E" }, -- pos7 E (not S)
[4] = { "S","S","S","S","E","E","E", "E","E","E","E","E","E","E" },
},
-- -jas type stress pattern (vė́jas, kraũjas): as standard_ias, except that
-- the vocative singular -jau keeps the stem stress in every class (vė́jau,
-- galvìjau, kraũjau; the name Iñdrajas: Iñdrajau), where the -ias nouns
-- stress the ending (kelỹ). Classes 3 and 4 are rare in this type.
["standard_jas"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "S","S","S","S","S","E","S", "E","E","E","S","E","E","E" },
[4] = { "S","S","S","S","E","E","S", "E","E","E","E","E","E","E" },
},
-- -is/-ys type stress pattern (kiaušìnis, ožỹs, etc.)
-- AP2: almost all S, only sg.ins (5) and pl.acc (11) are E
-- AP3/AP4: sg.nom and sg.voc are E (ending-stressed: -ỹs, -ỹ)
["standard_is_ys"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","S","S","S","S","E","E", "E","E","E","S","E","E","E" },
[4] = { "E","S","S","S","E","E","E", "E","E","E","E","E","E","E" },
},
-- Feminine vowel-stem stress pattern for -a/-ia type (e.g., rankà)
-- AP2: sg.nom, sg.ins, pl.acc are E (short ending -a attracts accent in AP2)
["feminine_vowel"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "E","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","S","E","S", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","S", "S","E","E","E","E","E","S" },
},
-- Feminine vowel-stem stress pattern for -ė type (e.g., žvãkė)
-- AP2: sg.nom stays on stem (long -ė does not attract AP2 accent); only sg.ins and pl.acc are E
["feminine_vowel_e"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","S","E","S", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","S", "S","E","E","E","E","E","S" },
},
-- Paradigms 9/10 (declension III i-stems) stress pattern
-- AP2 (geluõnis, deguonis, palikuonis, pirmuonis, vagis, žiniuonis):
-- only sg.ins (5) and pl.acc (11) are E, as in standard_is_ys AP2.
-- AP3: positions 1,2,5,6,7 are E; pl.nom/acc/voc S
-- AP4: positions 8,14 are S (par9-12 AP4 pl.nom always S)
["par9_10"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","E","E","E", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
-- Paradigm 4 (declension IV -us) stress pattern
-- AP2 (cùkrus): almost all S, only pl.acc (pos 11) is E
-- AP3 (sūnùs): sg.nom/gen/ins/loc/voc E, sg.dat/acc S; pl.nom/acc/voc S, rest E
-- AP4 (alùs): sg.dat/acc S, rest E; pl.nom/voc S, rest E
["par4"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","S","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","E","E","E", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
-- Paradigm 5 (-ius/-jus): AP1 and AP2, plus isolated AP4 items (Sìrius).
-- AP4 follows par4 AP4 except sg.nom/voc, which stay S: the -ius
-- nominative is weak (Sìrius, not *Siriùs), unlike -us (dangùs).
["par5"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","S","S","S", "S","S","S","E","S","S","S" },
[4] = { "S","E","S","S","E","E","S", "S","E","E","E","E","E","S" },
},
-- Paradigm 11 (-uo, e.g. akmuõ: akmeniẽ; šuõ: šuniẽ) stress pattern
-- -uo nouns are AP3 or AP4 (AP1 only for mė́nuo, below)
-- sg.gen (pos 2) is E: the generated genitive (short stem + -eñs) is
-- always ending-stressed (akmeñs, vandeñs)
-- AP3: sg.loc and sg.voc are also E; AP4: sg.ins/loc/voc and pl.acc also E
["par11"] = {
-- AP1 exists only for mė́nuo, which declines per the (i)a-declension
-- with every slot overridden; fixed stem stress as a fallback.
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[3] = { "E","E","S","S","S","E","E", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
-- Paradigm 12 (sesuõ, duktė̃): only AP3 exists (a closed two-noun class).
-- Identical to the par9_10 AP3 row: sg.dat/acc and pl.nom/acc/voc are S
-- (on the oblique -er- stem: sẽseriai, dùkterį ...), everything else E.
["par12"] = {
[3] = { "E","E","S","S","E","E","E", "S","E","E","S","E","E","S" },
},
-- Paradigm 7 -i subtype stress map (patì, martì): AP4 only
["par7_i"] = {
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
}
-- =============================================================================
-- Ending tables {naked, accented}
-- accented = nil means this ending never bears stress.
-- =============================================================================
local endings = {
["par1_as"] = {
{"as",nil}, {"o",nil}, {"ui",nil}, {"ą",nil},
{"u","ù"}, {"e","è"}, {"e",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
-- j-stem type (-jas): vė́jas, vertė̃jas, naudótojas, etc.
-- Differs from 1_as in: sg.loc -uje (not -e), sg.voc -au (not -e). The
-- vocative singular is never stressed on the ending (standard_jas).
["par2_jas"] = {
{"as",nil}, {"o",nil}, {"ui",nil}, {"ą",nil},
{"u","ù"}, {"uje","ujè"}, {"au",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
["par3_is"] = {
{"is",nil}, {"io",nil}, {"iui",nil}, {"į",nil},
{"iu","iù"}, {"yje","yjè"}, {"i",nil},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
["par3_ys"] = {
{"ys","ỹs"}, {"io",nil}, {"iui",nil}, {"į",nil},
{"iu","iù"}, {"yje","yjè"}, {"y","ỹ"},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
-- j-stem -ys type (žvejỹs): the par3_ys endings with the glide i
-- absorbed after stem-final j (gen. žvẽjo, pl. žvejaĩ; cf. par2_jas).
-- The true-vowel i of sg.nom/acc/loc/voc is kept (žvejỹs, žvẽjį, žvejyjè, žvejỹ).
["par3_jys"] = {
{"ys","ỹs"}, {"o",nil}, {"ui",nil}, {"į",nil},
{"u","ù"}, {"yje","yjè"}, {"y","ỹ"},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
-- j-stem -is type (sker̃svėjis, gen. sker̃svėjo): the par3_is endings
-- with the same absorption.
["par3_jis"] = {
{"is",nil}, {"o",nil}, {"ui",nil}, {"į",nil},
{"u","ù"}, {"yje","yjè"}, {"i",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
["par2_ias"] = {
{"ias",nil}, {"io",nil}, {"iui",nil}, {"ią",nil},
{"iu","iù"}, {"yje","yjè"}, {"i","ỹ"},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
["par6_a"] = {
{"a","à"}, {"os","õs"}, {"ai",nil}, {"ą",nil},
{"a","à"}, {"oje","ojè"}, {"a",nil},
{"os","õs"}, {"ų","ų̃"}, {"oms","óms"}, {"as","às"},
{"omis","omìs"},{"ose","osè"},{"os","õs"},
},
["par7_ia"] = {
{"ia","ià"}, {"ios","iõs"}, {"iai",nil}, {"ią",nil},
{"ia","ià"}, {"ioje","iojè"},{"ia",nil},
{"ios","iõs"}, {"ių","ių̃"}, {"ioms","ióms"},{"ias","iàs"},
{"iomis","iomìs"},{"iose","iosè"},{"ios","iõs"},
},
["par8_e"] = {
{"ė","ė̃"}, {"ės","ė̃s"}, {"ei",nil}, {"ę",nil},
{"e","è"}, {"ėje","ėjè"},{"e",nil},
{"ės","ė̃s"}, {"ių","ių̃"}, {"ėms","ė́ms"},{"es","ès"},
{"ėmis","ėmìs"},{"ėse","ėsè"},{"ės","ė̃s"},
},
-- Rare -i type (patì, martì) — positions 1,7 use lemma directly ({nil,nil})
-- Oblique cases follow the same pattern as 2_ia
["par7_i"] = {
{nil,nil}, {"ios","iõs"}, {"iai",nil}, {"ią",nil},
{"ia","ià"}, {"ioje","iojè"},{nil,nil},
{"ios","iõs"}, {"ių","ių̃"}, {"ioms","ióms"},{"ias","iàs"},
{"iomis","iomìs"},{"iose","iosè"},{"ios","iõs"},
},
["par9_is"] = {
{"is","ìs"}, {"ies","iẽs"}, {"iai",nil}, {"į",nil},
{"imi","imì"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ių","ių̃"}, {"ims","ìms"},{"is","ìs"},
{"imis","imìs"},{"yse","ysè"},{"ys","ỹs"},
},
["par10_is"] = {
{"is","ìs"}, {"ies","iẽs"}, {"iui",nil}, {"į",nil},
{"imi","imì"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ių","ių̃"}, {"ims","ìms"},{"is","ìs"},
{"imis","imìs"},{"yse","ysè"},{"ys","ỹs"},
},
["par4_us"] = {
{"us","ùs"}, {"aus","aũs"}, {"ui",nil}, {"ų",nil},
{"umi","umì"}, {"uje","ujè"}, {"au","aũ"},
{"ūs","ū̃s"}, {"ų","ų̃"}, {"ums","ùms"}, {"us","ùs"},
{"umis","umìs"},{"uose","uosè"},{"ūs","ū̃s"},
},
["par5_ius"] = {
{"ius",nil}, {"iaus",nil}, {"iui",nil}, {"ių",nil},
{"iumi","iumì"},{"iuje","iujè"},{"iau",nil},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
["par5_jus"] = {
{"us",nil}, {"aus",nil}, {"ui",nil}, {"ų",nil},
{"umi","umì"}, {"uje","ujè"}, {"au",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
-- Paradigm 11 (-uo): nom sg = lemma directly ({nil,nil}); gen sg is built
-- on the NOMINATIVE short stem (akm-uõ → akm-eñs), not the oblique -en-
-- stem supplied via .stem: — see the gen_short_stem special case in the
-- form generator. šuõ (gen. šuñs) is irregular: override with '.gen:šuñs'.
["par11_uo"] = {
{nil,nil}, {"ens","eñs"}, {"iui",nil}, {"į",nil},
{"iu","iù"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ų","ų̃"}, {"ims","ìms"}, {"is","ìs"},
{"imis","imìs"}, {"yse","ysè"}, {"ys","ỹs"},
},
-- Paradigm 12 (sesuõ, duktė̃): nom sg = lemma directly; gen sg on the
-- nominative short stem (ses-uõ/dukt-ė̃ → ses-er̃s/dukt-er̃s); all other
-- slots on the accented -er- stem from .stem: (sẽser-, dùkter-), with
-- declension III feminine endings (dat -iai, i-stem obliques).
-- sg ins: only the standard -imì is generated; the secondary (i)o-type
-- variant (sẽseria, dùkteria) is added by the editor via '.ins:+:-ia'.
["par12_er"] = {
{nil,nil}, {"ers","er̃s"}, {"iai",nil}, {"į",nil},
{"imi","imì"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ų","ų̃"}, {"ims","ìms"}, {"is","ìs"},
{"imis","imìs"}, {"yse","ysè"}, {"ys","ỹs"},
},
}
-- =============================================================================
-- Family plural of surnames ('sur')
-- Beside its ordinary plural, which names several men of the surname, a
-- masculine surname has a collective plural naming a married couple or a
-- family. It is stressed on every ending that can carry the stress, whatever
-- the accentuation paradigm of the surname (Petráitis: Petráičiai, but
-- Petraičiaĩ of the family), and surnames in -a, -ia and -ė form it with the
-- endings -(i)ai (Noreikà: Noreĩkos, but Noreikaĩ). Surnames in -us take the
-- -ai endings first and those of their own declension after them (Bar̃tkus:
-- Bartkaĩ, Bar̃tkūs).
-- Each class lists one or more ending sets: `endings` names the row of the
-- ending table whose plural half is used, `stress` gives the seven plural
-- slots (nominative to vocative).
-- =============================================================================
local FAMILY_NOTE = "[referring to a married couple or a family]"
local family_all_endings = { "E","E","E","E","E","E","E" }
-- Nominative and vocative in -os and -ūs never take the stress.
local family_mobile = { "S","E","E","E","E","E","S" }
local family_plural = {
par1_as = { { endings = "par1_as", stress = family_all_endings } },
par2_jas = { { endings = "par2_jas", stress = family_all_endings } },
par2_ias = { { endings = "par2_ias", stress = family_all_endings } },
par3_is = { { endings = "par3_is", stress = family_all_endings } },
par3_ys = { { endings = "par3_ys", stress = family_all_endings } },
par3_jys = { { endings = "par3_jys", stress = family_all_endings } },
par3_jis = { { endings = "par3_jis", stress = family_all_endings } },
par5_ius = { { endings = "par5_ius", stress = family_all_endings } },
par5_jus = { { endings = "par5_jus", stress = family_all_endings } },
par4_us = {
{ endings = "par1_as", stress = family_all_endings },
{ endings = "par4_us", stress = family_mobile },
},
par6_a = {
{ endings = "par1_as", stress = family_all_endings },
{ endings = "par6_a", stress = family_mobile },
},
par7_ia = { { endings = "par3_is", stress = family_all_endings } },
par8_e = { { endings = "par3_is", stress = family_all_endings } },
}
-- =============================================================================
-- Illative endings (secondary local case)
-- Formed by adding -n to the accusative (plural -sna)
-- A stressed ending is circumflex in the singular, acute in the plural.
-- The singular is still used in the standard language beside į + accusative;
-- the plural is archaic or dialectal, as are the allative and the adessive.
-- =============================================================================
local ill_endings = {
["par1_as"] = { {"an","añ"}, {"uosna","úosna"} },
["par2_jas"] = { {"an","añ"}, {"uosna","úosna"} },
["par3_is"] = { {"in","iñ"}, {"iuosna","iúosna"} },
["par3_ys"] = { {"in","iñ"}, {"iuosna","iúosna"} },
["par3_jys"] = { {"in","iñ"}, {"uosna","úosna"} },
["par3_jis"] = { {"in","iñ"}, {"uosna","úosna"} },
["par2_ias"] = { {"ian","iañ"}, {"iuosna","iúosna"} },
["par6_a"] = { {"on","õn"}, {"osna","ósna"} },
["par7_ia"] = { {"ion","iõn"}, {"iosna","iósna"} },
["par7_i"] = { {"ion","iõn"}, {"iosna","iósna"} },
["par8_e"] = { {"ėn","ė̃n"}, {"ėsna","ė́sna"} },
["par9_is"] = { {"in","iñ"}, {"ysna","ýsna"} },
["par10_is"] = { {"in","iñ"}, {"ysna","ýsna"} },
["par4_us"] = { {"un","uñ"}, {"uosna","úosna"} },
["par5_ius"] = { {"iun","iuñ"}, {"iuosna","iúosna"} },
["par5_jus"] = { {"un","uñ"}, {"uosna","úosna"} },
["par11_uo"] = { {"in","iñ"}, {"ysna","ýsna"} },
["par12_er"] = { {"in","iñ"}, {"ysna","ýsna"} },
}
-- Illative stress map: {sg_stress, pl_stress}
-- AP1/2: S,S — both singular and plural stem-stressed
-- AP3/4: E,E — both singular and plural ending-stressed
local ill_stress_map = { [1] = {"S","S"}, [2] = {"S","S"}, [3] = {"E","E"}, [4] = {"E","E"} }
-- =============================================================================
-- Allative endings {naked, accented}, singular
-- Keyed by ending_key
-- Formed by: Genitive + postposition *pi/*p
-- A stressed ending keeps the tone of the genitive singular (-õs → -õsp);
-- -(i)óp is acute.
-- The plural is built on the genitive plural: -ų → -ump, stressed where the
-- genitive plural is (miškų̃ → miškum̃p, akių̃ → akium̃p).
-- Nouns in -uo and -er add -p to the older genitive in -ès (akmenèsp). Those
-- in -er have three forms: on the genitive in -er̃s, built like it on the
-- short stem and listed first, on the older genitive, and with the ending of
-- the i-stems (dukter̃sp, dukterèsp, dukteriẽsp).
-- =============================================================================
local all_endings = {
["par1_as"] = {"op","óp"},
["par2_jas"] = {"op","óp"},
["par3_is"] = {"iop","ióp"},
["par3_ys"] = {"iop","ióp"},
["par3_jys"] = {"op","óp"},
["par3_jis"] = {"op","óp"},
["par2_ias"] = {"iop","ióp"},
["par6_a"] = {"osp","õsp"},
["par7_ia"] = {"iosp","iõsp"},
["par7_i"] = {"iosp","iõsp"},
["par8_e"] = {"ėsp","ė̃sp"},
["par9_is"] = {"iesp","iẽsp"},
["par10_is"] = {"iesp","iẽsp"},
["par4_us"] = {"ausp","aũsp"},
["par5_ius"] = {"iausp","iaũsp"},
["par5_jus"] = {"ausp","aũsp"},
["par11_uo"] = {"esp","èsp"},
["par12_er"] = { {"ersp","er̃sp", short_stem = true}, {"esp","èsp"}, {"iesp","iẽsp"} },
}
-- Allative singular stress
-- AP1/AP2 → S (stem-stressed)
-- AP3/AP4 → E (ending-stressed)
local all_stress_map = { [1] = "S", [2] = "S", [3] = "E", [4] = "E" }
-- =============================================================================
-- Adessive endings {naked, accented}
-- Keyed by ending_key; each entry = { {sg_naked, sg_accented}, {pl_naked, pl_accented} }
-- Formed by: Old Locative + postposition *pi/*p
-- Plural forms insert nasal -m- between Locative Pl and -p(i)
-- Nouns in -is and -ys of paradigm 3 have two singular forms: -ip, as in the
-- i-stems, and -iep beside it.
-- =============================================================================
local ade_endings = {
["par1_as"] = { {"iep","íep"}, {"uosemp","úosemp"} },
["par2_jas"] = { {"iep","íep"}, {"uosemp","úosemp"} },
["par3_is"] = { { {"ip","ìp"}, {"iep","íep"} }, {"iuosemp","iúosemp"} },
["par3_ys"] = { { {"ip","ìp"}, {"iep","íep"} }, {"iuosemp","iúosemp"} },
["par3_jys"] = { { {"ip","ìp"}, {"iep","íep"} }, {"uosemp","úosemp"} },
["par3_jis"] = { { {"ip","ìp"}, {"iep","íep"} }, {"uosemp","úosemp"} },
["par2_ias"] = { {"iep","íep"}, {"iuosemp","iúosemp"} },
["par6_a"] = { {"aip","áip"}, {"osemp","ósemp"} },
["par7_ia"] = { {"iaip","iáip"}, {"iosemp","iósemp"} },
["par7_i"] = { {"iaip","iáip"}, {"iosemp","iósemp"} },
["par8_e"] = { {"eip","éip"}, {"ėsemp","ė́semp"} },
["par9_is"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
["par10_is"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
["par4_us"] = { {"up","ùp"}, {"uosemp","úosemp"} },
["par5_ius"] = { {"iup","iùp"}, {"iuosemp","iúosemp"} },
["par5_jus"] = { {"up","ùp"}, {"uosemp","úosemp"} },
["par11_uo"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
["par12_er"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
}
-- Adessive stress map: {sg_loc, pl_loc}
-- AP1/AP2 → S, S (stem-stressed)
-- AP3/AP4 → E, E (ending-stressed in both singular and plural)
local ade_stress_map = { [1] = {"S","S"}, [2] = {"S","S"}, [3] = {"E","E"}, [4] = {"E","E"}, }
-- =============================================================================
-- Slot-name mapping: external names (used in overrides) → internal keys
-- =============================================================================
local slot_map = {
nom = "nom_s", gen = "gen_s", dat = "dat_s", acc = "acc_s",
ins = "ins_s", loc = "loc_s", voc = "voc_s",
nompl = "nom_p", genpl = "gen_p", datpl = "dat_p", accpl = "acc_p",
inspl = "ins_p", locpl = "loc_p", vocpl = "voc_p",
-- Secondary local cases
ill = "ill_s", illpl = "ill_p",
all = "all_s", allpl = "all_p",
ade = "ade_s", adepl = "ade_p",
}
local slot_external_names = {}
for ext, int in pairs(slot_map) do slot_external_names[int] = ext end
-- =============================================================================
-- Slot list for iut.show_forms (slot name → ACCEL tag)
-- Secondary local case slots are only activated dynamically when data exists.
-- =============================================================================
local lt_noun_slot_list = {
{"nom_s","nom|s"}, {"gen_s","gen|s"}, {"dat_s","dat|s"}, {"acc_s","acc|s"},
{"ins_s","ins|s"}, {"loc_s","loc|s"}, {"voc_s","voc|s"},
{"nom_p","nom|p"}, {"gen_p","gen|p"}, {"dat_p","dat|p"}, {"acc_p","acc|p"},
{"ins_p","ins|p"}, {"loc_p","loc|p"}, {"voc_p","voc|p"},
{"ill_s","ill|s"}, {"ill_p","ill|p"},
{"all_s","all|s"}, {"all_p","all|p"},
{"ade_s","ade|s"}, {"ade_p","ade|p"},
}
local lt_noun_secondary_slots = {
ill_s=true, ill_p=true, all_s=true, all_p=true, ade_s=true, ade_p=true,
}
-- =============================================================================
-- Table renderer
-- =============================================================================
local function make_table(forms, number_restr, show_ill, show_all, show_ade)
local frame = mw.getCurrentFrame()
local top = frame:expandTemplate {
title = "inflection-table-top",
args = { title = forms.title, palette = "yellow", tall = "yes" },
}
local bot = frame:expandTemplate {
title = "inflection-table-bottom",
args = { notes = forms.footnote or "" },
}
local cases = {
{ "nominative", "nom" },
{ "genitive", "gen" },
{ "dative", "dat" },
{ "accusative", "acc" },
{ "instrumental", "ins" },
{ "locative", "loc" },
{ "vocative", "voc" },
}
local show_sg = (number_restr ~= "pl")
local show_pl = (number_restr ~= "sg")
local rows = '! rowspan="2" |\n|-\n'
if show_sg then rows = rows .. '! singular' end
if show_pl then rows = rows .. '\n! plural' end
rows = rows .. "\n|-\n"
for _, c in ipairs(cases) do
local label, key = c[1], c[2]
rows = rows .. "! " .. label .. "\n"
if show_sg then rows = rows .. "| " .. (forms[key .. "_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms[key .. "_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
-- Secondary local cases section
-- Only rendered when explicitly requested by the editor.
local has_secondary = show_ill or show_all or show_ade
-- Only strip the trailing row separator here if no secondary rows follow;
-- otherwise it must stay to separate vocative from the next case row.
if not has_secondary then
rows = rsub(rows, "|%-\n$", "")
end
if show_ill then
rows = rows .. "! illative\n"
if show_sg then rows = rows .. "| " .. (forms["ill_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms["ill_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
if show_all then
rows = rows .. "! allative\n"
if show_sg then rows = rows .. "| " .. (forms["all_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms["all_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
if show_ade then
rows = rows .. "! adessive\n"
if show_sg then rows = rows .. "| " .. (forms["ade_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms["ade_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
-- Remove trailing row separator
if has_secondary then
rows = rsub(rows, "|%-\n$", "")
end
return top .. rows .. bot
end
-- =============================================================================
-- Main entry point
-- =============================================================================
local function make_form(stem_ac, ending_ac)
local combined = stem_ac .. ending_ac
return makeDisplayText(combined)
end
-- Parse and process a single pattern (lemma,AP,gen with tags).
--
-- The lemma and AP fields may each hold a colon-separated list of variants,
-- optionally footnoted (e.g. "sūnùs:sūnùs[dial.],3:4[rare]"). Each lemma × AP
-- combination is declined separately and the results are merged slot by slot
-- (merge_alternant_results), as for an explicit (( )) alternant.
--
-- Returns a table of forms for all 14 slots, plus metadata.
local function decline_single_pattern(pattern_str, unescape_func)
local function parse_err(msg)
error("lt-ndecl: " .. msg .. ": '" .. pattern_str .. "'")
end
-- Isolate the [...] footnotes first, so a "," or "." inside one is not
-- taken for a field or tag separator.
local bracket_segs = put.parse_balanced_segment_run(pattern_str, "[", "]")
local comma_groups = put.split_alternating_runs_and_strip_spaces(bracket_segs, ",")
-- ── 1. Lemma (position 1): colon-list + footnote via fetch_specs ────────
local lemma_specs = m_common.fetch_specs(comma_groups[1] or {""}, ":", "lemma", nil, parse_err)
for _, spec in ipairs(lemma_specs) do
spec.form = unescape_func(spec.form)
end
-- ── 1a. Parse part 2: AP + optional tags ─────────────────────────────────
local part2_group = comma_groups[2] or {"0"}
local part2_dot_groups = put.split_alternating_runs_and_strip_spaces(part2_group, "%.")
local ap_specs = m_common.fetch_specs(part2_dot_groups[1], ":", "accent paradigm", nil, parse_err)
-- ── 1b. Parse part 3: optional genitive-singular keyword + tags ──────────
-- Position 3 only classifies: a plain, unaccented keyword naming the
-- genitive-singular ending ("io", "ies" or "ers") of a lemma ending shared
-- by several paradigms (-is: par3 -io vs par9/par10 -ies; -ė/-uo:
-- par8/par11 vs the sesuõ/duktė̃ type par12 -ers). The genitive cell is
-- still generated; ".gen:" overrides it (e.g. šuõ). Footnotes and
-- colon-lists are errors here.
local part3_dot_groups = {}
local gen_keyword
if comma_groups[3] then
part3_dot_groups = put.split_alternating_runs_and_strip_spaces(comma_groups[3], "%.")
local kw_group = part3_dot_groups[1]
if kw_group and (#kw_group > 1 or kw_group[1] ~= "") then
if #kw_group > 1 then
parse_err("Footnotes not allowed on the position-3 genitive keyword; " ..
"to footnote the genitive cell, use '.gen:+[note]' instead")
end
gen_keyword = kw_group[1]
if not rfind(gen_keyword, "^[a-z]+$") then
parse_err("Position 3 must be a plain genitive-singular keyword " ..
"('io', 'ies' or 'ers') without accents, '-' or variants; got '" ..
gen_keyword .. "'")
end
end
end
-- ── 1c. Collect all control tags ─────────────────────────────────────────
local gender, number_restr, common_gender
local personal_name, surname
local stem_param, plstem_param, decl_override
local overrides = {}
local whole_footnotes -- footnote(s) for the whole table
local all_tag_groups = {}
for i = 2, #part2_dot_groups do table.insert(all_tag_groups, part2_dot_groups[i]) end
for i = 2, #part3_dot_groups do table.insert(all_tag_groups, part3_dot_groups[i]) end
for _, tag_group in ipairs(all_tag_groups) do
local part = tag_group[1]
local has_footnote = #tag_group > 1
if part == "" then
-- A bare bracket (nothing before it) footnotes the entire declension.
if not has_footnote then
parse_err("Blank indicator")
end
whole_footnotes = iut.combine_footnotes(whole_footnotes, m_common.fetch_footnotes(tag_group, parse_err))
elseif part == "m" or part == "f" then
if has_footnote then
parse_err("Footnotes not allowed on '" .. part .. "' (used only to disambiguate declension class); " ..
"use a whole-declension footnote (a lone .[...]) or multi-alternant instead")
end
if common_gender then
parse_err("'" .. part .. "' cannot be combined with 'mfbysense'")
end
gender = part
elseif part == "mfbysense" then
-- Common-gender noun (vė́pla type): agreement gender follows the
-- referent; the declension is that of the feminine-form class.
if has_footnote then
parse_err("Footnotes not allowed on 'mfbysense'")
end
if gender then
parse_err("'mfbysense' cannot be combined with 'm'/'f'")
end
common_gender = true
elseif part == "sg" or part == "pl" then
if has_footnote then
parse_err("Footnotes not allowed on '" .. part .. "'")
end
number_restr = part
elseif part == "sur" then
-- A masculine surname: a surname in -as takes the vocative -ai, and
-- every surname adds the family plural.
if has_footnote then
parse_err("Footnotes not allowed on '" .. part .. "'")
end
personal_name = true
surname = true
elseif rfind(part, "^stem:") then
if has_footnote then
parse_err("Footnotes not allowed on 'stem:' (structural override); use multi-alternant instead")
end
local _, stem_ac = process_input(unescape_func(rsub(part, "^stem:", "")))
stem_param = stem_ac
elseif rfind(part, "^plstem:") then
if has_footnote then
parse_err("Footnotes not allowed on 'plstem:' (structural override); use multi-alternant instead")
end
local _, plstem_ac = process_input(unescape_func(rsub(part, "^plstem:", "")))
plstem_param = plstem_ac
elseif rfind(part, "^decl:") then
-- Table-header override (section 6); no effect on the forms.
if has_footnote then
parse_err("Footnotes not allowed on 'decl:' (header override); use multi-alternant instead")
end
decl_override = tonumber((rsub(part, "^decl:", "")))
else
-- Slot override: "nom:value", "genpl:value", etc. Keep the value as
-- a bracket-preserving run (may itself be --, +, -, -xx, or a
-- colon-list val1[note1]:val2[note2]); process_val resolves the
-- syntax later, once the natural/default form is known.
local key, rest = rmatch(part, "^([a-z]+):(.*)")
if key and slot_map[key] then
local override_run = {rest}
for i = 2, #tag_group do table.insert(override_run, tag_group[i]) end
overrides[slot_map[key]] = override_run
else
-- An unknown indicator is ignored, unless it carries a footnote.
if has_footnote then
parse_err("Footnotes not allowed on unrecognized indicator '" .. part .. "'")
end
end
end
end
if surname and number_restr then
parse_err("'sur' marks a surname, which declines in both numbers; it cannot be combined with '"
.. number_restr .. "'")
end
if surname and common_gender then
parse_err("'sur' marks a masculine surname; it cannot be combined with 'mfbysense'")
end
-- The gender tag as given: the inference below fills `gender`, and
-- compute_categories must tell an explicit '.m' from an inferred one.
local gender_tag = gender
-- ── One declension pass per lemma × AP combination, merged per slot. ──
local combinations = {}
for _, lspec in ipairs(lemma_specs) do
for _, aspec in ipairs(ap_specs) do
table.insert(combinations, {
lemma_form = lspec.form,
lemma_footnotes = lspec.footnotes,
ap_form = aspec.form,
ap_footnotes = aspec.footnotes,
})
end
end
local all_results = {}
for _, combo in ipairs(combinations) do
-- All pattern work done in partial NFD; NFC only for final output.
-- process_input handles all Unicode normalization (dotless i/j, dotabove, etc.)
local lemma_nfc = combo.lemma_form
local ap_str = combo.ap_form
local indeclinable = (ap_str == "-")
local ap = indeclinable and 0 or (tonumber(ap_str) or 0)
local lemma_bare, lemma = process_input(lemma_nfc)
-- ── 2. Detect declension & extract stems ────────────────────────────────
local uchar = m_string_utilities.char
local ucp = m_string_utilities.codepoint
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
-- Count base (non-accent) codepoints in a partial NFD string.
-- In partial NFD, only accent marks (grave/acute/tilde) are combining characters.
-- ą/ė/č etc. are single precomposed codepoints.
local function count_base(stem_ac)
local count = 0
local total = ulen(stem_ac)
for i = 1, total do
local cp = ucp(stem_ac, i)
if not is_accent(cp) then
count = count + 1
end
end
return count
end
-- Return the partial NFD prefix of `stem_ac` that contains exactly
-- `n` base (non-accent) codepoints, including any accent marks attached
-- to those base codepoints.
local function accented_prefix(stem_ac, n)
local out = {}
local count = 0
local i = 1
local total = ulen(stem_ac)
while i <= total do
local cp = ucp(stem_ac, i)
local is_acc = is_accent(cp)
table.insert(out, uchar(cp))
if not is_acc then
count = count + 1
if count == n then
-- Consume any immediately following accent marks too
i = i + 1
while i <= total do
local cp2 = ucp(stem_ac, i)
if is_accent(cp2) then
table.insert(out, uchar(cp2))
i = i + 1
else
break
end
end
break
end
end
i = i + 1
end
return table.concat(out)
end
local lemma_naked = strip_ac(lemma) -- partial NFD, accent combiners removed
-- Match suffix `sfx` (precomposed characters in partial NFD)
-- against lemma_naked. On success, return:
-- accented_stem – the corresponding prefix of the accented partial NFD lemma
-- naked_stem – the accent-free prefix
-- In partial NFD, ė/ą/č etc. are single codepoints, making matching straightforward.
local function strip_ending(sfx)
local sfx_bases = count_base(sfx)
local naked_bases = count_base(lemma_naked)
if sfx_bases > naked_bases then return nil end
-- Extract the stem portion (by base-character count) from lemma_naked
local stem_base_count = naked_bases - sfx_bases
local naked_stem
if stem_base_count == 0 then
naked_stem = ""
else
naked_stem = accented_prefix(lemma_naked, stem_base_count)
end
-- The suffix portion is everything after the stem
local suffix_part = usub(lemma_naked, ulen(naked_stem) + 1)
if suffix_part ~= sfx then return nil end
if stem_base_count == 0 then
return "", ""
end
local accented_stem = accented_prefix(lemma, stem_base_count)
return accented_stem, naked_stem
end
local stress_map_key, ending_key
local raw_stem_acc, raw_stem_naked
-- Paradigms 11/12 only: accent-free nominative short stem (akm-, ses-,
-- dukt-) on which the genitive singular is built (akmeñs, seser̃s).
local gen_short_stem
-- Set when an ambiguous lemma ending consumed the position-3 keyword;
-- a keyword left unconsumed is an error (see check after the ladder).
local keyword_ok = false
-- Handle indeclinable words: skip ending detection entirely
if indeclinable then
-- All forms = lemma; no ending detection needed.
raw_stem_acc = lemma
raw_stem_naked = lemma_naked
stress_map_key = "standard"
ending_key = nil -- special flag: indeclinable
else
-- Check longer/more-specific suffixes before shorter ones.
local sa, sn
sa, sn = strip_ending("ias")
if sa then
-- -čias/-džias lemmas keep the plain stop in the stem (svẽčias → svẽt-):
-- the softening i of the endings restores č/dž, the -y- of the locative
-- and vocative singular does not (svetyjè, svetỹ).
sa = rsub(rsub(sa, "č$", "t"), "dž$", "d")
sn = rsub(rsub(sn, "č$", "t"), "dž$", "d")
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "standard_ias"; ending_key = "par2_ias"
end
if not ending_key then
sa, sn = strip_ending("as")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- j-stem detection: if stem ends in "j", use par2_jas
if last_base_char(sn) == "j" then
stress_map_key = "standard_jas"; ending_key = "par2_jas"
else
stress_map_key = "standard"; ending_key = "par1_as"
end
end
end
if not ending_key then
sa, sn = strip_ending("ys")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- -ys is always paradigm 3; i-declension pluralia tantum like
-- dùrys are entered via their theoretical singular (dùris,AP,ies.pl).
-- All -ys types use standard_is_ys for correct sg.nom/voc endings (-ỹs/-ỹ)
stress_map_key = "standard_is_ys"
-- j-stem detection: after stem-final j the glide i of the
-- endings is absorbed (žvejỹs, gen. žvẽjo, pl. žvejaĩ)
if last_base_char(sn) == "j" then
ending_key = "par3_jys"
else
ending_key = "par3_ys"
end
end
end
if not ending_key then
sa, sn = strip_ending("ius")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "par5"
ending_key = "par5_ius"
end
end
if not ending_key then
sa, sn = strip_ending("us")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- j-stem detection for paradigm 5 (-jus vs -us)
if last_base_char(sn) == "j" then
stress_map_key = "par5"
ending_key = "par5_jus"
else
stress_map_key = "par4"
ending_key = "par4_us"
end
end
end
if not ending_key then
sa, sn = strip_ending("is")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- -is is ambiguous (par3 brólis/-io vs par9/par10 širdìs,
-- dantìs/-ies), so the genitive keyword is mandatory.
if not gen_keyword then
error("lt-ndecl: the ending -is is ambiguous between declension I "
.. "(gen. -io, e.g. brólis) and declension III (gen. -ies, e.g. "
.. "širdìs); please give the genitive-singular keyword in position 3: '"
.. lemma_nfc .. ",AP,io' or '" .. lemma_nfc .. ",AP,ies'")
elseif gen_keyword == "io" then
if gender == "f" then
error("lt-ndecl: declension I -is nouns (gen. -io) are masculine; "
.. "'.f' conflicts with the keyword 'io' (feminine -is nouns "
.. "belong to declension III: use ',ies')")
end
-- -is type AP2 uses special stress_map
stress_map_key = (ap == 2) and "standard_is_ys" or "standard"
-- after stem-final j the glide i of the endings is absorbed
ending_key = (last_base_char(sn) == "j") and "par3_jis" or "par3_is"
keyword_ok = true
elseif gen_keyword == "ies" then
stress_map_key = "par9_10"
ending_key = (gender == "m") and "par10_is" or "par9_is"
keyword_ok = true
else
error("lt-ndecl: invalid genitive keyword '" .. gen_keyword
.. "' for an -is lemma; expected 'io' (declension I) or "
.. "'ies' (declension III)")
end
end
end
if not ending_key then
-- ė in partial NFD = single precomposed char U+0117
sa, sn = strip_ending("ė")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
if gen_keyword == "ers" then
-- duktė̃ (gen. dukter̃s), the only -ė noun of paradigm 12
stress_map_key = "par12"; ending_key = "par12_er"
gen_short_stem = sn
keyword_ok = true
elseif gen_keyword then
error("lt-ndecl: invalid genitive keyword '" .. gen_keyword
.. "' for an -ė lemma; the only meaningful value is 'ers' "
.. "(duktė̃ type, gen. -er̃s)")
else
stress_map_key = "feminine_vowel_e"; ending_key = "par8_e"
end
end
end
if not ending_key then
sa, sn = strip_ending("ia")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "feminine_vowel"; ending_key = "par7_ia"
end
end
if not ending_key then
sa, sn = strip_ending("a")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "feminine_vowel"; ending_key = "par6_a"
end
end
if not ending_key then
sa, sn = strip_ending("uo")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
if gen_keyword == "ers" then
-- sesuõ (gen. seser̃s), the only -uo noun of paradigm 12
stress_map_key = "par12"; ending_key = "par12_er"
gen_short_stem = sn
keyword_ok = true
elseif gen_keyword then
error("lt-ndecl: invalid genitive keyword '" .. gen_keyword
.. "' for an -uo lemma; the only meaningful value is 'ers' "
.. "(sesuõ type, gen. -er̃s). Regular -uo nouns (paradigm 11) "
.. "need no keyword — their genitive -eñs is generated "
.. "automatically; for the irregular šuõ, override with '.gen:šuñs'")
else
stress_map_key = "par11"; ending_key = "par11_uo"
gen_short_stem = sn
end
end
end
-- Rare -i type (patì, martì)
if not ending_key then
sa, sn = strip_ending("i")
if sa and ap == 4 then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "par7_i"; ending_key = "par7_i"
end
end
if not ending_key then
error("lt-ndecl: cannot detect declension type from lemma \""
.. lemma_nfc .. "\". Expected ending: -as/-ias/-is/-ys/-ius/-us/-a/-ia/-ė/-uo/-i")
end
end
-- A position-3 keyword on an unambiguous lemma ending is an error.
if gen_keyword and not keyword_ok then
error("lt-ndecl: the position-3 genitive keyword does not apply to '"
.. lemma_nfc .. "': it is used only to disambiguate -is lemmas "
.. "('io'/'ies') and to mark the sesuõ/duktė̃ type ('ers')")
end
-- Paradigm 12 sanity checks: closed two-noun class (sesuõ, duktė̃).
if ending_key == "par12_er" then
if gender == "m" then
error("lt-ndecl: paradigm 12 nouns (sesuõ/duktė̃ type) are feminine; remove '.m'")
end
if not stem_param then
error("lt-ndecl: sesuõ/duktė̃-type nouns build their oblique cases on an "
.. "accented -er- stem that cannot be derived from the lemma; please "
.. "supply it, e.g. '.stem:sẽser' or '.stem:dùkter'")
end
local expected_bare = raw_stem_naked .. "er"
if strip_ac(stem_param) ~= expected_bare then
error("lt-ndecl: '.stem:" .. nfc(stem_param) .. "' does not match lemma \""
.. lemma_nfc .. "\": expected the -er- stem '" .. nfc(expected_bare)
.. "' plus an accent mark")
end
end
-- Apply stem override if provided
local stem_stress, stem_clean, plstem_stress, plstem_clean
if stem_param then
stem_stress = stem_param
stem_clean = strip_ac(stem_param)
else
stem_stress = raw_stem_acc
stem_clean = raw_stem_naked
end
if plstem_param then
plstem_stress = plstem_param
plstem_clean = strip_ac(plstem_param)
else
plstem_stress = stem_stress
plstem_clean = stem_clean
end
-- ── 3. Validate accent paradigm ─────────────────────────────────────────
if not indeclinable then
if ap < 1 or ap > 4 then
error("lt-ndecl: accent paradigm must be 1, 2, 3, or 4 (got " .. ap .. ")")
end
if not stress_maps[stress_map_key][ap] then
error("lt-ndecl: accent paradigm " .. ap .. " is not valid for " .. stress_map_key)
end
-- Paradigms 2 and 4 stress the last syllable of the stem in their
-- stem-stressed forms (laũk-as, kraũj-as, dañt-is); a stem stressed on
-- an earlier syllable (atsãkym-as) belongs to paradigm 1 or 3.
if (ap == 2 or ap == 4) and has_ac(stem_stress) then
local syllables, stressed = m_common.stressed_syllable(stem_stress)
if stressed and stressed < syllables then
error("lt-ndecl: accent paradigm " .. ap .. " stresses the last syllable of the stem, but \""
.. nfc(makeDisplayText(stem_stress)) .. "-\" is stressed on an earlier one; check the paradigm")
end
end
end
-- ── 4. Determine gender from ending if not explicitly specified ─────────
-- par9_is defaults to feminine: the declension III i-stems are
-- overwhelmingly feminine; the small closed masculine set (dantìs,
-- žvėrìs, vagìs ...) opts in with '.m' (→ par10_is, dat. sg. -iui).
if not gender then
if ending_key == "par1_as" or ending_key == "par2_ias" or ending_key == "par2_jas"
or ending_key == "par3_is" or ending_key == "par3_ys" or ending_key == "par3_jys"
or ending_key == "par3_jis" or ending_key == "par4_us"
or ending_key == "par5_ius" or ending_key == "par5_jus" or ending_key == "par11_uo" then
gender = "m"
elseif ending_key == "par6_a" or ending_key == "par7_ia" or ending_key == "par7_i"
or ending_key == "par8_e" or ending_key == "par9_is" or ending_key == "par12_er" then
gender = "f"
elseif ending_key == "par10_is" then
gender = "m"
else
gender = "m" -- default fallback
end
end
-- Common-gender nouns are restricted to the -a/-ia/-ė types (vė́pla,
-- drìmba, mėmė̃ ...); other classes have no common-gender nouns.
if common_gender and not (ending_key == "par6_a" or ending_key == "par7_ia"
or ending_key == "par8_e") then
parse_err("'mfbysense' is only valid for common-gender nouns in -a, -ia or -ė")
end
-- The family plural is formed from the masculine surname only.
if surname then
if indeclinable then
parse_err("'sur' cannot be used with an indeclinable surname")
end
if gender ~= "m" then
parse_err("'sur' marks a masculine surname (a masculine surname in -a, -ia or -ė "
.. "also needs 'm'); feminine surnames have no family plural")
end
if not family_plural[ending_key] then
parse_err("'sur' is not supported for this declension class")
end
end
-- ── 5. Determine declension type (educational I-V, display only) ────────
local decl_type
if ending_key == "par1_as" or ending_key == "par2_ias" or ending_key == "par2_jas"
or ending_key == "par3_is" or ending_key == "par3_ys" or ending_key == "par3_jys"
or ending_key == "par3_jis" then
decl_type = 1
elseif ending_key == "par6_a" or ending_key == "par7_ia" or ending_key == "par7_i"
or ending_key == "par8_e" then
decl_type = 2
elseif ending_key == "par9_is" or ending_key == "par10_is" then
decl_type = 3
elseif ending_key == "par4_us" or ending_key == "par5_ius" or ending_key == "par5_jus" then
decl_type = 4
elseif ending_key == "par11_uo" or ending_key == "par12_er" then
decl_type = 5
else
decl_type = 1 -- fallback
end
-- ── 6. Table-header override ────────────────────────────────────────────
-- 'decl:N' replaces the roman numeral shown in the table header; it has
-- no effect on the generated forms.
local decl_roman = localization.declension[decl_type]
if decl_override then
local roman_from_override = localization.declension[decl_override]
if roman_from_override then
decl_roman = roman_from_override
end
end
-- Process slot value with support for special syntax.
-- `val` is either a plain string (a generated default, or "--"; no
-- brackets or ":") or a bracket-preserving run from
-- put.parse_balanced_segment_run (an override, possibly a colon-list with
-- per-value footnotes: "val1[note1]:val2[note2]").
-- stem_clean: accent-free stem (possibly pre-palatalized for natural ending)
-- stem_stress: accented stem (possibly pre-palatalized for natural ending)
-- stem_clean_no_pal: original accent-free stem (never pre-palatalized)
-- stem_stress_no_pal: original accented stem (never pre-palatalized)
local function process_val(val, default_val, stem_clean, stem_stress, stem_clean_no_pal, stem_stress_no_pal)
if not val then return nil end
local val_run = (type(val) == "string") and {val} or val
-- Special case: "--" means slot doesn't exist
if table.concat(val_run) == "--" then
return nil
end
local form_list = {}
-- Composition of a single "-SUFFIX" override, or false once any spec in
-- the run is of another kind (a colon list of mixed specs has no single
-- breakdown to report).
local comp_out = nil
local specs = m_common.fetch_specs(val_run, ":", "override", nil, parse_err)
for _, spec in ipairs(specs) do
local v_clean = spec.form
local v_note = spec.footnotes -- already {"[...]", ...} or nil, iut-ready
-- Special case: "+" means use default value
if v_clean == "+" then
if not default_val then
error("lt-ndecl: '+' used in override but no default value available.")
end
v_clean = default_val -- default_val is always a string here
end
-- Special case: "-" or "-xx" means bare stem or stem+suffix
local stem_notation_comp = nil
if v_clean and rfind(v_clean, "^%-") then
-- For stem notation, use the non-palatalized original stems
-- and decide palatalization based on the suffix
if not stem_clean_no_pal or not stem_stress_no_pal then
error("lt-ndecl: stem notation used in override but no stem available.")
end
local suffix = rsub(v_clean, "^%-", "") -- Remove leading "-"
-- An accented suffix takes the clean stem, an unaccented one the stressed stem
local chosen_stem
local suffix_ac = to_stem_ac(suffix)
if suffix == "" then
-- Bare stem: use stressed stem
chosen_stem = stem_stress_no_pal
elseif has_ac(suffix_ac) then
-- Suffix has accent → use clean stem
chosen_stem = stem_clean_no_pal
else
-- Suffix has no accent → use stressed stem
chosen_stem = stem_stress_no_pal
end
-- Palatalize the stem if the suffix calls for it
if should_palatalize(suffix_ac) then
chosen_stem = nfc(palatalize_stem(nfd(chosen_stem)))
end
v_clean = nfc(nfd(chosen_stem) .. suffix_ac)
-- Record the breakdown so appendix_row can highlight the
-- stressed morpheme of an overridden slot as well; the stress
-- side follows the same test that picked the stem.
stem_notation_comp = {
stem = nfd(chosen_stem),
ending = nfd(suffix_ac),
stress = has_ac(suffix_ac) and "E" or "S",
}
end
if stem_notation_comp then
comp_out = (comp_out == nil) and stem_notation_comp or false
else
comp_out = false
end
-- A comma separates forms (a default with two forms)
for _, v2 in ipairs(rsplit(v_clean, "%s*,%s*")) do
if v2 ~= "" then
local form_obj = { form = nfc(v2) }
if v_note then form_obj.footnotes = v_note end
iut.insert_form_into_list(form_list, form_obj)
end
end
end
return (#form_list > 0) and form_list or nil, comp_out or nil
end
-- ── 7. Generate forms ────────────────────────────────────────────────────
local forms = {}
local family_forms
-- Per-slot stem/ending breakdown (partial NFD), consumed by appendix_row.
-- Overridden slots keep a breakdown only when the override uses stem
-- notation ("-ų̃"); any other override clears the slot, and appendix_row
-- then falls back to the plain form. Slots the lemma fills directly
-- (Decl V nom sg, indeclinables) record {whole = ...}.
local compositions = {}
if indeclinable then
local case_keys = {
"nom_s","gen_s","dat_s","acc_s","ins_s","loc_s","voc_s",
"nom_p","gen_p","dat_p","acc_p","ins_p","loc_p","voc_p",
}
for _, case_key in ipairs(case_keys) do
local override_val = overrides[case_key]
local default_val = lemma_nfc
if override_val then
-- For indeclinable words, both stem versions are the same (no palatalization)
local stem_clean = strip_ac(lemma)
local stem_stress = lemma
forms[case_key] = process_val(override_val, default_val, stem_clean, stem_stress, stem_clean, stem_stress)
else
forms[case_key] = process_val(default_val, nil, nil, nil, nil, nil)
end
end
else
-- ── 8. Generate each form (Declinable) ───────────────────────────────
local map = (stress_maps[stress_map_key] or {})[ap] or stress_maps["standard"][1]
-- -ė type AP2 sg.nom should be S (stem-stressed), not E
if ending_key == "par8_e" and ap == 2 then
local new_map = {}
for i = 1, 14 do new_map[i] = map[i] end
new_map[1] = "S"
map = new_map
end
-- When plstem is provided, force all slots to S (stem-stressed)
-- This handles AP2 tonal alternation (e.g., putýtis: sg putý-, pl putỹ-)
if plstem_param then
local new_map = {}
for i = 1, 14 do new_map[i] = "S" end
map = new_map
end
local end_list = endings[ending_key]
-- Personal names in -as take the vocative -ai (Jõnai, Kazláuskai),
-- not the -e of common nouns.
if personal_name and ending_key == "par1_as" then
local personal_endings = {}
for i = 1, 14 do personal_endings[i] = end_list[i] end
personal_endings[7] = {"ai", nil}
end_list = personal_endings
end
local case_keys = {
"nom_s","gen_s","dat_s","acc_s","ins_s","loc_s","voc_s",
"nom_p","gen_p","dat_p","acc_p","ins_p","loc_p","voc_p",
}
local function need_stem_error()
error("lt-ndecl: word \"" .. lemma_nfc .. "\" (AP " .. ap
.. ") has a stem-stressed form but the stem carries no accent mark. "
.. "Please supply a .stem:… parameter.")
end
for i, case_key in ipairs(case_keys) do
local override_val = overrides[case_key]
local generated_form = nil -- Will be computed as default
-- Generalized {nil,nil} handling (positions using lemma directly:
-- nom sg of par7_i/par11_uo/par12_er, plus voc sg of par7_i)
if end_list[i][1] == nil then
generated_form = makeDisplayText(lemma_nfc)
compositions[case_key] = { whole = generated_form }
else
-- Generate the form normally
local stress_loc = map[i]
local ed = end_list[i]
local naked_e = ed[1]
local accent_e = ed[2]
-- Select stem based on number (singular: stem, plural: plstem)
local cur_stem_stress = (i >= 8) and plstem_stress or stem_stress
local cur_stem_clean = (i >= 8) and plstem_clean or stem_clean
-- Paradigms 11/12 build the genitive singular on the NOMINATIVE
-- short stem (akm-uõ → akm-eñs, ses-uõ → ses-er̃s), not on the
-- oblique -en-/-er- stem used by every other slot. The slot is
-- always "E" with an accented allomorph, so only the clean stem
-- is ever consumed here.
if gen_short_stem and i == 2 then
cur_stem_clean = gen_short_stem
cur_stem_stress = gen_short_stem
end
-- The ending takes the stress only when the map says "E" and an
-- accented ending allomorph exists; otherwise the stem is
-- stressed, as in an "S" slot.
local stem_nfd, ending_nfd, eff_stress
if stress_loc == "E" and accent_e then
stem_nfd = nfd(cur_stem_clean)
ending_nfd = nfd(accent_e)
eff_stress = "E"
else
if not has_ac(cur_stem_stress) and ap ~= 1 then need_stem_error() end
stem_nfd = nfd(cur_stem_stress)
ending_nfd = naked_e and nfd(naked_e) or ""
eff_stress = "S"
end
if should_palatalize(ending_nfd) then
stem_nfd = palatalize_stem(stem_nfd)
end
generated_form = make_form(stem_nfd, ending_nfd)
compositions[case_key] = {
stem = stem_nfd, ending = ending_nfd, stress = eff_stress,
}
end
-- Determine which stems to use for stem notation (-, -xx).
-- Need both clean and stressed versions for smart stem selection.
-- If this slot's natural ending would trigger palatalization, pre-palatalize
-- both stem versions so that "-xxx" overrides produce the correct palatalised form.
local cur_stem_clean = (i >= 8) and plstem_clean or stem_clean
local cur_stem_stress = (i >= 8) and plstem_stress or stem_stress
-- Keep original non-palatalized versions for override processing
local orig_stem_clean = cur_stem_clean
local orig_stem_stress = cur_stem_stress
if end_list[i][1] ~= nil and should_palatalize(nfd(end_list[i][1])) then
cur_stem_clean = nfc(palatalize_stem(nfd(cur_stem_clean)))
cur_stem_stress = nfc(palatalize_stem(nfd(cur_stem_stress)))
end
-- Process value: override if provided, otherwise use generated form
if override_val then
-- Process special syntax (--, +, -, -xx, val1:val2)
-- Pass both palatalized and original stems for proper processing
local ov_forms, ov_comp = process_val(override_val, generated_form, cur_stem_clean, cur_stem_stress, orig_stem_clean, orig_stem_stress)
forms[case_key] = ov_forms
-- The generated composition describes a form the override just
-- replaced; keep it only when the override reproduces a
-- stem+ending split of its own.
compositions[case_key] = ov_comp
else
forms[case_key] = process_val(generated_form, nil, nil, nil, nil, nil)
end
end
-- Family plural of a surname, kept apart from the ordinary plural
-- until add_family_forms joins the two. A plural slot the editor
-- overrides is left as written.
if surname then
family_forms = {}
for _, set in ipairs(family_plural[ending_key]) do
local set_key = set.endings
-- After stem-final j the glide i of the endings is absorbed.
if set_key == "par3_is" and last_base_char(plstem_clean) == "j" then
set_key = "par3_jys"
end
local set_endings = endings[set_key]
for n = 1, 7 do
local case_key = case_keys[n + 7]
if not overrides[case_key] then
local ed = set_endings[n + 7]
local stem_nfd, ending_nfd
if set.stress[n] == "E" and ed[2] then
stem_nfd, ending_nfd = nfd(plstem_clean), nfd(ed[2])
else
stem_nfd, ending_nfd = nfd(plstem_stress), nfd(ed[1])
end
if should_palatalize(ending_nfd) then
stem_nfd = palatalize_stem(stem_nfd)
end
family_forms[case_key] = family_forms[case_key] or {}
iut.insert_form_into_list(family_forms[case_key], {
form = nfc(make_form(stem_nfd, ending_nfd)),
footnotes = {FAMILY_NOTE},
})
end
end
end
end
end
-- ── 8–10. Secondary local case forms (illative, allative, adessive) ────────
-- Hidden by default; shown when at least one slot is explicitly requested.
if not indeclinable then
local function gen_sec(stress_loc, ed, use_plstem)
-- A list of ending pairs gives one form per pair.
if type(ed[1]) == "table" then
local variants = {}
for _, pair in ipairs(ed) do
table.insert(variants, gen_sec(stress_loc, pair, use_plstem))
end
return table.concat(variants, ", ")
end
local cur_stress = use_plstem and plstem_stress or stem_stress
local cur_clean = use_plstem and plstem_clean or stem_clean
if ed.short_stem then
cur_stress, cur_clean = gen_short_stem, gen_short_stem
end
local stem_nfd, ending_nfd
if stress_loc == "S" then
stem_nfd, ending_nfd = nfd(cur_stress), nfd(ed[1])
elseif ed[2] then
stem_nfd, ending_nfd = nfd(cur_clean), nfd(ed[2])
else
stem_nfd, ending_nfd = nfd(cur_stress), nfd(ed[1])
end
if should_palatalize(ending_nfd) then stem_nfd = palatalize_stem(stem_nfd) end
return make_form(stem_nfd, ending_nfd)
end
-- Illative
local ill_ov_sg, ill_ov_pl = overrides["ill_s"], overrides["ill_p"]
if ill_ov_sg or ill_ov_pl then
local ill_ed = ill_endings[ending_key]
local ill_map = ill_stress_map[ap] or {"S","S"}
if ill_ov_sg then
local def = gen_sec(ill_map[1], ill_ed[1], false)
forms["ill_s"] = process_val(ill_ov_sg, def, stem_clean, stem_stress, stem_clean, stem_stress)
end
if ill_ov_pl then
local def = gen_sec(ill_map[2], ill_ed[2], true)
forms["ill_p"] = process_val(ill_ov_pl, def, plstem_clean, plstem_stress, plstem_clean, plstem_stress)
end
end
-- Allative
local all_ov_sg, all_ov_pl = overrides["all_s"], overrides["all_p"]
if all_ov_sg or all_ov_pl then
local all_ed = all_endings[ending_key]
if all_ov_sg then
local def = gen_sec(all_stress_map[ap] or "S", all_ed, false)
forms["all_s"] = process_val(all_ov_sg, def, stem_clean, stem_stress, stem_clean, stem_stress)
end
if all_ov_pl then
-- Every form of the genitive plural, an overridden one
-- included, gives one allative: -ų → -ump, -ų̃ → -um̃p.
local derived = {}
for _, form_obj in ipairs(forms["gen_p"] or {}) do
local form_nfd = nfd(form_obj.form)
local tone = TILDE
local base = rmatch(form_nfd, "^(.*)ų" .. TILDE .. "$")
if not base then
base, tone = rmatch(form_nfd, "^(.*)ų$"), ""
end
if base then
table.insert(derived, make_form(base, "um" .. tone .. "p"))
end
end
local def = derived[1] and table.concat(derived, ", ") or nil
forms["all_p"] = process_val(all_ov_pl, def, plstem_clean, plstem_stress, plstem_clean, plstem_stress)
end
end
-- Adessive
local ade_ov_sg, ade_ov_pl = overrides["ade_s"], overrides["ade_p"]
if ade_ov_sg or ade_ov_pl then
local ade_ed = ade_endings[ending_key]
local ade_map = ade_stress_map[ap] or {"S","S"}
if ade_ov_sg then
local def = gen_sec(ade_map[1], ade_ed[1], false)
forms["ade_s"] = process_val(ade_ov_sg, def, stem_clean, stem_stress, stem_clean, stem_stress)
end
if ade_ov_pl then
local def = gen_sec(ade_map[2], ade_ed[2], true)
forms["ade_p"] = process_val(ade_ov_pl, def, plstem_clean, plstem_stress, plstem_clean, plstem_stress)
end
end
end
-- ── 11. Build result structure ───────────────────────────────────────────
local result = {
forms = forms,
lemma = lemma_nfc,
ap = ap,
indeclinable = indeclinable,
gender = common_gender and "mfbysense" or gender,
decl_roman = decl_roman,
number_restr = number_restr,
family_forms = family_forms,
-- appendix_row support (not preserved across merge_alternant_results):
compositions = compositions,
stem_accented = stem_stress,
plstem_accented = plstem_stress,
}
-- Category-relevant facts; one entry per declension pass, preserved
-- across merge_alternant_results and consumed by compute_categories.
local overridden = {}
for slot in pairs(overrides) do overridden[slot] = true end
local genpl_relic = false
if (ending_key == "par9_is" or ending_key == "par10_is") and forms["gen_p"] then
-- Unpalatalized -ų in the i-declension genitive plural marks the
-- consonant-stem relic type (dantų̃, naktų̃ ...); -ių (including
-- -čių/-džių) is the regular i-stem ending.
for _, fo in ipairs(forms["gen_p"]) do
local bare = strip_ac(nfd(fo.form))
if rfind(bare, "ų$") and not rfind(bare, "ių$") then
genpl_relic = true
end
end
end
result.catinfo = {{
ending_key = ending_key,
ap = ap,
indeclinable = indeclinable,
gender_tag = gender_tag,
common_gender = common_gender or nil,
number_restr = number_restr,
overridden = overridden,
genpl_relic = genpl_relic,
decl_override = decl_override and true or nil,
lemma_bare = nfc(lemma_bare),
}}
-- A whole-table footnote (".[note]") goes on every form, overrides included.
-- Lemma and AP footnotes have no cell of their own: they become qualifiers on
-- the headword line (result.lemma_footnotes, result.gender_footnotes).
if whole_footnotes then
for _, form_list in pairs(result.forms) do
for _, form_obj in ipairs(form_list) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes, whole_footnotes)
end
end
for _, form_list in pairs(result.family_forms or {}) do
for _, form_obj in ipairs(form_list) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes, whole_footnotes)
end
end
end
-- Headword-line qualifiers: lemma_footnotes on the head term,
-- gender_footnotes (AP) on the gender/AP badge.
result.lemma_footnotes = combo.lemma_footnotes
result.gender_footnotes = combo.ap_footnotes
table.insert(all_results, result)
end -- for _, combo in ipairs(combinations)
if #all_results == 1 then
return all_results[1]
end
return merge_alternant_results(all_results)
end
-- =============================================================================
-- Alternant support: ((alt1;alt2;...))
-- =============================================================================
-- Merge multiple decline results into one by unioning form lists per slot.
-- Used for (( )) alternants and for the lemma/AP variants of one pattern
-- (see decline_single_pattern).
function merge_alternant_results(results)
local merged_forms = {}
for _, result in ipairs(results) do
for slot, form_list in pairs(result.forms) do
if not merged_forms[slot] then merged_forms[slot] = {} end
for _, form_obj in ipairs(form_list) do
iut.insert_form_into_list(merged_forms[slot], form_obj)
end
end
end
local lemmas, seen_l = {}, {}
for _, r in ipairs(results) do
if not seen_l[r.lemma] then seen_l[r.lemma] = true; table.insert(lemmas, r.lemma) end
end
local ap_strs, seen_ap = {}, {}
for _, r in ipairs(results) do
if r.ap and r.ap > 0 then
local s = tostring(r.ap)
if not seen_ap[s] then seen_ap[s] = true; table.insert(ap_strs, s) end
end
end
local merged_lemma_footnotes, merged_gender_footnotes
for _, r in ipairs(results) do
merged_lemma_footnotes = iut.combine_footnotes(merged_lemma_footnotes, r.lemma_footnotes)
merged_gender_footnotes = iut.combine_footnotes(merged_gender_footnotes, r.gender_footnotes)
end
local merged_catinfo = {}
for _, r in ipairs(results) do
for _, ci in ipairs(r.catinfo or {}) do
table.insert(merged_catinfo, ci)
end
end
local merged_family
for _, r in ipairs(results) do
for slot, form_list in pairs(r.family_forms or {}) do
merged_family = merged_family or {}
merged_family[slot] = merged_family[slot] or {}
for _, form_obj in ipairs(form_list) do
iut.insert_form_into_list(merged_family[slot], form_obj)
end
end
end
local first = results[1]
return {
forms = merged_forms,
family_forms = merged_family,
lemma = table.concat(lemmas, " / "),
ap = #ap_strs == 1 and tonumber(ap_strs[1]) or 0,
ap_display = #ap_strs > 1 and table.concat(ap_strs, " // ") or nil,
indeclinable = false,
gender = first.gender,
decl_roman = first.decl_roman,
number_restr = first.number_restr,
lemma_footnotes = merged_lemma_footnotes,
gender_footnotes = merged_gender_footnotes,
catinfo = merged_catinfo,
}
end
-- Join the family plural of a surname to the ordinary plural: its forms follow
-- the ordinary ones in each slot, and a form the ordinary plural already has
-- is not repeated (it then serves both readings and carries no footnote).
local function add_family_forms(result)
local family_forms = result.family_forms
if not family_forms then return result end
for slot, form_list in pairs(family_forms) do
local slot_forms = result.forms[slot]
if slot_forms then
for _, form_obj in ipairs(form_list) do
local present = false
for _, existing in ipairs(slot_forms) do
if existing.form == form_obj.form then
present = true
break
end
end
if not present then
table.insert(slot_forms, form_obj)
end
end
end
end
result.family_forms = nil
return result
end
-- Split text at commas not nested inside <...> or [...].
-- Used to separate alternants inside ((...)).
local function split_top_level_commas(text)
local parts, depth_a, depth_s, cur = {}, 0, 0, {}
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
for i = 1, ulen(text) do
local ch = usub(text, i, i)
if ch == "<" then depth_a = depth_a + 1; table.insert(cur, ch)
elseif ch == ">" then depth_a = math.max(0, depth_a - 1); table.insert(cur, ch)
elseif ch == "[" then depth_s = depth_s + 1; table.insert(cur, ch)
elseif ch == "]" then depth_s = math.max(0, depth_s - 1); table.insert(cur, ch)
elseif ch == "," and depth_a == 0 and depth_s == 0 then
table.insert(parts, table.concat(cur)); cur = {}
else
table.insert(cur, ch)
end
end
table.insert(parts, table.concat(cur))
return parts
end
-- Process a ((...)) alternant string (already stripped of outer parentheses).
-- Alternants are separated by top-level commas.
-- Every alternant must use angle-bracket format: word<type,AP.tags> [word<type,AP.tags> ...]
-- Single-word example: nãmas<n,4>
-- Multiword example: gimtóji<a,4> kalbà<n,4>
local function process_alternants(alternant_text, unescape)
local alt_results = {}
for _, part in ipairs(split_top_level_commas(alternant_text)) do
part = trim(part)
if part ~= "" then
if not rfind(part, "<[^>]+>") then
error("lt-ndecl: each alternant inside (( )) must use angle-bracket format (e.g. nãmas<n,4>), got: '" .. part .. "'")
end
local parsed = parse_multiword(part, unescape)
if parsed.mode == "single" then
-- No spaces: single word with <type,AP> — force as one-word multiword
local word = parse_word_component(part, unescape)
parsed = {mode = "multi", words = {word}}
end
local r = export.decline_multiword_pattern(parsed, unescape)
table.insert(alt_results, r)
end
end
if #alt_results == 0 then error("lt-ndecl: empty alternant list in (( ))") end
if #alt_results == 1 then return alt_results[1] end
return merge_alternant_results(alt_results)
end
-- =============================================================================
-- Automatic categorization
-- =============================================================================
-- Words whose paradigm is not what their surface ending suggests, keyed by
-- accent-stripped lemma. "suppress": irregular category only, no
-- declension-class or class+AP categories (accentuation-paradigm categories
-- are kept). "keep": irregular category in addition to the normal ones.
local irregular_lemmas = {
["mėnuo"] = "suppress",
["žmogus"] = "suppress",
["petys"] = "keep",
["viešpats"] = "keep",
}
-- Classes whose declension is the feminine type; an explicit '.m' on one of
-- these marks the vaidilà/dė̃dė type (masculine agreement, feminine-form
-- declension).
local feminine_form_keys = {
par6_a = true, par7_ia = true, par7_i = true, par8_e = true, par12_er = true,
}
-- Compute the category list for an array of headword results (one per
-- ';'-separated pattern; alternant and colon-list members contribute one
-- catinfo entry each). Returns full category names without the "Category:"
-- prefix; all name material comes from localization.categories.
local function compute_categories(results)
local lc = localization.categories
local cats, seen = {}, {}
local function ins(name)
if not name then return end
local full = name .. " " .. localization.langname
if not seen[full] then
seen[full] = true
table.insert(cats, full)
end
end
local infos = {}
for _, r in ipairs(results) do
for _, ci in ipairs(r.catinfo or {}) do
table.insert(infos, ci)
end
end
local class_seen, ap_seen = {}, {}
local n_classes, n_aps = 0, 0
for _, ci in ipairs(infos) do
if ci.indeclinable then
ins(lc.indeclinable)
else
local irr = irregular_lemmas[ci.lemma_bare]
if irr then
ins(lc.irregular)
end
local class_name = ci.ending_key and lc.class[ci.ending_key]
local has_ap = ci.ap >= 1 and ci.ap <= 4
if class_name and irr ~= "suppress" and not ci.decl_override then
ins(class_name)
if has_ap then
ins(lc.class_ap:format(class_name, ci.ap))
end
if not class_seen[class_name] then
class_seen[class_name] = true
n_classes = n_classes + 1
end
end
if has_ap then
ins(lc.ap:format(ci.ap))
if not ap_seen[ci.ap] then
ap_seen[ci.ap] = true
n_aps = n_aps + 1
end
end
if ci.genpl_relic then
ins(lc.relic_genpl[ci.ending_key])
end
if ci.gender_tag == "m" and feminine_form_keys[ci.ending_key] then
ins(lc.gender_mismatch)
end
if ci.number_restr == "pl" then
ins(lc.pluralia_tantum)
elseif ci.number_restr == "sg" then
ins(lc.singularia_tantum)
end
local ov = ci.overridden or {}
if ov.ill_s or ov.ill_p then ins(lc.case_form.ill) end
if ov.all_s or ov.all_p then ins(lc.case_form.all) end
if ov.ade_s or ov.ade_p then ins(lc.case_form.ade) end
end
end
if n_aps > 1 then
ins(lc.multiple_ap)
end
if n_classes > 1 then
ins(lc.multiple_decl)
end
return cats
end
-- =============================================================================
-- Pattern list handling
-- =============================================================================
-- Generate declension data for multiple patterns
function export.get_headword_data(input_str)
local COMMA_PH = "\001"
local DOT_PH = "\002"
input_str = rsub(input_str, "\\,", COMMA_PH)
input_str = rsub(input_str, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
-- Split by unescaped semicolons
local patterns = rsplit(input_str, ";")
local results = {}
for _, pattern_str in ipairs(patterns) do
pattern_str = trim(pattern_str)
if pattern_str ~= "" then
local alternant_text = rmatch(pattern_str, "^%(%((.*)%)%)$")
local result
if alternant_text then
result = process_alternants(alternant_text, unescape)
else
local parsed = parse_multiword(pattern_str, unescape)
if parsed.mode == "single" then
result = decline_single_pattern(parsed.raw_input, unescape)
else
result = export.decline_multiword_pattern(parsed, unescape)
end
end
table.insert(results, add_family_forms(result))
end
end
-- Page categories derived from the same inputs (named field on the
-- returned array; inserted on the page by Module:lt-headword only).
results.categories = compute_categories(results)
return results
end
-- =============================================================================
-- Wikitext output
-- =============================================================================
function export.show(frame)
local parent_args = frame:getParent().args
local params = {
[1] = {required = true, default = "nãmas,4"},
["id"] = {},
["pagename"] = {},
}
local args = m_para.process(parent_args, params)
local input = args[1]
local COMMA_PH = "\001"
local DOT_PH = "\002"
input = rsub(input, "\\,", COMMA_PH)
input = rsub(input, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
-- Parse input: detect ((...)) alternants or fall through to single/multi-word
local result
local alternant_text = rmatch(input, "^%(%((.*)%)%)$")
if alternant_text then
result = process_alternants(alternant_text, unescape)
else
local parsed = parse_multiword(input, unescape)
if parsed.mode == "single" then
result = decline_single_pattern(parsed.raw_input, unescape)
else
result = export.decline_multiword_pattern(parsed, unescape)
end
end
add_family_forms(result)
-- Overridden case forms are tracked, not categorized:
-- [[Special:WhatLinksHere/Wiktionary:Tracking/lt-ndecl/override/genpl]]
local track
for _, ci in ipairs(result.catinfo or {}) do
for slot in pairs(ci.overridden or {}) do
if not lt_noun_secondary_slots[slot] then
track = track or require("Module:debug/track")
track("lt-ndecl/override/" .. (slot_external_names[slot] or slot))
end
end
end
-- Build active slot list: always include primary cases;
-- include secondary cases only when data is present.
local active_slots = {}
for _, entry in ipairs(lt_noun_slot_list) do
local slot = entry[1]
if not lt_noun_secondary_slots[slot] or result.forms[slot] then
table.insert(active_slots, entry)
end
end
-- Render forms to linked wikitext strings (also adds ACCEL info and footnotes)
iut.show_forms(result.forms, {
lang = lang,
lemmas = {{form = result.lemma}},
slot_list = active_slots,
skip_slot = function(slot)
if result.number_restr == "pl" and rfind(slot, "_s$") then return true end
if result.number_restr == "sg" and rfind(slot, "_p$") then return true end
return false
end,
})
-- Build title with metadata
local title_parts = {}
if result.gender then
table.insert(title_parts, localization.full_gender[result.gender])
end
if result.decl_roman and not result.indeclinable then
table.insert(title_parts, localization.full_declension[result.decl_roman])
end
if not result.indeclinable then
local ap_str = result.ap_display or (result.ap > 0 and tostring(result.ap)) or nil
if ap_str then
table.insert(title_parts, localization.accent_paradigm .. " " .. ap_str)
end
end
if result.indeclinable then
table.insert(title_parts, "không biến cách")
end
result.forms.title = table.concat(title_parts, ", ")
local show_ill = result.forms["ill_s"] ~= nil or result.forms["ill_p"] ~= nil
local show_all = result.forms["all_s"] ~= nil or result.forms["all_p"] ~= nil
local show_ade = result.forms["ade_s"] ~= nil or result.forms["ade_p"] ~= nil
return make_table(result.forms, result.number_restr, show_ill, show_all, show_ade)
end
-- =============================================================================
-- Appendix row output (for [[Appendix:Lithuanian accentuation]])
-- =============================================================================
-- Renders one wikitable row holding the seven case forms of one declension
-- pattern in one number:
-- {{lt-ndecl-row|výras,1|s}}
-- Arg 1 takes a simple {{lt-ndecl}} pattern (no semicolons, no colon-list
-- variants); arg 2 selects the number ("s" = singular, "p" = plural).
-- The first cell holds the accented stem and a hyphen (|label= replaces it).
-- The row is right-aligned in monospace so the endings line up; each form is
-- unlinked {{m|lt||...}}, the stressed morpheme (stem or ending) in bold on a
-- palette background.
-- Reads frame.args. {{lt-ndecl-row}} forwards each parameter by name, so a
-- parameter added here must be added to the template too.
function export.appendix_row(frame)
local params = {
[1] = {required = true},
[2] = {required = true},
["label"] = {},
["mark"] = {},
}
local args = m_para.process(frame.args, params)
local number = args[2]
if number ~= "s" and number ~= "p" then
error("lt-noun appendix_row: parameter 2 must be 's' (singular) or 'p' (plural), got '"
.. tostring(number) .. "'")
end
-- mark= selects which morpheme the highlight falls on: "stress" (default)
-- highlights the stressed morpheme, "ending" always highlights the ending.
local mark = args.mark or "stress"
if mark ~= "stress" and mark ~= "ending" then
error("lt-noun appendix_row: mark= must be 'stress' or 'ending', got '"
.. tostring(mark) .. "'")
end
local results = export.get_headword_data(args[1])
if #results > 1 then
error("lt-noun appendix_row: only a single pattern is supported (no semicolons)")
end
local result = results[1]
if not result.compositions then
error("lt-noun appendix_row: pattern produced no composition data "
.. "(colon-list variants and alternants are not supported)")
end
local function m_tpl(display)
return frame:expandTemplate{ title = "m", args = {"lt", "", display} }
end
-- Stressed-morpheme highlight: palette variable so dark mode adapts;
-- the hex fallback covers wikis where the palette variables are undefined.
local function hl(s)
return "<span style=\"background-color:var(--wikt-palette-purple-3, #e8dbfb)\">'''" .. s .. "'''</span>"
end
local label = args.label
if not label then
local stem_src = result.stem_accented or result.lemma
label = m_tpl(nfc(makeDisplayText(stem_src)) .. "-")
end
local cells = {}
for _, key in ipairs({"nom", "gen", "dat", "acc", "ins", "loc", "voc"}) do
local slot = key .. "_" .. number
local comp = result.compositions[slot]
local cell
if comp and comp.whole then
cell = m_tpl(nfc(comp.whole))
elseif comp then
local stem_disp = nfc(makeDisplayText(comp.stem))
local ending_disp = comp.ending ~= "" and nfc(makeDisplayText(comp.ending)) or ""
local display
if mark == "ending" then
display = ending_disp ~= "" and (stem_disp .. hl(ending_disp)) or stem_disp
elseif comp.stress == "E" then
display = stem_disp .. hl(ending_disp)
else
display = hl(stem_disp) .. ending_disp
end
cell = m_tpl(display)
else
-- Overridden or absent slot: fall back to the plain merged form.
local form_list = result.forms[slot]
if form_list and form_list[1] and form_list[1].form then
cell = m_tpl(form_list[1].form)
else
cell = "—"
end
end
table.insert(cells, cell)
end
return "|- style=\"font-family: monospace; text-align: right;\"\n| " .. label .. "\n| " .. table.concat(cells, " || ")
end
-- Expose multiword parsing for testing purposes
function export.parse_multiword_for_testing(input_str)
local COMMA_PH = "\001"
local DOT_PH = "\002"
input_str = rsub(input_str, "\\,", COMMA_PH)
input_str = rsub(input_str, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
local parsed = parse_multiword(input_str, unescape)
if parsed.mode == "single" then
return {mode = "single", raw_input = parsed.raw_input}
else
-- Return structured info about each word
local word_info = {}
for i, word in ipairs(parsed.words) do
table.insert(word_info, {
index = i,
type = word.type,
given_form = word.given_form,
lemma = word.lemma,
link_target = word.link_target,
ap = word.ap,
control_tags = word.control_tags,
genitive_and_tags = word.genitive_and_tags,
})
end
return {mode = "multi", words = word_info}
end
end
-- =============================================================================
-- Multiword phrase declension
-- =============================================================================
-- Generate forms for a multiword phrase (e.g., "baltasis lokys")
-- Returns a result structure similar to decline_single_pattern
function export.decline_multiword_pattern(parsed, unescape_func)
local words = parsed.words
-- Find the head noun (rightmost noun)
local head_noun_idx = nil
for i = #words, 1, -1 do
if words[i].type == "n" then
head_noun_idx = i
break
end
end
if not head_noun_idx then
error("lt-ndecl: multiword phrase must contain at least one noun")
end
local head_noun = words[head_noun_idx]
-- Decline the head noun to get its forms and metadata
-- Build the pattern string for the head noun
-- Format: given_form,AP[.tag1][.tag2]...[,genitive[.tag1][.tag2]...]
-- Use given_form (not lemma) to preserve capitalization for proper nouns
local noun_pattern = head_noun.given_form .. "," .. tostring(head_noun.ap)
if #head_noun.control_tags > 0 then
noun_pattern = noun_pattern .. "." .. table.concat(head_noun.control_tags, ".")
end
-- Add genitive parameter if present (for Decl V)
if head_noun.genitive_and_tags then
noun_pattern = noun_pattern .. "," .. head_noun.genitive_and_tags
end
local noun_result = decline_single_pattern(noun_pattern, unescape_func)
-- Analyze adjectives and collect their features
local adj_features = {} -- indexed by position in words array
for i = 1, #words do
if words[i].type == "a" then
adj_features[i] = analyze_adjective(words[i])
end
end
-- Collect numeral components' agreement paradigms (from Module:lt-numeral).
-- Only numerals that agree with the quantified noun in gender/number/case are
-- accepted here; the noun-governing numerals (dešimt, the tens, -lika, pus-
-- fractions) take the genitive of the quantified noun, a different
-- construction, and are rejected with a pointer.
local NUM_AGREEING_TYPES = {
adj_full = true, ord = true, card = true, cardpl = true, du = true, trys = true,
}
local num_agreement = {} -- indexed by position in words array
for i = 1, #words do
if words[i].type == "num" then
local m_lt_num = require("Module:lt-numeral")
local data = m_lt_num.get_agreement_forms(words[i].lemma)
if not data then
error("lt-ndecl: <num> component '" .. words[i].lemma ..
"' is not a recognized numeral (check the link target is a numeral lemma)")
end
if not NUM_AGREEING_TYPES[data.type] then
error("lt-ndecl: numeral '" .. words[i].lemma .. "' (type " .. data.type ..
") governs the genitive of the quantified noun rather than agreeing with " ..
"it, so it cannot be a <num> component; the <num> component supports only " ..
"agreeing numerals (1–9, ordinals, du, trys, and the cardinal plurals)")
end
num_agreement[i] = data
end
end
-- Generate the phrase slot by slot, each adjective in the noun's case/number
local multiword_forms = {}
local multiword_family
-- Helper: numeral form for a given noun slot, agreeing in the head noun's
-- gender and the slot's number and case. Returns nil when the numeral has no
-- such form (e.g. the plural-only cardinals in a singular slot, or any
-- vocative/local-case slot — numerals decline in six cases only), which drops
-- that slot from the phrase (so "nine crafts" comes out plural-only).
local NUM_CASES = { nom = true, gen = true, dat = true, acc = true, ins = true, loc = true }
local function get_num_form(num_idx, slot_key, head_gender)
if head_gender ~= "m" and head_gender ~= "f" then
error("lt-ndecl: numeral agreement requires a masculine or feminine "
.. "head noun; a common-gender ('mfbysense') head cannot select "
.. "the numeral's form")
end
local case, number = rmatch(slot_key, "^(%a+)_(%a+)$")
if not case or not NUM_CASES[case] then return nil end
local data = num_agreement[num_idx]
local pk
local nt = data.type
if nt == "adj_full" or nt == "ord" then
pk = "indef_" .. head_gender .. "_" .. number
elseif nt == "card" or nt == "cardpl" then
if number ~= "p" then return nil end
pk = "indef_" .. head_gender .. "_p"
elseif nt == "du" or nt == "trys" then
if number ~= "p" then return nil end
pk = "com_" .. head_gender
else
return nil
end
local paradigm = data.forms[pk]
if not paradigm then return nil end
local flist = paradigm[case]
if not flist or not flist[1] then return nil end
return flist[1].form
end
-- Helper: the adjective's forms for a specific slot, a list of form objects
-- (the long form first, then any colloquial short variant)
local function get_adj_form(adj_idx, slot_key)
local adj = words[adj_idx]
local features = adj_features[adj_idx]
-- Load adjective module
local m_lt_adj = require("Module:lt-adjective")
-- Build stem parameter
local stem_param = nil
for _, tag in ipairs(adj.control_tags) do
if rfind(tag, "^stem:") then
local _, stem_ac = process_input(rsub(tag, "^stem:", ""))
stem_param = stem_ac
break
end
end
-- Generate only the definite and compared forms the given form needs
local suppress_def = (features.definiteness == "indef")
local suppress_comp = (features.degree == "pos")
-- Generate full declension for the adjective
local adj_all_forms = m_lt_adj.decline_forms(
adj.lemma, adj.ap,
suppress_def,
suppress_comp,
stem_param
)
-- Select the appropriate form table based on features
local form_table_key
if features.definiteness == "indef" then
if features.degree == "pos" then
form_table_key = "pos_indef_" .. features.gender
elseif features.degree == "comp" then
form_table_key = "comp_indef_" .. features.gender
else -- sup
form_table_key = "sup_indef_" .. features.gender
end
else -- def
if features.degree == "pos" then
form_table_key = "pos_def_" .. features.gender
elseif features.degree == "comp" then
form_table_key = "comp_def_" .. features.gender
else -- sup
form_table_key = "sup_def_" .. features.gender
end
end
local form_table = adj_all_forms[form_table_key]
if not form_table then
local names = {pos = "positive", comp = "comparative", sup = "superlative",
indef = "indefinite", def = "definite", m = "masculine", f = "feminine"}
error("lt-ndecl: internal error: Module:lt-adjective gives no " .. names[features.degree] .. " "
.. names[features.definiteness] .. " " .. names[features.gender] .. " forms of '" .. adj.lemma
.. "', although '" .. adj.given_form .. "' is one; please report it at Module talk:lt-noun")
end
local form_list = form_table[slot_key]
if not form_list or not form_list[1] then
-- This slot doesn't exist for this adjective form (e.g., vocative for comparative)
return nil
end
-- Preserve capitalization from given_form: where the adjective is
-- written capitalized (a proper noun such as "Aukščiáusioji"), every
-- variant of the generated form is capitalized, short variants included.
local capitalize = adj.given_form ~= lcfirst(adj.given_form)
local out = {}
for _, fobj in ipairs(form_list) do
table.insert(out, {form = capitalize and ucfirst(fobj.form) or fobj.form, footnotes = fobj.footnotes})
end
return out
end
-- Generate forms for all 14 slots (+ secondary local cases if present)
local slot_keys = {
"nom_s","gen_s","dat_s","acc_s","ins_s","loc_s","voc_s",
"nom_p","gen_p","dat_p","acc_p","ins_p","loc_p","voc_p",
}
-- Check if noun has secondary local case forms
if noun_result.forms["ill_s"] or noun_result.forms["ill_p"] then
table.insert(slot_keys, "ill_s")
table.insert(slot_keys, "ill_p")
end
if noun_result.forms["all_s"] or noun_result.forms["all_p"] then
table.insert(slot_keys, "all_s")
table.insert(slot_keys, "all_p")
end
if noun_result.forms["ade_s"] or noun_result.forms["ade_p"] then
table.insert(slot_keys, "ade_s")
table.insert(slot_keys, "ade_p")
end
for _, slot_key in ipairs(slot_keys) do
local noun_forms = noun_result.forms[slot_key]
if noun_forms then
-- The forms of each word in this slot (lists of form objects)
local variants = {}
local all_parts_valid = true
for i = 1, #words do
if words[i].type == "inv" then
-- Invariant word: use as-is
variants[i] = {{form = words[i].given_form}}
elseif words[i].type == "a" then
-- Adjective: generate the appropriate forms
local adj_forms = get_adj_form(i, slot_key)
if adj_forms then
variants[i] = adj_forms
else
-- Slot doesn't exist for this adjective (e.g., comparative vocative)
-- Skip this entire slot
all_parts_valid = false
break
end
elseif words[i].type == "num" then
-- Numeral: generate the form agreeing with the head noun's
-- gender and this slot's number/case
local num_form = get_num_form(i, slot_key, noun_result.gender)
if num_form then
variants[i] = {{form = num_form}}
else
-- No agreeing numeral form for this slot (e.g. a singular
-- slot for a plural-only cardinal): drop the slot
all_parts_valid = false
break
end
elseif words[i].type == "n" and i == head_noun_idx then
-- Head noun: its first form (noun_forms is a list of
-- {form=..., footnotes=...})
variants[i] = {noun_forms[1]}
else
-- A second noun is not supported
error("lt-ndecl: multiple nouns in multiword phrase not supported")
end
end
if all_parts_valid then
-- One phrase per variant: the k-th phrase takes each word's k-th
-- form, or its first where it has fewer (an adjective's long form
-- gives the first phrase, its colloquial short form the second);
-- each phrase carries the footnotes of the forms it is made of.
local count = 1
for i = 1, #words do
count = math.max(count, #variants[i])
end
local phrase_list = {}
for k = 1, count do
local phrase_parts = {}
local footnotes = iut.combine_footnotes(nil, noun_forms[1].footnotes)
for i = 1, #words do
local v = variants[i][k] or variants[i][1]
phrase_parts[i] = v.form
if i ~= head_noun_idx then
footnotes = iut.combine_footnotes(footnotes, v.footnotes)
end
end
iut.insert_form_into_list(phrase_list,
{form = table.concat(phrase_parts, " "), footnotes = footnotes})
end
multiword_forms[slot_key] = phrase_list
-- A surname head brings its family plural into the phrase
-- (the other words in their first form).
local parts = {}
for i = 1, #words do
parts[i] = variants[i][1].form
end
local head_family = noun_result.family_forms and noun_result.family_forms[slot_key]
if head_family then
multiword_family = multiword_family or {}
multiword_family[slot_key] = {}
for _, form_obj in ipairs(head_family) do
parts[head_noun_idx] = form_obj.form
table.insert(multiword_family[slot_key], {
form = table.concat(parts, " "),
footnotes = form_obj.footnotes,
})
end
end
end
-- If not all_parts_valid, the slot is not added to multiword_forms
end
end
-- Build result structure similar to decline_single_pattern
-- Build lemma string from all given forms
local lemma_parts = {}
for _, w in ipairs(words) do
table.insert(lemma_parts, w.given_form)
end
return {
forms = multiword_forms,
family_forms = multiword_family,
lemma = table.concat(lemma_parts, " "),
ap = noun_result.ap,
indeclinable = false, -- multiword phrases are always declinable
gender = noun_result.gender,
decl_roman = noun_result.decl_roman,
number_restr = noun_result.number_restr,
lemma_footnotes = noun_result.lemma_footnotes,
gender_footnotes = noun_result.gender_footnotes,
-- The phrase declines with its head noun; categorize accordingly.
catinfo = noun_result.catinfo,
}
end
-- =============================================================================
-- Testing functions
-- =============================================================================
-- Decline a noun for testing purposes (returns simple string forms)
function export.decline_for_testing(spec)
-- Handle escape sequences
local COMMA_PH = "\001"
local DOT_PH = "\002"
spec = rsub(spec, "\\,", COMMA_PH)
spec = rsub(spec, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
local result
local alternant_text = rmatch(spec, "^%s*%(%((.*)%)%)%s*$")
if alternant_text then
result = process_alternants(alternant_text, unescape)
else
-- Check if this is multiword mode
local parsed = parse_multiword(spec, unescape)
if parsed.mode == "multi" then
-- Multiword mode
result = export.decline_multiword_pattern(parsed, unescape)
else
-- Single-word mode
result = decline_single_pattern(spec, unescape)
end
end
add_family_forms(result)
-- Convert form objects to simple strings
local simple_forms = {}
for key, form_list in pairs(result.forms) do
if form_list and #form_list > 0 then
-- Collect all forms
local forms = {}
for _, form_obj in ipairs(form_list) do
table.insert(forms, form_obj.form)
end
-- Join with ", " if multiple
simple_forms[key] = table.concat(forms, ", ")
end
end
return simple_forms
end
return export
np6t7hymw8vzaha1a0mfy44y3end4qh
2576459
2576457
2026-11-09T01:38:20Z
Hiyuune
50834
2576459
Scribunto
text/plain
--[=[
Authorship: <TongcyDai>
Lithuanian noun declension module ({{lt-ndecl}}). Unicode handling, including
the partial NFD stem representation, comes from Module:lt-common.
Declension classes are keyed by the twelve-paradigm classification
("par1_as" ... "par12_er"); "AP 1-4" always refers to the accentuation
paradigms. Ambiguous lemma endings are resolved by the position-3
genitive-singular keyword ("io", "ies", "ers"); word-level irregulars
(šuõ, mė́nuo, žmogùs, petỹs ...) use slot overrides, not extra paradigms.
]=]
local export = {}
local m_string_utilities = require("Module:string utilities")
local m_links = require("Module:links")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local m_para = require("Module:parameters")
local lang = require("Module:languages").getByCode("lt")
local m_common = require("Module:lt-common")
-- Forward declaration: merges the results of (( )) alternants and of the
-- passes for colon-separated lemma/AP variants.
local merge_alternant_results
-- Use optimized string utilities (automatically uses string library when possible)
local rfind = m_string_utilities.find
local rsub = m_string_utilities.gsub
local rmatch = m_string_utilities.match
local rsplit = mw.text.split
-- String utility aliases
local uchar = m_string_utilities.char
local trim = m_string_utilities.trim
local lcfirst = m_string_utilities.lcfirst
local ucfirst = m_string_utilities.ucfirst
-- Import Unicode processing functions from lt-common
local process_input = m_common.process_input
local to_stem_ac = m_common.to_stem_ac
local to_stem_bare = m_common.to_stem_bare
local makeDisplayText = m_common.makeDisplayText
local has_accent = m_common.has_accent
-- Accent mark constants (combining characters) from lt-common
local GRAVE = m_common.GRAVE -- U+0300
local ACUTE = m_common.ACUTE -- U+0301
local TILDE = m_common.TILDE -- U+0303
-- =============================================================================
-- Multiword phrase parsing
-- =============================================================================
-- Parse wikilink [[target|text]] or [[text]] or plain text
-- Returns: link_target (or nil), display_text
local function parse_wikilink(text)
local link_target, display_text = rmatch(text, "^%[%[([^|%]]+)|([^%]]+)%]%]$")
if link_target then
return link_target, display_text
end
local simple_link = rmatch(text, "^%[%[([^%]]+)%]%]$")
if simple_link then
return simple_link, simple_link
end
return nil, text
end
-- Parse a single word component from multiword input
-- Format: word_text<type,params> or just word_text (invariant)
-- word_text can be: [[target|text]], [[text]], or plain text
-- Returns: {type, given_form, lemma, link_target, ap, control_tags}
-- given_form is converted to display notation (dot above i or j before an
-- accent), the notation of the generated forms, so either spelling is
-- recognized; the lemma and the link target are kept as written.
local function parse_word_component(word_str, unescape_func)
-- Check if there's a <...> control block
local word_text, control_block = rmatch(word_str, "^(.-)(<[^>]+>)$")
if not control_block then
-- No control block → invariant word
local link_target, display_text = parse_wikilink(word_str)
return {
type = "inv",
given_form = makeDisplayText(display_text),
lemma = nil,
link_target = link_target,
ap = nil,
control_tags = {},
genitive_and_tags = nil,
}
end
-- Extract control block content: <type,params>
local control_content = rmatch(control_block, "^<(.+)>$")
if not control_content then
error("lt-ndecl: malformed control block '" .. control_block .. "'")
end
-- Split by comma: type,ap[.tag1][.tag2][...][,genitive[.tag1][.tag2][...]]
local control_parts = rsplit(control_content, ",")
local word_type = trim(control_parts[1])
if word_type ~= "n" and word_type ~= "a" and word_type ~= "num" then
error("lt-ndecl: word type must be 'n' (noun), 'a' (adjective) or 'num' (numeral), got '" .. word_type .. "'")
end
-- Numeral component (<num>): no AP, genitive or other control parts.
-- Module:lt-numeral declines it to agree with the head noun (see
-- decline_multiword_pattern).
if word_type == "num" then
if control_parts[2] then
error("lt-ndecl: the <num> component takes no accent paradigm or tags " ..
"(the numeral is looked up automatically); got '" .. control_block .. "'")
end
local link_target, display_text = parse_wikilink(word_text)
return {
type = "num",
given_form = makeDisplayText(display_text),
lemma = link_target or display_text,
link_target = link_target,
ap = nil,
control_tags = {},
genitive_and_tags = nil,
}
end
-- Parse AP and control tags from position 2
local ap_and_tags = trim(control_parts[2] or "")
if ap_and_tags == "" then
error("lt-ndecl: missing accent paradigm in '" .. control_block .. "'")
end
local ap_parts = rsplit(ap_and_tags, "%.")
local ap = tonumber(ap_parts[1])
if not ap or ap < 1 or ap > 4 then
error("lt-ndecl: accent paradigm must be 1-4, got '" .. tostring(ap_parts[1]) .. "'")
end
-- Collect control tags from position 2 (after AP)
local control_tags = {}
for i = 2, #ap_parts do
local tag = trim(ap_parts[i])
if tag ~= "" then
table.insert(control_tags, unescape_func(tag))
end
end
-- Parse optional genitive (position 3) for Decl V nouns
local genitive_and_tags = nil
if control_parts[3] then
genitive_and_tags = trim(control_parts[3])
-- genitive_and_tags will be appended to pattern as third comma-separated part
end
-- Parse wikilink from word_text
local link_target, display_text = parse_wikilink(word_text)
-- Determine lemma:
-- - If there's a link [[lemma|given_form]], lemma is the link target
-- - Otherwise, lemma = given_form (they are the same)
local lemma = link_target or display_text
return {
type = word_type,
given_form = makeDisplayText(display_text),
lemma = lemma,
link_target = link_target,
ap = ap,
control_tags = control_tags,
genitive_and_tags = genitive_and_tags, -- May be nil for non-Decl V nouns
}
end
-- Parse multiword input and determine mode (single vs multi)
-- Returns: {mode, words} where words is an array of parsed components
local function parse_multiword(input_str, unescape_func)
-- Only a space outside [...] footnotes makes a multiword phrase
-- ("nãmas,3[used mainly in Aukštaitija]" is one word).
local dispatch_segs = put.parse_balanced_segment_run(input_str, "[", "]")
local has_space_outside_brackets = false
for i = 1, #dispatch_segs, 2 do -- odd indices: text outside [...]
if rfind(dispatch_segs[i], " ") then
has_space_outside_brackets = true
break
end
end
if not has_space_outside_brackets then
return {mode = "single", raw_input = input_str}
end
-- Multiword mode: split by spaces and parse each component
local word_strings = rsplit(input_str, " +")
local words = {}
for _, word_str in ipairs(word_strings) do
word_str = trim(word_str)
if word_str ~= "" then
table.insert(words, parse_word_component(word_str, unescape_func))
end
end
if #words == 0 then
error("lt-ndecl: multiword input is empty after parsing")
end
return {mode = "multi", words = words}
end
-- Analyze adjective form and extract grammatical features
-- Uses Module:lt-adjective's get_nominative_mapping function
-- Returns: {definiteness, degree, gender, number}
local function analyze_adjective(word_info)
local m_lt_adj = require("Module:lt-adjective")
-- Build stem parameter from control tags
local stem_param = nil
for _, tag in ipairs(word_info.control_tags) do
if rfind(tag, "^stem:") then
local _, stem_ac = process_input(rsub(tag, "^stem:", ""))
stem_param = stem_ac
break
end
end
-- Get nominative mapping
local success, mapping = pcall(m_lt_adj.get_nominative_mapping,
word_info.lemma, word_info.ap, stem_param)
if not success then
error("lt-ndecl: failed to analyze adjective '" .. word_info.lemma ..
"': " .. tostring(mapping))
end
-- Look up the given form
local features = mapping[word_info.given_form]
-- If not found, try with lowercase first letter (for proper nouns like "Aukščiausioji")
if not features then
local lowercase_form = lcfirst(word_info.given_form)
features = mapping[lowercase_form]
end
if not features then
error("lt-ndecl: given form '" .. word_info.given_form ..
"' is not a valid nominative form of '" .. word_info.lemma .. "," ..
word_info.ap .. "'. Please check that the link target [[" ..
word_info.lemma .. "]] is the correct base form (indefinite positive " ..
"masculine nominative singular).")
end
return features
end
-- =============================================================================
-- Localization strings (for easy translation)
-- =============================================================================
local localization = {
langname = "tiếng Litva", -- l10n: language name; prefixed to every category
declension = {
[1] = "I",
[2] = "II",
[3] = "III",
[4] = "IV",
[5] = "V",
},
-- Full descriptive strings
full_gender = {
m = "giống đực",
f = "giống cái",
mfbysense = "giống đực hoặc giống cái theo nghĩa", -- l10n
},
full_declension = {
I = "biến cách loại I",
II = "biến cách loại II",
III = "biến cách loại III",
IV = "biến cách loại IV",
V = "biến cách loại V",
},
accent_paradigm = "trọng âm mẫu hình",
-- Category names (without the language prefix). Every category this
-- module emits is built from the strings below; see compute_categories.
categories = {
-- l10n: declension-class categories, keyed by paradigm ending key
class = {
par1_as = "danh từ giống đực -as",
par2_ias = "danh từ giống đực -ias/-jas",
par2_jas = "danh từ giống đực -ias/-jas",
par3_is = "danh từ giống đực -is/-ys với số nhiều -iai",
par3_ys = "danh từ giống đực -is/-ys với số nhiều -iai",
par3_jys = "danh từ giống đực -is/-ys với số nhiều -iai",
par3_jis = "danh từ giống đực -is/-ys với số nhiều -iai",
par4_us = "danh từ giống đực -us",
par5_ius = "danh từ giống đực -ius/-jus",
par5_jus = "danh từ giống đực -ius/-jus",
par6_a = "danh từ giống cái -a",
par7_ia = "danh từ giống cái -ia/-i",
par7_i = "danh từ giống cái -ia/-i",
par8_e = "danh từ giống cái -ė",
par9_is = "danh từ giống cái -is",
par10_is = "danh từ giống đực -is với số nhiều -ys",
par11_uo = "danh từ giống đực -uo",
par12_er = "danh từ giống cái -uo/-ė",
},
ap = "danh từ với trọng âm mẫu hình %d", -- l10n
class_ap = "%s với trọng âm mẫu hình %d", -- l10n: class name + AP
-- l10n: i-declension consonant-stem relic genitive plural (dantų̃ type)
relic_genpl = {
par9_is = "danh từ giống cái -is vơi sinh cách số nhiều -ų",
par10_is = "danh từ giống đực -is vơi sinh cách số nhiều -ų",
},
indeclinable = "danh từ không biến cách", -- l10n
irregular = "danh từ bất quy tắc", -- l10n
multiple_ap = "danh từ với nhiều trọng âm mẫu hình", -- l10n
multiple_decl = "danh từ với nhiều biến cách", -- l10n
gender_mismatch = "danh từ với giống thực tế khác với giống biến tố", -- l10n
pluralia_tantum = "danh từ chỉ có số nhiều", -- l10n
singularia_tantum = "danh từ chỉ có số ít", -- l10n
-- l10n: secondary local cases (generated only on explicit request)
case_form = {
ill = "danh từ dạng nhập cách",
all = "danh từ dạng đích cách",
ade = "danh từ dạng cách kế cận",
},
},
}
-- =============================================================================
-- Accent helpers (partial NFD architecture)
-- =============================================================================
local nfd = to_stem_ac
local nfc = mw.ustring.toNFC
local strip_ac = to_stem_bare
local has_ac = has_accent
-- Is this codepoint an accent mark? (In partial NFD, only accents are combining)
local function is_accent(cp)
local c = uchar(cp)
return c == GRAVE or c == ACUTE or c == TILDE
end
-- =============================================================================
-- Palatalization helpers (d → dž, t → č before softening i)
-- Lithuanian d and t become dž and č before the softening marker i, i.e. when
-- i is followed by a back vowel (a, o, u and their ogonek/macron variants).
-- This does NOT apply when i is the vowel itself (-is, -ies, -imi, -į, etc.).
-- =============================================================================
-- Check whether an ending (partial NFD string) starts with i as a softening
-- marker, i.e. "i" followed by a back vowel (a, o, u, or their ogonek/macron variants).
-- In partial NFD, ogonek and macron vowels are precomposed single characters.
local function should_palatalize(ending)
return rfind(ending, "^i[aąouųū]") ~= nil
end
-- Apply d→dž / t→č to the final base character of a partial NFD stem string.
local function palatalize_stem(stem_nfd)
local uchar = m_string_utilities.char
local ucp = m_string_utilities.codepoint
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
local len = ulen(stem_nfd)
if len == 0 then return stem_nfd end
-- Find the last base character position
local last_base_pos = len
while last_base_pos > 0 do
if not is_accent(ucp(stem_nfd, last_base_pos)) then break end
last_base_pos = last_base_pos - 1
end
if last_base_pos == 0 then return stem_nfd end
local last_char = uchar(ucp(stem_nfd, last_base_pos))
local prefix = (last_base_pos > 1) and usub(stem_nfd, 1, last_base_pos - 1) or ""
-- Any trailing combiners after the base character (unusual for d/t, but safe)
local trailing = (last_base_pos < len) and usub(stem_nfd, last_base_pos + 1) or ""
if last_char == "d" then
-- dž in partial NFD: d + ž (where ž = U+017E precomposed)
return prefix .. "dž" .. trailing
elseif last_char == "t" then
-- č in partial NFD: U+010D (precomposed)
return prefix .. "č" .. trailing
end
return stem_nfd -- no change
end
-- Return the last base (non-combining) character of a partial NFD string.
-- Used for j-stem detection.
local function last_base_char(nfd_str)
local ucp = m_string_utilities.codepoint
local ulen = m_string_utilities.len
local len = ulen(nfd_str)
for i = len, 1, -1 do
local cp = ucp(nfd_str, i)
if not is_accent(cp) then
return m_string_utilities.char(cp)
end
end
return nil
end
-- =============================================================================
-- Stress maps
-- "S" = stressed stem + naked ending
-- "E" = clean stem + accented ending
-- Positions 1-7: Sg Nom/Gen/Dat/Acc/Ins/Loc/Voc
-- Positions 8-14: Pl Nom/Gen/Dat/Acc/Ins/Loc/Voc
-- =============================================================================
local stress_maps = {
["standard"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","E","S", "S","S","S","E","S","S","S" },
[3] = { "S","S","S","S","S","E","S", "E","E","E","S","E","E","E" },
[4] = { "S","S","S","S","E","E","E", "E","E","E","E","E","E","E" },
},
-- -ias type stress pattern (élnias, kẽlias, etc.)
-- Differs from standard:
-- AP2 sg.loc (pos 6) = S: long -yje ending does not attract AP2 accent (cf. -as type -e which does)
-- AP3 sg.voc (pos 7) = E (el̃nias AP2, vélnias AP3)
-- Known gap: AP3 sg.voc comes out "velnỹ" (ending {"i","ỹ"}), but the form is
-- "velniẽ"; the ending {"ie","iẽ"} would be wrong for AP4 (kelỹ, not *keliẽ).
-- AP2 and AP3 are rare for this type.
["standard_ias"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" }, -- pos6 S (not E)
[3] = { "S","S","S","S","S","E","E", "E","E","E","S","E","E","E" }, -- pos7 E (not S)
[4] = { "S","S","S","S","E","E","E", "E","E","E","E","E","E","E" },
},
-- -jas type stress pattern (vė́jas, kraũjas): as standard_ias, except that
-- the vocative singular -jau keeps the stem stress in every class (vė́jau,
-- galvìjau, kraũjau; the name Iñdrajas: Iñdrajau), where the -ias nouns
-- stress the ending (kelỹ). Classes 3 and 4 are rare in this type.
["standard_jas"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "S","S","S","S","S","E","S", "E","E","E","S","E","E","E" },
[4] = { "S","S","S","S","E","E","S", "E","E","E","E","E","E","E" },
},
-- -is/-ys type stress pattern (kiaušìnis, ožỹs, etc.)
-- AP2: almost all S, only sg.ins (5) and pl.acc (11) are E
-- AP3/AP4: sg.nom and sg.voc are E (ending-stressed: -ỹs, -ỹ)
["standard_is_ys"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","S","S","S","S","E","E", "E","E","E","S","E","E","E" },
[4] = { "E","S","S","S","E","E","E", "E","E","E","E","E","E","E" },
},
-- Feminine vowel-stem stress pattern for -a/-ia type (e.g., rankà)
-- AP2: sg.nom, sg.ins, pl.acc are E (short ending -a attracts accent in AP2)
["feminine_vowel"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "E","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","S","E","S", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","S", "S","E","E","E","E","E","S" },
},
-- Feminine vowel-stem stress pattern for -ė type (e.g., žvãkė)
-- AP2: sg.nom stays on stem (long -ė does not attract AP2 accent); only sg.ins and pl.acc are E
["feminine_vowel_e"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","S","E","S", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","S", "S","E","E","E","E","E","S" },
},
-- Paradigms 9/10 (declension III i-stems) stress pattern
-- AP2 (geluõnis, deguonis, palikuonis, pirmuonis, vagis, žiniuonis):
-- only sg.ins (5) and pl.acc (11) are E, as in standard_is_ys AP2.
-- AP3: positions 1,2,5,6,7 are E; pl.nom/acc/voc S
-- AP4: positions 8,14 are S (par9-12 AP4 pl.nom always S)
["par9_10"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","E","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","E","E","E", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
-- Paradigm 4 (declension IV -us) stress pattern
-- AP2 (cùkrus): almost all S, only pl.acc (pos 11) is E
-- AP3 (sūnùs): sg.nom/gen/ins/loc/voc E, sg.dat/acc S; pl.nom/acc/voc S, rest E
-- AP4 (alùs): sg.dat/acc S, rest E; pl.nom/voc S, rest E
["par4"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","S","S","S", "S","S","S","E","S","S","S" },
[3] = { "E","E","S","S","E","E","E", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
-- Paradigm 5 (-ius/-jus): AP1 and AP2, plus isolated AP4 items (Sìrius).
-- AP4 follows par4 AP4 except sg.nom/voc, which stay S: the -ius
-- nominative is weak (Sìrius, not *Siriùs), unlike -us (dangùs).
["par5"] = {
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[2] = { "S","S","S","S","S","S","S", "S","S","S","E","S","S","S" },
[4] = { "S","E","S","S","E","E","S", "S","E","E","E","E","E","S" },
},
-- Paradigm 11 (-uo, e.g. akmuõ: akmeniẽ; šuõ: šuniẽ) stress pattern
-- -uo nouns are AP3 or AP4 (AP1 only for mė́nuo, below)
-- sg.gen (pos 2) is E: the generated genitive (short stem + -eñs) is
-- always ending-stressed (akmeñs, vandeñs)
-- AP3: sg.loc and sg.voc are also E; AP4: sg.ins/loc/voc and pl.acc also E
["par11"] = {
-- AP1 exists only for mė́nuo, which declines per the (i)a-declension
-- with every slot overridden; fixed stem stress as a fallback.
[1] = { "S","S","S","S","S","S","S", "S","S","S","S","S","S","S" },
[3] = { "E","E","S","S","S","E","E", "S","E","E","S","E","E","S" },
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
-- Paradigm 12 (sesuõ, duktė̃): only AP3 exists (a closed two-noun class).
-- Identical to the par9_10 AP3 row: sg.dat/acc and pl.nom/acc/voc are S
-- (on the oblique -er- stem: sẽseriai, dùkterį ...), everything else E.
["par12"] = {
[3] = { "E","E","S","S","E","E","E", "S","E","E","S","E","E","S" },
},
-- Paradigm 7 -i subtype stress map (patì, martì): AP4 only
["par7_i"] = {
[4] = { "E","E","S","S","E","E","E", "S","E","E","E","E","E","S" },
},
}
-- =============================================================================
-- Ending tables {naked, accented}
-- accented = nil means this ending never bears stress.
-- =============================================================================
local endings = {
["par1_as"] = {
{"as",nil}, {"o",nil}, {"ui",nil}, {"ą",nil},
{"u","ù"}, {"e","è"}, {"e",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
-- j-stem type (-jas): vė́jas, vertė̃jas, naudótojas, etc.
-- Differs from 1_as in: sg.loc -uje (not -e), sg.voc -au (not -e). The
-- vocative singular is never stressed on the ending (standard_jas).
["par2_jas"] = {
{"as",nil}, {"o",nil}, {"ui",nil}, {"ą",nil},
{"u","ù"}, {"uje","ujè"}, {"au",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
["par3_is"] = {
{"is",nil}, {"io",nil}, {"iui",nil}, {"į",nil},
{"iu","iù"}, {"yje","yjè"}, {"i",nil},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
["par3_ys"] = {
{"ys","ỹs"}, {"io",nil}, {"iui",nil}, {"į",nil},
{"iu","iù"}, {"yje","yjè"}, {"y","ỹ"},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
-- j-stem -ys type (žvejỹs): the par3_ys endings with the glide i
-- absorbed after stem-final j (gen. žvẽjo, pl. žvejaĩ; cf. par2_jas).
-- The true-vowel i of sg.nom/acc/loc/voc is kept (žvejỹs, žvẽjį, žvejyjè, žvejỹ).
["par3_jys"] = {
{"ys","ỹs"}, {"o",nil}, {"ui",nil}, {"į",nil},
{"u","ù"}, {"yje","yjè"}, {"y","ỹ"},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
-- j-stem -is type (sker̃svėjis, gen. sker̃svėjo): the par3_is endings
-- with the same absorption.
["par3_jis"] = {
{"is",nil}, {"o",nil}, {"ui",nil}, {"į",nil},
{"u","ù"}, {"yje","yjè"}, {"i",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
["par2_ias"] = {
{"ias",nil}, {"io",nil}, {"iui",nil}, {"ią",nil},
{"iu","iù"}, {"yje","yjè"}, {"i","ỹ"},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
["par6_a"] = {
{"a","à"}, {"os","õs"}, {"ai",nil}, {"ą",nil},
{"a","à"}, {"oje","ojè"}, {"a",nil},
{"os","õs"}, {"ų","ų̃"}, {"oms","óms"}, {"as","às"},
{"omis","omìs"},{"ose","osè"},{"os","õs"},
},
["par7_ia"] = {
{"ia","ià"}, {"ios","iõs"}, {"iai",nil}, {"ią",nil},
{"ia","ià"}, {"ioje","iojè"},{"ia",nil},
{"ios","iõs"}, {"ių","ių̃"}, {"ioms","ióms"},{"ias","iàs"},
{"iomis","iomìs"},{"iose","iosè"},{"ios","iõs"},
},
["par8_e"] = {
{"ė","ė̃"}, {"ės","ė̃s"}, {"ei",nil}, {"ę",nil},
{"e","è"}, {"ėje","ėjè"},{"e",nil},
{"ės","ė̃s"}, {"ių","ių̃"}, {"ėms","ė́ms"},{"es","ès"},
{"ėmis","ėmìs"},{"ėse","ėsè"},{"ės","ė̃s"},
},
-- Rare -i type (patì, martì) — positions 1,7 use lemma directly ({nil,nil})
-- Oblique cases follow the same pattern as 2_ia
["par7_i"] = {
{nil,nil}, {"ios","iõs"}, {"iai",nil}, {"ią",nil},
{"ia","ià"}, {"ioje","iojè"},{nil,nil},
{"ios","iõs"}, {"ių","ių̃"}, {"ioms","ióms"},{"ias","iàs"},
{"iomis","iomìs"},{"iose","iosè"},{"ios","iõs"},
},
["par9_is"] = {
{"is","ìs"}, {"ies","iẽs"}, {"iai",nil}, {"į",nil},
{"imi","imì"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ių","ių̃"}, {"ims","ìms"},{"is","ìs"},
{"imis","imìs"},{"yse","ysè"},{"ys","ỹs"},
},
["par10_is"] = {
{"is","ìs"}, {"ies","iẽs"}, {"iui",nil}, {"į",nil},
{"imi","imì"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ių","ių̃"}, {"ims","ìms"},{"is","ìs"},
{"imis","imìs"},{"yse","ysè"},{"ys","ỹs"},
},
["par4_us"] = {
{"us","ùs"}, {"aus","aũs"}, {"ui",nil}, {"ų",nil},
{"umi","umì"}, {"uje","ujè"}, {"au","aũ"},
{"ūs","ū̃s"}, {"ų","ų̃"}, {"ums","ùms"}, {"us","ùs"},
{"umis","umìs"},{"uose","uosè"},{"ūs","ū̃s"},
},
["par5_ius"] = {
{"ius",nil}, {"iaus",nil}, {"iui",nil}, {"ių",nil},
{"iumi","iumì"},{"iuje","iujè"},{"iau",nil},
{"iai","iaĩ"}, {"ių","ių̃"}, {"iams","iáms"},{"ius","iùs"},
{"iais","iaĩs"},{"iuose","iuosè"},{"iai","iaĩ"},
},
["par5_jus"] = {
{"us",nil}, {"aus",nil}, {"ui",nil}, {"ų",nil},
{"umi","umì"}, {"uje","ujè"}, {"au",nil},
{"ai","aĩ"}, {"ų","ų̃"}, {"ams","áms"}, {"us","ùs"},
{"ais","aĩs"}, {"uose","uosè"},{"ai","aĩ"},
},
-- Paradigm 11 (-uo): nom sg = lemma directly ({nil,nil}); gen sg is built
-- on the NOMINATIVE short stem (akm-uõ → akm-eñs), not the oblique -en-
-- stem supplied via .stem: — see the gen_short_stem special case in the
-- form generator. šuõ (gen. šuñs) is irregular: override with '.gen:šuñs'.
["par11_uo"] = {
{nil,nil}, {"ens","eñs"}, {"iui",nil}, {"į",nil},
{"iu","iù"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ų","ų̃"}, {"ims","ìms"}, {"is","ìs"},
{"imis","imìs"}, {"yse","ysè"}, {"ys","ỹs"},
},
-- Paradigm 12 (sesuõ, duktė̃): nom sg = lemma directly; gen sg on the
-- nominative short stem (ses-uõ/dukt-ė̃ → ses-er̃s/dukt-er̃s); all other
-- slots on the accented -er- stem from .stem: (sẽser-, dùkter-), with
-- declension III feminine endings (dat -iai, i-stem obliques).
-- sg ins: only the standard -imì is generated; the secondary (i)o-type
-- variant (sẽseria, dùkteria) is added by the editor via '.ins:+:-ia'.
["par12_er"] = {
{nil,nil}, {"ers","er̃s"}, {"iai",nil}, {"į",nil},
{"imi","imì"}, {"yje","yjè"}, {"ie","iẽ"},
{"ys","ỹs"}, {"ų","ų̃"}, {"ims","ìms"}, {"is","ìs"},
{"imis","imìs"}, {"yse","ysè"}, {"ys","ỹs"},
},
}
-- =============================================================================
-- Family plural of surnames ('sur')
-- Beside its ordinary plural, which names several men of the surname, a
-- masculine surname has a collective plural naming a married couple or a
-- family. It is stressed on every ending that can carry the stress, whatever
-- the accentuation paradigm of the surname (Petráitis: Petráičiai, but
-- Petraičiaĩ of the family), and surnames in -a, -ia and -ė form it with the
-- endings -(i)ai (Noreikà: Noreĩkos, but Noreikaĩ). Surnames in -us take the
-- -ai endings first and those of their own declension after them (Bar̃tkus:
-- Bartkaĩ, Bar̃tkūs).
-- Each class lists one or more ending sets: `endings` names the row of the
-- ending table whose plural half is used, `stress` gives the seven plural
-- slots (nominative to vocative).
-- =============================================================================
local FAMILY_NOTE = "[referring to a married couple or a family]"
local family_all_endings = { "E","E","E","E","E","E","E" }
-- Nominative and vocative in -os and -ūs never take the stress.
local family_mobile = { "S","E","E","E","E","E","S" }
local family_plural = {
par1_as = { { endings = "par1_as", stress = family_all_endings } },
par2_jas = { { endings = "par2_jas", stress = family_all_endings } },
par2_ias = { { endings = "par2_ias", stress = family_all_endings } },
par3_is = { { endings = "par3_is", stress = family_all_endings } },
par3_ys = { { endings = "par3_ys", stress = family_all_endings } },
par3_jys = { { endings = "par3_jys", stress = family_all_endings } },
par3_jis = { { endings = "par3_jis", stress = family_all_endings } },
par5_ius = { { endings = "par5_ius", stress = family_all_endings } },
par5_jus = { { endings = "par5_jus", stress = family_all_endings } },
par4_us = {
{ endings = "par1_as", stress = family_all_endings },
{ endings = "par4_us", stress = family_mobile },
},
par6_a = {
{ endings = "par1_as", stress = family_all_endings },
{ endings = "par6_a", stress = family_mobile },
},
par7_ia = { { endings = "par3_is", stress = family_all_endings } },
par8_e = { { endings = "par3_is", stress = family_all_endings } },
}
-- =============================================================================
-- Illative endings (secondary local case)
-- Formed by adding -n to the accusative (plural -sna)
-- A stressed ending is circumflex in the singular, acute in the plural.
-- The singular is still used in the standard language beside į + accusative;
-- the plural is archaic or dialectal, as are the allative and the adessive.
-- =============================================================================
local ill_endings = {
["par1_as"] = { {"an","añ"}, {"uosna","úosna"} },
["par2_jas"] = { {"an","añ"}, {"uosna","úosna"} },
["par3_is"] = { {"in","iñ"}, {"iuosna","iúosna"} },
["par3_ys"] = { {"in","iñ"}, {"iuosna","iúosna"} },
["par3_jys"] = { {"in","iñ"}, {"uosna","úosna"} },
["par3_jis"] = { {"in","iñ"}, {"uosna","úosna"} },
["par2_ias"] = { {"ian","iañ"}, {"iuosna","iúosna"} },
["par6_a"] = { {"on","õn"}, {"osna","ósna"} },
["par7_ia"] = { {"ion","iõn"}, {"iosna","iósna"} },
["par7_i"] = { {"ion","iõn"}, {"iosna","iósna"} },
["par8_e"] = { {"ėn","ė̃n"}, {"ėsna","ė́sna"} },
["par9_is"] = { {"in","iñ"}, {"ysna","ýsna"} },
["par10_is"] = { {"in","iñ"}, {"ysna","ýsna"} },
["par4_us"] = { {"un","uñ"}, {"uosna","úosna"} },
["par5_ius"] = { {"iun","iuñ"}, {"iuosna","iúosna"} },
["par5_jus"] = { {"un","uñ"}, {"uosna","úosna"} },
["par11_uo"] = { {"in","iñ"}, {"ysna","ýsna"} },
["par12_er"] = { {"in","iñ"}, {"ysna","ýsna"} },
}
-- Illative stress map: {sg_stress, pl_stress}
-- AP1/2: S,S — both singular and plural stem-stressed
-- AP3/4: E,E — both singular and plural ending-stressed
local ill_stress_map = { [1] = {"S","S"}, [2] = {"S","S"}, [3] = {"E","E"}, [4] = {"E","E"} }
-- =============================================================================
-- Allative endings {naked, accented}, singular
-- Keyed by ending_key
-- Formed by: Genitive + postposition *pi/*p
-- A stressed ending keeps the tone of the genitive singular (-õs → -õsp);
-- -(i)óp is acute.
-- The plural is built on the genitive plural: -ų → -ump, stressed where the
-- genitive plural is (miškų̃ → miškum̃p, akių̃ → akium̃p).
-- Nouns in -uo and -er add -p to the older genitive in -ès (akmenèsp). Those
-- in -er have three forms: on the genitive in -er̃s, built like it on the
-- short stem and listed first, on the older genitive, and with the ending of
-- the i-stems (dukter̃sp, dukterèsp, dukteriẽsp).
-- =============================================================================
local all_endings = {
["par1_as"] = {"op","óp"},
["par2_jas"] = {"op","óp"},
["par3_is"] = {"iop","ióp"},
["par3_ys"] = {"iop","ióp"},
["par3_jys"] = {"op","óp"},
["par3_jis"] = {"op","óp"},
["par2_ias"] = {"iop","ióp"},
["par6_a"] = {"osp","õsp"},
["par7_ia"] = {"iosp","iõsp"},
["par7_i"] = {"iosp","iõsp"},
["par8_e"] = {"ėsp","ė̃sp"},
["par9_is"] = {"iesp","iẽsp"},
["par10_is"] = {"iesp","iẽsp"},
["par4_us"] = {"ausp","aũsp"},
["par5_ius"] = {"iausp","iaũsp"},
["par5_jus"] = {"ausp","aũsp"},
["par11_uo"] = {"esp","èsp"},
["par12_er"] = { {"ersp","er̃sp", short_stem = true}, {"esp","èsp"}, {"iesp","iẽsp"} },
}
-- Allative singular stress
-- AP1/AP2 → S (stem-stressed)
-- AP3/AP4 → E (ending-stressed)
local all_stress_map = { [1] = "S", [2] = "S", [3] = "E", [4] = "E" }
-- =============================================================================
-- Adessive endings {naked, accented}
-- Keyed by ending_key; each entry = { {sg_naked, sg_accented}, {pl_naked, pl_accented} }
-- Formed by: Old Locative + postposition *pi/*p
-- Plural forms insert nasal -m- between Locative Pl and -p(i)
-- Nouns in -is and -ys of paradigm 3 have two singular forms: -ip, as in the
-- i-stems, and -iep beside it.
-- =============================================================================
local ade_endings = {
["par1_as"] = { {"iep","íep"}, {"uosemp","úosemp"} },
["par2_jas"] = { {"iep","íep"}, {"uosemp","úosemp"} },
["par3_is"] = { { {"ip","ìp"}, {"iep","íep"} }, {"iuosemp","iúosemp"} },
["par3_ys"] = { { {"ip","ìp"}, {"iep","íep"} }, {"iuosemp","iúosemp"} },
["par3_jys"] = { { {"ip","ìp"}, {"iep","íep"} }, {"uosemp","úosemp"} },
["par3_jis"] = { { {"ip","ìp"}, {"iep","íep"} }, {"uosemp","úosemp"} },
["par2_ias"] = { {"iep","íep"}, {"iuosemp","iúosemp"} },
["par6_a"] = { {"aip","áip"}, {"osemp","ósemp"} },
["par7_ia"] = { {"iaip","iáip"}, {"iosemp","iósemp"} },
["par7_i"] = { {"iaip","iáip"}, {"iosemp","iósemp"} },
["par8_e"] = { {"eip","éip"}, {"ėsemp","ė́semp"} },
["par9_is"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
["par10_is"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
["par4_us"] = { {"up","ùp"}, {"uosemp","úosemp"} },
["par5_ius"] = { {"iup","iùp"}, {"iuosemp","iúosemp"} },
["par5_jus"] = { {"up","ùp"}, {"uosemp","úosemp"} },
["par11_uo"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
["par12_er"] = { {"ip","ìp"}, {"ysemp","ýsemp"} },
}
-- Adessive stress map: {sg_loc, pl_loc}
-- AP1/AP2 → S, S (stem-stressed)
-- AP3/AP4 → E, E (ending-stressed in both singular and plural)
local ade_stress_map = { [1] = {"S","S"}, [2] = {"S","S"}, [3] = {"E","E"}, [4] = {"E","E"}, }
-- =============================================================================
-- Slot-name mapping: external names (used in overrides) → internal keys
-- =============================================================================
local slot_map = {
nom = "nom_s", gen = "gen_s", dat = "dat_s", acc = "acc_s",
ins = "ins_s", loc = "loc_s", voc = "voc_s",
nompl = "nom_p", genpl = "gen_p", datpl = "dat_p", accpl = "acc_p",
inspl = "ins_p", locpl = "loc_p", vocpl = "voc_p",
-- Secondary local cases
ill = "ill_s", illpl = "ill_p",
all = "all_s", allpl = "all_p",
ade = "ade_s", adepl = "ade_p",
}
local slot_external_names = {}
for ext, int in pairs(slot_map) do slot_external_names[int] = ext end
-- =============================================================================
-- Slot list for iut.show_forms (slot name → ACCEL tag)
-- Secondary local case slots are only activated dynamically when data exists.
-- =============================================================================
local lt_noun_slot_list = {
{"nom_s","nom|s"}, {"gen_s","gen|s"}, {"dat_s","dat|s"}, {"acc_s","acc|s"},
{"ins_s","ins|s"}, {"loc_s","loc|s"}, {"voc_s","voc|s"},
{"nom_p","nom|p"}, {"gen_p","gen|p"}, {"dat_p","dat|p"}, {"acc_p","acc|p"},
{"ins_p","ins|p"}, {"loc_p","loc|p"}, {"voc_p","voc|p"},
{"ill_s","ill|s"}, {"ill_p","ill|p"},
{"all_s","all|s"}, {"all_p","all|p"},
{"ade_s","ade|s"}, {"ade_p","ade|p"},
}
local lt_noun_secondary_slots = {
ill_s=true, ill_p=true, all_s=true, all_p=true, ade_s=true, ade_p=true,
}
-- =============================================================================
-- Table renderer
-- =============================================================================
local function make_table(forms, number_restr, show_ill, show_all, show_ade)
local frame = mw.getCurrentFrame()
local top = frame:expandTemplate {
title = "inflection-table-top",
args = { title = forms.title, palette = "blue", tall = "yes" },
}
local bot = frame:expandTemplate {
title = "inflection-table-bottom",
args = { notes = forms.footnote or "" },
}
local cases = {
{ "danh cách", "nom" },
{ "sinh cách", "gen" },
{ "dữ cách", "dat" },
{ "đối cách", "acc" },
{ "cách công cụ", "ins" },
{ "định vị cách", "loc" },
{ "hô cách", "voc" },
}
local show_sg = (number_restr ~= "pl")
local show_pl = (number_restr ~= "sg")
local rows = '! class="outer" rowspan="2" |\n|-\n'
if show_sg then rows = rows .. ' ! class="outer" | số ít' end
if show_pl then rows = rows .. '\n! class="outer" | số nhiều' end
rows = rows .. "\n|-\n"
for _, c in ipairs(cases) do
local label, key = c[1], c[2]
rows = rows .. "! " .. label .. "\n"
if show_sg then rows = rows .. "| " .. (forms[key .. "_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms[key .. "_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
-- Secondary local cases section
-- Only rendered when explicitly requested by the editor.
local has_secondary = show_ill or show_all or show_ade
-- Only strip the trailing row separator here if no secondary rows follow;
-- otherwise it must stay to separate vocative from the next case row.
if not has_secondary then
rows = rsub(rows, "|%-\n$", "")
end
if show_ill then
rows = rows .. "! illative\n"
if show_sg then rows = rows .. "| " .. (forms["ill_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms["ill_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
if show_all then
rows = rows .. "! allative\n"
if show_sg then rows = rows .. "| " .. (forms["all_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms["all_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
if show_ade then
rows = rows .. "! adessive\n"
if show_sg then rows = rows .. "| " .. (forms["ade_s"] or "—") .. "\n" end
if show_pl then rows = rows .. "| " .. (forms["ade_p"] or "—") .. "\n" end
rows = rows .. "|-\n"
end
-- Remove trailing row separator
if has_secondary then
rows = rsub(rows, "|%-\n$", "")
end
return top .. rows .. bot
end
-- =============================================================================
-- Main entry point
-- =============================================================================
local function make_form(stem_ac, ending_ac)
local combined = stem_ac .. ending_ac
return makeDisplayText(combined)
end
-- Parse and process a single pattern (lemma,AP,gen with tags).
--
-- The lemma and AP fields may each hold a colon-separated list of variants,
-- optionally footnoted (e.g. "sūnùs:sūnùs[dial.],3:4[rare]"). Each lemma × AP
-- combination is declined separately and the results are merged slot by slot
-- (merge_alternant_results), as for an explicit (( )) alternant.
--
-- Returns a table of forms for all 14 slots, plus metadata.
local function decline_single_pattern(pattern_str, unescape_func)
local function parse_err(msg)
error("lt-ndecl: " .. msg .. ": '" .. pattern_str .. "'")
end
-- Isolate the [...] footnotes first, so a "," or "." inside one is not
-- taken for a field or tag separator.
local bracket_segs = put.parse_balanced_segment_run(pattern_str, "[", "]")
local comma_groups = put.split_alternating_runs_and_strip_spaces(bracket_segs, ",")
-- ── 1. Lemma (position 1): colon-list + footnote via fetch_specs ────────
local lemma_specs = m_common.fetch_specs(comma_groups[1] or {""}, ":", "lemma", nil, parse_err)
for _, spec in ipairs(lemma_specs) do
spec.form = unescape_func(spec.form)
end
-- ── 1a. Parse part 2: AP + optional tags ─────────────────────────────────
local part2_group = comma_groups[2] or {"0"}
local part2_dot_groups = put.split_alternating_runs_and_strip_spaces(part2_group, "%.")
local ap_specs = m_common.fetch_specs(part2_dot_groups[1], ":", "accent paradigm", nil, parse_err)
-- ── 1b. Parse part 3: optional genitive-singular keyword + tags ──────────
-- Position 3 only classifies: a plain, unaccented keyword naming the
-- genitive-singular ending ("io", "ies" or "ers") of a lemma ending shared
-- by several paradigms (-is: par3 -io vs par9/par10 -ies; -ė/-uo:
-- par8/par11 vs the sesuõ/duktė̃ type par12 -ers). The genitive cell is
-- still generated; ".gen:" overrides it (e.g. šuõ). Footnotes and
-- colon-lists are errors here.
local part3_dot_groups = {}
local gen_keyword
if comma_groups[3] then
part3_dot_groups = put.split_alternating_runs_and_strip_spaces(comma_groups[3], "%.")
local kw_group = part3_dot_groups[1]
if kw_group and (#kw_group > 1 or kw_group[1] ~= "") then
if #kw_group > 1 then
parse_err("Footnotes not allowed on the position-3 genitive keyword; " ..
"to footnote the genitive cell, use '.gen:+[note]' instead")
end
gen_keyword = kw_group[1]
if not rfind(gen_keyword, "^[a-z]+$") then
parse_err("Position 3 must be a plain genitive-singular keyword " ..
"('io', 'ies' or 'ers') without accents, '-' or variants; got '" ..
gen_keyword .. "'")
end
end
end
-- ── 1c. Collect all control tags ─────────────────────────────────────────
local gender, number_restr, common_gender
local personal_name, surname
local stem_param, plstem_param, decl_override
local overrides = {}
local whole_footnotes -- footnote(s) for the whole table
local all_tag_groups = {}
for i = 2, #part2_dot_groups do table.insert(all_tag_groups, part2_dot_groups[i]) end
for i = 2, #part3_dot_groups do table.insert(all_tag_groups, part3_dot_groups[i]) end
for _, tag_group in ipairs(all_tag_groups) do
local part = tag_group[1]
local has_footnote = #tag_group > 1
if part == "" then
-- A bare bracket (nothing before it) footnotes the entire declension.
if not has_footnote then
parse_err("Blank indicator")
end
whole_footnotes = iut.combine_footnotes(whole_footnotes, m_common.fetch_footnotes(tag_group, parse_err))
elseif part == "m" or part == "f" then
if has_footnote then
parse_err("Footnotes not allowed on '" .. part .. "' (used only to disambiguate declension class); " ..
"use a whole-declension footnote (a lone .[...]) or multi-alternant instead")
end
if common_gender then
parse_err("'" .. part .. "' cannot be combined with 'mfbysense'")
end
gender = part
elseif part == "mfbysense" then
-- Common-gender noun (vė́pla type): agreement gender follows the
-- referent; the declension is that of the feminine-form class.
if has_footnote then
parse_err("Footnotes not allowed on 'mfbysense'")
end
if gender then
parse_err("'mfbysense' cannot be combined with 'm'/'f'")
end
common_gender = true
elseif part == "sg" or part == "pl" then
if has_footnote then
parse_err("Footnotes not allowed on '" .. part .. "'")
end
number_restr = part
elseif part == "sur" then
-- A masculine surname: a surname in -as takes the vocative -ai, and
-- every surname adds the family plural.
if has_footnote then
parse_err("Footnotes not allowed on '" .. part .. "'")
end
personal_name = true
surname = true
elseif rfind(part, "^stem:") then
if has_footnote then
parse_err("Footnotes not allowed on 'stem:' (structural override); use multi-alternant instead")
end
local _, stem_ac = process_input(unescape_func(rsub(part, "^stem:", "")))
stem_param = stem_ac
elseif rfind(part, "^plstem:") then
if has_footnote then
parse_err("Footnotes not allowed on 'plstem:' (structural override); use multi-alternant instead")
end
local _, plstem_ac = process_input(unescape_func(rsub(part, "^plstem:", "")))
plstem_param = plstem_ac
elseif rfind(part, "^decl:") then
-- Table-header override (section 6); no effect on the forms.
if has_footnote then
parse_err("Footnotes not allowed on 'decl:' (header override); use multi-alternant instead")
end
decl_override = tonumber((rsub(part, "^decl:", "")))
else
-- Slot override: "nom:value", "genpl:value", etc. Keep the value as
-- a bracket-preserving run (may itself be --, +, -, -xx, or a
-- colon-list val1[note1]:val2[note2]); process_val resolves the
-- syntax later, once the natural/default form is known.
local key, rest = rmatch(part, "^([a-z]+):(.*)")
if key and slot_map[key] then
local override_run = {rest}
for i = 2, #tag_group do table.insert(override_run, tag_group[i]) end
overrides[slot_map[key]] = override_run
else
-- An unknown indicator is ignored, unless it carries a footnote.
if has_footnote then
parse_err("Footnotes not allowed on unrecognized indicator '" .. part .. "'")
end
end
end
end
if surname and number_restr then
parse_err("'sur' marks a surname, which declines in both numbers; it cannot be combined with '"
.. number_restr .. "'")
end
if surname and common_gender then
parse_err("'sur' marks a masculine surname; it cannot be combined with 'mfbysense'")
end
-- The gender tag as given: the inference below fills `gender`, and
-- compute_categories must tell an explicit '.m' from an inferred one.
local gender_tag = gender
-- ── One declension pass per lemma × AP combination, merged per slot. ──
local combinations = {}
for _, lspec in ipairs(lemma_specs) do
for _, aspec in ipairs(ap_specs) do
table.insert(combinations, {
lemma_form = lspec.form,
lemma_footnotes = lspec.footnotes,
ap_form = aspec.form,
ap_footnotes = aspec.footnotes,
})
end
end
local all_results = {}
for _, combo in ipairs(combinations) do
-- All pattern work done in partial NFD; NFC only for final output.
-- process_input handles all Unicode normalization (dotless i/j, dotabove, etc.)
local lemma_nfc = combo.lemma_form
local ap_str = combo.ap_form
local indeclinable = (ap_str == "-")
local ap = indeclinable and 0 or (tonumber(ap_str) or 0)
local lemma_bare, lemma = process_input(lemma_nfc)
-- ── 2. Detect declension & extract stems ────────────────────────────────
local uchar = m_string_utilities.char
local ucp = m_string_utilities.codepoint
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
-- Count base (non-accent) codepoints in a partial NFD string.
-- In partial NFD, only accent marks (grave/acute/tilde) are combining characters.
-- ą/ė/č etc. are single precomposed codepoints.
local function count_base(stem_ac)
local count = 0
local total = ulen(stem_ac)
for i = 1, total do
local cp = ucp(stem_ac, i)
if not is_accent(cp) then
count = count + 1
end
end
return count
end
-- Return the partial NFD prefix of `stem_ac` that contains exactly
-- `n` base (non-accent) codepoints, including any accent marks attached
-- to those base codepoints.
local function accented_prefix(stem_ac, n)
local out = {}
local count = 0
local i = 1
local total = ulen(stem_ac)
while i <= total do
local cp = ucp(stem_ac, i)
local is_acc = is_accent(cp)
table.insert(out, uchar(cp))
if not is_acc then
count = count + 1
if count == n then
-- Consume any immediately following accent marks too
i = i + 1
while i <= total do
local cp2 = ucp(stem_ac, i)
if is_accent(cp2) then
table.insert(out, uchar(cp2))
i = i + 1
else
break
end
end
break
end
end
i = i + 1
end
return table.concat(out)
end
local lemma_naked = strip_ac(lemma) -- partial NFD, accent combiners removed
-- Match suffix `sfx` (precomposed characters in partial NFD)
-- against lemma_naked. On success, return:
-- accented_stem – the corresponding prefix of the accented partial NFD lemma
-- naked_stem – the accent-free prefix
-- In partial NFD, ė/ą/č etc. are single codepoints, making matching straightforward.
local function strip_ending(sfx)
local sfx_bases = count_base(sfx)
local naked_bases = count_base(lemma_naked)
if sfx_bases > naked_bases then return nil end
-- Extract the stem portion (by base-character count) from lemma_naked
local stem_base_count = naked_bases - sfx_bases
local naked_stem
if stem_base_count == 0 then
naked_stem = ""
else
naked_stem = accented_prefix(lemma_naked, stem_base_count)
end
-- The suffix portion is everything after the stem
local suffix_part = usub(lemma_naked, ulen(naked_stem) + 1)
if suffix_part ~= sfx then return nil end
if stem_base_count == 0 then
return "", ""
end
local accented_stem = accented_prefix(lemma, stem_base_count)
return accented_stem, naked_stem
end
local stress_map_key, ending_key
local raw_stem_acc, raw_stem_naked
-- Paradigms 11/12 only: accent-free nominative short stem (akm-, ses-,
-- dukt-) on which the genitive singular is built (akmeñs, seser̃s).
local gen_short_stem
-- Set when an ambiguous lemma ending consumed the position-3 keyword;
-- a keyword left unconsumed is an error (see check after the ladder).
local keyword_ok = false
-- Handle indeclinable words: skip ending detection entirely
if indeclinable then
-- All forms = lemma; no ending detection needed.
raw_stem_acc = lemma
raw_stem_naked = lemma_naked
stress_map_key = "standard"
ending_key = nil -- special flag: indeclinable
else
-- Check longer/more-specific suffixes before shorter ones.
local sa, sn
sa, sn = strip_ending("ias")
if sa then
-- -čias/-džias lemmas keep the plain stop in the stem (svẽčias → svẽt-):
-- the softening i of the endings restores č/dž, the -y- of the locative
-- and vocative singular does not (svetyjè, svetỹ).
sa = rsub(rsub(sa, "č$", "t"), "dž$", "d")
sn = rsub(rsub(sn, "č$", "t"), "dž$", "d")
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "standard_ias"; ending_key = "par2_ias"
end
if not ending_key then
sa, sn = strip_ending("as")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- j-stem detection: if stem ends in "j", use par2_jas
if last_base_char(sn) == "j" then
stress_map_key = "standard_jas"; ending_key = "par2_jas"
else
stress_map_key = "standard"; ending_key = "par1_as"
end
end
end
if not ending_key then
sa, sn = strip_ending("ys")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- -ys is always paradigm 3; i-declension pluralia tantum like
-- dùrys are entered via their theoretical singular (dùris,AP,ies.pl).
-- All -ys types use standard_is_ys for correct sg.nom/voc endings (-ỹs/-ỹ)
stress_map_key = "standard_is_ys"
-- j-stem detection: after stem-final j the glide i of the
-- endings is absorbed (žvejỹs, gen. žvẽjo, pl. žvejaĩ)
if last_base_char(sn) == "j" then
ending_key = "par3_jys"
else
ending_key = "par3_ys"
end
end
end
if not ending_key then
sa, sn = strip_ending("ius")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "par5"
ending_key = "par5_ius"
end
end
if not ending_key then
sa, sn = strip_ending("us")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- j-stem detection for paradigm 5 (-jus vs -us)
if last_base_char(sn) == "j" then
stress_map_key = "par5"
ending_key = "par5_jus"
else
stress_map_key = "par4"
ending_key = "par4_us"
end
end
end
if not ending_key then
sa, sn = strip_ending("is")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
-- -is is ambiguous (par3 brólis/-io vs par9/par10 širdìs,
-- dantìs/-ies), so the genitive keyword is mandatory.
if not gen_keyword then
error("lt-ndecl: the ending -is is ambiguous between declension I "
.. "(gen. -io, e.g. brólis) and declension III (gen. -ies, e.g. "
.. "širdìs); please give the genitive-singular keyword in position 3: '"
.. lemma_nfc .. ",AP,io' or '" .. lemma_nfc .. ",AP,ies'")
elseif gen_keyword == "io" then
if gender == "f" then
error("lt-ndecl: declension I -is nouns (gen. -io) are masculine; "
.. "'.f' conflicts with the keyword 'io' (feminine -is nouns "
.. "belong to declension III: use ',ies')")
end
-- -is type AP2 uses special stress_map
stress_map_key = (ap == 2) and "standard_is_ys" or "standard"
-- after stem-final j the glide i of the endings is absorbed
ending_key = (last_base_char(sn) == "j") and "par3_jis" or "par3_is"
keyword_ok = true
elseif gen_keyword == "ies" then
stress_map_key = "par9_10"
ending_key = (gender == "m") and "par10_is" or "par9_is"
keyword_ok = true
else
error("lt-ndecl: invalid genitive keyword '" .. gen_keyword
.. "' for an -is lemma; expected 'io' (declension I) or "
.. "'ies' (declension III)")
end
end
end
if not ending_key then
-- ė in partial NFD = single precomposed char U+0117
sa, sn = strip_ending("ė")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
if gen_keyword == "ers" then
-- duktė̃ (gen. dukter̃s), the only -ė noun of paradigm 12
stress_map_key = "par12"; ending_key = "par12_er"
gen_short_stem = sn
keyword_ok = true
elseif gen_keyword then
error("lt-ndecl: invalid genitive keyword '" .. gen_keyword
.. "' for an -ė lemma; the only meaningful value is 'ers' "
.. "(duktė̃ type, gen. -er̃s)")
else
stress_map_key = "feminine_vowel_e"; ending_key = "par8_e"
end
end
end
if not ending_key then
sa, sn = strip_ending("ia")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "feminine_vowel"; ending_key = "par7_ia"
end
end
if not ending_key then
sa, sn = strip_ending("a")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "feminine_vowel"; ending_key = "par6_a"
end
end
if not ending_key then
sa, sn = strip_ending("uo")
if sa then
raw_stem_acc = sa; raw_stem_naked = sn
if gen_keyword == "ers" then
-- sesuõ (gen. seser̃s), the only -uo noun of paradigm 12
stress_map_key = "par12"; ending_key = "par12_er"
gen_short_stem = sn
keyword_ok = true
elseif gen_keyword then
error("lt-ndecl: invalid genitive keyword '" .. gen_keyword
.. "' for an -uo lemma; the only meaningful value is 'ers' "
.. "(sesuõ type, gen. -er̃s). Regular -uo nouns (paradigm 11) "
.. "need no keyword — their genitive -eñs is generated "
.. "automatically; for the irregular šuõ, override with '.gen:šuñs'")
else
stress_map_key = "par11"; ending_key = "par11_uo"
gen_short_stem = sn
end
end
end
-- Rare -i type (patì, martì)
if not ending_key then
sa, sn = strip_ending("i")
if sa and ap == 4 then
raw_stem_acc = sa; raw_stem_naked = sn
stress_map_key = "par7_i"; ending_key = "par7_i"
end
end
if not ending_key then
error("lt-ndecl: cannot detect declension type from lemma \""
.. lemma_nfc .. "\". Expected ending: -as/-ias/-is/-ys/-ius/-us/-a/-ia/-ė/-uo/-i")
end
end
-- A position-3 keyword on an unambiguous lemma ending is an error.
if gen_keyword and not keyword_ok then
error("lt-ndecl: the position-3 genitive keyword does not apply to '"
.. lemma_nfc .. "': it is used only to disambiguate -is lemmas "
.. "('io'/'ies') and to mark the sesuõ/duktė̃ type ('ers')")
end
-- Paradigm 12 sanity checks: closed two-noun class (sesuõ, duktė̃).
if ending_key == "par12_er" then
if gender == "m" then
error("lt-ndecl: paradigm 12 nouns (sesuõ/duktė̃ type) are feminine; remove '.m'")
end
if not stem_param then
error("lt-ndecl: sesuõ/duktė̃-type nouns build their oblique cases on an "
.. "accented -er- stem that cannot be derived from the lemma; please "
.. "supply it, e.g. '.stem:sẽser' or '.stem:dùkter'")
end
local expected_bare = raw_stem_naked .. "er"
if strip_ac(stem_param) ~= expected_bare then
error("lt-ndecl: '.stem:" .. nfc(stem_param) .. "' does not match lemma \""
.. lemma_nfc .. "\": expected the -er- stem '" .. nfc(expected_bare)
.. "' plus an accent mark")
end
end
-- Apply stem override if provided
local stem_stress, stem_clean, plstem_stress, plstem_clean
if stem_param then
stem_stress = stem_param
stem_clean = strip_ac(stem_param)
else
stem_stress = raw_stem_acc
stem_clean = raw_stem_naked
end
if plstem_param then
plstem_stress = plstem_param
plstem_clean = strip_ac(plstem_param)
else
plstem_stress = stem_stress
plstem_clean = stem_clean
end
-- ── 3. Validate accent paradigm ─────────────────────────────────────────
if not indeclinable then
if ap < 1 or ap > 4 then
error("lt-ndecl: accent paradigm must be 1, 2, 3, or 4 (got " .. ap .. ")")
end
if not stress_maps[stress_map_key][ap] then
error("lt-ndecl: accent paradigm " .. ap .. " is not valid for " .. stress_map_key)
end
-- Paradigms 2 and 4 stress the last syllable of the stem in their
-- stem-stressed forms (laũk-as, kraũj-as, dañt-is); a stem stressed on
-- an earlier syllable (atsãkym-as) belongs to paradigm 1 or 3.
if (ap == 2 or ap == 4) and has_ac(stem_stress) then
local syllables, stressed = m_common.stressed_syllable(stem_stress)
if stressed and stressed < syllables then
error("lt-ndecl: accent paradigm " .. ap .. " stresses the last syllable of the stem, but \""
.. nfc(makeDisplayText(stem_stress)) .. "-\" is stressed on an earlier one; check the paradigm")
end
end
end
-- ── 4. Determine gender from ending if not explicitly specified ─────────
-- par9_is defaults to feminine: the declension III i-stems are
-- overwhelmingly feminine; the small closed masculine set (dantìs,
-- žvėrìs, vagìs ...) opts in with '.m' (→ par10_is, dat. sg. -iui).
if not gender then
if ending_key == "par1_as" or ending_key == "par2_ias" or ending_key == "par2_jas"
or ending_key == "par3_is" or ending_key == "par3_ys" or ending_key == "par3_jys"
or ending_key == "par3_jis" or ending_key == "par4_us"
or ending_key == "par5_ius" or ending_key == "par5_jus" or ending_key == "par11_uo" then
gender = "m"
elseif ending_key == "par6_a" or ending_key == "par7_ia" or ending_key == "par7_i"
or ending_key == "par8_e" or ending_key == "par9_is" or ending_key == "par12_er" then
gender = "f"
elseif ending_key == "par10_is" then
gender = "m"
else
gender = "m" -- default fallback
end
end
-- Common-gender nouns are restricted to the -a/-ia/-ė types (vė́pla,
-- drìmba, mėmė̃ ...); other classes have no common-gender nouns.
if common_gender and not (ending_key == "par6_a" or ending_key == "par7_ia"
or ending_key == "par8_e") then
parse_err("'mfbysense' is only valid for common-gender nouns in -a, -ia or -ė")
end
-- The family plural is formed from the masculine surname only.
if surname then
if indeclinable then
parse_err("'sur' cannot be used with an indeclinable surname")
end
if gender ~= "m" then
parse_err("'sur' marks a masculine surname (a masculine surname in -a, -ia or -ė "
.. "also needs 'm'); feminine surnames have no family plural")
end
if not family_plural[ending_key] then
parse_err("'sur' is not supported for this declension class")
end
end
-- ── 5. Determine declension type (educational I-V, display only) ────────
local decl_type
if ending_key == "par1_as" or ending_key == "par2_ias" or ending_key == "par2_jas"
or ending_key == "par3_is" or ending_key == "par3_ys" or ending_key == "par3_jys"
or ending_key == "par3_jis" then
decl_type = 1
elseif ending_key == "par6_a" or ending_key == "par7_ia" or ending_key == "par7_i"
or ending_key == "par8_e" then
decl_type = 2
elseif ending_key == "par9_is" or ending_key == "par10_is" then
decl_type = 3
elseif ending_key == "par4_us" or ending_key == "par5_ius" or ending_key == "par5_jus" then
decl_type = 4
elseif ending_key == "par11_uo" or ending_key == "par12_er" then
decl_type = 5
else
decl_type = 1 -- fallback
end
-- ── 6. Table-header override ────────────────────────────────────────────
-- 'decl:N' replaces the roman numeral shown in the table header; it has
-- no effect on the generated forms.
local decl_roman = localization.declension[decl_type]
if decl_override then
local roman_from_override = localization.declension[decl_override]
if roman_from_override then
decl_roman = roman_from_override
end
end
-- Process slot value with support for special syntax.
-- `val` is either a plain string (a generated default, or "--"; no
-- brackets or ":") or a bracket-preserving run from
-- put.parse_balanced_segment_run (an override, possibly a colon-list with
-- per-value footnotes: "val1[note1]:val2[note2]").
-- stem_clean: accent-free stem (possibly pre-palatalized for natural ending)
-- stem_stress: accented stem (possibly pre-palatalized for natural ending)
-- stem_clean_no_pal: original accent-free stem (never pre-palatalized)
-- stem_stress_no_pal: original accented stem (never pre-palatalized)
local function process_val(val, default_val, stem_clean, stem_stress, stem_clean_no_pal, stem_stress_no_pal)
if not val then return nil end
local val_run = (type(val) == "string") and {val} or val
-- Special case: "--" means slot doesn't exist
if table.concat(val_run) == "--" then
return nil
end
local form_list = {}
-- Composition of a single "-SUFFIX" override, or false once any spec in
-- the run is of another kind (a colon list of mixed specs has no single
-- breakdown to report).
local comp_out = nil
local specs = m_common.fetch_specs(val_run, ":", "override", nil, parse_err)
for _, spec in ipairs(specs) do
local v_clean = spec.form
local v_note = spec.footnotes -- already {"[...]", ...} or nil, iut-ready
-- Special case: "+" means use default value
if v_clean == "+" then
if not default_val then
error("lt-ndecl: '+' used in override but no default value available.")
end
v_clean = default_val -- default_val is always a string here
end
-- Special case: "-" or "-xx" means bare stem or stem+suffix
local stem_notation_comp = nil
if v_clean and rfind(v_clean, "^%-") then
-- For stem notation, use the non-palatalized original stems
-- and decide palatalization based on the suffix
if not stem_clean_no_pal or not stem_stress_no_pal then
error("lt-ndecl: stem notation used in override but no stem available.")
end
local suffix = rsub(v_clean, "^%-", "") -- Remove leading "-"
-- An accented suffix takes the clean stem, an unaccented one the stressed stem
local chosen_stem
local suffix_ac = to_stem_ac(suffix)
if suffix == "" then
-- Bare stem: use stressed stem
chosen_stem = stem_stress_no_pal
elseif has_ac(suffix_ac) then
-- Suffix has accent → use clean stem
chosen_stem = stem_clean_no_pal
else
-- Suffix has no accent → use stressed stem
chosen_stem = stem_stress_no_pal
end
-- Palatalize the stem if the suffix calls for it
if should_palatalize(suffix_ac) then
chosen_stem = nfc(palatalize_stem(nfd(chosen_stem)))
end
v_clean = nfc(nfd(chosen_stem) .. suffix_ac)
-- Record the breakdown so appendix_row can highlight the
-- stressed morpheme of an overridden slot as well; the stress
-- side follows the same test that picked the stem.
stem_notation_comp = {
stem = nfd(chosen_stem),
ending = nfd(suffix_ac),
stress = has_ac(suffix_ac) and "E" or "S",
}
end
if stem_notation_comp then
comp_out = (comp_out == nil) and stem_notation_comp or false
else
comp_out = false
end
-- A comma separates forms (a default with two forms)
for _, v2 in ipairs(rsplit(v_clean, "%s*,%s*")) do
if v2 ~= "" then
local form_obj = { form = nfc(v2) }
if v_note then form_obj.footnotes = v_note end
iut.insert_form_into_list(form_list, form_obj)
end
end
end
return (#form_list > 0) and form_list or nil, comp_out or nil
end
-- ── 7. Generate forms ────────────────────────────────────────────────────
local forms = {}
local family_forms
-- Per-slot stem/ending breakdown (partial NFD), consumed by appendix_row.
-- Overridden slots keep a breakdown only when the override uses stem
-- notation ("-ų̃"); any other override clears the slot, and appendix_row
-- then falls back to the plain form. Slots the lemma fills directly
-- (Decl V nom sg, indeclinables) record {whole = ...}.
local compositions = {}
if indeclinable then
local case_keys = {
"nom_s","gen_s","dat_s","acc_s","ins_s","loc_s","voc_s",
"nom_p","gen_p","dat_p","acc_p","ins_p","loc_p","voc_p",
}
for _, case_key in ipairs(case_keys) do
local override_val = overrides[case_key]
local default_val = lemma_nfc
if override_val then
-- For indeclinable words, both stem versions are the same (no palatalization)
local stem_clean = strip_ac(lemma)
local stem_stress = lemma
forms[case_key] = process_val(override_val, default_val, stem_clean, stem_stress, stem_clean, stem_stress)
else
forms[case_key] = process_val(default_val, nil, nil, nil, nil, nil)
end
end
else
-- ── 8. Generate each form (Declinable) ───────────────────────────────
local map = (stress_maps[stress_map_key] or {})[ap] or stress_maps["standard"][1]
-- -ė type AP2 sg.nom should be S (stem-stressed), not E
if ending_key == "par8_e" and ap == 2 then
local new_map = {}
for i = 1, 14 do new_map[i] = map[i] end
new_map[1] = "S"
map = new_map
end
-- When plstem is provided, force all slots to S (stem-stressed)
-- This handles AP2 tonal alternation (e.g., putýtis: sg putý-, pl putỹ-)
if plstem_param then
local new_map = {}
for i = 1, 14 do new_map[i] = "S" end
map = new_map
end
local end_list = endings[ending_key]
-- Personal names in -as take the vocative -ai (Jõnai, Kazláuskai),
-- not the -e of common nouns.
if personal_name and ending_key == "par1_as" then
local personal_endings = {}
for i = 1, 14 do personal_endings[i] = end_list[i] end
personal_endings[7] = {"ai", nil}
end_list = personal_endings
end
local case_keys = {
"nom_s","gen_s","dat_s","acc_s","ins_s","loc_s","voc_s",
"nom_p","gen_p","dat_p","acc_p","ins_p","loc_p","voc_p",
}
local function need_stem_error()
error("lt-ndecl: word \"" .. lemma_nfc .. "\" (AP " .. ap
.. ") has a stem-stressed form but the stem carries no accent mark. "
.. "Please supply a .stem:… parameter.")
end
for i, case_key in ipairs(case_keys) do
local override_val = overrides[case_key]
local generated_form = nil -- Will be computed as default
-- Generalized {nil,nil} handling (positions using lemma directly:
-- nom sg of par7_i/par11_uo/par12_er, plus voc sg of par7_i)
if end_list[i][1] == nil then
generated_form = makeDisplayText(lemma_nfc)
compositions[case_key] = { whole = generated_form }
else
-- Generate the form normally
local stress_loc = map[i]
local ed = end_list[i]
local naked_e = ed[1]
local accent_e = ed[2]
-- Select stem based on number (singular: stem, plural: plstem)
local cur_stem_stress = (i >= 8) and plstem_stress or stem_stress
local cur_stem_clean = (i >= 8) and plstem_clean or stem_clean
-- Paradigms 11/12 build the genitive singular on the NOMINATIVE
-- short stem (akm-uõ → akm-eñs, ses-uõ → ses-er̃s), not on the
-- oblique -en-/-er- stem used by every other slot. The slot is
-- always "E" with an accented allomorph, so only the clean stem
-- is ever consumed here.
if gen_short_stem and i == 2 then
cur_stem_clean = gen_short_stem
cur_stem_stress = gen_short_stem
end
-- The ending takes the stress only when the map says "E" and an
-- accented ending allomorph exists; otherwise the stem is
-- stressed, as in an "S" slot.
local stem_nfd, ending_nfd, eff_stress
if stress_loc == "E" and accent_e then
stem_nfd = nfd(cur_stem_clean)
ending_nfd = nfd(accent_e)
eff_stress = "E"
else
if not has_ac(cur_stem_stress) and ap ~= 1 then need_stem_error() end
stem_nfd = nfd(cur_stem_stress)
ending_nfd = naked_e and nfd(naked_e) or ""
eff_stress = "S"
end
if should_palatalize(ending_nfd) then
stem_nfd = palatalize_stem(stem_nfd)
end
generated_form = make_form(stem_nfd, ending_nfd)
compositions[case_key] = {
stem = stem_nfd, ending = ending_nfd, stress = eff_stress,
}
end
-- Determine which stems to use for stem notation (-, -xx).
-- Need both clean and stressed versions for smart stem selection.
-- If this slot's natural ending would trigger palatalization, pre-palatalize
-- both stem versions so that "-xxx" overrides produce the correct palatalised form.
local cur_stem_clean = (i >= 8) and plstem_clean or stem_clean
local cur_stem_stress = (i >= 8) and plstem_stress or stem_stress
-- Keep original non-palatalized versions for override processing
local orig_stem_clean = cur_stem_clean
local orig_stem_stress = cur_stem_stress
if end_list[i][1] ~= nil and should_palatalize(nfd(end_list[i][1])) then
cur_stem_clean = nfc(palatalize_stem(nfd(cur_stem_clean)))
cur_stem_stress = nfc(palatalize_stem(nfd(cur_stem_stress)))
end
-- Process value: override if provided, otherwise use generated form
if override_val then
-- Process special syntax (--, +, -, -xx, val1:val2)
-- Pass both palatalized and original stems for proper processing
local ov_forms, ov_comp = process_val(override_val, generated_form, cur_stem_clean, cur_stem_stress, orig_stem_clean, orig_stem_stress)
forms[case_key] = ov_forms
-- The generated composition describes a form the override just
-- replaced; keep it only when the override reproduces a
-- stem+ending split of its own.
compositions[case_key] = ov_comp
else
forms[case_key] = process_val(generated_form, nil, nil, nil, nil, nil)
end
end
-- Family plural of a surname, kept apart from the ordinary plural
-- until add_family_forms joins the two. A plural slot the editor
-- overrides is left as written.
if surname then
family_forms = {}
for _, set in ipairs(family_plural[ending_key]) do
local set_key = set.endings
-- After stem-final j the glide i of the endings is absorbed.
if set_key == "par3_is" and last_base_char(plstem_clean) == "j" then
set_key = "par3_jys"
end
local set_endings = endings[set_key]
for n = 1, 7 do
local case_key = case_keys[n + 7]
if not overrides[case_key] then
local ed = set_endings[n + 7]
local stem_nfd, ending_nfd
if set.stress[n] == "E" and ed[2] then
stem_nfd, ending_nfd = nfd(plstem_clean), nfd(ed[2])
else
stem_nfd, ending_nfd = nfd(plstem_stress), nfd(ed[1])
end
if should_palatalize(ending_nfd) then
stem_nfd = palatalize_stem(stem_nfd)
end
family_forms[case_key] = family_forms[case_key] or {}
iut.insert_form_into_list(family_forms[case_key], {
form = nfc(make_form(stem_nfd, ending_nfd)),
footnotes = {FAMILY_NOTE},
})
end
end
end
end
end
-- ── 8–10. Secondary local case forms (illative, allative, adessive) ────────
-- Hidden by default; shown when at least one slot is explicitly requested.
if not indeclinable then
local function gen_sec(stress_loc, ed, use_plstem)
-- A list of ending pairs gives one form per pair.
if type(ed[1]) == "table" then
local variants = {}
for _, pair in ipairs(ed) do
table.insert(variants, gen_sec(stress_loc, pair, use_plstem))
end
return table.concat(variants, ", ")
end
local cur_stress = use_plstem and plstem_stress or stem_stress
local cur_clean = use_plstem and plstem_clean or stem_clean
if ed.short_stem then
cur_stress, cur_clean = gen_short_stem, gen_short_stem
end
local stem_nfd, ending_nfd
if stress_loc == "S" then
stem_nfd, ending_nfd = nfd(cur_stress), nfd(ed[1])
elseif ed[2] then
stem_nfd, ending_nfd = nfd(cur_clean), nfd(ed[2])
else
stem_nfd, ending_nfd = nfd(cur_stress), nfd(ed[1])
end
if should_palatalize(ending_nfd) then stem_nfd = palatalize_stem(stem_nfd) end
return make_form(stem_nfd, ending_nfd)
end
-- Illative
local ill_ov_sg, ill_ov_pl = overrides["ill_s"], overrides["ill_p"]
if ill_ov_sg or ill_ov_pl then
local ill_ed = ill_endings[ending_key]
local ill_map = ill_stress_map[ap] or {"S","S"}
if ill_ov_sg then
local def = gen_sec(ill_map[1], ill_ed[1], false)
forms["ill_s"] = process_val(ill_ov_sg, def, stem_clean, stem_stress, stem_clean, stem_stress)
end
if ill_ov_pl then
local def = gen_sec(ill_map[2], ill_ed[2], true)
forms["ill_p"] = process_val(ill_ov_pl, def, plstem_clean, plstem_stress, plstem_clean, plstem_stress)
end
end
-- Allative
local all_ov_sg, all_ov_pl = overrides["all_s"], overrides["all_p"]
if all_ov_sg or all_ov_pl then
local all_ed = all_endings[ending_key]
if all_ov_sg then
local def = gen_sec(all_stress_map[ap] or "S", all_ed, false)
forms["all_s"] = process_val(all_ov_sg, def, stem_clean, stem_stress, stem_clean, stem_stress)
end
if all_ov_pl then
-- Every form of the genitive plural, an overridden one
-- included, gives one allative: -ų → -ump, -ų̃ → -um̃p.
local derived = {}
for _, form_obj in ipairs(forms["gen_p"] or {}) do
local form_nfd = nfd(form_obj.form)
local tone = TILDE
local base = rmatch(form_nfd, "^(.*)ų" .. TILDE .. "$")
if not base then
base, tone = rmatch(form_nfd, "^(.*)ų$"), ""
end
if base then
table.insert(derived, make_form(base, "um" .. tone .. "p"))
end
end
local def = derived[1] and table.concat(derived, ", ") or nil
forms["all_p"] = process_val(all_ov_pl, def, plstem_clean, plstem_stress, plstem_clean, plstem_stress)
end
end
-- Adessive
local ade_ov_sg, ade_ov_pl = overrides["ade_s"], overrides["ade_p"]
if ade_ov_sg or ade_ov_pl then
local ade_ed = ade_endings[ending_key]
local ade_map = ade_stress_map[ap] or {"S","S"}
if ade_ov_sg then
local def = gen_sec(ade_map[1], ade_ed[1], false)
forms["ade_s"] = process_val(ade_ov_sg, def, stem_clean, stem_stress, stem_clean, stem_stress)
end
if ade_ov_pl then
local def = gen_sec(ade_map[2], ade_ed[2], true)
forms["ade_p"] = process_val(ade_ov_pl, def, plstem_clean, plstem_stress, plstem_clean, plstem_stress)
end
end
end
-- ── 11. Build result structure ───────────────────────────────────────────
local result = {
forms = forms,
lemma = lemma_nfc,
ap = ap,
indeclinable = indeclinable,
gender = common_gender and "mfbysense" or gender,
decl_roman = decl_roman,
number_restr = number_restr,
family_forms = family_forms,
-- appendix_row support (not preserved across merge_alternant_results):
compositions = compositions,
stem_accented = stem_stress,
plstem_accented = plstem_stress,
}
-- Category-relevant facts; one entry per declension pass, preserved
-- across merge_alternant_results and consumed by compute_categories.
local overridden = {}
for slot in pairs(overrides) do overridden[slot] = true end
local genpl_relic = false
if (ending_key == "par9_is" or ending_key == "par10_is") and forms["gen_p"] then
-- Unpalatalized -ų in the i-declension genitive plural marks the
-- consonant-stem relic type (dantų̃, naktų̃ ...); -ių (including
-- -čių/-džių) is the regular i-stem ending.
for _, fo in ipairs(forms["gen_p"]) do
local bare = strip_ac(nfd(fo.form))
if rfind(bare, "ų$") and not rfind(bare, "ių$") then
genpl_relic = true
end
end
end
result.catinfo = {{
ending_key = ending_key,
ap = ap,
indeclinable = indeclinable,
gender_tag = gender_tag,
common_gender = common_gender or nil,
number_restr = number_restr,
overridden = overridden,
genpl_relic = genpl_relic,
decl_override = decl_override and true or nil,
lemma_bare = nfc(lemma_bare),
}}
-- A whole-table footnote (".[note]") goes on every form, overrides included.
-- Lemma and AP footnotes have no cell of their own: they become qualifiers on
-- the headword line (result.lemma_footnotes, result.gender_footnotes).
if whole_footnotes then
for _, form_list in pairs(result.forms) do
for _, form_obj in ipairs(form_list) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes, whole_footnotes)
end
end
for _, form_list in pairs(result.family_forms or {}) do
for _, form_obj in ipairs(form_list) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes, whole_footnotes)
end
end
end
-- Headword-line qualifiers: lemma_footnotes on the head term,
-- gender_footnotes (AP) on the gender/AP badge.
result.lemma_footnotes = combo.lemma_footnotes
result.gender_footnotes = combo.ap_footnotes
table.insert(all_results, result)
end -- for _, combo in ipairs(combinations)
if #all_results == 1 then
return all_results[1]
end
return merge_alternant_results(all_results)
end
-- =============================================================================
-- Alternant support: ((alt1;alt2;...))
-- =============================================================================
-- Merge multiple decline results into one by unioning form lists per slot.
-- Used for (( )) alternants and for the lemma/AP variants of one pattern
-- (see decline_single_pattern).
function merge_alternant_results(results)
local merged_forms = {}
for _, result in ipairs(results) do
for slot, form_list in pairs(result.forms) do
if not merged_forms[slot] then merged_forms[slot] = {} end
for _, form_obj in ipairs(form_list) do
iut.insert_form_into_list(merged_forms[slot], form_obj)
end
end
end
local lemmas, seen_l = {}, {}
for _, r in ipairs(results) do
if not seen_l[r.lemma] then seen_l[r.lemma] = true; table.insert(lemmas, r.lemma) end
end
local ap_strs, seen_ap = {}, {}
for _, r in ipairs(results) do
if r.ap and r.ap > 0 then
local s = tostring(r.ap)
if not seen_ap[s] then seen_ap[s] = true; table.insert(ap_strs, s) end
end
end
local merged_lemma_footnotes, merged_gender_footnotes
for _, r in ipairs(results) do
merged_lemma_footnotes = iut.combine_footnotes(merged_lemma_footnotes, r.lemma_footnotes)
merged_gender_footnotes = iut.combine_footnotes(merged_gender_footnotes, r.gender_footnotes)
end
local merged_catinfo = {}
for _, r in ipairs(results) do
for _, ci in ipairs(r.catinfo or {}) do
table.insert(merged_catinfo, ci)
end
end
local merged_family
for _, r in ipairs(results) do
for slot, form_list in pairs(r.family_forms or {}) do
merged_family = merged_family or {}
merged_family[slot] = merged_family[slot] or {}
for _, form_obj in ipairs(form_list) do
iut.insert_form_into_list(merged_family[slot], form_obj)
end
end
end
local first = results[1]
return {
forms = merged_forms,
family_forms = merged_family,
lemma = table.concat(lemmas, " / "),
ap = #ap_strs == 1 and tonumber(ap_strs[1]) or 0,
ap_display = #ap_strs > 1 and table.concat(ap_strs, " // ") or nil,
indeclinable = false,
gender = first.gender,
decl_roman = first.decl_roman,
number_restr = first.number_restr,
lemma_footnotes = merged_lemma_footnotes,
gender_footnotes = merged_gender_footnotes,
catinfo = merged_catinfo,
}
end
-- Join the family plural of a surname to the ordinary plural: its forms follow
-- the ordinary ones in each slot, and a form the ordinary plural already has
-- is not repeated (it then serves both readings and carries no footnote).
local function add_family_forms(result)
local family_forms = result.family_forms
if not family_forms then return result end
for slot, form_list in pairs(family_forms) do
local slot_forms = result.forms[slot]
if slot_forms then
for _, form_obj in ipairs(form_list) do
local present = false
for _, existing in ipairs(slot_forms) do
if existing.form == form_obj.form then
present = true
break
end
end
if not present then
table.insert(slot_forms, form_obj)
end
end
end
end
result.family_forms = nil
return result
end
-- Split text at commas not nested inside <...> or [...].
-- Used to separate alternants inside ((...)).
local function split_top_level_commas(text)
local parts, depth_a, depth_s, cur = {}, 0, 0, {}
local ulen = m_string_utilities.len
local usub = m_string_utilities.sub
for i = 1, ulen(text) do
local ch = usub(text, i, i)
if ch == "<" then depth_a = depth_a + 1; table.insert(cur, ch)
elseif ch == ">" then depth_a = math.max(0, depth_a - 1); table.insert(cur, ch)
elseif ch == "[" then depth_s = depth_s + 1; table.insert(cur, ch)
elseif ch == "]" then depth_s = math.max(0, depth_s - 1); table.insert(cur, ch)
elseif ch == "," and depth_a == 0 and depth_s == 0 then
table.insert(parts, table.concat(cur)); cur = {}
else
table.insert(cur, ch)
end
end
table.insert(parts, table.concat(cur))
return parts
end
-- Process a ((...)) alternant string (already stripped of outer parentheses).
-- Alternants are separated by top-level commas.
-- Every alternant must use angle-bracket format: word<type,AP.tags> [word<type,AP.tags> ...]
-- Single-word example: nãmas<n,4>
-- Multiword example: gimtóji<a,4> kalbà<n,4>
local function process_alternants(alternant_text, unescape)
local alt_results = {}
for _, part in ipairs(split_top_level_commas(alternant_text)) do
part = trim(part)
if part ~= "" then
if not rfind(part, "<[^>]+>") then
error("lt-ndecl: each alternant inside (( )) must use angle-bracket format (e.g. nãmas<n,4>), got: '" .. part .. "'")
end
local parsed = parse_multiword(part, unescape)
if parsed.mode == "single" then
-- No spaces: single word with <type,AP> — force as one-word multiword
local word = parse_word_component(part, unescape)
parsed = {mode = "multi", words = {word}}
end
local r = export.decline_multiword_pattern(parsed, unescape)
table.insert(alt_results, r)
end
end
if #alt_results == 0 then error("lt-ndecl: empty alternant list in (( ))") end
if #alt_results == 1 then return alt_results[1] end
return merge_alternant_results(alt_results)
end
-- =============================================================================
-- Automatic categorization
-- =============================================================================
-- Words whose paradigm is not what their surface ending suggests, keyed by
-- accent-stripped lemma. "suppress": irregular category only, no
-- declension-class or class+AP categories (accentuation-paradigm categories
-- are kept). "keep": irregular category in addition to the normal ones.
local irregular_lemmas = {
["mėnuo"] = "suppress",
["žmogus"] = "suppress",
["petys"] = "keep",
["viešpats"] = "keep",
}
-- Classes whose declension is the feminine type; an explicit '.m' on one of
-- these marks the vaidilà/dė̃dė type (masculine agreement, feminine-form
-- declension).
local feminine_form_keys = {
par6_a = true, par7_ia = true, par7_i = true, par8_e = true, par12_er = true,
}
-- Compute the category list for an array of headword results (one per
-- ';'-separated pattern; alternant and colon-list members contribute one
-- catinfo entry each). Returns full category names without the "Category:"
-- prefix; all name material comes from localization.categories.
local function compute_categories(results)
local lc = localization.categories
local cats, seen = {}, {}
local function ins(name)
if not name then return end
local full = name .. " " .. localization.langname
if not seen[full] then
seen[full] = true
table.insert(cats, full)
end
end
local infos = {}
for _, r in ipairs(results) do
for _, ci in ipairs(r.catinfo or {}) do
table.insert(infos, ci)
end
end
local class_seen, ap_seen = {}, {}
local n_classes, n_aps = 0, 0
for _, ci in ipairs(infos) do
if ci.indeclinable then
ins(lc.indeclinable)
else
local irr = irregular_lemmas[ci.lemma_bare]
if irr then
ins(lc.irregular)
end
local class_name = ci.ending_key and lc.class[ci.ending_key]
local has_ap = ci.ap >= 1 and ci.ap <= 4
if class_name and irr ~= "suppress" and not ci.decl_override then
ins(class_name)
if has_ap then
ins(lc.class_ap:format(class_name, ci.ap))
end
if not class_seen[class_name] then
class_seen[class_name] = true
n_classes = n_classes + 1
end
end
if has_ap then
ins(lc.ap:format(ci.ap))
if not ap_seen[ci.ap] then
ap_seen[ci.ap] = true
n_aps = n_aps + 1
end
end
if ci.genpl_relic then
ins(lc.relic_genpl[ci.ending_key])
end
if ci.gender_tag == "m" and feminine_form_keys[ci.ending_key] then
ins(lc.gender_mismatch)
end
if ci.number_restr == "pl" then
ins(lc.pluralia_tantum)
elseif ci.number_restr == "sg" then
ins(lc.singularia_tantum)
end
local ov = ci.overridden or {}
if ov.ill_s or ov.ill_p then ins(lc.case_form.ill) end
if ov.all_s or ov.all_p then ins(lc.case_form.all) end
if ov.ade_s or ov.ade_p then ins(lc.case_form.ade) end
end
end
if n_aps > 1 then
ins(lc.multiple_ap)
end
if n_classes > 1 then
ins(lc.multiple_decl)
end
return cats
end
-- =============================================================================
-- Pattern list handling
-- =============================================================================
-- Generate declension data for multiple patterns
function export.get_headword_data(input_str)
local COMMA_PH = "\001"
local DOT_PH = "\002"
input_str = rsub(input_str, "\\,", COMMA_PH)
input_str = rsub(input_str, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
-- Split by unescaped semicolons
local patterns = rsplit(input_str, ";")
local results = {}
for _, pattern_str in ipairs(patterns) do
pattern_str = trim(pattern_str)
if pattern_str ~= "" then
local alternant_text = rmatch(pattern_str, "^%(%((.*)%)%)$")
local result
if alternant_text then
result = process_alternants(alternant_text, unescape)
else
local parsed = parse_multiword(pattern_str, unescape)
if parsed.mode == "single" then
result = decline_single_pattern(parsed.raw_input, unescape)
else
result = export.decline_multiword_pattern(parsed, unescape)
end
end
table.insert(results, add_family_forms(result))
end
end
-- Page categories derived from the same inputs (named field on the
-- returned array; inserted on the page by Module:lt-headword only).
results.categories = compute_categories(results)
return results
end
-- =============================================================================
-- Wikitext output
-- =============================================================================
function export.show(frame)
local parent_args = frame:getParent().args
local params = {
[1] = {required = true, default = "nãmas,4"},
["id"] = {},
["pagename"] = {},
}
local args = m_para.process(parent_args, params)
local input = args[1]
local COMMA_PH = "\001"
local DOT_PH = "\002"
input = rsub(input, "\\,", COMMA_PH)
input = rsub(input, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
-- Parse input: detect ((...)) alternants or fall through to single/multi-word
local result
local alternant_text = rmatch(input, "^%(%((.*)%)%)$")
if alternant_text then
result = process_alternants(alternant_text, unescape)
else
local parsed = parse_multiword(input, unescape)
if parsed.mode == "single" then
result = decline_single_pattern(parsed.raw_input, unescape)
else
result = export.decline_multiword_pattern(parsed, unescape)
end
end
add_family_forms(result)
-- Overridden case forms are tracked, not categorized:
-- [[Special:WhatLinksHere/Wiktionary:Tracking/lt-ndecl/override/genpl]]
local track
for _, ci in ipairs(result.catinfo or {}) do
for slot in pairs(ci.overridden or {}) do
if not lt_noun_secondary_slots[slot] then
track = track or require("Module:debug/track")
track("lt-ndecl/override/" .. (slot_external_names[slot] or slot))
end
end
end
-- Build active slot list: always include primary cases;
-- include secondary cases only when data is present.
local active_slots = {}
for _, entry in ipairs(lt_noun_slot_list) do
local slot = entry[1]
if not lt_noun_secondary_slots[slot] or result.forms[slot] then
table.insert(active_slots, entry)
end
end
-- Render forms to linked wikitext strings (also adds ACCEL info and footnotes)
iut.show_forms(result.forms, {
lang = lang,
lemmas = {{form = result.lemma}},
slot_list = active_slots,
skip_slot = function(slot)
if result.number_restr == "pl" and rfind(slot, "_s$") then return true end
if result.number_restr == "sg" and rfind(slot, "_p$") then return true end
return false
end,
})
-- Build title with metadata
local title_parts = {}
if result.gender then
table.insert(title_parts, localization.full_gender[result.gender])
end
if result.decl_roman and not result.indeclinable then
table.insert(title_parts, localization.full_declension[result.decl_roman])
end
if not result.indeclinable then
local ap_str = result.ap_display or (result.ap > 0 and tostring(result.ap)) or nil
if ap_str then
table.insert(title_parts, localization.accent_paradigm .. " " .. ap_str)
end
end
if result.indeclinable then
table.insert(title_parts, "không biến cách")
end
result.forms.title = table.concat(title_parts, ", ")
local show_ill = result.forms["ill_s"] ~= nil or result.forms["ill_p"] ~= nil
local show_all = result.forms["all_s"] ~= nil or result.forms["all_p"] ~= nil
local show_ade = result.forms["ade_s"] ~= nil or result.forms["ade_p"] ~= nil
return make_table(result.forms, result.number_restr, show_ill, show_all, show_ade)
end
-- =============================================================================
-- Appendix row output (for [[Appendix:Lithuanian accentuation]])
-- =============================================================================
-- Renders one wikitable row holding the seven case forms of one declension
-- pattern in one number:
-- {{lt-ndecl-row|výras,1|s}}
-- Arg 1 takes a simple {{lt-ndecl}} pattern (no semicolons, no colon-list
-- variants); arg 2 selects the number ("s" = singular, "p" = plural).
-- The first cell holds the accented stem and a hyphen (|label= replaces it).
-- The row is right-aligned in monospace so the endings line up; each form is
-- unlinked {{m|lt||...}}, the stressed morpheme (stem or ending) in bold on a
-- palette background.
-- Reads frame.args. {{lt-ndecl-row}} forwards each parameter by name, so a
-- parameter added here must be added to the template too.
function export.appendix_row(frame)
local params = {
[1] = {required = true},
[2] = {required = true},
["label"] = {},
["mark"] = {},
}
local args = m_para.process(frame.args, params)
local number = args[2]
if number ~= "s" and number ~= "p" then
error("lt-noun appendix_row: parameter 2 must be 's' (singular) or 'p' (plural), got '"
.. tostring(number) .. "'")
end
-- mark= selects which morpheme the highlight falls on: "stress" (default)
-- highlights the stressed morpheme, "ending" always highlights the ending.
local mark = args.mark or "stress"
if mark ~= "stress" and mark ~= "ending" then
error("lt-noun appendix_row: mark= must be 'stress' or 'ending', got '"
.. tostring(mark) .. "'")
end
local results = export.get_headword_data(args[1])
if #results > 1 then
error("lt-noun appendix_row: only a single pattern is supported (no semicolons)")
end
local result = results[1]
if not result.compositions then
error("lt-noun appendix_row: pattern produced no composition data "
.. "(colon-list variants and alternants are not supported)")
end
local function m_tpl(display)
return frame:expandTemplate{ title = "m", args = {"lt", "", display} }
end
-- Stressed-morpheme highlight: palette variable so dark mode adapts;
-- the hex fallback covers wikis where the palette variables are undefined.
local function hl(s)
return "<span style=\"background-color:var(--wikt-palette-purple-3, #e8dbfb)\">'''" .. s .. "'''</span>"
end
local label = args.label
if not label then
local stem_src = result.stem_accented or result.lemma
label = m_tpl(nfc(makeDisplayText(stem_src)) .. "-")
end
local cells = {}
for _, key in ipairs({"nom", "gen", "dat", "acc", "ins", "loc", "voc"}) do
local slot = key .. "_" .. number
local comp = result.compositions[slot]
local cell
if comp and comp.whole then
cell = m_tpl(nfc(comp.whole))
elseif comp then
local stem_disp = nfc(makeDisplayText(comp.stem))
local ending_disp = comp.ending ~= "" and nfc(makeDisplayText(comp.ending)) or ""
local display
if mark == "ending" then
display = ending_disp ~= "" and (stem_disp .. hl(ending_disp)) or stem_disp
elseif comp.stress == "E" then
display = stem_disp .. hl(ending_disp)
else
display = hl(stem_disp) .. ending_disp
end
cell = m_tpl(display)
else
-- Overridden or absent slot: fall back to the plain merged form.
local form_list = result.forms[slot]
if form_list and form_list[1] and form_list[1].form then
cell = m_tpl(form_list[1].form)
else
cell = "—"
end
end
table.insert(cells, cell)
end
return "|- style=\"font-family: monospace; text-align: right;\"\n| " .. label .. "\n| " .. table.concat(cells, " || ")
end
-- Expose multiword parsing for testing purposes
function export.parse_multiword_for_testing(input_str)
local COMMA_PH = "\001"
local DOT_PH = "\002"
input_str = rsub(input_str, "\\,", COMMA_PH)
input_str = rsub(input_str, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
local parsed = parse_multiword(input_str, unescape)
if parsed.mode == "single" then
return {mode = "single", raw_input = parsed.raw_input}
else
-- Return structured info about each word
local word_info = {}
for i, word in ipairs(parsed.words) do
table.insert(word_info, {
index = i,
type = word.type,
given_form = word.given_form,
lemma = word.lemma,
link_target = word.link_target,
ap = word.ap,
control_tags = word.control_tags,
genitive_and_tags = word.genitive_and_tags,
})
end
return {mode = "multi", words = word_info}
end
end
-- =============================================================================
-- Multiword phrase declension
-- =============================================================================
-- Generate forms for a multiword phrase (e.g., "baltasis lokys")
-- Returns a result structure similar to decline_single_pattern
function export.decline_multiword_pattern(parsed, unescape_func)
local words = parsed.words
-- Find the head noun (rightmost noun)
local head_noun_idx = nil
for i = #words, 1, -1 do
if words[i].type == "n" then
head_noun_idx = i
break
end
end
if not head_noun_idx then
error("lt-ndecl: multiword phrase must contain at least one noun")
end
local head_noun = words[head_noun_idx]
-- Decline the head noun to get its forms and metadata
-- Build the pattern string for the head noun
-- Format: given_form,AP[.tag1][.tag2]...[,genitive[.tag1][.tag2]...]
-- Use given_form (not lemma) to preserve capitalization for proper nouns
local noun_pattern = head_noun.given_form .. "," .. tostring(head_noun.ap)
if #head_noun.control_tags > 0 then
noun_pattern = noun_pattern .. "." .. table.concat(head_noun.control_tags, ".")
end
-- Add genitive parameter if present (for Decl V)
if head_noun.genitive_and_tags then
noun_pattern = noun_pattern .. "," .. head_noun.genitive_and_tags
end
local noun_result = decline_single_pattern(noun_pattern, unescape_func)
-- Analyze adjectives and collect their features
local adj_features = {} -- indexed by position in words array
for i = 1, #words do
if words[i].type == "a" then
adj_features[i] = analyze_adjective(words[i])
end
end
-- Collect numeral components' agreement paradigms (from Module:lt-numeral).
-- Only numerals that agree with the quantified noun in gender/number/case are
-- accepted here; the noun-governing numerals (dešimt, the tens, -lika, pus-
-- fractions) take the genitive of the quantified noun, a different
-- construction, and are rejected with a pointer.
local NUM_AGREEING_TYPES = {
adj_full = true, ord = true, card = true, cardpl = true, du = true, trys = true,
}
local num_agreement = {} -- indexed by position in words array
for i = 1, #words do
if words[i].type == "num" then
local m_lt_num = require("Module:lt-numeral")
local data = m_lt_num.get_agreement_forms(words[i].lemma)
if not data then
error("lt-ndecl: <num> component '" .. words[i].lemma ..
"' is not a recognized numeral (check the link target is a numeral lemma)")
end
if not NUM_AGREEING_TYPES[data.type] then
error("lt-ndecl: numeral '" .. words[i].lemma .. "' (type " .. data.type ..
") governs the genitive of the quantified noun rather than agreeing with " ..
"it, so it cannot be a <num> component; the <num> component supports only " ..
"agreeing numerals (1–9, ordinals, du, trys, and the cardinal plurals)")
end
num_agreement[i] = data
end
end
-- Generate the phrase slot by slot, each adjective in the noun's case/number
local multiword_forms = {}
local multiword_family
-- Helper: numeral form for a given noun slot, agreeing in the head noun's
-- gender and the slot's number and case. Returns nil when the numeral has no
-- such form (e.g. the plural-only cardinals in a singular slot, or any
-- vocative/local-case slot — numerals decline in six cases only), which drops
-- that slot from the phrase (so "nine crafts" comes out plural-only).
local NUM_CASES = { nom = true, gen = true, dat = true, acc = true, ins = true, loc = true }
local function get_num_form(num_idx, slot_key, head_gender)
if head_gender ~= "m" and head_gender ~= "f" then
error("lt-ndecl: numeral agreement requires a masculine or feminine "
.. "head noun; a common-gender ('mfbysense') head cannot select "
.. "the numeral's form")
end
local case, number = rmatch(slot_key, "^(%a+)_(%a+)$")
if not case or not NUM_CASES[case] then return nil end
local data = num_agreement[num_idx]
local pk
local nt = data.type
if nt == "adj_full" or nt == "ord" then
pk = "indef_" .. head_gender .. "_" .. number
elseif nt == "card" or nt == "cardpl" then
if number ~= "p" then return nil end
pk = "indef_" .. head_gender .. "_p"
elseif nt == "du" or nt == "trys" then
if number ~= "p" then return nil end
pk = "com_" .. head_gender
else
return nil
end
local paradigm = data.forms[pk]
if not paradigm then return nil end
local flist = paradigm[case]
if not flist or not flist[1] then return nil end
return flist[1].form
end
-- Helper: the adjective's forms for a specific slot, a list of form objects
-- (the long form first, then any colloquial short variant)
local function get_adj_form(adj_idx, slot_key)
local adj = words[adj_idx]
local features = adj_features[adj_idx]
-- Load adjective module
local m_lt_adj = require("Module:lt-adjective")
-- Build stem parameter
local stem_param = nil
for _, tag in ipairs(adj.control_tags) do
if rfind(tag, "^stem:") then
local _, stem_ac = process_input(rsub(tag, "^stem:", ""))
stem_param = stem_ac
break
end
end
-- Generate only the definite and compared forms the given form needs
local suppress_def = (features.definiteness == "indef")
local suppress_comp = (features.degree == "pos")
-- Generate full declension for the adjective
local adj_all_forms = m_lt_adj.decline_forms(
adj.lemma, adj.ap,
suppress_def,
suppress_comp,
stem_param
)
-- Select the appropriate form table based on features
local form_table_key
if features.definiteness == "indef" then
if features.degree == "pos" then
form_table_key = "pos_indef_" .. features.gender
elseif features.degree == "comp" then
form_table_key = "comp_indef_" .. features.gender
else -- sup
form_table_key = "sup_indef_" .. features.gender
end
else -- def
if features.degree == "pos" then
form_table_key = "pos_def_" .. features.gender
elseif features.degree == "comp" then
form_table_key = "comp_def_" .. features.gender
else -- sup
form_table_key = "sup_def_" .. features.gender
end
end
local form_table = adj_all_forms[form_table_key]
if not form_table then
local names = {pos = "positive", comp = "comparative", sup = "superlative",
indef = "indefinite", def = "definite", m = "masculine", f = "feminine"}
error("lt-ndecl: internal error: Module:lt-adjective gives no " .. names[features.degree] .. " "
.. names[features.definiteness] .. " " .. names[features.gender] .. " forms of '" .. adj.lemma
.. "', although '" .. adj.given_form .. "' is one; please report it at Module talk:lt-noun")
end
local form_list = form_table[slot_key]
if not form_list or not form_list[1] then
-- This slot doesn't exist for this adjective form (e.g., vocative for comparative)
return nil
end
-- Preserve capitalization from given_form: where the adjective is
-- written capitalized (a proper noun such as "Aukščiáusioji"), every
-- variant of the generated form is capitalized, short variants included.
local capitalize = adj.given_form ~= lcfirst(adj.given_form)
local out = {}
for _, fobj in ipairs(form_list) do
table.insert(out, {form = capitalize and ucfirst(fobj.form) or fobj.form, footnotes = fobj.footnotes})
end
return out
end
-- Generate forms for all 14 slots (+ secondary local cases if present)
local slot_keys = {
"nom_s","gen_s","dat_s","acc_s","ins_s","loc_s","voc_s",
"nom_p","gen_p","dat_p","acc_p","ins_p","loc_p","voc_p",
}
-- Check if noun has secondary local case forms
if noun_result.forms["ill_s"] or noun_result.forms["ill_p"] then
table.insert(slot_keys, "ill_s")
table.insert(slot_keys, "ill_p")
end
if noun_result.forms["all_s"] or noun_result.forms["all_p"] then
table.insert(slot_keys, "all_s")
table.insert(slot_keys, "all_p")
end
if noun_result.forms["ade_s"] or noun_result.forms["ade_p"] then
table.insert(slot_keys, "ade_s")
table.insert(slot_keys, "ade_p")
end
for _, slot_key in ipairs(slot_keys) do
local noun_forms = noun_result.forms[slot_key]
if noun_forms then
-- The forms of each word in this slot (lists of form objects)
local variants = {}
local all_parts_valid = true
for i = 1, #words do
if words[i].type == "inv" then
-- Invariant word: use as-is
variants[i] = {{form = words[i].given_form}}
elseif words[i].type == "a" then
-- Adjective: generate the appropriate forms
local adj_forms = get_adj_form(i, slot_key)
if adj_forms then
variants[i] = adj_forms
else
-- Slot doesn't exist for this adjective (e.g., comparative vocative)
-- Skip this entire slot
all_parts_valid = false
break
end
elseif words[i].type == "num" then
-- Numeral: generate the form agreeing with the head noun's
-- gender and this slot's number/case
local num_form = get_num_form(i, slot_key, noun_result.gender)
if num_form then
variants[i] = {{form = num_form}}
else
-- No agreeing numeral form for this slot (e.g. a singular
-- slot for a plural-only cardinal): drop the slot
all_parts_valid = false
break
end
elseif words[i].type == "n" and i == head_noun_idx then
-- Head noun: its first form (noun_forms is a list of
-- {form=..., footnotes=...})
variants[i] = {noun_forms[1]}
else
-- A second noun is not supported
error("lt-ndecl: multiple nouns in multiword phrase not supported")
end
end
if all_parts_valid then
-- One phrase per variant: the k-th phrase takes each word's k-th
-- form, or its first where it has fewer (an adjective's long form
-- gives the first phrase, its colloquial short form the second);
-- each phrase carries the footnotes of the forms it is made of.
local count = 1
for i = 1, #words do
count = math.max(count, #variants[i])
end
local phrase_list = {}
for k = 1, count do
local phrase_parts = {}
local footnotes = iut.combine_footnotes(nil, noun_forms[1].footnotes)
for i = 1, #words do
local v = variants[i][k] or variants[i][1]
phrase_parts[i] = v.form
if i ~= head_noun_idx then
footnotes = iut.combine_footnotes(footnotes, v.footnotes)
end
end
iut.insert_form_into_list(phrase_list,
{form = table.concat(phrase_parts, " "), footnotes = footnotes})
end
multiword_forms[slot_key] = phrase_list
-- A surname head brings its family plural into the phrase
-- (the other words in their first form).
local parts = {}
for i = 1, #words do
parts[i] = variants[i][1].form
end
local head_family = noun_result.family_forms and noun_result.family_forms[slot_key]
if head_family then
multiword_family = multiword_family or {}
multiword_family[slot_key] = {}
for _, form_obj in ipairs(head_family) do
parts[head_noun_idx] = form_obj.form
table.insert(multiword_family[slot_key], {
form = table.concat(parts, " "),
footnotes = form_obj.footnotes,
})
end
end
end
-- If not all_parts_valid, the slot is not added to multiword_forms
end
end
-- Build result structure similar to decline_single_pattern
-- Build lemma string from all given forms
local lemma_parts = {}
for _, w in ipairs(words) do
table.insert(lemma_parts, w.given_form)
end
return {
forms = multiword_forms,
family_forms = multiword_family,
lemma = table.concat(lemma_parts, " "),
ap = noun_result.ap,
indeclinable = false, -- multiword phrases are always declinable
gender = noun_result.gender,
decl_roman = noun_result.decl_roman,
number_restr = noun_result.number_restr,
lemma_footnotes = noun_result.lemma_footnotes,
gender_footnotes = noun_result.gender_footnotes,
-- The phrase declines with its head noun; categorize accordingly.
catinfo = noun_result.catinfo,
}
end
-- =============================================================================
-- Testing functions
-- =============================================================================
-- Decline a noun for testing purposes (returns simple string forms)
function export.decline_for_testing(spec)
-- Handle escape sequences
local COMMA_PH = "\001"
local DOT_PH = "\002"
spec = rsub(spec, "\\,", COMMA_PH)
spec = rsub(spec, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
s = rsub(s, COMMA_PH, ",")
s = rsub(s, DOT_PH, ".")
return s
end
local result
local alternant_text = rmatch(spec, "^%s*%(%((.*)%)%)%s*$")
if alternant_text then
result = process_alternants(alternant_text, unescape)
else
-- Check if this is multiword mode
local parsed = parse_multiword(spec, unescape)
if parsed.mode == "multi" then
-- Multiword mode
result = export.decline_multiword_pattern(parsed, unescape)
else
-- Single-word mode
result = decline_single_pattern(spec, unescape)
end
end
add_family_forms(result)
-- Convert form objects to simple strings
local simple_forms = {}
for key, form_list in pairs(result.forms) do
if form_list and #form_list > 0 then
-- Collect all forms
local forms = {}
for _, form_obj in ipairs(form_list) do
table.insert(forms, form_obj.form)
end
-- Join with ", " if multiple
simple_forms[key] = table.concat(forms, ", ")
end
end
return simple_forms
end
return export
5b83d3i9kuoz2bhk7kx1cipl84s99yx
Bản mẫu:lt-ndecl
10
422435
2576458
2026-11-09T01:35:07Z
Hiyuune
50834
Trang mới: “{{#invoke:lt-noun|show}}<noinclude>{{documentation}}</noinclude>”
2576458
wikitext
text/x-wiki
{{#invoke:lt-noun|show}}<noinclude>{{documentation}}</noinclude>
eftmyy59cx2705a6k368zv4nutg9f1l
matematikė
0
422436
2576460
2026-11-09T01:40:28Z
Hiyuune
50834
Trang mới: “=={{langname|lt}}== ==={{section|etym}}=== {{ety|lt|:af|matemãtika|-ė|text=+|tree=+}} ==={{section|pron}}=== {{lt-pr|matemãtikė}} ==={{section|n}}=== {{lt-noun|m|head=matemãtikė|matemãtikės|1|m=matemãtikas}} # {{femeq|lt|matemãtikas}} #* {{quote-book|lt|year=1997|author={{w|Jonas Basanavičius}}|title=Mano gyvenimo kronika ir nervų ligos istorija: 1851-1922 m|isbn=9789986813408|location={{w|Vilnius}}|publisher=Baltos lankos|page=16|pageurl=https://books.goo…”
2576460
wikitext
text/x-wiki
=={{langname|lt}}==
==={{section|etym}}===
{{ety|lt|:af|matemãtika|-ė|text=+|tree=+}}
==={{section|pron}}===
{{lt-pr|matemãtikė}}
==={{section|n}}===
{{lt-noun|m|head=matemãtikė|matemãtikės|1|m=matemãtikas}}
# {{femeq|lt|matemãtikas}}
#* {{quote-book|lt|year=1997|author={{w|Jonas Basanavičius}}|title=Mano gyvenimo kronika ir nervų ligos istorija: 1851-1922 m|isbn=9789986813408|location={{w|Vilnius}}|publisher=Baltos lankos|page=16|pageurl=https://books.google.com/books?id=uBshAQAAMAAJ&q=%22matematik%C4%97%22&dq=%22matematik%C4%97%22&hl=lt&newbks=1&newbks_redir=0&source=gb_mobile_search&ovdme=1&sa=X&ved=2ahUKEwjN9P71uvGXAxUkjIkEHefLDK44KBDoAXoECA0QAw#%22matematik%C4%97%22|text={{...}} kitos jos sesers Uršės, ištekėjusios už Šmulkščio Gražiškiuose, duktė Kastancija Matulaitienė - hysterikė, labai gabi '''matematikė'''.}}
===={{section|decl}}====
{{lt-ndecl|matemãtikė,1}}
==={{section|further}}===
* {{R:lt:BŽ|matematikas}}
* {{R:lt:DŽ|matematikas}}
* {{R:LKZ|matematikas}}
{{C|lt|Thiên văn học|Toán học|Nghề nghiệp}}
5e4b0a0t2fmzs2mjrx4bfga8hiqtuw1
matematikas
0
422437
2576461
2026-11-09T01:43:35Z
Hiyuune
50834
Trang mới: “{{also|matemātikas}} =={{langname|lt}}== {{wp|lt:}} ==={{section|etym}}=== {{ety|lt|:af|matemãtika|-as|text=+|tree=+}} ==={{section|pron}}=== {{lt-pr|matemãtikas}} ==={{section|n}}=== {{lt-noun|m|head=matemãtikas|matemãtikai|1|f=matemãtikė}} # [[nhà]] [[toán học]]. # {{lb|lt|obsolete}} [[nhà]] [[chiêm tinh]]. #: {{syn|lt|astrològas}} ===={{section|decl}}==== {{lt-ndecl|matemãtikas,1}} ==={{section|further}}=== * {{R:lt:BŽ}} * {{R:lt:DŽ}} * {{R:LKZ}}…”
2576461
wikitext
text/x-wiki
{{also|matemātikas}}
=={{langname|lt}}==
{{wp|lt:}}
==={{section|etym}}===
{{ety|lt|:af|matemãtika|-as|text=+|tree=+}}
==={{section|pron}}===
{{lt-pr|matemãtikas}}
==={{section|n}}===
{{lt-noun|m|head=matemãtikas|matemãtikai|1|f=matemãtikė}}
# [[nhà]] [[toán học]].
# {{lb|lt|obsolete}} [[nhà]] [[chiêm tinh]].
#: {{syn|lt|astrològas}}
===={{section|decl}}====
{{lt-ndecl|matemãtikas,1}}
==={{section|further}}===
* {{R:lt:BŽ}}
* {{R:lt:DŽ}}
* {{R:LKZ}}
{{C|lt|Thiên văn học|Toán học|Nghề nghiệp}}
b2xys17dqn88izfpq8h83q3ibbv61w2
Mô đun:number list/data/nai-kum
828
422438
2576463
2026-11-09T01:46:00Z
Hiyuune
50834
Trang mới: “local export = {numbers = {}} local numbers = export.numbers export.numbers[1] = { cardinal = "ʼesin" } export.numbers[2] = { cardinal = "hewak" } export.numbers[3] = { cardinal = "hemuk" } export.numbers[4] = { cardinal = "chepap" } export.numbers[5] = { cardinal = "saarrap" } export.numbers[6] = { cardinal = "hemhuuk" } export.numbers[7] = { cardinal = "pehkaay" } export.numbers[8] = { cardinal = "chemhuuk" } export.numbers[9] = { cardinal = "nyemhem…”
2576463
Scribunto
text/plain
local export = {numbers = {}}
local numbers = export.numbers
export.numbers[1] = {
cardinal = "ʼesin"
}
export.numbers[2] = {
cardinal = "hewak"
}
export.numbers[3] = {
cardinal = "hemuk"
}
export.numbers[4] = {
cardinal = "chepap"
}
export.numbers[5] = {
cardinal = "saarrap"
}
export.numbers[6] = {
cardinal = "hemhuuk"
}
export.numbers[7] = {
cardinal = "pehkaay"
}
export.numbers[8] = {
cardinal = "chemhuuk"
}
export.numbers[9] = {
cardinal = "nyemhemuuk"
}
export.numbers[10] = {
cardinal = "shaahuuk"
}
return export
i6vlbqgi35inzbmux0ny1gfreuzyki8
ケビン
0
422439
2576464
2026-11-09T01:47:50Z
Hiyuune
50834
+ ja
2576464
wikitext
text/x-wiki
=={{langname|ja}}==
==={{ĐM|pron}}===
{{ja-pron|acc=1|acc_ref=DJR4,SMK8}}
==={{ĐM|n}}===
{{ja-noun}}
# {{lb|ja|dated}} {{alt of|ja|キャビン|tr=kyabin|t=cabin}}
==={{ĐM|ref}}===
{{reflist}}
ebwnq27xz273qmh3gsvspy7l9jrg1f5
ἀστεροειδής
0
422440
2576466
2026-11-09T01:51:57Z
Hiyuune
50834
+ grc
2576466
wikitext
text/x-wiki
=={{langname|grc}}==
==={{section|etym}}===
{{ety|grc|:af|ἀστήρ|-ειδής}}
Từ {{af|grc|ἀστήρ|-ειδής}}
==={{section|pron}}===
{{grc-IPA|ἀ˘στεροειδής}}
==={{section|adj}}===
{{grc-adj-3rd|ἀστεροειδές}}
# Có nhiều [[sao]].
===={{section|decl}}====
{{grc-adecl|ἀ˘στεροειδής|ες}}
===={{section|desc}}====
{{col-top|2|desc}}
* {{desc|ast|asteroide|bor=1}}
* {{desc|eu|asteroide|bor=1}}
* {{desc|bg|астерои́д|bor=1}}
* {{desc|ca|asteroide|bor=1}}
* {{desc|cs|asteroid|bor=1}}
* {{desc|da|asteroide|bor=1}}
* {{desc|nl|asteroïde|bor=1}}
* {{desc|en|asteroid|bor=1}}
* {{desc|et|asteroid|bor=1}}
* {{desc|fi|asteroidi|bor=1}}
* {{desc|fr|astéroïde|bor=1}}
* {{desc|gl|asteroide|bor=1}}
* {{desc|de|Asteroid|bor=1}}
* {{desc|id|asteroid|bor=1}}
* {{desc|it|asteroide|bor=1}}
* {{desc|lv|asteroīds|bor=1}}
* {{desc|mk|астерои́д|bor=1}}
* {{desc|nb|asteroide|bor=1}}
* {{desc|nn|asteroide|bor=1}}
* {{desc|pt|asteroide|bor=1}}
* {{desc|ro|asteroid|bor=1}}
* {{desctree|ru|астеро́ид|bor=1}}
* {{desc|sh|asteròīd|bor=1}}
* {{desc|sl|asteroȋd|bor=1}}
* {{desc|es|asteroide|bor=1}}
* {{desc|sw|asteroidi|bor=1}}
* {{desc|sv|asteroid|bor=1}}
* {{desc|tr|asteroit|bor=1}}
{{col-bottom}}
==={{section|further}}===
* {{R:grc:Bailly}}
* {{R:grc:DGE}}
* {{R:Logeion}}
* {{R:grc:LSJ}}
* {{R:grc:Woodhouse}}
k1hho67yqdpo2slrfnguz2ya8onjpma
2576469
2576466
2026-11-09T01:54:57Z
Hiyuune
50834
/* Tính từ */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2576469
wikitext
text/x-wiki
=={{langname|grc}}==
==={{section|etym}}===
{{ety|grc|:af|ἀστήρ|-ειδής}}
Từ {{af|grc|ἀστήρ|-ειδής}}
==={{section|pron}}===
{{grc-IPA|ἀ˘στεροειδής}}
==={{section|adj}}===
{{grc-adj-3rd|ἀστεροειδές}}
# Giống như [[ngôi sao]]; có nhiều [[ngôi sao]].
===={{section|decl}}====
{{grc-adecl|ἀ˘στεροειδής|ες}}
===={{section|desc}}====
{{col-top|2|desc}}
* {{desc|ast|asteroide|bor=1}}
* {{desc|eu|asteroide|bor=1}}
* {{desc|bg|астерои́д|bor=1}}
* {{desc|ca|asteroide|bor=1}}
* {{desc|cs|asteroid|bor=1}}
* {{desc|da|asteroide|bor=1}}
* {{desc|nl|asteroïde|bor=1}}
* {{desc|en|asteroid|bor=1}}
* {{desc|et|asteroid|bor=1}}
* {{desc|fi|asteroidi|bor=1}}
* {{desc|fr|astéroïde|bor=1}}
* {{desc|gl|asteroide|bor=1}}
* {{desc|de|Asteroid|bor=1}}
* {{desc|id|asteroid|bor=1}}
* {{desc|it|asteroide|bor=1}}
* {{desc|lv|asteroīds|bor=1}}
* {{desc|mk|астерои́д|bor=1}}
* {{desc|nb|asteroide|bor=1}}
* {{desc|nn|asteroide|bor=1}}
* {{desc|pt|asteroide|bor=1}}
* {{desc|ro|asteroid|bor=1}}
* {{desctree|ru|астеро́ид|bor=1}}
* {{desc|sh|asteròīd|bor=1}}
* {{desc|sl|asteroȋd|bor=1}}
* {{desc|es|asteroide|bor=1}}
* {{desc|sw|asteroidi|bor=1}}
* {{desc|sv|asteroid|bor=1}}
* {{desc|tr|asteroit|bor=1}}
{{col-bottom}}
==={{section|further}}===
* {{R:grc:Bailly}}
* {{R:grc:DGE}}
* {{R:Logeion}}
* {{R:grc:LSJ}}
* {{R:grc:Woodhouse}}
obz5b8p6q6iue333b6v7w0s9htfx0fa
ἀστεροειδές
0
422441
2576467
2026-11-09T01:52:59Z
Hiyuune
50834
+ grc
2576467
wikitext
text/x-wiki
=={{langname|grc}}==
==={{section|pron}}===
{{grc-IPA|ᾰ̓στεροειδές}}
==={{section|adj}}===
{{grc-adjective form|ᾰ̓στεροειδές}}
# {{infl of|grc|ᾰ̓στεροειδής||voc|ở|m//f|s|;|nom//acc//voc|ở|n|s}}
axssg1oy4syr78nxi02pfjc44323o8c
ἀστεροειδοῦς
0
422442
2576468
2026-11-09T01:53:59Z
Hiyuune
50834
+ grc
2576468
wikitext
text/x-wiki
=={{langname|grc}}==
==={{section|pron}}===
{{grc-IPA|ᾰ̓στεροειδοῦς}}
==={{section|adj}}===
{{grc-adjective form|ᾰ̓στεροειδοῦς}}
# {{infl of|grc|ᾰ̓στεροειδής||gen|ở|m//f//n|s}}
jj3y3mgaoy46fzrrbr69mfq03taqa2r
サンピードロ
0
422443
2576470
2026-11-09T01:57:23Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== ==={{ĐM|alt}}=== * {{ja-r|^サン ^ピドロ}} ==={{ĐM|etym}}=== Từ {{bor|ja|en|San Pedro}}. ==={{ĐM|pr-noun}}=== {{ja-pos|proper|サン ピードロ}} # {{lb|ja|dated}} {{place|ja|t=San Pedro|khu dân cư|city/Los Angeles|state/California|c/Hoa Kỳ}} ===={{ĐM|syn}}==== * {{ja-r|^サン ^ペドロ}}”
2576470
wikitext
text/x-wiki
=={{langname|ja}}==
==={{ĐM|alt}}===
* {{ja-r|^サン ^ピドロ}}
==={{ĐM|etym}}===
Từ {{bor|ja|en|San Pedro}}.
==={{ĐM|pr-noun}}===
{{ja-pos|proper|サン ピードロ}}
# {{lb|ja|dated}} {{place|ja|t=San Pedro|khu dân cư|city/Los Angeles|state/California|c/Hoa Kỳ}}
===={{ĐM|syn}}====
* {{ja-r|^サン ^ペドロ}}
549c9ik5lcjm4nqw5i6f2u0u94zjqfk
赤撞木鮫
0
422444
2576471
2026-11-09T01:58:57Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|あか|しゅ|もく|さめ|r=y|k4=ざめ|y=k,o2,k}} {{swp|ja:アカシュモクザメ}} ==={{ĐM|etym}}=== {{ja-com|赤|あか|撞木鮫|しゅもくざめ|sort=あかしゅもくざめ}} ==={{ĐM|n}}=== {{ja-noun|あかしゅもくざめ}} # {{w|Cá nhám búa}}, {{taxlink|Sphyrna lewini|loài}}. ===={{section|usage}}==== {{U:ja:biology|アカシュモクザメ}}”
2576471
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|あか|しゅ|もく|さめ|r=y|k4=ざめ|y=k,o2,k}}
{{swp|ja:アカシュモクザメ}}
==={{ĐM|etym}}===
{{ja-com|赤|あか|撞木鮫|しゅもくざめ|sort=あかしゅもくざめ}}
==={{ĐM|n}}===
{{ja-noun|あかしゅもくざめ}}
# {{w|Cá nhám búa}}, {{taxlink|Sphyrna lewini|loài}}.
===={{section|usage}}====
{{U:ja:biology|アカシュモクザメ}}
rditoyiow33s3wle32ostyrxgo8ffat
アカシュモクザメ
0
422445
2576472
2026-11-09T01:59:19Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-see|赤撞木鮫}}”
2576472
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|赤撞木鮫}}
3dm6z5xm2c92ops6t1mrr10053w3sbo
赤腹井守
0
422446
2576473
2026-11-09T02:00:50Z
Hiyuune
50834
+ ja
2576473
wikitext
text/x-wiki
=={{langname|ja}}==
{{wp|ja:アカハライモリ}}
{{ja-kanjitab|あか|はら|い|も|o4=り|yomi=k|alt=赤腹蠑螈}}
==={{ĐM|etym}}===
{{com|ja|赤腹|井守|tr1=akahara|tr2=imori}}
==={{ĐM|pron}}===
{{ja-pron|あかはら いもり|acc=5}}
==={{ĐM|n}}===
{{ja-noun|あかはら いもり|アカハラ イモリ|hist1=あかはらゐもり|hist2=アカハラヰモリ}}
# Sa giông bụng đỏ [[Nhật Bản]] ({{taxlink|Cynops pyrrhogaster|loài}}).
===={{ĐM|syn}}====
* {{ja-r|日%本%井%守|^ニ%ホン% イ%モリ}}
* {{ja-r|赤%腹|アカ%ハラ}}
* {{ja-r|井%守|イ%モリ}}
gmdpd5tv462prt2b9b5zd34g6qd5b9h
2576477
2576473
2026-11-09T02:03:11Z
Hiyuune
50834
/* Đồng nghĩa */ (sử dụng [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]])
2576477
wikitext
text/x-wiki
=={{langname|ja}}==
{{wp|ja:アカハライモリ}}
{{ja-kanjitab|あか|はら|い|も|o4=り|yomi=k|alt=赤腹蠑螈}}
==={{ĐM|etym}}===
{{com|ja|赤腹|井守|tr1=akahara|tr2=imori}}
==={{ĐM|pron}}===
{{ja-pron|あかはら いもり|acc=5}}
==={{ĐM|n}}===
{{ja-noun|あかはら いもり|アカハラ イモリ|hist1=あかはらゐもり|hist2=アカハラヰモリ}}
# Sa giông bụng đỏ [[Nhật Bản]] ({{taxlink|Cynops pyrrhogaster|loài}}).
===={{ĐM|syn}}====
* {{ja-r|日%本%井%守|^ニ%ホン% イ%モリ}}
* {{ja-r|赤%腹|アカ%ハラ}}
* {{ja-r|井%守|イ%モリ}}
{{C|ja|Phân họ Sa giông}}
h4l72hy734np82w6hqn6hbmln75nxwi
アカハラヰモリ
0
422447
2576474
2026-11-09T02:01:57Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-see|赤腹井守}}”
2576474
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|赤腹井守}}
im8nhg9ur5hw4zlc1bqs83y7xf0j0hc
赤腹蠑螈
0
422448
2576475
2026-11-09T02:02:12Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|あか|はら|いもり2|yomi=k2,juku2}} {{ja-see|赤腹井守}}”
2576475
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|あか|はら|いもり2|yomi=k2,juku2}}
{{ja-see|赤腹井守}}
ekckic9lfs88o8a008u3elhzxjnw8y8
アカハライモリ
0
422449
2576476
2026-11-09T02:02:26Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-see|赤腹井守}}”
2576476
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-see|赤腹井守}}
im8nhg9ur5hw4zlc1bqs83y7xf0j0hc
Thể loại:ja:Phân họ Sa giông
14
422450
2576479
2026-11-09T02:04:34Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576479
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
大山椒魚
0
422451
2576480
2026-11-09T02:06:51Z
Hiyuune
50834
Trang mới: “=={{langname|ja}}== {{ja-kanjitab|おお|さん|しょう|うお}} {{swp|ja:オオサンショウウオ}} [[Image:Cryptobranchus japonicus.jpg|thumb|{{lang|ja|オオサンショウウオ}}]] ==={{section|etym}}=== {{ja-compound|大|おお|山椒魚|さんしょううお}} ==={{section|pron}}=== {{ja-pron|おおさんしょう.うお|acc=5}} ==={{section|n}}=== {{ja-noun|おおさんしょう.うお|オオサンショウウオ|hist1=おほさんせううを|hist2=オホ…”
2576480
wikitext
text/x-wiki
=={{langname|ja}}==
{{ja-kanjitab|おお|さん|しょう|うお}}
{{swp|ja:オオサンショウウオ}}
[[Image:Cryptobranchus japonicus.jpg|thumb|{{lang|ja|オオサンショウウオ}}]]
==={{section|etym}}===
{{ja-compound|大|おお|山椒魚|さんしょううお}}
==={{section|pron}}===
{{ja-pron|おおさんしょう.うお|acc=5}}
==={{section|n}}===
{{ja-noun|おおさんしょう.うお|オオサンショウウオ|hist1=おほさんせううを|hist2=オホサンセウウヲ}}
# {{w|Kỳ giông khổng lồ Nhật Bản}}, {{taxlink|Andrias japonicus|loài}}
#: {{syn|ja|半割|tr=hanzaki}}
===={{section|usage}}====
{{U:ja:biology}}
{{C|ja|Bộ Có đuôi}}
eg09k84h45iwo9nzg0wv9y3uqmol9a7
Thể loại:ja:Bộ Có đuôi
14
422452
2576481
2026-11-09T02:07:08Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576481
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Thể loại:ja:Lớp Lưỡng cư
14
422453
2576482
2026-11-09T02:07:35Z
Hiyuune
50834
Trang mới: “{{auto cat}}”
2576482
wikitext
text/x-wiki
{{auto cat}}
eomzlm5v4j7ond1phrju7cnue91g5qx
Mô đun:lt-headword
828
422454
2576487
2026-11-09T09:43:59Z
Hiyuune
50834
nhập module từ enwikt, tác giả User:TongcyDai
2576487
Scribunto
text/plain
local export = {}
local pos_functions = {}
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_para = require("Module:parameters")
local m_common = require("Module:lt-common")
local m_headword_utilities = require("Module:headword utilities")
local lang = require("Module:languages").getByCode("lt")
local function glossary_link(anchor, text)
text = text or anchor
return "[[Phụ lục:Từ điển thuật ngữ#" .. anchor .. "|" .. text .. "]]"
end
-- Tác giả: [[:en:User:TongcyDai]]
-- The heads are accented forms, which Module:headword shows unlinked; a head
-- of several words gets a link on each word, as Module:headword gives a head
-- taken from the page name. A head that already holds a link is left as it is.
local function full_headword(data)
local m_headword = require("Module:headword")
for _, head in ipairs(data.heads) do
if head.term and not head.term:find("[[", 1, true) and m_headword.head_is_multiword(head.term) then
head.term = m_headword.add_multiword_links(head.term)
end
end
return m_headword.full_headword(data)
end
-- Calls written for the legacy template of the same name (each template passes
-- legacy=<its name>). A call is legacy when it has a parameter that only the
-- legacy template takes, or a parameter 1 that cannot be a pattern of the new
-- one. A call without parameter 1 is new only on a page that has the table the
-- new template reads.
local function page_has(pattern)
return (mw.title.getCurrentTitle():getContent() or ""):find(pattern) ~= nil
end
local function plain(text)
return m_common.stripDiacritics(text)
end
local LEGACY = {
["lt-noun"] = {
keys = {2, 3, "head", "head2", "g2", "indecl"},
test = function(first)
if first then
return not first:find("[,<]")
end
return not page_has("{{%s*lt%-ndecl")
end,
},
["lt-adj"] = {
keys = {2, 3, "head"},
test = function(first)
if first then
return not first:find(",")
end
return not page_has("{{%s*lt%-adecl")
end,
},
["lt-verb"] = {
keys = {2, 3, "head"},
test = function(first)
if first then
return not mw.ustring.find(first, "^[^,]*,[^,]*,")
end
return not page_has("{{%s*lt%-conj%s*|[^|}]-,[^|}]-,")
and not page_has("{{%s*lt%-conj%+")
end,
},
["lt-adv"] = {
keys = {"head", "head2"},
test = function(first, pagename)
return not first or first == "-"
or plain(mw.ustring.match(first, "^[^.%[]*")) ~= pagename
end,
},
["lt-part"] = {
keys = {"m"},
test = function(first)
if first then
return mw.ustring.find(plain(first), "dam$") ~= nil
end
return not page_has("{{%s*lt%-pdecl")
end,
},
}
LEGACY["lt-proper noun"] = {
keys = {2, "head", "head2", "pl", "indecl", "fs", "hypocor"},
test = LEGACY["lt-noun"].test,
}
local function is_legacy_call(name, pargs)
local legacy = LEGACY[name]
-- The template's own page calls it without parameters.
if not legacy or pargs.pagename
or (next(pargs) == nil and mw.title.getCurrentTitle().nsText == "Template") then
return false
end
for _, key in ipairs(legacy.keys) do
if pargs[key] ~= nil then
return true
end
end
local first = pargs[1]
if first == "" then
first = nil
end
return legacy.test(first, mw.loadData("Module:headword/data").pagename)
end
-- Main entry point
function export.show(frame)
local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.")
if frame.args.legacy and is_legacy_call(frame.args.legacy, frame:getParent().args) then
return m_common.render_legacy(frame, frame.args.legacy)
end
local params = {
[1] = {}, -- inflection spec; nil triggers scraping from {{lt-ndecl}}/{{lt-adecl}}/{{lt-conj}}/{{lt-pdecl}}
-- (numerals: nil = spec-table lookup with scraping fallback; "noun" forces the lt-ndecl path;
-- pronouns: the accented head of a pronoun without a declension table)
["id"] = {}, -- disambiguates when multiple inflection templates exist on the page
["pagename"] = {}, -- for testing
}
-- Add derivation parameters for nouns.
if poscat == "nouns" or poscat == "proper nouns" then
params["m"] = {list = true}
params["f"] = {list = true}
params["adj"] = {list = true}
params["dim"] = {list = true}
params["aug"] = {list = true}
params["pej"] = {list = true}
-- Proper nouns only. m/f keep their meaning above for common nouns
-- (male/female equivalent); under "proper nouns" they are reused for
-- surname derivation instead (see handle_nouns), nee/n add the other
-- surname forms, and dem/fdem the demonyms of a place name.
if poscat == "proper nouns" then
params["nee"] = {list = true}
params["n"] = {list = true}
params["dem"] = {list = true}
params["fdem"] = {list = true}
end
-- Add derivation parameters for adjectives.
elseif poscat == "adjectives" then
params["adv"] = {list = true}
params["dim"] = {list = true}
params["aug"] = {list = true}
params["pej"] = {list = true}
-- Add derivation parameters for adverbs.
elseif poscat == "adverbs" then
params["adj"] = {list = true}
params["dim"] = {list = true}
end
-- Verbs take no derivation parameters.
local args = m_para.process(frame:getParent().args, params)
local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
local data = {
lang = lang,
pos_category = poscat,
categories = {},
heads = {},
genders = {},
inflections = {},
id = args.id,
no_redundant_head_cat = true,
-- Without it, Module:headword takes the title of the current page and
-- ignores |pagename=.
pagename = pagename,
}
-- On a template's own page (Template:lt-num, Template:lt-noun, …) there
-- is no entry to scrape or look up: render a bare headword line instead
-- of letting the pos handler error out.
if not args[1] and not args.pagename
and mw.title.getCurrentTitle().nsText == "Template" then
table.insert(data.heads, {term = pagename})
return full_headword(data)
end
if pos_functions[poscat] then
pos_functions[poscat](args, data, pagename)
end
return full_headword(data)
end
-- Insert a derivation parameter into data.inflections.
-- Supports comma-separated values within a single param (e.g. |dim=darbužis,darbelis)
-- and inline modifiers (e.g. |dim=darbužis<q:informal>).
local function handle_deriv(args, data, param_name, label, accel_form)
m_headword_utilities.parse_and_insert_inflection {
headdata = data,
forms = args[param_name],
paramname = param_name,
label = label,
splitchar = ",",
accel = accel_form and {form = accel_form} or nil,
}
end
-- =============================================================================
-- Toponym-derived demonym / adjective (dem, fdem, adj auto-generation)
-- =============================================================================
--
-- |dem=+ or a suffix keyword derives the demonym from the entry's lemma (the
-- toponym). fdem and adj are then derived from the resulting dem, whether
-- derived or typed.
-- The suffix of "+".
local DEM_DEFAULT_SUFFIX = "iẽtis"
-- Toponym endings replaced by the suffix, for "+" and the suffix keywords.
-- None is a suffix of another. -ija is handled before this list.
local TOPONYM_ENDINGS = {"as", "a", "ė", "is", "us", "ai", "os"}
-- Suffix keywords accepted in |dem=.
local DEM_SUFFIX_KEYWORDS = {
["as"] = true, ["is"] = true,
["ietis"] = true, ["iẽtis"] = true,
["jietis"] = true, ["jiẽtis"] = true,
}
-- Hardcoded exceptions where the regular dem -> fdem/adj rules misfire.
local DEM_EXCEPTIONS = {
["vokietis"] = {fdem = "vókietė", adj = "vókiškas"},
}
-- Collapse a (possibly multi-word) toponym into a single lowercase, accent-
-- free string for ending detection. The demonym's accent comes entirely from
-- the suffix, so the toponym's own accent marks and word spacing are dropped.
local function clean_toponym(toponym)
local bare = m_common.process_input(toponym)
bare = mw.ustring.lower(bare)
bare = mw.ustring.gsub(bare, " ", "")
return bare
end
-- Strip `n` base characters from the end of a two-track stem, keeping any
-- combining accent marks that belong to characters before the cut point.
local function strip_n_chars(stem_bare, stem_ac, n)
local bare_result = mw.ustring.sub(stem_bare, 1, -(n + 1))
local target = mw.ustring.len(bare_result)
if target == 0 then return "", "" end
local GRAVE, ACUTE, TILDE = m_common.GRAVE, m_common.ACUTE, m_common.TILDE
local base_count, pos = 0, 0
local total = mw.ustring.len(stem_ac)
while pos < total and base_count < target do
pos = pos + 1
local ch = mw.ustring.sub(stem_ac, pos, pos)
if ch ~= GRAVE and ch ~= ACUTE and ch ~= TILDE then
base_count = base_count + 1
end
end
while pos < total do
local nxt = mw.ustring.sub(stem_ac, pos + 1, pos + 1)
if nxt == GRAVE or nxt == ACUTE or nxt == TILDE then
pos = pos + 1
else
break
end
end
return bare_result, mw.ustring.sub(stem_ac, 1, pos)
end
-- Join a toponym stem and a demonym suffix. A stem left ending in i after
-- its ending is stripped (Vilnius, Šiauliai, Telšiai) drops that i before
-- a suffix that begins with one: vilniẽtis, šiauliẽtis, not *vilniiẽtis.
local function join_dem(stem, suffix)
if mw.ustring.sub(stem, -1) == "i" and mw.ustring.sub(suffix, 1, 1) == "i" then
stem = mw.ustring.sub(stem, 1, -2)
end
return m_common.makeDisplayText(stem .. suffix)
end
-- "+": derive a demonym from the toponym's ending. Returns dem, or nil and an
-- error message when the ending is not recognized.
local function derive_dem_plus(toponym)
local bare = clean_toponym(toponym)
if mw.ustring.sub(bare, -3) == "ija" then
return nil, "toponym \"" .. toponym .. "\" ends in \"-ija\"; please specify the demonym type manually (|dem=<suffix> or the full word)"
end
for _, ending in ipairs(TOPONYM_ENDINGS) do
local elen = mw.ustring.len(ending)
if mw.ustring.sub(bare, -elen) == ending then
return join_dem(mw.ustring.sub(bare, 1, -(elen + 1)), DEM_DEFAULT_SUFFIX)
end
end
return nil, "cannot auto-derive a demonym from toponym \"" .. toponym .. "\"; please specify the demonym type manually (|dem=<suffix> or the full word)"
end
-- Derive a demonym with a suffix keyword (as/is/ietis/iẽtis/jietis/jiẽtis).
-- Returns dem, or nil and an error message when the ending is not recognized.
local function derive_dem_semiauto(toponym, suffix)
local bare = clean_toponym(toponym)
-- An -ija toponym drops the whole ending, whatever the suffix.
if mw.ustring.sub(bare, -3) == "ija" then
return join_dem(mw.ustring.sub(bare, 1, -4), suffix)
end
-- -jietis is added to the whole name; -ietis replaces an invariant final
-- -u/-o (Peru, Nauru).
if suffix == "jietis" or suffix == "jiẽtis" then
return m_common.makeDisplayText(bare .. suffix)
end
if suffix == "ietis" or suffix == "iẽtis" then
local last = mw.ustring.sub(bare, -1)
if last == "u" or last == "o" then
return join_dem(mw.ustring.sub(bare, 1, -2), suffix)
end
end
-- Otherwise the suffix replaces one of TOPONYM_ENDINGS.
for _, ending in ipairs(TOPONYM_ENDINGS) do
local elen = mw.ustring.len(ending)
if mw.ustring.sub(bare, -elen) == ending then
return join_dem(mw.ustring.sub(bare, 1, -(elen + 1)), suffix)
end
end
return nil, "cannot derive a demonym from toponym \"" .. toponym .. "\" with suffix \"" .. suffix .. "\"; please enter the full word manually"
end
-- Derive fdem and adj from one dem word (derived or typed), by its ending.
-- Returns fdem, adj, or nil, nil when the ending is not recognized.
local function derive_fdem_adj(dem)
local stem_bare, stem_ac = m_common.process_input(dem)
local exception = DEM_EXCEPTIONS[mw.ustring.lower(stem_bare)]
if exception then
return exception.fdem, exception.adj
end
local suffix_len
if mw.ustring.sub(stem_bare, -2) == "as" or mw.ustring.sub(stem_bare, -2) == "is" then
suffix_len = 2
else
return nil, nil
end
local stem_bare2, stem_ac2 = strip_n_chars(stem_bare, stem_ac, suffix_len)
local fdem = stem_ac2 .. "ė"
local adj
if mw.ustring.sub(stem_bare, -5) == "ietis" then
-- -iẽtis carries its own accent: the adjective replaces the whole
-- suffix with -iẽtiškas.
local deep_bare, deep_ac = strip_n_chars(stem_bare, stem_ac, 5)
adj = deep_ac .. "iẽtiškas"
else
adj = stem_ac2 .. "iškas"
end
return m_common.makeDisplayText(fdem), m_common.makeDisplayText(adj)
end
-- Split a |dem= list item's comma-separated piece into its core word and any
-- trailing inline modifier (e.g. "kubietis<q:informal>"), so the core alone
-- can be checked against "+"/suffix keywords while the modifier passes through.
local function split_core_and_modifier(piece)
local lt_pos = mw.ustring.find(piece, "<", 1, true)
if lt_pos then
return mw.text.trim(mw.ustring.sub(piece, 1, lt_pos - 1)), mw.ustring.sub(piece, lt_pos)
end
return mw.text.trim(piece), ""
end
-- Resolve |dem= (expanding "+" and suffix keywords) and, unless |fdem=/|adj=
-- are given, fill them from the resolved dem.
local function handle_toponym_derivation(args, data, toponym)
if not (args.dem and #args.dem > 0) then return end
local fdem_words, adj_words = {}, {}
for i, raw in ipairs(args.dem) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
local resolved
if core == "+" then
local dem, err = derive_dem_plus(toponym)
if not dem then error("lt-headword: " .. err) end
resolved = dem
elseif DEM_SUFFIX_KEYWORDS[core] then
local dem, err = derive_dem_semiauto(toponym, core)
if not dem then error("lt-headword: " .. err) end
resolved = dem
else
resolved = core
end
pieces[j] = resolved .. modifier
local fdem, adj = derive_fdem_adj(resolved)
if fdem then table.insert(fdem_words, fdem) end
if adj then table.insert(adj_words, adj) end
end
args.dem[i] = table.concat(pieces, ",")
end
if (not args.fdem or #args.fdem == 0) and #fdem_words > 0 then
args.fdem = {table.concat(fdem_words, ",")}
end
if (not args.adj or #args.adj == 0) and #adj_words > 0 then
args.adj = {table.concat(adj_words, ",")}
end
end
-- =============================================================================
-- Surname derivation (m -> f/nee/n, proper nouns only)
-- =============================================================================
--
-- Proper nouns only: m/f mean "male surname"/"married surname" here, not
-- "male/female equivalent".
--
-- f/nee/n are derived from the entry's lemma, the masculine surname, with the
-- accent paradigm of its {{lt-ndecl}} pattern (results[1].lemma,
-- results[1].ap). |m= is shown as typed.
--
-- Every derived form has exactly one accent mark: an unaccented keyword keeps
-- the accent of the masculine stem, an accented one replaces it with the
-- suffix's (attach_surname_suffix).
-- Masculine endings replaced by -ienė or -ė. The two-letter endings come
-- before the one-letter ones (ja/ia before a).
local SURNAME_M_ENDINGS = {"as", "is", "ys", "ia", "ja", "us", "ė", "a"}
local function surname_m_ending_len(m_bare)
for _, ending in ipairs(SURNAME_M_ENDINGS) do
local elen = mw.ustring.len(ending)
if mw.ustring.sub(m_bare, -elen) == ending then
return elen
end
end
return nil
end
-- The maiden-name suffix for a masculine ending. Returns strip_len,
-- suffix_bare, suffix_accented, force_retain (true for -ėnas/-ynas/-ūnas,
-- which keep the masculine's accent). -ius/-jus are checked before -us; only
-- "us" is stripped, the i/j stays in the stem.
local function select_daughter_suffix(m_bare)
local last3 = mw.ustring.sub(m_bare, -3)
if last3 == "ius" or last3 == "jus" then
return 2, "ūtė", "ū̃tė", false
end
local last2 = mw.ustring.sub(m_bare, -2)
if last2 == "ys" or last2 == "ia" or last2 == "ja" or last2 == "is" then
return 2, "ytė", "ýtė", false
end
if mw.ustring.sub(m_bare, -1) == "ė" then
return 1, "ytė", "ýtė", false
end
if last2 == "as" then
local last4 = mw.ustring.sub(m_bare, -4)
local force_retain = last4 == "ėnas" or last4 == "ynas" or last4 == "ūnas"
return 2, "aitė", "áitė", force_retain
end
if last2 == "us" then
return 2, "utė", "ùtė", false
end
if mw.ustring.sub(m_bare, -1) == "a" then
return 1, "aitė", "áitė", false
end
return nil
end
-- Strip `strip_len` characters from the masculine surname's two-track form
-- and attach `suffix` (an NFC literal). suffix_has_own_accent controls which
-- side keeps the word's single accent mark: true drops any accent left in
-- the retained stem (the suffix supplies it), false keeps the stem's own
-- accent (if any) and adds no accent from the suffix. Errors if neither side
-- ends up carrying an accent (e.g. the masculine's own accent was on the
-- part just stripped away, and the suffix carries none either).
local function attach_surname_suffix(m_bare, m_ac, strip_len, suffix, suffix_has_own_accent)
local stem_bare, stem_ac = strip_n_chars(m_bare, m_ac, strip_len)
if suffix_has_own_accent then
stem_ac = m_common.to_stem_bare(stem_ac)
end
-- The suffix literal is precomposed (í, á, ý, ù); bring it onto the
-- stem_ac track, where the accent is a combining mark, before joining.
local result = stem_ac .. m_common.to_stem_ac(suffix)
if not m_common.has_accent(result) then
error("derived surname form \"" .. result .. "\" has no accent mark; please check the input or enter the full word manually")
end
-- Insert the dot-above required between i/j and a combining accent mark
-- ("íenė" renders as "i̇́enė").
return m_common.makeDisplayText(result)
end
-- nee (maiden surname): "+" only; the suffix follows from the masculine ending.
local function resolve_nee_core(core, m_bare, m_ac)
if core ~= "+" then return nil, nil end
local strip_len, suffix_bare, suffix_ac, force_retain = select_daughter_suffix(m_bare)
if not strip_len then
return nil, "cannot auto-derive an unmarried surname from \"" .. m_bare .. "\"; please enter the full word manually"
end
if force_retain then
return attach_surname_suffix(m_bare, m_ac, strip_len, suffix_bare, false)
end
return attach_surname_suffix(m_bare, m_ac, strip_len, suffix_ac, true)
end
-- n (gender-neutral surname): "+" only; -ė replaces the ending and the stem
-- keeps its accent.
local function resolve_n_core(core, m_bare, m_ac)
if core ~= "+" then return nil, nil end
local strip_len = surname_m_ending_len(m_bare)
if not strip_len then
return nil, "cannot auto-derive a gender-neutral surname from \"" .. m_bare .. "\"; please enter the full word manually"
end
return attach_surname_suffix(m_bare, m_ac, strip_len, "ė", false)
end
-- -ienė/-íenė begin with i, so a masculine in -ius loses the whole -ius
-- (Kliučius → Kliuč- + -ienė).
local function iene_strip_len(m_bare)
if mw.ustring.sub(m_bare, -3) == "ius" then
return 3
end
return surname_m_ending_len(m_bare)
end
-- f (married surname): "+" or one of ienė/íenė/uvienė/iuvienė. "+" takes
-- -ienė after an AP1 masculine (its accent kept) and -íenė after AP2-4;
-- without an AP it errors.
local function resolve_f_core(core, m_bare, m_ac, ap)
if core == "ienė" or core == "íenė" then
local strip_len = iene_strip_len(m_bare)
if not strip_len then
return nil, "cannot attach -ienė to \"" .. m_bare .. "\"; please enter the full word manually"
end
return attach_surname_suffix(m_bare, m_ac, strip_len, core, core == "íenė")
end
if core == "uvienė" or core == "iuvienė" then
if mw.ustring.sub(m_bare, -2) ~= "us" then
return nil, "-uvienė/-iuvienė only applies to masculine surnames ending in -us/-ius, not \"" .. m_bare .. "\""
end
return attach_surname_suffix(m_bare, m_ac, 2, "uvienė", false)
end
if core == "+" then
if not ap or ap == 0 then
return nil, "cannot auto-derive a married surname from \"" .. m_bare ..
"\" without an accent paradigm; add it to the entry's own inflection pattern (e.g. \",1\"), " ..
"or use an explicit |f=ienė or |f=íenė instead of \"+\""
end
local strip_len = iene_strip_len(m_bare)
if not strip_len then
return nil, "cannot auto-derive a married surname from \"" .. m_bare .. "\"; please enter the full word manually"
end
if ap == 1 then
return attach_surname_suffix(m_bare, m_ac, strip_len, "ienė", false)
end
return attach_surname_suffix(m_bare, m_ac, strip_len, "íenė", true)
end
return nil, nil
end
-- Expand "+"/keywords in a surname-derivation list param (f/nee/n), keeping
-- the text as typed where `resolve` returns nil, nil.
local function process_surname_list(args, param_name, resolve)
local list = args[param_name]
if not (list and #list > 0) then return end
for i, raw in ipairs(list) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
local word, err = resolve(core)
if err then error("lt-headword: " .. err) end
pieces[j] = (word or core) .. modifier
end
list[i] = table.concat(pieces, ",")
end
end
-- Expand |f=/|nee=/|n= on a surname entry (is_proper) using the masculine
-- entry's own lemma + accent paradigm as the base to derive from.
local function handle_surname_derivation(args, data, masculine_lemma, ap)
if not masculine_lemma then return end
if not ((args.f and #args.f > 0) or (args.nee and #args.nee > 0) or (args.n and #args.n > 0)) then
return
end
local m_bare, m_ac = m_common.process_input(masculine_lemma)
process_surname_list(args, "nee", function(core) return resolve_nee_core(core, m_bare, m_ac) end)
process_surname_list(args, "n", function(core) return resolve_n_core(core, m_bare, m_ac) end)
process_surname_list(args, "f", function(core) return resolve_f_core(core, m_bare, m_ac, ap) end)
end
-- Table footnotes come in bracketed form ("[irregular]"); the headword line
-- takes them as qualifier text plus [ref:...] references. Callers put the
-- qualifiers in the left slot, `q`.
local function footnotes_to_quals_refs(footnotes)
if not footnotes then
return nil, nil
end
local iut = require("Module:inflection utilities")
return iut.convert_footnotes_to_qualifiers_and_references(footnotes)
end
-- Build the AP badge label list for the `l` field of a gender spec.
-- "AP1".."AP4" are defined in [[Module:labels/data/lang/lt]] and render as
-- links to [[Appendix:Lithuanian accentuation]]. `ap_str` may hold several
-- paradigm numbers (alternant merges produce e.g. "3 // 4" → AP3, AP4).
local function ap_badge_labels(ap_str)
if not ap_str then
return nil
end
local ap_labels = {}
for ap in ap_str:gmatch("%d+") do
table.insert(ap_labels, "AP" .. ap)
end
return ap_labels[1] and ap_labels or nil
end
-- Insert a list of form objects as one inflection line: each form becomes its
-- own part so a per-form footnote carries through as a qualifier on just that
-- form (format_inflection_parts joins parts with " or " automatically).
local function insert_form_parts(data, form_list, label)
if not form_list then return end
local parts = {}
for _, form_obj in ipairs(form_list) do
local q, refs = footnotes_to_quals_refs(form_obj.footnotes)
table.insert(parts, {term = form_obj.form, q = q, refs = refs})
end
if #parts > 0 then
parts.label = label
table.insert(data.inflections, parts)
end
end
-- The noun headword line, for nouns, proper nouns and the numerals that
-- decline as nouns (šim̃tas): run an lt-ndecl pattern through Module:lt-noun
-- and fill the heads, the AP-badged genders, the indeclinable label and the
-- genitive line. Returns the pattern results (for surnames and demonyms).
local function noun_headword_core(data, pattern_str)
local m_lt_noun = require("Module:lt-noun")
local results = m_lt_noun.get_headword_data(pattern_str)
-- Track if any result is indeclinable or plural-only
local all_indeclinable = true
local any_plural_only = false
-- Process each pattern result
for _, result in ipairs(results) do
-- The lemma is the head; a lemma footnote, having no table cell,
-- becomes a qualifier on it. A plurale tantum is entered by its
-- theoretical singular (dùris,2,ies.pl); its head is the nominative
-- plural.
local lemma_q, lemma_refs = footnotes_to_quals_refs(result.lemma_footnotes)
local nom_p = result.number_restr == "pl" and result.forms.nom_p
if nom_p and nom_p[1] then
for _, form_obj in ipairs(nom_p) do
table.insert(data.heads, {term = form_obj.form, q = lemma_q, refs = lemma_refs})
end
else
table.insert(data.heads, {term = result.lemma, q = lemma_q, refs = lemma_refs})
end
-- AP badge as a left label on the gender. Indeclinable nouns get no
-- badge; ap_display covers alternant merges with differing APs.
local ap_labels
if not result.indeclinable then
ap_labels = ap_badge_labels(result.ap_display
or result.ap > 0 and tostring(result.ap) or nil)
end
-- A gender footnote becomes a left qualifier on the gender.
local gender_q, gender_refs = footnotes_to_quals_refs(result.gender_footnotes)
table.insert(data.genders, {
spec = result.gender,
l = ap_labels,
q = gender_q,
refs = gender_refs,
})
-- Track indeclinable and plural-only status
if not result.indeclinable then
all_indeclinable = false
end
if result.number_restr == "pl" then
any_plural_only = true
end
end
-- Add indeclinable label if all patterns are indeclinable
if all_indeclinable then
table.insert(data.inflections, {label = glossary_link("indeclinable")})
end
-- Collect genitive forms (singular or plural depending on number restriction)
if not all_indeclinable then
local gen_slot = any_plural_only and "gen_p" or "gen_s"
local gen_label = any_plural_only and "genitive plural" or "genitive singular"
-- Each genitive is a part of its own, so that its footnote (e.g. from
-- a ".gen:" override) becomes a qualifier on that form only.
local gen_parts = {}
local seen_gen = {}
for _, result in ipairs(results) do
if result.forms[gen_slot] then
for _, form_obj in ipairs(result.forms[gen_slot]) do
if not seen_gen[form_obj.form] then
seen_gen[form_obj.form] = true
local gen_q, gen_refs = footnotes_to_quals_refs(form_obj.footnotes)
table.insert(gen_parts, {term = form_obj.form, q = gen_q, refs = gen_refs})
end
end
end
end
if #gen_parts > 0 then
gen_parts.label = gen_label
table.insert(data.inflections, gen_parts)
end
end
return results
end
-- Common function for nouns and proper nouns
local function handle_nouns(args, data, is_proper, pagename)
-- If no inflection spec given, scrape it from {{lt-ndecl}} on the same page.
local pattern_str = args[1]
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename, "lt-ndecl", args.id)
if err then error("lt-noun: " .. err) end
pattern_str = infl
end
local results = noun_headword_core(data, pattern_str)
-- Declension and accentuation categories come from Module:lt-noun and are
-- added only here ({{lt-ndecl}} adds none), so that indeclinables and
-- proper nouns get them too. Module:headword adds the gender categories.
if results.categories then
for _, cat in ipairs(results.categories) do
table.insert(data.categories, cat)
end
end
if is_proper then
-- Expand |dem= ("+" or a suffix keyword) and fill fdem/adj from it,
-- unless |fdem=/|adj= are given.
handle_toponym_derivation(args, data, results[1] and results[1].lemma)
-- m/f mean "male surname"/"married surname" here, derived from the
-- entry's own lemma+ap; nee/n are surname-only params (see above).
handle_surname_derivation(args, data, results[1] and results[1].lemma, results[1] and results[1].ap)
handle_deriv(args, data, "m", "male surname")
handle_deriv(args, data, "f", "married surname")
handle_deriv(args, data, "nee", "maiden surname")
handle_deriv(args, data, "n", "gender-neutral surname")
else
handle_deriv(args, data, "m", "male equivalent")
handle_deriv(args, data, "f", "female equivalent", "f")
end
-- Handle derivation parameters
handle_deriv(args, data, "adj", "relational adjective")
handle_deriv(args, data, "dim", "<<diminutive>>", "diminutive")
handle_deriv(args, data, "aug", "<<augmentative>>", "augmentative")
handle_deriv(args, data, "pej", "<<pejorative>>", "pejorative")
handle_deriv(args, data, "dem", "<<demonym>>")
handle_deriv(args, data, "fdem", "female <<demonym>>")
end
pos_functions["nouns"] = function(args, data, pagename)
handle_nouns(args, data, false, pagename)
end
pos_functions["proper nouns"] = function(args, data, pagename)
handle_nouns(args, data, true, pagename)
end
-- Function for adjectives
pos_functions["adjectives"] = function(args, data, pagename)
local m_lt_adj = require("Module:lt-adjective")
-- If no inflection spec given, scrape it from {{lt-adecl}} on the same page.
local pattern_str = args[1]
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename, "lt-adecl", args.id)
if err then error("lt-adj: " .. err) end
pattern_str = infl
end
local result = m_lt_adj.get_headword_data(pattern_str)
-- Lemma footnote → qualifier on the head; AP footnote → qualifier on the
-- gender and AP badge (neither has a table cell).
local lemma_q, lemma_refs = footnotes_to_quals_refs(result.lemma_footnotes)
table.insert(data.heads, {term = result.lemma, q = lemma_q, refs = lemma_refs})
local gender_q, gender_refs = footnotes_to_quals_refs(result.gender_footnotes)
table.insert(data.genders, {
spec = "m",
l = ap_badge_labels(tostring(result.ap)),
q = gender_q,
refs = gender_refs,
})
-- gen_m_sg / fem_nom_sg are form-object lists; each form becomes its own
-- inflection part so a per-form footnote (e.g. a whole-declension .[note])
-- carries through as a qualifier on just that form.
insert_form_parts(data, result.gen_m_sg, "genitive masculine singular")
insert_form_parts(data, result.fem_nom_sg, "feminine")
-- Degree categories, from the same shape rules (and .comp/.nocomp tags)
-- that decide whether {{lt-adecl}} shows the compared forms.
table.insert(data.categories, "Lithuanian " .. (result.suppress_comp and "uncomparable" or "comparable") .. " adjectives")
-- |adv=+ derives the -(i)ai adverb from the adjective's own paradigm
-- (Module:lt-adverb; the accent follows the dative plural, or the
-- accusative singular for disyllabic -us adjectives). The lexical
-- exceptions (greĩtai, the taste adverbs, vėlaĩ) are typed in full.
if args.adv and #args.adv > 0 then
for i, raw in ipairs(args.adv) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
if core == "+" then
local m_lt_adv = require("Module:lt-adverb")
local dat_pl = result.dat_m_pl and result.dat_m_pl[1] and result.dat_m_pl[1].form
local acc_sg = result.acc_m_sg and result.acc_m_sg[1] and result.acc_m_sg[1].form
local adv, err = m_lt_adv.derive_from_adjective(result.lemma, dat_pl, acc_sg)
if not adv then error("lt-adj: " .. err) end
pieces[j] = adv .. modifier
end
end
args.adv[i] = table.concat(pieces, ",")
end
end
handle_deriv(args, data, "adv", "adverb")
handle_deriv(args, data, "dim", "<<diminutive>>", "diminutive")
handle_deriv(args, data, "aug", "<<augmentative>>", "augmentative")
handle_deriv(args, data, "pej", "<<pejorative>>", "pejorative")
end
-- Numerals ({{lt-num}}). Without parameter 1 the page name is looked up in
-- Module:lt-numeral, as {{lt-numdecl}} does. The numerals that decline as
-- nouns (šim̃tas, tū́kstantis, milijõnas, dvẽjetas, the -dalis fractions) take
-- the noun path: a page Module:lt-numeral does not know falls back to it,
-- |1=noun forces it (the cardinal section of šimtas, whose lookup finds the
-- ordinal), and any other |1= is an lt-ndecl pattern. |id= picks among
-- several {{lt-ndecl}} on the page.
pos_functions["numerals"] = function(args, data, pagename)
local m_lt_num = require("Module:lt-numeral")
local hd
if not args[1] then
hd = m_lt_num.get_headword_data(pagename)
end
if not hd then
local pattern_str = args[1]
if not pattern_str or pattern_str == "noun" then
local infl, err = m_common.find_lt_inflection(pagename, "lt-ndecl", args.id)
if err then error("lt-num: " .. err) end
pattern_str = infl
end
noun_headword_core(data, pattern_str)
return
end
table.insert(data.heads, {term = hd.head})
-- AP badge as a left label on the gender, as in the noun/adjective
-- branches. The pus- fractions carry no gender spec; they get the
-- indeclinable label instead.
if hd.gender then
table.insert(data.genders, {
spec = hd.gender,
l = hd.ap and ap_badge_labels(tostring(hd.ap)) or nil,
})
end
if hd.indeclinable then
table.insert(data.inflections, {label = glossary_link("indeclinable")})
end
-- Inflection line (canonical pages only; alias pages show just the head —
-- get_headword_data returns no form slots for them).
insert_form_parts(data, hd.fem, "feminine")
insert_form_parts(data, hd.neut, "neuter")
insert_form_parts(data, hd.gen, "genitive")
insert_form_parts(data, hd.pl, "with plural-only nouns")
end
-- Pronouns ({{lt-pronoun}}) and determiners: the head and its forms come from
-- Module:lt-pronoun by the page name, as in {{lt-prondecl}}. An indeclinable
-- pronoun, or one without a table there, takes its accented head in |1=.
local function handle_pronouns(args, data, pagename)
local hd = require("Module:lt-pronoun").get_headword_data(pagename)
if not hd or hd.indeclinable then
if not hd and not args[1] then
error("lt-pronoun: no declension of '" .. pagename .. "' is known; "
.. "write the head with its accent mark in 1=")
end
table.insert(data.heads, {term = args[1] or pagename})
if hd then
table.insert(data.inflections, {label = glossary_link("indeclinable")})
end
return
end
if args[1] then
error("lt-pronoun: 1= is only for a pronoun without a declension table; "
.. "the forms of '" .. pagename .. "' come from its table")
end
for _, head in ipairs(hd.heads) do
table.insert(data.heads, {term = head})
end
if hd.gender then
table.insert(data.genders, {spec = hd.gender})
end
insert_form_parts(data, hd.fem, "feminine")
insert_form_parts(data, hd.neut, "neuter")
insert_form_parts(data, hd.gen, "genitive")
end
pos_functions["pronouns"] = function(args, data, pagename)
handle_pronouns(args, data, pagename)
end
pos_functions["determiners"] = function(args, data, pagename)
handle_pronouns(args, data, pagename)
end
-- Participles ({{lt-part}}): the pattern of {{lt-pdecl}}, read from the page
-- unless given in |1=. A passive participle carries its accentuation
-- paradigm as a badge on the gender; one that exists only in the neuter
-- (an unprefixed reflexive passive, .intr) has the neuter as its head. A
-- half-participle (-damas, -damasis) is given in |1= and has no table.
pos_functions["participles"] = function(args, data, pagename)
local pattern_str = args[1]
-- A half-participle (-damas) has no table: its pattern is given in |1=, and
-- the line shows its four forms.
local plain = pattern_str and mw.ustring.lower(m_common.stripDiacritics(pattern_str))
if plain and (plain:find("damas[%.%[]") or plain:find("damasis[%.%[]")) then
error("lt-part: \"" .. pattern_str .. "\": a half-participle takes no tags or footnotes")
end
if plain and (plain:find("damas$") or plain:find("damasis$")) then
local hp = require("Module:lt-participle").half_participle(pattern_str)
for _, head in ipairs(hp.heads) do
table.insert(data.heads, {term = head})
end
table.insert(data.genders, {spec = "m"})
local function forms(list, label)
local parts = {label = label}
for _, f in ipairs(list) do
table.insert(parts, {term = f})
end
table.insert(data.inflections, parts)
end
forms(hp.fem_s, "feminine singular")
forms(hp.masc_p, "masculine plural")
forms(hp.fem_p, "feminine plural")
table.insert(data.categories, "Lithuanian pusdalyvis participles")
return
end
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename, "lt-pdecl", args.id)
if err then error("lt-part: " .. err) end
pattern_str = infl
end
local hd = require("Module:lt-participle").get_headword_data(pattern_str)
for _, head in ipairs(hd.heads) do
table.insert(data.heads, {term = head})
end
table.insert(data.genders, {
spec = hd.neuter_only and "n" or "m",
l = hd.ap and ap_badge_labels(tostring(hd.ap)) or nil,
})
insert_form_parts(data, hd.gen, "genitive masculine singular")
insert_form_parts(data, hd.fem, "feminine")
end
-- =============================================================================
-- Adverbs ({{lt-adv}})
-- =============================================================================
--
-- Adverbs have no inflection table, so parameter 1 is the accented positive
-- with Module:lt-adverb's degree tags (see that module's header); nothing is
-- scraped. The module hands back spec lists whose forms may carry bracketed
-- footnotes and raw inline modifiers (<q:…> <qq:…> <l:…> <ll:…> <ref:…>);
-- both are turned into headword parts here.
-- Turn one form spec into a Module:headword part: the inline modifiers are
-- parsed by Module:headword utilities, a bracketed footnote becomes a left
-- qualifier (or a reference), as in the other branches.
local function spec_to_part(spec, paramname, is_head)
local part
if spec.mods then
part = m_headword_utilities.parse_term_with_modifiers {
val = spec.form .. spec.mods,
paramname = paramname,
is_head = is_head,
}
else
part = {term = spec.form}
end
local q, refs = footnotes_to_quals_refs(spec.footnotes)
if q then
part.q = part.q and m_headword_utilities.combine_qualifiers_or_labels(part.q, q) or q
end
if refs then
part.refs = part.refs or {}
for _, ref in ipairs(refs) do
table.insert(part.refs, ref)
end
end
return part
end
local function insert_spec_parts(data, specs, label, accel_form)
if not specs then return end
local parts = {label = label}
for _, spec in ipairs(specs) do
table.insert(parts, spec_to_part(spec, "1"))
end
if accel_form then
parts.accel = {form = accel_form}
end
table.insert(data.inflections, parts)
end
-- Keywords accepted in |adj= on adverb entries: "+" tries every adjective
-- the adverb can come from, an ending keyword narrows it to one.
local ADJ_KEYWORDS = {["+"] = true, ["as"] = true, ["us"] = true, ["ias"] = true, ["is"] = true}
-- Expand "+"/keyword items of |adj= into the adjective's accented lemma,
-- read from the {{lt-adecl}} pattern of the candidate page (the adverb's
-- accent does not show the adjective's paradigm). Errors when no candidate
-- page has a pattern; the full word can be typed instead.
local function expand_adj_keywords(args, positive)
if not (args.adj and #args.adj > 0) then return end
local m_lt_adv = require("Module:lt-adverb")
for i, raw in ipairs(args.adj) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
if ADJ_KEYWORDS[core] then
local candidates = m_lt_adv.derive_adjective(positive, core ~= "+" and core or nil)
local lemma
for _, candidate in ipairs(candidates) do
local infl = m_common.find_lt_inflection(candidate, "lt-adecl")
if infl then
lemma = require("Module:lt-adjective").get_headword_data(infl).lemma
break
end
end
if not lemma then
error("lt-adv: no adjective entry with {{lt-adecl}} found for |adj=" .. core ..
(candidates[1] and (" (tried: " .. table.concat(candidates, ", ") .. ")") or
" (the adverb \"" .. positive .. "\" is not an -(i)ai form)") ..
"; please give the adjective in full")
end
pieces[j] = lemma .. modifier
end
end
args.adj[i] = table.concat(pieces, ",")
end
end
pos_functions["adverbs"] = function(args, data, pagename)
local m_lt_adv = require("Module:lt-adverb")
local pattern_str = args[1]
if not pattern_str then
error("lt-adv: the accented adverb is required in parameter 1 (adverbs have no inflection table to read it from)")
end
local hd = m_lt_adv.get_headword_data(pattern_str)
for _, spec in ipairs(hd.head) do
table.insert(data.heads, spec_to_part(spec, "1", true))
end
if hd.comparable then
insert_spec_parts(data, hd.comp, "comparative", "comparative")
insert_spec_parts(data, hd.sup, "superlative", "superlative")
insert_spec_parts(data, hd.dim, "diminutive comparative")
else
table.insert(data.inflections, {label = glossary_link("uncomparable", "not comparable")})
end
for _, cat in ipairs(hd.categories) do
table.insert(data.categories, cat)
end
expand_adj_keywords(args, hd.positive)
handle_deriv(args, data, "adj", "adjective")
handle_deriv(args, data, "dim", "<<diminutive>>", "diminutive")
end
-- Function for verbs
pos_functions["verbs"] = function(args, data, pagename)
local m_lt_verb = require("Module:lt-verb")
-- If no inflection spec given, scrape it from {{lt-conj}} on the same
-- page ({{lt-conj+}} redirects to it; a call of the legacy table is
-- skipped).
local pattern_str = args[1]
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename,
{"lt-conj", "lt-conj+"}, args.id,
function(targs) return not m_common.is_legacy_conj(targs) end)
if err then error("lt-verb: " .. err) end
pattern_str = infl
end
local result = m_lt_verb.get_headword_data(pattern_str)
-- An infinitive (lemma) footnote has no table cell: it becomes a
-- qualifier on the head.
local lemma_q, lemma_refs = footnotes_to_quals_refs(result.lemma_footnotes)
table.insert(data.heads, {term = result.lemma, q = lemma_q, refs = lemma_refs})
-- pres_3/past_3 are form-object lists; each form is a part of its own, so
-- that its footnote lands on that form only.
local function insert_forms(slot_forms, label)
if not slot_forms or #slot_forms == 0 then
return
end
local parts = {label = label}
for _, form_obj in ipairs(slot_forms) do
local q, refs = footnotes_to_quals_refs(form_obj.footnotes)
table.insert(parts, {term = form_obj.form, q = q, refs = refs})
end
table.insert(data.inflections, parts)
end
insert_forms(result.pres_3, "third-person present tense")
insert_forms(result.past_3, "third-person past tense")
if result.reflexive then
table.insert(data.categories, "Lithuanian reflexive verbs")
end
end
-- =============================================================================
-- Non-lemma forms ({{lt-head}})
-- =============================================================================
--
-- {{lt-head|noun form|LEMMA}} computes its definition lines from the lemma's
-- own table: the Lithuanian section of the lemma's page is searched for the
-- table templates of the part of speech, and every cell whose form, without
-- accent marks, is the page name gives a tag set. The readings are grouped by
-- their accented form, which is the head (|head= keeps one of them), and
-- within a head by their labels: the cell footnotes that are usage labels
-- (FORM_LABELS), and "AP n" where a noun pattern with several paradigms gives
-- the form in some of them only. A reading identical to the lemma itself is
-- left out.
-- Cell footnotes that become labels of a definition line; any other footnote
-- stays in the table. "colloquial short form" becomes the label colloquial;
-- the family plural of a surname keeps its note, which tells it from the
-- ordinary plural.
local FORM_LABELS = {
["referring to a married couple or a family"] = "referring to a married couple or a family",
["archaic"] = "archaic", ["colloquial"] = "colloquial", ["colloquial short form"] = "colloquial",
["dated"] = "dated", ["dialectal"] = "dialectal", ["humorous"] = "humorous",
["literary"] = "literary", ["obsolete"] = "obsolete", ["pejorative"] = "pejorative",
["poetic"] = "poetic", ["proscribed"] = "proscribed", ["rare"] = "rare",
["regional"] = "regional", ["vulgar"] = "vulgar",
}
local NOUN_SLOT_ORDER = {}
for i, case in ipairs({"nom", "gen", "dat", "acc", "ins", "loc", "voc", "ill", "all", "ade"}) do
NOUN_SLOT_ORDER[case .. "_s"] = i
NOUN_SLOT_ORDER[case .. "_p"] = 20 + i
end
-- The cells of one {{lt-ndecl}} pattern in table order, as the other table
-- modules give them through their form_cells: {lemma =, gender =, cells =
-- {{tags =, forms =}, …}}. The tags are the slot split at "_" (nom|s …).
local function noun_cells(pattern)
local results = require("Module:lt-noun").get_headword_data(pattern)
local cells = {}
for _, result in ipairs(results) do
for slot, list in pairs(result.forms) do
table.insert(cells, {tags = mw.text.split(slot, "_"), forms = list,
order = NOUN_SLOT_ORDER[slot] or 99, seq = #cells + 1})
end
end
table.sort(cells, function(a, b)
if a.order ~= b.order then
return a.order < b.order
end
return a.seq < b.seq
end)
local first = results[1]
return {lemma = first and first.lemma, gender = first and first.gender, cells = cells}
end
local function module_cells(module)
return function(pattern)
return require(module).form_cells(pattern)
end
end
-- The table templates read on the lemma's page: their names, the function
-- giving the cells of one call, the input it takes (parameter 1 unless
-- `input` says otherwise), calls to skip ("legacy" for a call of the earlier
-- template of that name, "other" for a call with nothing to read), and
-- whether a colon list of paradigms is split (nouns).
local NOUN_TABLE = {names = {"lt-ndecl"}, cells = noun_cells, ap_passes = true}
local TABLES = {
adjective = {names = {"lt-adecl"}, cells = module_cells("Module:lt-adjective")},
participle = {names = {"lt-pdecl"}, cells = module_cells("Module:lt-participle")},
verb = {names = {"lt-conj", "lt-conj+"}, cells = module_cells("Module:lt-verb"),
-- A call of the legacy table (Template:lt-conj/old) has no cells to read.
skip = function(targs) return m_common.is_legacy_conj(targs) and "legacy" end},
-- A half-participle has no table: its forms come from the headword line.
half_participle = {names = {"lt-part"}, label = "{{lt-part}} line of a half-participle",
cells = function(pattern) return require("Module:lt-participle").half_participle_cells(pattern) end,
skip = function(targs)
local first = targs[1] and plain(targs[1]):gsub("%-", "")
if targs.m or (first and mw.ustring.find(first, "dam$")) then
return "legacy"
elseif not first or not (mw.ustring.find(first, "damas$") or mw.ustring.find(first, "damasis$")) then
return "other"
end
end},
-- {{lt-numdecl}} takes no pattern: it looks the numeral up by page name.
numeral = {names = {"lt-numdecl"}, cells = module_cells("Module:lt-numeral"),
input = function(targs, term) return targs.pagename or term end},
}
-- The parts of speech {{lt-head}} takes: the category, the singular for
-- Module:accel, the tables read, and whether the line shows the lemma's
-- gender (nouns).
local FORM_POS = {
["noun form"] = {pos = "noun forms", singular = "noun", tables = {NOUN_TABLE}, gender = true},
["proper noun form"] = {pos = "proper noun forms", singular = "proper noun", tables = {NOUN_TABLE},
gender = true},
["adjective form"] = {pos = "adjective forms", singular = "adjective", tables = {TABLES.adjective}},
["participle form"] = {pos = "participle forms", singular = "participle",
tables = {TABLES.participle, TABLES.half_participle}},
["verb form"] = {pos = "verb forms", singular = "verb", tables = {TABLES.verb}},
-- The numerals that decline as nouns have a {{lt-ndecl}} table.
["numeral form"] = {pos = "numeral forms", singular = "numeral", tables = {TABLES.numeral, NOUN_TABLE}},
}
local FORM_POS_LIST = "noun form, proper noun form, adjective form, participle form, verb form and numeral form"
-- The section of `text` under the level-two heading `name`, or nil.
local function language_section(text, name)
local lines, inside = {}, false
for line in mw.text.gsplit(text, "\n", true) do
if mw.ustring.find(line, "^==[^=].*[^=]==%s*$") then
inside = mw.ustring.match(line, "^==%s*(.-)%s*==%s*$") == name
elseif inside then
table.insert(lines, line)
end
end
return lines[1] and table.concat(lines, "\n") or nil
end
local function display_form(form)
return m_common.makeDisplayText(mw.ustring.toNFD(form), lang)
end
-- Readings of `pagename` (of every form when it is nil) in one table
-- pattern: {form =, plain =, tags =, labels =, order =}, and the table's lemma
-- data. A noun pattern with a colon list of paradigms ("lemma,1:3…") is
-- declined once per paradigm, so that a reading given by some of them only
-- carries their labels.
local function table_readings(tbl, pattern, pagename)
local lemma_part, aps, rest
if tbl.ap_passes then
lemma_part, aps, rest = mw.ustring.match(pattern, "^([^,%(<]+),([1-4]:[1-4:]*)(.*)$")
end
local passes = {}
if aps then
for ap in aps:gmatch("[1-4]") do
table.insert(passes, {ap = ap, pattern = lemma_part .. "," .. ap .. rest})
end
else
passes[1] = {pattern = pattern}
end
local readings, by_key, info = {}, {}, nil
for _, pass in ipairs(passes) do
local data = tbl.cells(pass.pattern)
if not data then
error("lt-head: {{" .. tbl.names[1] .. "}} gives no table for '" .. tostring(pass.pattern) .. "'")
end
if not info then
info = data
-- The readings of the lemma: every form of the first cell that holds
-- the lemma (both readings of "((Ùrbanas<n,1>,Urbãnas<n,2>))", of
-- "Ùrbanas:Urbãnas,1"), or the variants of a lemma that is no cell
-- (an infinitive, "X / Y").
local first = display_form(mw.text.split(data.lemma or "", "%s*/%s*")[1])
info.lemma_forms = {}
for _, cell in ipairs(data.cells) do
local here = false
for _, fobj in ipairs(cell.forms) do
if display_form(fobj.form) == first then
here = true
end
end
if here then
for _, fobj in ipairs(cell.forms) do
info.lemma_forms[display_form(fobj.form)] = true
end
break
end
end
for _, v in ipairs(mw.text.split(data.lemma or "", "%s*/%s*")) do
if v ~= "" then
info.lemma_forms[display_form(v)] = true
end
end
end
for order, cell in ipairs(data.cells) do
for _, fobj in ipairs(cell.forms) do
local plain = m_common.stripDiacritics(fobj.form)
if not pagename or plain == pagename then
local labels = {}
for _, note in ipairs(fobj.footnotes or {}) do
local label = FORM_LABELS[mw.ustring.lower((note:gsub("^%[(.*)%]$", "%1")))]
if label then
table.insert(labels, label)
end
end
local form = display_form(fobj.form)
local tags = table.concat(cell.tags, "|")
local key = form .. "\0" .. tags .. "\0" .. table.concat(labels, "|")
local r = by_key[key]
if not r then
r = {form = form, plain = plain, tags = cell.tags, labels = labels, aps = {},
order = order, seq = #readings + 1}
by_key[key] = r
table.insert(readings, r)
end
if pass.ap then
r.aps[pass.ap] = true
end
end
end
end
end
if aps then
for _, r in ipairs(readings) do
local mine = {}
for _, pass in ipairs(passes) do
if r.aps[pass.ap] then
table.insert(mine, "AP" .. pass.ap)
end
end
if #mine < #passes then
for i = #mine, 1, -1 do
table.insert(r.labels, 1, mine[i])
end
end
end
end
return readings, info
end
-- The lemma as the definition lines show it: a table with several infinitives
-- ("X / Y") shows the one spelled like the lemma's page.
local function lemma_display(lemma, term)
if not lemma then
return nil
end
local variants = mw.text.split(lemma, "%s*/%s*")
for _, v in ipairs(variants) do
if m_common.stripDiacritics(v) == term then
return display_form(v)
end
end
return display_form(variants[1])
end
-- The readings {{lt-head}} works from, for every form of one table call:
-- {lemma =, gender =, readings = {{form =, plain =, tags =, labels =,
-- is_lemma =}, …}} in table order. `pos` is a value of parameter 1 of
-- {{lt-head}}, `name` the table template and `input` its parameter 1 (for
-- {{lt-numdecl}} the numeral's page name).
function export.form_readings(pos, name, input)
local spec = FORM_POS[pos] or error("lt-head: unknown part of speech '" .. tostring(pos) .. "'")
local tbl
for _, t in ipairs(spec.tables) do
for _, n in ipairs(t.names) do
if n == name then
tbl = t
end
end
end
if not tbl then
error("lt-head: " .. pos .. " does not read {{" .. tostring(name) .. "}}")
end
local readings, info = table_readings(tbl, input, nil)
table.sort(readings, function(a, b)
if a.order ~= b.order then
return a.order < b.order
end
return a.seq < b.seq
end)
local lemma_form = info and info.lemma and display_form(mw.text.split(info.lemma, "%s*/%s*")[1])
local lemma_forms = info and info.lemma_forms or {}
local out = {}
for _, r in ipairs(readings) do
table.insert(out, {form = r.form, plain = r.plain, tags = r.tags, labels = r.labels,
is_lemma = lemma_forms[r.form] or nil})
end
return {lemma = lemma_form, gender = spec.gender and info and info.gender or nil, readings = out}
end
function export.show_form(frame)
local args = m_para.process(frame:getParent().args, {
[1] = {required = true},
[2] = {required = true},
["head"] = {},
["t"] = {},
["pagename"] = {},
})
-- On the template's own page there is no lemma to read: render a bare line.
if not args[1] and mw.title.getCurrentTitle().nsText == "Template" then
return full_headword {
lang = lang, pos_category = "noun forms", categories = {}, genders = {}, inflections = {},
heads = {{term = args.pagename or mw.loadData("Module:headword/data").pagename}},
pagename = args.pagename, no_redundant_head_cat = true,
}
end
local spec = FORM_POS[args[1]]
if not spec then
error("lt-head: '" .. tostring(args[1]) .. "' is not supported; the template takes "
.. FORM_POS_LIST .. ", whose definitions come from the table on the lemma's page")
end
local table_by_name, table_list = {}, {}
for _, tbl in ipairs(spec.tables) do
table.insert(table_list, tbl.label or ("{{" .. tbl.names[1] .. "}} table"))
for _, name in ipairs(tbl.names) do
table_by_name[name] = tbl
end
end
local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
-- head= names the accented forms to show; one written with links
-- ("[[mẽtraščių|Mẽtraščių]] [[knỹgos]]") is shown as written.
local wanted_heads
if args.head then
wanted_heads = {}
for _, h in ipairs(mw.text.split(args.head, "%s*,%s*")) do
local linked = h:find("[[", 1, true) and h
wanted_heads[display_form(m_common.canonicalize_input(linked and m_links.remove_links(h) or h))] =
linked or true
end
end
local data = {
lang = lang, pos_category = spec.pos, categories = {}, heads = {}, genders = {},
inflections = {}, pagename = pagename, no_redundant_head_cat = true,
}
local lines, seen_head, gender_done = {}, {}, false
for _, lemma_spec in ipairs(mw.text.split(args[2], "%s*,%s*")) do
local term, id = mw.ustring.match(lemma_spec, "^(.-)<id:([^>]*)>$")
term = term or lemma_spec
local title = mw.title.new(term)
local content = title and title:getContent()
local section = content and language_section(content, "Lithuanian")
if not section then
error("lt-head: no Lithuanian section on [[" .. term .. "]]")
end
local readings, info, found_table, legacy_table = {}, nil, false, false
for template in require("Module:template parser").find_templates(section) do
local tbl = table_by_name[template:get_name()]
if tbl then
local targs = template:get_arguments()
local skip = tbl.skip and tbl.skip(targs)
if skip == "legacy" then
legacy_table = tbl
elseif not skip and (not id or targs.id == id) then
found_table = true
local input = tbl.input and tbl.input(targs, term) or targs[1]
local rs, inf = table_readings(tbl, input, pagename)
info = info or inf
for _, r in ipairs(rs) do
table.insert(readings, r)
end
end
end
end
if not found_table then
error("lt-head: no " .. table.concat(table_list, " or ") .. (id and (" with id=" .. id) or "")
.. " on [[" .. term .. "]]" .. (legacy_table and (" (the {{" .. legacy_table.names[1]
.. "}} call there is written for the earlier template of that name, which has no forms to read)") or ""))
end
local lemma_form = info and lemma_display(info.lemma, term)
local lemma_forms = info and info.lemma_forms or {}
if spec.gender and info and not gender_done then
gender_done = true
table.insert(data.genders, {spec = info.gender})
end
-- Heads in table order; within each head, groups of tag sets by labels,
-- the unlabelled group first.
table.sort(readings, function(a, b)
if a.order ~= b.order then
return a.order < b.order
end
return a.seq < b.seq
end)
local heads, by_head = {}, {}
for _, r in ipairs(readings) do
if not lemma_forms[r.form] and (not wanted_heads or wanted_heads[r.form]) then
if not by_head[r.form] then
by_head[r.form] = {groups = {}, order = {}}
table.insert(heads, r.form)
end
local h = by_head[r.form]
local key = table.concat(r.labels, "|")
if not h.groups[key] then
h.groups[key] = {labels = r.labels, tag_sets = {}, seen = {}}
table.insert(h.order, r.labels[1] and #h.order + 1 or 1, key)
end
local tags = table.concat(r.tags, "|")
if not h.groups[key].seen[tags] then
h.groups[key].seen[tags] = true
table.insert(h.groups[key].tag_sets, {tags = r.tags})
end
end
end
for _, head in ipairs(heads) do
if not seen_head[head] then
seen_head[head] = true
local linked = wanted_heads and wanted_heads[head]
table.insert(data.heads, {term = type(linked) == "string" and linked or head})
end
for _, key in ipairs(by_head[head].order) do
local group = by_head[head].groups[key]
local line = require("Module:form of").tagged_inflections {
lang = lang,
tag_sets = require("Module:accel").combine_tag_sets_into_multipart(group.tag_sets, lang, spec.singular),
lemmas = {{lang = lang, term = term, alt = lemma_form, gloss = args.t}},
lemma_face = "term",
}
if group.labels[1] then
line = require("Module:labels").show_labels {labels = group.labels, lang = lang} .. " " .. line
end
table.insert(lines, line)
end
end
end
if not lines[1] then
local named = {}
for _, lemma_spec in ipairs(mw.text.split(args[2], "%s*,%s*")) do
local term, id = mw.ustring.match(lemma_spec, "^(.-)<id:([^>]*)>$")
table.insert(named, "[[" .. (term or lemma_spec) .. "]]" .. (id and (" (table id=" .. id .. ")") or ""))
end
error("lt-head: '" .. pagename .. "' is not a form of " .. table.concat(named, " or ")
.. (args.head and (" with the accent " .. args.head) or ""))
end
return full_headword(data) .. "\n\n# " .. table.concat(lines, "\n# ")
end
return export
4llc3ijx9g7m4c4ldcsvepbhmtql1bo
2576488
2576487
2026-11-09T09:50:47Z
Hiyuune
50834
2576488
Scribunto
text/plain
local export = {}
local pos_functions = {}
local m_table = require("Module:table")
local m_links = require("Module:links")
local m_para = require("Module:parameters")
local m_common = require("Module:lt-common")
local m_headword_utilities = require("Module:headword utilities")
local lang = require("Module:languages").getByCode("lt")
local function glossary_link(anchor, text)
text = text or anchor
return "[[Phụ lục:Từ điển thuật ngữ#" .. anchor .. "|" .. text .. "]]"
end
-- Tác giả: [[:en:User:TongcyDai]]
-- The heads are accented forms, which Module:headword shows unlinked; a head
-- of several words gets a link on each word, as Module:headword gives a head
-- taken from the page name. A head that already holds a link is left as it is.
local function full_headword(data)
local m_headword = require("Module:headword")
for _, head in ipairs(data.heads) do
if head.term and not head.term:find("[[", 1, true) and m_headword.head_is_multiword(head.term) then
head.term = m_headword.add_multiword_links(head.term)
end
end
return m_headword.full_headword(data)
end
-- Calls written for the legacy template of the same name (each template passes
-- legacy=<its name>). A call is legacy when it has a parameter that only the
-- legacy template takes, or a parameter 1 that cannot be a pattern of the new
-- one. A call without parameter 1 is new only on a page that has the table the
-- new template reads.
local function page_has(pattern)
return (mw.title.getCurrentTitle():getContent() or ""):find(pattern) ~= nil
end
local function plain(text)
return m_common.stripDiacritics(text)
end
local LEGACY = {
["lt-noun"] = {
keys = {2, 3, "head", "head2", "g2", "indecl"},
test = function(first)
if first then
return not first:find("[,<]")
end
return not page_has("{{%s*lt%-ndecl")
end,
},
["lt-adj"] = {
keys = {2, 3, "head"},
test = function(first)
if first then
return not first:find(",")
end
return not page_has("{{%s*lt%-adecl")
end,
},
["lt-verb"] = {
keys = {2, 3, "head"},
test = function(first)
if first then
return not mw.ustring.find(first, "^[^,]*,[^,]*,")
end
return not page_has("{{%s*lt%-conj%s*|[^|}]-,[^|}]-,")
and not page_has("{{%s*lt%-conj%+")
end,
},
["lt-adv"] = {
keys = {"head", "head2"},
test = function(first, pagename)
return not first or first == "-"
or plain(mw.ustring.match(first, "^[^.%[]*")) ~= pagename
end,
},
["lt-part"] = {
keys = {"m"},
test = function(first)
if first then
return mw.ustring.find(plain(first), "dam$") ~= nil
end
return not page_has("{{%s*lt%-pdecl")
end,
},
}
LEGACY["lt-proper noun"] = {
keys = {2, "head", "head2", "pl", "indecl", "fs", "hypocor"},
test = LEGACY["lt-noun"].test,
}
local function is_legacy_call(name, pargs)
local legacy = LEGACY[name]
-- The template's own page calls it without parameters.
if not legacy or pargs.pagename
or (next(pargs) == nil and mw.title.getCurrentTitle().nsText == "Bản_mẫu") then
return false
end
for _, key in ipairs(legacy.keys) do
if pargs[key] ~= nil then
return true
end
end
local first = pargs[1]
if first == "" then
first = nil
end
return legacy.test(first, mw.loadData("Module:headword/data").pagename)
end
-- Main entry point
function export.show(frame)
local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.")
if frame.args.legacy and is_legacy_call(frame.args.legacy, frame:getParent().args) then
return m_common.render_legacy(frame, frame.args.legacy)
end
local params = {
[1] = {}, -- inflection spec; nil triggers scraping from {{lt-ndecl}}/{{lt-adecl}}/{{lt-conj}}/{{lt-pdecl}}
-- (numerals: nil = spec-table lookup with scraping fallback; "noun" forces the lt-ndecl path;
-- pronouns: the accented head of a pronoun without a declension table)
["id"] = {}, -- disambiguates when multiple inflection templates exist on the page
["pagename"] = {}, -- for testing
}
-- Add derivation parameters for nouns.
if poscat == "Danh từ" or poscat == "Danh từ riêng" then
params["m"] = {list = true}
params["f"] = {list = true}
params["adj"] = {list = true}
params["dim"] = {list = true}
params["aug"] = {list = true}
params["pej"] = {list = true}
-- Proper nouns only. m/f keep their meaning above for common nouns
-- (male/female equivalent); under "proper nouns" they are reused for
-- surname derivation instead (see handle_nouns), nee/n add the other
-- surname forms, and dem/fdem the demonyms of a place name.
if poscat == "Danh từ riêng" then
params["nee"] = {list = true}
params["n"] = {list = true}
params["dem"] = {list = true}
params["fdem"] = {list = true}
end
-- Add derivation parameters for adjectives.
elseif poscat == "Tính từ" then
params["adv"] = {list = true}
params["dim"] = {list = true}
params["aug"] = {list = true}
params["pej"] = {list = true}
-- Add derivation parameters for adverbs.
elseif poscat == "Phó từ" then
params["adj"] = {list = true}
params["dim"] = {list = true}
end
-- Verbs take no derivation parameters.
local args = m_para.process(frame:getParent().args, params)
local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
local data = {
lang = lang,
pos_category = poscat,
categories = {},
heads = {},
genders = {},
inflections = {},
id = args.id,
no_redundant_head_cat = true,
-- Without it, Module:headword takes the title of the current page and
-- ignores |pagename=.
pagename = pagename,
}
-- On a template's own page (Template:lt-num, Template:lt-noun, …) there
-- is no entry to scrape or look up: render a bare headword line instead
-- of letting the pos handler error out.
if not args[1] and not args.pagename
and mw.title.getCurrentTitle().nsText == "Bản_mẫu" then
table.insert(data.heads, {term = pagename})
return full_headword(data)
end
if pos_functions[poscat] then
pos_functions[poscat](args, data, pagename)
end
return full_headword(data)
end
-- Insert a derivation parameter into data.inflections.
-- Supports comma-separated values within a single param (e.g. |dim=darbužis,darbelis)
-- and inline modifiers (e.g. |dim=darbužis<q:informal>).
local function handle_deriv(args, data, param_name, label, accel_form)
m_headword_utilities.parse_and_insert_inflection {
headdata = data,
forms = args[param_name],
paramname = param_name,
label = label,
splitchar = ",",
accel = accel_form and {form = accel_form} or nil,
}
end
-- =============================================================================
-- Toponym-derived demonym / adjective (dem, fdem, adj auto-generation)
-- =============================================================================
--
-- |dem=+ or a suffix keyword derives the demonym from the entry's lemma (the
-- toponym). fdem and adj are then derived from the resulting dem, whether
-- derived or typed.
-- The suffix of "+".
local DEM_DEFAULT_SUFFIX = "iẽtis"
-- Toponym endings replaced by the suffix, for "+" and the suffix keywords.
-- None is a suffix of another. -ija is handled before this list.
local TOPONYM_ENDINGS = {"as", "a", "ė", "is", "us", "ai", "os"}
-- Suffix keywords accepted in |dem=.
local DEM_SUFFIX_KEYWORDS = {
["as"] = true, ["is"] = true,
["ietis"] = true, ["iẽtis"] = true,
["jietis"] = true, ["jiẽtis"] = true,
}
-- Hardcoded exceptions where the regular dem -> fdem/adj rules misfire.
local DEM_EXCEPTIONS = {
["vokietis"] = {fdem = "vókietė", adj = "vókiškas"},
}
-- Collapse a (possibly multi-word) toponym into a single lowercase, accent-
-- free string for ending detection. The demonym's accent comes entirely from
-- the suffix, so the toponym's own accent marks and word spacing are dropped.
local function clean_toponym(toponym)
local bare = m_common.process_input(toponym)
bare = mw.ustring.lower(bare)
bare = mw.ustring.gsub(bare, " ", "")
return bare
end
-- Strip `n` base characters from the end of a two-track stem, keeping any
-- combining accent marks that belong to characters before the cut point.
local function strip_n_chars(stem_bare, stem_ac, n)
local bare_result = mw.ustring.sub(stem_bare, 1, -(n + 1))
local target = mw.ustring.len(bare_result)
if target == 0 then return "", "" end
local GRAVE, ACUTE, TILDE = m_common.GRAVE, m_common.ACUTE, m_common.TILDE
local base_count, pos = 0, 0
local total = mw.ustring.len(stem_ac)
while pos < total and base_count < target do
pos = pos + 1
local ch = mw.ustring.sub(stem_ac, pos, pos)
if ch ~= GRAVE and ch ~= ACUTE and ch ~= TILDE then
base_count = base_count + 1
end
end
while pos < total do
local nxt = mw.ustring.sub(stem_ac, pos + 1, pos + 1)
if nxt == GRAVE or nxt == ACUTE or nxt == TILDE then
pos = pos + 1
else
break
end
end
return bare_result, mw.ustring.sub(stem_ac, 1, pos)
end
-- Join a toponym stem and a demonym suffix. A stem left ending in i after
-- its ending is stripped (Vilnius, Šiauliai, Telšiai) drops that i before
-- a suffix that begins with one: vilniẽtis, šiauliẽtis, not *vilniiẽtis.
local function join_dem(stem, suffix)
if mw.ustring.sub(stem, -1) == "i" and mw.ustring.sub(suffix, 1, 1) == "i" then
stem = mw.ustring.sub(stem, 1, -2)
end
return m_common.makeDisplayText(stem .. suffix)
end
-- "+": derive a demonym from the toponym's ending. Returns dem, or nil and an
-- error message when the ending is not recognized.
local function derive_dem_plus(toponym)
local bare = clean_toponym(toponym)
if mw.ustring.sub(bare, -3) == "ija" then
return nil, "toponym \"" .. toponym .. "\" ends in \"-ija\"; please specify the demonym type manually (|dem=<suffix> or the full word)"
end
for _, ending in ipairs(TOPONYM_ENDINGS) do
local elen = mw.ustring.len(ending)
if mw.ustring.sub(bare, -elen) == ending then
return join_dem(mw.ustring.sub(bare, 1, -(elen + 1)), DEM_DEFAULT_SUFFIX)
end
end
return nil, "cannot auto-derive a demonym from toponym \"" .. toponym .. "\"; please specify the demonym type manually (|dem=<suffix> or the full word)"
end
-- Derive a demonym with a suffix keyword (as/is/ietis/iẽtis/jietis/jiẽtis).
-- Returns dem, or nil and an error message when the ending is not recognized.
local function derive_dem_semiauto(toponym, suffix)
local bare = clean_toponym(toponym)
-- An -ija toponym drops the whole ending, whatever the suffix.
if mw.ustring.sub(bare, -3) == "ija" then
return join_dem(mw.ustring.sub(bare, 1, -4), suffix)
end
-- -jietis is added to the whole name; -ietis replaces an invariant final
-- -u/-o (Peru, Nauru).
if suffix == "jietis" or suffix == "jiẽtis" then
return m_common.makeDisplayText(bare .. suffix)
end
if suffix == "ietis" or suffix == "iẽtis" then
local last = mw.ustring.sub(bare, -1)
if last == "u" or last == "o" then
return join_dem(mw.ustring.sub(bare, 1, -2), suffix)
end
end
-- Otherwise the suffix replaces one of TOPONYM_ENDINGS.
for _, ending in ipairs(TOPONYM_ENDINGS) do
local elen = mw.ustring.len(ending)
if mw.ustring.sub(bare, -elen) == ending then
return join_dem(mw.ustring.sub(bare, 1, -(elen + 1)), suffix)
end
end
return nil, "cannot derive a demonym from toponym \"" .. toponym .. "\" with suffix \"" .. suffix .. "\"; please enter the full word manually"
end
-- Derive fdem and adj from one dem word (derived or typed), by its ending.
-- Returns fdem, adj, or nil, nil when the ending is not recognized.
local function derive_fdem_adj(dem)
local stem_bare, stem_ac = m_common.process_input(dem)
local exception = DEM_EXCEPTIONS[mw.ustring.lower(stem_bare)]
if exception then
return exception.fdem, exception.adj
end
local suffix_len
if mw.ustring.sub(stem_bare, -2) == "as" or mw.ustring.sub(stem_bare, -2) == "is" then
suffix_len = 2
else
return nil, nil
end
local stem_bare2, stem_ac2 = strip_n_chars(stem_bare, stem_ac, suffix_len)
local fdem = stem_ac2 .. "ė"
local adj
if mw.ustring.sub(stem_bare, -5) == "ietis" then
-- -iẽtis carries its own accent: the adjective replaces the whole
-- suffix with -iẽtiškas.
local deep_bare, deep_ac = strip_n_chars(stem_bare, stem_ac, 5)
adj = deep_ac .. "iẽtiškas"
else
adj = stem_ac2 .. "iškas"
end
return m_common.makeDisplayText(fdem), m_common.makeDisplayText(adj)
end
-- Split a |dem= list item's comma-separated piece into its core word and any
-- trailing inline modifier (e.g. "kubietis<q:informal>"), so the core alone
-- can be checked against "+"/suffix keywords while the modifier passes through.
local function split_core_and_modifier(piece)
local lt_pos = mw.ustring.find(piece, "<", 1, true)
if lt_pos then
return mw.text.trim(mw.ustring.sub(piece, 1, lt_pos - 1)), mw.ustring.sub(piece, lt_pos)
end
return mw.text.trim(piece), ""
end
-- Resolve |dem= (expanding "+" and suffix keywords) and, unless |fdem=/|adj=
-- are given, fill them from the resolved dem.
local function handle_toponym_derivation(args, data, toponym)
if not (args.dem and #args.dem > 0) then return end
local fdem_words, adj_words = {}, {}
for i, raw in ipairs(args.dem) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
local resolved
if core == "+" then
local dem, err = derive_dem_plus(toponym)
if not dem then error("lt-headword: " .. err) end
resolved = dem
elseif DEM_SUFFIX_KEYWORDS[core] then
local dem, err = derive_dem_semiauto(toponym, core)
if not dem then error("lt-headword: " .. err) end
resolved = dem
else
resolved = core
end
pieces[j] = resolved .. modifier
local fdem, adj = derive_fdem_adj(resolved)
if fdem then table.insert(fdem_words, fdem) end
if adj then table.insert(adj_words, adj) end
end
args.dem[i] = table.concat(pieces, ",")
end
if (not args.fdem or #args.fdem == 0) and #fdem_words > 0 then
args.fdem = {table.concat(fdem_words, ",")}
end
if (not args.adj or #args.adj == 0) and #adj_words > 0 then
args.adj = {table.concat(adj_words, ",")}
end
end
-- =============================================================================
-- Surname derivation (m -> f/nee/n, proper nouns only)
-- =============================================================================
--
-- Proper nouns only: m/f mean "male surname"/"married surname" here, not
-- "male/female equivalent".
--
-- f/nee/n are derived from the entry's lemma, the masculine surname, with the
-- accent paradigm of its {{lt-ndecl}} pattern (results[1].lemma,
-- results[1].ap). |m= is shown as typed.
--
-- Every derived form has exactly one accent mark: an unaccented keyword keeps
-- the accent of the masculine stem, an accented one replaces it with the
-- suffix's (attach_surname_suffix).
-- Masculine endings replaced by -ienė or -ė. The two-letter endings come
-- before the one-letter ones (ja/ia before a).
local SURNAME_M_ENDINGS = {"as", "is", "ys", "ia", "ja", "us", "ė", "a"}
local function surname_m_ending_len(m_bare)
for _, ending in ipairs(SURNAME_M_ENDINGS) do
local elen = mw.ustring.len(ending)
if mw.ustring.sub(m_bare, -elen) == ending then
return elen
end
end
return nil
end
-- The maiden-name suffix for a masculine ending. Returns strip_len,
-- suffix_bare, suffix_accented, force_retain (true for -ėnas/-ynas/-ūnas,
-- which keep the masculine's accent). -ius/-jus are checked before -us; only
-- "us" is stripped, the i/j stays in the stem.
local function select_daughter_suffix(m_bare)
local last3 = mw.ustring.sub(m_bare, -3)
if last3 == "ius" or last3 == "jus" then
return 2, "ūtė", "ū̃tė", false
end
local last2 = mw.ustring.sub(m_bare, -2)
if last2 == "ys" or last2 == "ia" or last2 == "ja" or last2 == "is" then
return 2, "ytė", "ýtė", false
end
if mw.ustring.sub(m_bare, -1) == "ė" then
return 1, "ytė", "ýtė", false
end
if last2 == "as" then
local last4 = mw.ustring.sub(m_bare, -4)
local force_retain = last4 == "ėnas" or last4 == "ynas" or last4 == "ūnas"
return 2, "aitė", "áitė", force_retain
end
if last2 == "us" then
return 2, "utė", "ùtė", false
end
if mw.ustring.sub(m_bare, -1) == "a" then
return 1, "aitė", "áitė", false
end
return nil
end
-- Strip `strip_len` characters from the masculine surname's two-track form
-- and attach `suffix` (an NFC literal). suffix_has_own_accent controls which
-- side keeps the word's single accent mark: true drops any accent left in
-- the retained stem (the suffix supplies it), false keeps the stem's own
-- accent (if any) and adds no accent from the suffix. Errors if neither side
-- ends up carrying an accent (e.g. the masculine's own accent was on the
-- part just stripped away, and the suffix carries none either).
local function attach_surname_suffix(m_bare, m_ac, strip_len, suffix, suffix_has_own_accent)
local stem_bare, stem_ac = strip_n_chars(m_bare, m_ac, strip_len)
if suffix_has_own_accent then
stem_ac = m_common.to_stem_bare(stem_ac)
end
-- The suffix literal is precomposed (í, á, ý, ù); bring it onto the
-- stem_ac track, where the accent is a combining mark, before joining.
local result = stem_ac .. m_common.to_stem_ac(suffix)
if not m_common.has_accent(result) then
error("derived surname form \"" .. result .. "\" has no accent mark; please check the input or enter the full word manually")
end
-- Insert the dot-above required between i/j and a combining accent mark
-- ("íenė" renders as "i̇́enė").
return m_common.makeDisplayText(result)
end
-- nee (maiden surname): "+" only; the suffix follows from the masculine ending.
local function resolve_nee_core(core, m_bare, m_ac)
if core ~= "+" then return nil, nil end
local strip_len, suffix_bare, suffix_ac, force_retain = select_daughter_suffix(m_bare)
if not strip_len then
return nil, "cannot auto-derive an unmarried surname from \"" .. m_bare .. "\"; please enter the full word manually"
end
if force_retain then
return attach_surname_suffix(m_bare, m_ac, strip_len, suffix_bare, false)
end
return attach_surname_suffix(m_bare, m_ac, strip_len, suffix_ac, true)
end
-- n (gender-neutral surname): "+" only; -ė replaces the ending and the stem
-- keeps its accent.
local function resolve_n_core(core, m_bare, m_ac)
if core ~= "+" then return nil, nil end
local strip_len = surname_m_ending_len(m_bare)
if not strip_len then
return nil, "cannot auto-derive a gender-neutral surname from \"" .. m_bare .. "\"; please enter the full word manually"
end
return attach_surname_suffix(m_bare, m_ac, strip_len, "ė", false)
end
-- -ienė/-íenė begin with i, so a masculine in -ius loses the whole -ius
-- (Kliučius → Kliuč- + -ienė).
local function iene_strip_len(m_bare)
if mw.ustring.sub(m_bare, -3) == "ius" then
return 3
end
return surname_m_ending_len(m_bare)
end
-- f (married surname): "+" or one of ienė/íenė/uvienė/iuvienė. "+" takes
-- -ienė after an AP1 masculine (its accent kept) and -íenė after AP2-4;
-- without an AP it errors.
local function resolve_f_core(core, m_bare, m_ac, ap)
if core == "ienė" or core == "íenė" then
local strip_len = iene_strip_len(m_bare)
if not strip_len then
return nil, "cannot attach -ienė to \"" .. m_bare .. "\"; please enter the full word manually"
end
return attach_surname_suffix(m_bare, m_ac, strip_len, core, core == "íenė")
end
if core == "uvienė" or core == "iuvienė" then
if mw.ustring.sub(m_bare, -2) ~= "us" then
return nil, "-uvienė/-iuvienė only applies to masculine surnames ending in -us/-ius, not \"" .. m_bare .. "\""
end
return attach_surname_suffix(m_bare, m_ac, 2, "uvienė", false)
end
if core == "+" then
if not ap or ap == 0 then
return nil, "cannot auto-derive a married surname from \"" .. m_bare ..
"\" without an accent paradigm; add it to the entry's own inflection pattern (e.g. \",1\"), " ..
"or use an explicit |f=ienė or |f=íenė instead of \"+\""
end
local strip_len = iene_strip_len(m_bare)
if not strip_len then
return nil, "cannot auto-derive a married surname from \"" .. m_bare .. "\"; please enter the full word manually"
end
if ap == 1 then
return attach_surname_suffix(m_bare, m_ac, strip_len, "ienė", false)
end
return attach_surname_suffix(m_bare, m_ac, strip_len, "íenė", true)
end
return nil, nil
end
-- Expand "+"/keywords in a surname-derivation list param (f/nee/n), keeping
-- the text as typed where `resolve` returns nil, nil.
local function process_surname_list(args, param_name, resolve)
local list = args[param_name]
if not (list and #list > 0) then return end
for i, raw in ipairs(list) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
local word, err = resolve(core)
if err then error("lt-headword: " .. err) end
pieces[j] = (word or core) .. modifier
end
list[i] = table.concat(pieces, ",")
end
end
-- Expand |f=/|nee=/|n= on a surname entry (is_proper) using the masculine
-- entry's own lemma + accent paradigm as the base to derive from.
local function handle_surname_derivation(args, data, masculine_lemma, ap)
if not masculine_lemma then return end
if not ((args.f and #args.f > 0) or (args.nee and #args.nee > 0) or (args.n and #args.n > 0)) then
return
end
local m_bare, m_ac = m_common.process_input(masculine_lemma)
process_surname_list(args, "nee", function(core) return resolve_nee_core(core, m_bare, m_ac) end)
process_surname_list(args, "n", function(core) return resolve_n_core(core, m_bare, m_ac) end)
process_surname_list(args, "f", function(core) return resolve_f_core(core, m_bare, m_ac, ap) end)
end
-- Table footnotes come in bracketed form ("[irregular]"); the headword line
-- takes them as qualifier text plus [ref:...] references. Callers put the
-- qualifiers in the left slot, `q`.
local function footnotes_to_quals_refs(footnotes)
if not footnotes then
return nil, nil
end
local iut = require("Module:inflection utilities")
return iut.convert_footnotes_to_qualifiers_and_references(footnotes)
end
-- Build the AP badge label list for the `l` field of a gender spec.
-- "AP1".."AP4" are defined in [[Module:labels/data/lang/lt]] and render as
-- links to [[Appendix:Lithuanian accentuation]]. `ap_str` may hold several
-- paradigm numbers (alternant merges produce e.g. "3 // 4" → AP3, AP4).
local function ap_badge_labels(ap_str)
if not ap_str then
return nil
end
local ap_labels = {}
for ap in ap_str:gmatch("%d+") do
table.insert(ap_labels, "AP" .. ap)
end
return ap_labels[1] and ap_labels or nil
end
-- Insert a list of form objects as one inflection line: each form becomes its
-- own part so a per-form footnote carries through as a qualifier on just that
-- form (format_inflection_parts joins parts with " or " automatically).
local function insert_form_parts(data, form_list, label)
if not form_list then return end
local parts = {}
for _, form_obj in ipairs(form_list) do
local q, refs = footnotes_to_quals_refs(form_obj.footnotes)
table.insert(parts, {term = form_obj.form, q = q, refs = refs})
end
if #parts > 0 then
parts.label = label
table.insert(data.inflections, parts)
end
end
-- The noun headword line, for nouns, proper nouns and the numerals that
-- decline as nouns (šim̃tas): run an lt-ndecl pattern through Module:lt-noun
-- and fill the heads, the AP-badged genders, the indeclinable label and the
-- genitive line. Returns the pattern results (for surnames and demonyms).
local function noun_headword_core(data, pattern_str)
local m_lt_noun = require("Module:lt-noun")
local results = m_lt_noun.get_headword_data(pattern_str)
-- Track if any result is indeclinable or plural-only
local all_indeclinable = true
local any_plural_only = false
-- Process each pattern result
for _, result in ipairs(results) do
-- The lemma is the head; a lemma footnote, having no table cell,
-- becomes a qualifier on it. A plurale tantum is entered by its
-- theoretical singular (dùris,2,ies.pl); its head is the nominative
-- plural.
local lemma_q, lemma_refs = footnotes_to_quals_refs(result.lemma_footnotes)
local nom_p = result.number_restr == "pl" and result.forms.nom_p
if nom_p and nom_p[1] then
for _, form_obj in ipairs(nom_p) do
table.insert(data.heads, {term = form_obj.form, q = lemma_q, refs = lemma_refs})
end
else
table.insert(data.heads, {term = result.lemma, q = lemma_q, refs = lemma_refs})
end
-- AP badge as a left label on the gender. Indeclinable nouns get no
-- badge; ap_display covers alternant merges with differing APs.
local ap_labels
if not result.indeclinable then
ap_labels = ap_badge_labels(result.ap_display
or result.ap > 0 and tostring(result.ap) or nil)
end
-- A gender footnote becomes a left qualifier on the gender.
local gender_q, gender_refs = footnotes_to_quals_refs(result.gender_footnotes)
table.insert(data.genders, {
spec = result.gender,
l = ap_labels,
q = gender_q,
refs = gender_refs,
})
-- Track indeclinable and plural-only status
if not result.indeclinable then
all_indeclinable = false
end
if result.number_restr == "pl" then
any_plural_only = true
end
end
-- Add indeclinable label if all patterns are indeclinable
if all_indeclinable then
table.insert(data.inflections, {label = glossary_link("không biến cách")})
end
-- Collect genitive forms (singular or plural depending on number restriction)
if not all_indeclinable then
local gen_slot = any_plural_only and "gen_p" or "gen_s"
local gen_label = any_plural_only and "sinh cách số nhiều" or "sinh cách số ít"
-- Each genitive is a part of its own, so that its footnote (e.g. from
-- a ".gen:" override) becomes a qualifier on that form only.
local gen_parts = {}
local seen_gen = {}
for _, result in ipairs(results) do
if result.forms[gen_slot] then
for _, form_obj in ipairs(result.forms[gen_slot]) do
if not seen_gen[form_obj.form] then
seen_gen[form_obj.form] = true
local gen_q, gen_refs = footnotes_to_quals_refs(form_obj.footnotes)
table.insert(gen_parts, {term = form_obj.form, q = gen_q, refs = gen_refs})
end
end
end
end
if #gen_parts > 0 then
gen_parts.label = gen_label
table.insert(data.inflections, gen_parts)
end
end
return results
end
-- Common function for nouns and proper nouns
local function handle_nouns(args, data, is_proper, pagename)
-- If no inflection spec given, scrape it from {{lt-ndecl}} on the same page.
local pattern_str = args[1]
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename, "lt-ndecl", args.id)
if err then error("lt-noun: " .. err) end
pattern_str = infl
end
local results = noun_headword_core(data, pattern_str)
-- Declension and accentuation categories come from Module:lt-noun and are
-- added only here ({{lt-ndecl}} adds none), so that indeclinables and
-- proper nouns get them too. Module:headword adds the gender categories.
if results.categories then
for _, cat in ipairs(results.categories) do
table.insert(data.categories, cat)
end
end
if is_proper then
-- Expand |dem= ("+" or a suffix keyword) and fill fdem/adj from it,
-- unless |fdem=/|adj= are given.
handle_toponym_derivation(args, data, results[1] and results[1].lemma)
-- m/f mean "male surname"/"married surname" here, derived from the
-- entry's own lemma+ap; nee/n are surname-only params (see above).
handle_surname_derivation(args, data, results[1] and results[1].lemma, results[1] and results[1].ap)
handle_deriv(args, data, "m", "họ nam")
handle_deriv(args, data, "f", "họ kết hôn")
handle_deriv(args, data, "nee", "maiden surname")
handle_deriv(args, data, "n", "gender-neutral surname")
else
handle_deriv(args, data, "m", "giống đực tương đương")
handle_deriv(args, data, "f", "giống cái tương đương", "f")
end
-- Handle derivation parameters
handle_deriv(args, data, "adj", "tính từ quan hệ")
handle_deriv(args, data, "dim", "<<giảm nhẹ nghĩa>>", "giảm nhẹ nghĩa")
handle_deriv(args, data, "aug", "<<tăng nhẹ nghĩa>>", "tăng nhẹ nghĩa")
handle_deriv(args, data, "pej", "<<nghĩa xấu>>", "nghĩa xấu")
handle_deriv(args, data, "dem", "tên gọi dân cư")
handle_deriv(args, data, "fdem", "tên gọi dân cư danh cho nữ giới>")
end
pos_functions["Danh từ"] = function(args, data, pagename)
handle_nouns(args, data, false, pagename)
end
pos_functions["Danh từ riêng"] = function(args, data, pagename)
handle_nouns(args, data, true, pagename)
end
-- Function for adjectives
pos_functions["Tính từ"] = function(args, data, pagename)
local m_lt_adj = require("Module:lt-adjective")
-- If no inflection spec given, scrape it from {{lt-adecl}} on the same page.
local pattern_str = args[1]
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename, "lt-adecl", args.id)
if err then error("lt-adj: " .. err) end
pattern_str = infl
end
local result = m_lt_adj.get_headword_data(pattern_str)
-- Lemma footnote → qualifier on the head; AP footnote → qualifier on the
-- gender and AP badge (neither has a table cell).
local lemma_q, lemma_refs = footnotes_to_quals_refs(result.lemma_footnotes)
table.insert(data.heads, {term = result.lemma, q = lemma_q, refs = lemma_refs})
local gender_q, gender_refs = footnotes_to_quals_refs(result.gender_footnotes)
table.insert(data.genders, {
spec = "m",
l = ap_badge_labels(tostring(result.ap)),
q = gender_q,
refs = gender_refs,
})
-- gen_m_sg / fem_nom_sg are form-object lists; each form becomes its own
-- inflection part so a per-form footnote (e.g. a whole-declension .[note])
-- carries through as a qualifier on just that form.
insert_form_parts(data, result.gen_m_sg, "giống đực ở sinh cách số ít")
insert_form_parts(data, result.fem_nom_sg, "feminine")
-- Degree categories, from the same shape rules (and .comp/.nocomp tags)
-- that decide whether {{lt-adecl}} shows the compared forms.
table.insert(data.categories, "Tính từ " .. (result.suppress_comp and "không so sánh được" or "so sánh được") .. " tiếng Litva")
-- |adv=+ derives the -(i)ai adverb from the adjective's own paradigm
-- (Module:lt-adverb; the accent follows the dative plural, or the
-- accusative singular for disyllabic -us adjectives). The lexical
-- exceptions (greĩtai, the taste adverbs, vėlaĩ) are typed in full.
if args.adv and #args.adv > 0 then
for i, raw in ipairs(args.adv) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
if core == "+" then
local m_lt_adv = require("Module:lt-adverb")
local dat_pl = result.dat_m_pl and result.dat_m_pl[1] and result.dat_m_pl[1].form
local acc_sg = result.acc_m_sg and result.acc_m_sg[1] and result.acc_m_sg[1].form
local adv, err = m_lt_adv.derive_from_adjective(result.lemma, dat_pl, acc_sg)
if not adv then error("lt-adj: " .. err) end
pieces[j] = adv .. modifier
end
end
args.adv[i] = table.concat(pieces, ",")
end
end
handle_deriv(args, data, "adv", "phó từ")
handle_deriv(args, data, "dim", "<<giảm nhẹ nghĩa>>", "giảm nhẹ nghĩa")
handle_deriv(args, data, "aug", "<<tăng nhẹ nghĩa>>", "tăng nhẹ nghĩa")
handle_deriv(args, data, "pej", "<<nghĩa xấu>>", "nghĩa xấu")
end
-- Numerals ({{lt-num}}). Without parameter 1 the page name is looked up in
-- Module:lt-numeral, as {{lt-numdecl}} does. The numerals that decline as
-- nouns (šim̃tas, tū́kstantis, milijõnas, dvẽjetas, the -dalis fractions) take
-- the noun path: a page Module:lt-numeral does not know falls back to it,
-- |1=noun forces it (the cardinal section of šimtas, whose lookup finds the
-- ordinal), and any other |1= is an lt-ndecl pattern. |id= picks among
-- several {{lt-ndecl}} on the page.
pos_functions["Số từ"] = function(args, data, pagename)
local m_lt_num = require("Module:lt-numeral")
local hd
if not args[1] then
hd = m_lt_num.get_headword_data(pagename)
end
if not hd then
local pattern_str = args[1]
if not pattern_str or pattern_str == "noun" then
local infl, err = m_common.find_lt_inflection(pagename, "lt-ndecl", args.id)
if err then error("lt-num: " .. err) end
pattern_str = infl
end
noun_headword_core(data, pattern_str)
return
end
table.insert(data.heads, {term = hd.head})
-- AP badge as a left label on the gender, as in the noun/adjective
-- branches. The pus- fractions carry no gender spec; they get the
-- indeclinable label instead.
if hd.gender then
table.insert(data.genders, {
spec = hd.gender,
l = hd.ap and ap_badge_labels(tostring(hd.ap)) or nil,
})
end
if hd.indeclinable then
table.insert(data.inflections, {label = glossary_link("không biến cách")})
end
-- Inflection line (canonical pages only; alias pages show just the head —
-- get_headword_data returns no form slots for them).
insert_form_parts(data, hd.fem, "giống cái")
insert_form_parts(data, hd.neut, "giống trung")
insert_form_parts(data, hd.gen, "sinh cách")
insert_form_parts(data, hd.pl, "danh từ chỉ có số nhiều")
end
-- Pronouns ({{lt-pronoun}}) and determiners: the head and its forms come from
-- Module:lt-pronoun by the page name, as in {{lt-prondecl}}. An indeclinable
-- pronoun, or one without a table there, takes its accented head in |1=.
local function handle_pronouns(args, data, pagename)
local hd = require("Module:lt-pronoun").get_headword_data(pagename)
if not hd or hd.indeclinable then
if not hd and not args[1] then
error("lt-pronoun: no declension of '" .. pagename .. "' is known; "
.. "write the head with its accent mark in 1=")
end
table.insert(data.heads, {term = args[1] or pagename})
if hd then
table.insert(data.inflections, {label = glossary_link("không biến cách")})
end
return
end
if args[1] then
error("lt-pronoun: 1= is only for a pronoun without a declension table; "
.. "the forms of '" .. pagename .. "' come from its table")
end
for _, head in ipairs(hd.heads) do
table.insert(data.heads, {term = head})
end
if hd.gender then
table.insert(data.genders, {spec = hd.gender})
end
insert_form_parts(data, hd.fem, "giống cái")
insert_form_parts(data, hd.neut, "giống trung")
insert_form_parts(data, hd.gen, "sinh cách")
end
pos_functions["Đại từ"] = function(args, data, pagename)
handle_pronouns(args, data, pagename)
end
pos_functions["Từ hạn định"] = function(args, data, pagename)
handle_pronouns(args, data, pagename)
end
-- Participles ({{lt-part}}): the pattern of {{lt-pdecl}}, read from the page
-- unless given in |1=. A passive participle carries its accentuation
-- paradigm as a badge on the gender; one that exists only in the neuter
-- (an unprefixed reflexive passive, .intr) has the neuter as its head. A
-- half-participle (-damas, -damasis) is given in |1= and has no table.
pos_functions["Phân từ"] = function(args, data, pagename)
local pattern_str = args[1]
-- A half-participle (-damas) has no table: its pattern is given in |1=, and
-- the line shows its four forms.
local plain = pattern_str and mw.ustring.lower(m_common.stripDiacritics(pattern_str))
if plain and (plain:find("damas[%.%[]") or plain:find("damasis[%.%[]")) then
error("lt-part: \"" .. pattern_str .. "\": a half-participle takes no tags or footnotes")
end
if plain and (plain:find("damas$") or plain:find("damasis$")) then
local hp = require("Module:lt-participle").half_participle(pattern_str)
for _, head in ipairs(hp.heads) do
table.insert(data.heads, {term = head})
end
table.insert(data.genders, {spec = "m"})
local function forms(list, label)
local parts = {label = label}
for _, f in ipairs(list) do
table.insert(parts, {term = f})
end
table.insert(data.inflections, parts)
end
forms(hp.fem_s, "feminine singular")
forms(hp.masc_p, "masculine plural")
forms(hp.fem_p, "feminine plural")
table.insert(data.categories, "Lithuanian pusdalyvis participles")
return
end
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename, "lt-pdecl", args.id)
if err then error("lt-part: " .. err) end
pattern_str = infl
end
local hd = require("Module:lt-participle").get_headword_data(pattern_str)
for _, head in ipairs(hd.heads) do
table.insert(data.heads, {term = head})
end
table.insert(data.genders, {
spec = hd.neuter_only and "n" or "m",
l = hd.ap and ap_badge_labels(tostring(hd.ap)) or nil,
})
insert_form_parts(data, hd.gen, "genitive masculine singular")
insert_form_parts(data, hd.fem, "feminine")
end
-- =============================================================================
-- Adverbs ({{lt-adv}})
-- =============================================================================
--
-- Adverbs have no inflection table, so parameter 1 is the accented positive
-- with Module:lt-adverb's degree tags (see that module's header); nothing is
-- scraped. The module hands back spec lists whose forms may carry bracketed
-- footnotes and raw inline modifiers (<q:…> <qq:…> <l:…> <ll:…> <ref:…>);
-- both are turned into headword parts here.
-- Turn one form spec into a Module:headword part: the inline modifiers are
-- parsed by Module:headword utilities, a bracketed footnote becomes a left
-- qualifier (or a reference), as in the other branches.
local function spec_to_part(spec, paramname, is_head)
local part
if spec.mods then
part = m_headword_utilities.parse_term_with_modifiers {
val = spec.form .. spec.mods,
paramname = paramname,
is_head = is_head,
}
else
part = {term = spec.form}
end
local q, refs = footnotes_to_quals_refs(spec.footnotes)
if q then
part.q = part.q and m_headword_utilities.combine_qualifiers_or_labels(part.q, q) or q
end
if refs then
part.refs = part.refs or {}
for _, ref in ipairs(refs) do
table.insert(part.refs, ref)
end
end
return part
end
local function insert_spec_parts(data, specs, label, accel_form)
if not specs then return end
local parts = {label = label}
for _, spec in ipairs(specs) do
table.insert(parts, spec_to_part(spec, "1"))
end
if accel_form then
parts.accel = {form = accel_form}
end
table.insert(data.inflections, parts)
end
-- Keywords accepted in |adj= on adverb entries: "+" tries every adjective
-- the adverb can come from, an ending keyword narrows it to one.
local ADJ_KEYWORDS = {["+"] = true, ["as"] = true, ["us"] = true, ["ias"] = true, ["is"] = true}
-- Expand "+"/keyword items of |adj= into the adjective's accented lemma,
-- read from the {{lt-adecl}} pattern of the candidate page (the adverb's
-- accent does not show the adjective's paradigm). Errors when no candidate
-- page has a pattern; the full word can be typed instead.
local function expand_adj_keywords(args, positive)
if not (args.adj and #args.adj > 0) then return end
local m_lt_adv = require("Module:lt-adverb")
for i, raw in ipairs(args.adj) do
local pieces = mw.text.split(raw, ",")
for j, piece in ipairs(pieces) do
local core, modifier = split_core_and_modifier(piece)
if ADJ_KEYWORDS[core] then
local candidates = m_lt_adv.derive_adjective(positive, core ~= "+" and core or nil)
local lemma
for _, candidate in ipairs(candidates) do
local infl = m_common.find_lt_inflection(candidate, "lt-adecl")
if infl then
lemma = require("Module:lt-adjective").get_headword_data(infl).lemma
break
end
end
if not lemma then
error("lt-adv: no adjective entry with {{lt-adecl}} found for |adj=" .. core ..
(candidates[1] and (" (tried: " .. table.concat(candidates, ", ") .. ")") or
" (the adverb \"" .. positive .. "\" is not an -(i)ai form)") ..
"; please give the adjective in full")
end
pieces[j] = lemma .. modifier
end
end
args.adj[i] = table.concat(pieces, ",")
end
end
pos_functions["Phó từ"] = function(args, data, pagename)
local m_lt_adv = require("Module:lt-adverb")
local pattern_str = args[1]
if not pattern_str then
error("lt-adv: the accented adverb is required in parameter 1 (adverbs have no inflection table to read it from)")
end
local hd = m_lt_adv.get_headword_data(pattern_str)
for _, spec in ipairs(hd.head) do
table.insert(data.heads, spec_to_part(spec, "1", true))
end
if hd.comparable then
insert_spec_parts(data, hd.comp, "comparative", "comparative")
insert_spec_parts(data, hd.sup, "superlative", "superlative")
insert_spec_parts(data, hd.dim, "diminutive comparative")
else
table.insert(data.inflections, {label = glossary_link("uncomparable", "not comparable")})
end
for _, cat in ipairs(hd.categories) do
table.insert(data.categories, cat)
end
expand_adj_keywords(args, hd.positive)
handle_deriv(args, data, "adj", "tính từ")
handle_deriv(args, data, "dim", "<<giảm nhẹ nghĩa>>", "giảm nhẹ nghĩa")
end
-- Function for verbs
pos_functions["Động từ"] = function(args, data, pagename)
local m_lt_verb = require("Module:lt-verb")
-- If no inflection spec given, scrape it from {{lt-conj}} on the same
-- page ({{lt-conj+}} redirects to it; a call of the legacy table is
-- skipped).
local pattern_str = args[1]
if not pattern_str then
local infl, err = m_common.find_lt_inflection(pagename,
{"lt-conj", "lt-conj+"}, args.id,
function(targs) return not m_common.is_legacy_conj(targs) end)
if err then error("lt-verb: " .. err) end
pattern_str = infl
end
local result = m_lt_verb.get_headword_data(pattern_str)
-- An infinitive (lemma) footnote has no table cell: it becomes a
-- qualifier on the head.
local lemma_q, lemma_refs = footnotes_to_quals_refs(result.lemma_footnotes)
table.insert(data.heads, {term = result.lemma, q = lemma_q, refs = lemma_refs})
-- pres_3/past_3 are form-object lists; each form is a part of its own, so
-- that its footnote lands on that form only.
local function insert_forms(slot_forms, label)
if not slot_forms or #slot_forms == 0 then
return
end
local parts = {label = label}
for _, form_obj in ipairs(slot_forms) do
local q, refs = footnotes_to_quals_refs(form_obj.footnotes)
table.insert(parts, {term = form_obj.form, q = q, refs = refs})
end
table.insert(data.inflections, parts)
end
insert_forms(result.pres_3, "third-person present tense")
insert_forms(result.past_3, "third-person past tense")
if result.reflexive then
table.insert(data.categories, "Lithuanian reflexive verbs")
end
end
-- =============================================================================
-- Non-lemma forms ({{lt-head}})
-- =============================================================================
--
-- {{lt-head|noun form|LEMMA}} computes its definition lines from the lemma's
-- own table: the Lithuanian section of the lemma's page is searched for the
-- table templates of the part of speech, and every cell whose form, without
-- accent marks, is the page name gives a tag set. The readings are grouped by
-- their accented form, which is the head (|head= keeps one of them), and
-- within a head by their labels: the cell footnotes that are usage labels
-- (FORM_LABELS), and "AP n" where a noun pattern with several paradigms gives
-- the form in some of them only. A reading identical to the lemma itself is
-- left out.
-- Cell footnotes that become labels of a definition line; any other footnote
-- stays in the table. "colloquial short form" becomes the label colloquial;
-- the family plural of a surname keeps its note, which tells it from the
-- ordinary plural.
local FORM_LABELS = {
["referring to a married couple or a family"] = "referring to a married couple or a family",
["archaic"] = "archaic", ["colloquial"] = "colloquial", ["colloquial short form"] = "colloquial",
["dated"] = "dated", ["dialectal"] = "dialectal", ["humorous"] = "humorous",
["literary"] = "literary", ["obsolete"] = "obsolete", ["pejorative"] = "pejorative",
["poetic"] = "poetic", ["proscribed"] = "proscribed", ["rare"] = "rare",
["regional"] = "regional", ["vulgar"] = "vulgar",
}
local NOUN_SLOT_ORDER = {}
for i, case in ipairs({"nom", "gen", "dat", "acc", "ins", "loc", "voc", "ill", "all", "ade"}) do
NOUN_SLOT_ORDER[case .. "_s"] = i
NOUN_SLOT_ORDER[case .. "_p"] = 20 + i
end
-- The cells of one {{lt-ndecl}} pattern in table order, as the other table
-- modules give them through their form_cells: {lemma =, gender =, cells =
-- {{tags =, forms =}, …}}. The tags are the slot split at "_" (nom|s …).
local function noun_cells(pattern)
local results = require("Module:lt-noun").get_headword_data(pattern)
local cells = {}
for _, result in ipairs(results) do
for slot, list in pairs(result.forms) do
table.insert(cells, {tags = mw.text.split(slot, "_"), forms = list,
order = NOUN_SLOT_ORDER[slot] or 99, seq = #cells + 1})
end
end
table.sort(cells, function(a, b)
if a.order ~= b.order then
return a.order < b.order
end
return a.seq < b.seq
end)
local first = results[1]
return {lemma = first and first.lemma, gender = first and first.gender, cells = cells}
end
local function module_cells(module)
return function(pattern)
return require(module).form_cells(pattern)
end
end
-- The table templates read on the lemma's page: their names, the function
-- giving the cells of one call, the input it takes (parameter 1 unless
-- `input` says otherwise), calls to skip ("legacy" for a call of the earlier
-- template of that name, "other" for a call with nothing to read), and
-- whether a colon list of paradigms is split (nouns).
local NOUN_TABLE = {names = {"lt-ndecl"}, cells = noun_cells, ap_passes = true}
local TABLES = {
adjective = {names = {"lt-adecl"}, cells = module_cells("Module:lt-adjective")},
participle = {names = {"lt-pdecl"}, cells = module_cells("Module:lt-participle")},
verb = {names = {"lt-conj", "lt-conj+"}, cells = module_cells("Module:lt-verb"),
-- A call of the legacy table (Template:lt-conj/old) has no cells to read.
skip = function(targs) return m_common.is_legacy_conj(targs) and "legacy" end},
-- A half-participle has no table: its forms come from the headword line.
half_participle = {names = {"lt-part"}, label = "{{lt-part}} line of a half-participle",
cells = function(pattern) return require("Module:lt-participle").half_participle_cells(pattern) end,
skip = function(targs)
local first = targs[1] and plain(targs[1]):gsub("%-", "")
if targs.m or (first and mw.ustring.find(first, "dam$")) then
return "legacy"
elseif not first or not (mw.ustring.find(first, "damas$") or mw.ustring.find(first, "damasis$")) then
return "other"
end
end},
-- {{lt-numdecl}} takes no pattern: it looks the numeral up by page name.
numeral = {names = {"lt-numdecl"}, cells = module_cells("Module:lt-numeral"),
input = function(targs, term) return targs.pagename or term end},
}
-- The parts of speech {{lt-head}} takes: the category, the singular for
-- Module:accel, the tables read, and whether the line shows the lemma's
-- gender (nouns).
local FORM_POS = {
["noun form"] = {pos = "noun forms", singular = "noun", tables = {NOUN_TABLE}, gender = true},
["proper noun form"] = {pos = "proper noun forms", singular = "proper noun", tables = {NOUN_TABLE},
gender = true},
["adjective form"] = {pos = "adjective forms", singular = "adjective", tables = {TABLES.adjective}},
["participle form"] = {pos = "participle forms", singular = "participle",
tables = {TABLES.participle, TABLES.half_participle}},
["verb form"] = {pos = "verb forms", singular = "verb", tables = {TABLES.verb}},
-- The numerals that decline as nouns have a {{lt-ndecl}} table.
["numeral form"] = {pos = "numeral forms", singular = "numeral", tables = {TABLES.numeral, NOUN_TABLE}},
}
local FORM_POS_LIST = "noun form, proper noun form, adjective form, participle form, verb form and numeral form"
-- The section of `text` under the level-two heading `name`, or nil.
local function language_section(text, name)
local lines, inside = {}, false
for line in mw.text.gsplit(text, "\n", true) do
if mw.ustring.find(line, "^==[^=].*[^=]==%s*$") then
inside = mw.ustring.match(line, "^==%s*(.-)%s*==%s*$") == name
elseif inside then
table.insert(lines, line)
end
end
return lines[1] and table.concat(lines, "\n") or nil
end
local function display_form(form)
return m_common.makeDisplayText(mw.ustring.toNFD(form), lang)
end
-- Readings of `pagename` (of every form when it is nil) in one table
-- pattern: {form =, plain =, tags =, labels =, order =}, and the table's lemma
-- data. A noun pattern with a colon list of paradigms ("lemma,1:3…") is
-- declined once per paradigm, so that a reading given by some of them only
-- carries their labels.
local function table_readings(tbl, pattern, pagename)
local lemma_part, aps, rest
if tbl.ap_passes then
lemma_part, aps, rest = mw.ustring.match(pattern, "^([^,%(<]+),([1-4]:[1-4:]*)(.*)$")
end
local passes = {}
if aps then
for ap in aps:gmatch("[1-4]") do
table.insert(passes, {ap = ap, pattern = lemma_part .. "," .. ap .. rest})
end
else
passes[1] = {pattern = pattern}
end
local readings, by_key, info = {}, {}, nil
for _, pass in ipairs(passes) do
local data = tbl.cells(pass.pattern)
if not data then
error("lt-head: {{" .. tbl.names[1] .. "}} gives no table for '" .. tostring(pass.pattern) .. "'")
end
if not info then
info = data
-- The readings of the lemma: every form of the first cell that holds
-- the lemma (both readings of "((Ùrbanas<n,1>,Urbãnas<n,2>))", of
-- "Ùrbanas:Urbãnas,1"), or the variants of a lemma that is no cell
-- (an infinitive, "X / Y").
local first = display_form(mw.text.split(data.lemma or "", "%s*/%s*")[1])
info.lemma_forms = {}
for _, cell in ipairs(data.cells) do
local here = false
for _, fobj in ipairs(cell.forms) do
if display_form(fobj.form) == first then
here = true
end
end
if here then
for _, fobj in ipairs(cell.forms) do
info.lemma_forms[display_form(fobj.form)] = true
end
break
end
end
for _, v in ipairs(mw.text.split(data.lemma or "", "%s*/%s*")) do
if v ~= "" then
info.lemma_forms[display_form(v)] = true
end
end
end
for order, cell in ipairs(data.cells) do
for _, fobj in ipairs(cell.forms) do
local plain = m_common.stripDiacritics(fobj.form)
if not pagename or plain == pagename then
local labels = {}
for _, note in ipairs(fobj.footnotes or {}) do
local label = FORM_LABELS[mw.ustring.lower((note:gsub("^%[(.*)%]$", "%1")))]
if label then
table.insert(labels, label)
end
end
local form = display_form(fobj.form)
local tags = table.concat(cell.tags, "|")
local key = form .. "\0" .. tags .. "\0" .. table.concat(labels, "|")
local r = by_key[key]
if not r then
r = {form = form, plain = plain, tags = cell.tags, labels = labels, aps = {},
order = order, seq = #readings + 1}
by_key[key] = r
table.insert(readings, r)
end
if pass.ap then
r.aps[pass.ap] = true
end
end
end
end
end
if aps then
for _, r in ipairs(readings) do
local mine = {}
for _, pass in ipairs(passes) do
if r.aps[pass.ap] then
table.insert(mine, "AP" .. pass.ap)
end
end
if #mine < #passes then
for i = #mine, 1, -1 do
table.insert(r.labels, 1, mine[i])
end
end
end
end
return readings, info
end
-- The lemma as the definition lines show it: a table with several infinitives
-- ("X / Y") shows the one spelled like the lemma's page.
local function lemma_display(lemma, term)
if not lemma then
return nil
end
local variants = mw.text.split(lemma, "%s*/%s*")
for _, v in ipairs(variants) do
if m_common.stripDiacritics(v) == term then
return display_form(v)
end
end
return display_form(variants[1])
end
-- The readings {{lt-head}} works from, for every form of one table call:
-- {lemma =, gender =, readings = {{form =, plain =, tags =, labels =,
-- is_lemma =}, …}} in table order. `pos` is a value of parameter 1 of
-- {{lt-head}}, `name` the table template and `input` its parameter 1 (for
-- {{lt-numdecl}} the numeral's page name).
function export.form_readings(pos, name, input)
local spec = FORM_POS[pos] or error("lt-head: unknown part of speech '" .. tostring(pos) .. "'")
local tbl
for _, t in ipairs(spec.tables) do
for _, n in ipairs(t.names) do
if n == name then
tbl = t
end
end
end
if not tbl then
error("lt-head: " .. pos .. " does not read {{" .. tostring(name) .. "}}")
end
local readings, info = table_readings(tbl, input, nil)
table.sort(readings, function(a, b)
if a.order ~= b.order then
return a.order < b.order
end
return a.seq < b.seq
end)
local lemma_form = info and info.lemma and display_form(mw.text.split(info.lemma, "%s*/%s*")[1])
local lemma_forms = info and info.lemma_forms or {}
local out = {}
for _, r in ipairs(readings) do
table.insert(out, {form = r.form, plain = r.plain, tags = r.tags, labels = r.labels,
is_lemma = lemma_forms[r.form] or nil})
end
return {lemma = lemma_form, gender = spec.gender and info and info.gender or nil, readings = out}
end
function export.show_form(frame)
local args = m_para.process(frame:getParent().args, {
[1] = {required = true},
[2] = {required = true},
["head"] = {},
["t"] = {},
["pagename"] = {},
})
-- On the template's own page there is no lemma to read: render a bare line.
if not args[1] and mw.title.getCurrentTitle().nsText == "Template" then
return full_headword {
lang = lang, pos_category = "noun forms", categories = {}, genders = {}, inflections = {},
heads = {{term = args.pagename or mw.loadData("Module:headword/data").pagename}},
pagename = args.pagename, no_redundant_head_cat = true,
}
end
local spec = FORM_POS[args[1]]
if not spec then
error("lt-head: '" .. tostring(args[1]) .. "' is not supported; the template takes "
.. FORM_POS_LIST .. ", whose definitions come from the table on the lemma's page")
end
local table_by_name, table_list = {}, {}
for _, tbl in ipairs(spec.tables) do
table.insert(table_list, tbl.label or ("{{" .. tbl.names[1] .. "}} table"))
for _, name in ipairs(tbl.names) do
table_by_name[name] = tbl
end
end
local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
-- head= names the accented forms to show; one written with links
-- ("[[mẽtraščių|Mẽtraščių]] [[knỹgos]]") is shown as written.
local wanted_heads
if args.head then
wanted_heads = {}
for _, h in ipairs(mw.text.split(args.head, "%s*,%s*")) do
local linked = h:find("[[", 1, true) and h
wanted_heads[display_form(m_common.canonicalize_input(linked and m_links.remove_links(h) or h))] =
linked or true
end
end
local data = {
lang = lang, pos_category = spec.pos, categories = {}, heads = {}, genders = {},
inflections = {}, pagename = pagename, no_redundant_head_cat = true,
}
local lines, seen_head, gender_done = {}, {}, false
for _, lemma_spec in ipairs(mw.text.split(args[2], "%s*,%s*")) do
local term, id = mw.ustring.match(lemma_spec, "^(.-)<id:([^>]*)>$")
term = term or lemma_spec
local title = mw.title.new(term)
local content = title and title:getContent()
local section = content and language_section(content, "Lithuanian")
if not section then
error("lt-head: no Lithuanian section on [[" .. term .. "]]")
end
local readings, info, found_table, legacy_table = {}, nil, false, false
for template in require("Module:template parser").find_templates(section) do
local tbl = table_by_name[template:get_name()]
if tbl then
local targs = template:get_arguments()
local skip = tbl.skip and tbl.skip(targs)
if skip == "legacy" then
legacy_table = tbl
elseif not skip and (not id or targs.id == id) then
found_table = true
local input = tbl.input and tbl.input(targs, term) or targs[1]
local rs, inf = table_readings(tbl, input, pagename)
info = info or inf
for _, r in ipairs(rs) do
table.insert(readings, r)
end
end
end
end
if not found_table then
error("lt-head: no " .. table.concat(table_list, " or ") .. (id and (" with id=" .. id) or "")
.. " on [[" .. term .. "]]" .. (legacy_table and (" (the {{" .. legacy_table.names[1]
.. "}} call there is written for the earlier template of that name, which has no forms to read)") or ""))
end
local lemma_form = info and lemma_display(info.lemma, term)
local lemma_forms = info and info.lemma_forms or {}
if spec.gender and info and not gender_done then
gender_done = true
table.insert(data.genders, {spec = info.gender})
end
-- Heads in table order; within each head, groups of tag sets by labels,
-- the unlabelled group first.
table.sort(readings, function(a, b)
if a.order ~= b.order then
return a.order < b.order
end
return a.seq < b.seq
end)
local heads, by_head = {}, {}
for _, r in ipairs(readings) do
if not lemma_forms[r.form] and (not wanted_heads or wanted_heads[r.form]) then
if not by_head[r.form] then
by_head[r.form] = {groups = {}, order = {}}
table.insert(heads, r.form)
end
local h = by_head[r.form]
local key = table.concat(r.labels, "|")
if not h.groups[key] then
h.groups[key] = {labels = r.labels, tag_sets = {}, seen = {}}
table.insert(h.order, r.labels[1] and #h.order + 1 or 1, key)
end
local tags = table.concat(r.tags, "|")
if not h.groups[key].seen[tags] then
h.groups[key].seen[tags] = true
table.insert(h.groups[key].tag_sets, {tags = r.tags})
end
end
end
for _, head in ipairs(heads) do
if not seen_head[head] then
seen_head[head] = true
local linked = wanted_heads and wanted_heads[head]
table.insert(data.heads, {term = type(linked) == "string" and linked or head})
end
for _, key in ipairs(by_head[head].order) do
local group = by_head[head].groups[key]
local line = require("Module:form of").tagged_inflections {
lang = lang,
tag_sets = require("Module:accel").combine_tag_sets_into_multipart(group.tag_sets, lang, spec.singular),
lemmas = {{lang = lang, term = term, alt = lemma_form, gloss = args.t}},
lemma_face = "term",
}
if group.labels[1] then
line = require("Module:labels").show_labels {labels = group.labels, lang = lang} .. " " .. line
end
table.insert(lines, line)
end
end
end
if not lines[1] then
local named = {}
for _, lemma_spec in ipairs(mw.text.split(args[2], "%s*,%s*")) do
local term, id = mw.ustring.match(lemma_spec, "^(.-)<id:([^>]*)>$")
table.insert(named, "[[" .. (term or lemma_spec) .. "]]" .. (id and (" (table id=" .. id .. ")") or ""))
end
error("lt-head: '" .. pagename .. "' is not a form of " .. table.concat(named, " or ")
.. (args.head and (" with the accent " .. args.head) or ""))
end
return full_headword(data) .. "\n\n# " .. table.concat(lines, "\n# ")
end
return export
mv5hs62aell8vghfqgz0ke8uk750bwo
livro
0
422455
2576490
2026-11-09T09:55:08Z
Hiyuune
50834
Trang mới: “{{also|livro-}} =={{langname|gl}}== ==={{section|n}}=== {{gl-reinteg-noun|m}} # {{gl-reinteg sp|libro}} ==={{section|further}}=== * {{R:gl:Estraviz}}”
2576490
wikitext
text/x-wiki
{{also|livro-}}
=={{langname|gl}}==
==={{section|n}}===
{{gl-reinteg-noun|m}}
# {{gl-reinteg sp|libro}}
==={{section|further}}===
* {{R:gl:Estraviz}}
9faazf5ymx6xfab25kzxglimc5cdp7n
2576491
2576490
2026-11-09T09:58:22Z
Hiyuune
50834
2576491
wikitext
text/x-wiki
{{also|livro-}}
=={{langname|pt}}==
{{wp|pt:}}
[[File:Gutenberg Bible (Pelplin copy) 05.jpg|thumb|250px]]
==={{section|pron}}===
{{pt-IPA}}
* {{IPA|pt|[ˈli.vɾʷ]|a=ngôi làng ở miền Trung Brasil}}
* {{audio|pt|pt-br-livro.ogg|a=Brasil}}
* {{audio|pt|LL-Q5146 (por)-Santamarcanda-livro.wav|a=Porto}}
* {{rhymes|pt|ivɾu|s=2}}
* {{hyph|pt|li|vro}}
==={{section|etym}} 1===
Từ {{inh|pt|roa-opt|livro}}, và trước đó vay mượn từ {{der|pt|la|liber|librum}}. Cùng gốc với {{cog|gl,es,it|libro}}, {{cog|ca|llibre}}, {{cog|oc|libre}} và {{cog|fr|livre}}.
===={{section|n}}====
{{pt-noun|m|dim=livrinho|aug=livrão}}
# [[sách]].
# {{lb|pt|zoology}} [[dạ]] lá sách, dạ [[múi]] [[khế]] hay [[sách]] [[bò]].
#: {{syn|pt|folhoso}}
====={{section|drv}}=====
{{col|pt
|livrão
|livraria
|livreco
|livreiro
|livrete
|livrinho
|livro branco
|livro de bolso
|livro de bordo
|livro de cheques
|livro de frases
|livro de fumos
|livro de honra
|livro de horas
|Livro de Mórmon
|livro de ouro
|livro de ponto
|livro de reclamações
|livro didático
|livro digital
|livro eletrônico
|livro-texto
|marca-livro
|ser um livro aberto
}}
====={{section|rel}}=====
{{col|pt|líber|livreto}}
====={{section|desc}}=====
* {{desc|kea|libru}}
* {{desc|mzs|livro}}
* {{desc|tet|livru|bor=1}}
==={{section|etym}} 2===
{{nonlemma}}
===={{section|v}}====
{{head|pt|vf}}
# {{pt-verb form of|livrar}}
==={{section|further}}===
* {{R:pt:Aulete}}
* {{R:pt:Infopédia}}
* {{R:pt:Priberam}}
=={{langname|gl}}==
==={{section|n}}===
{{gl-reinteg-noun|m}}
# {{gl-reinteg sp|libro}}
==={{section|further}}===
* {{R:gl:Estraviz}}
cmtj8fp0c36ku45zdo7dt89sumhxj86
Mô đun:lt-verb
828
422456
2576492
2026-11-09T10:01:27Z
Hiyuune
50834
nhập module từ enwikt, tác giả User:TongcyDai
2576492
Scribunto
text/plain
--[=[
Tác giả: <TongcyDai>
Mô đun chia động từ tiếng Litva
Generates conjugation tables for Lithuanian verbs from three principal parts:
infinitive, present 3rd person, past 3rd person.
Stems are kept in two tracks:
stem_ac – partial NFD: grave, acute and tilde are combining characters;
all other Lithuanian diacritics (ogonek, macron, caron, dot
above) are precomposed. Used for accent operations.
stem_bare – stem_ac without accent marks. Used for structural analysis:
suffix detection, palatalization, character positions.
Every function that modifies a stem returns both tracks, as (bare, ac).
Endings are NFC {naked, accented_or_nil} pairs; an accented ending carries
a grave on a short vowel and a tilde (circumflex) on a diphthong or long
vowel.
]=]
local export = {}
local m_string_utilities = require("Module:string utilities")
local iut = require("Module:inflection utilities")
local put = require("Module:parse utilities")
local lang = require("Module:languages").getByCode("lt")
local m_common = require("Module:lt-common")
local lt_pron = require("Module:lt-pron")
local rfind = mw.ustring.find
local rsub = mw.ustring.gsub
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local rlen = mw.ustring.len
local toNFC = mw.ustring.toNFC
local trim = m_string_utilities.trim
local concat = table.concat
local insert = table.insert
-- =============================================================================
-- Unicode constants
-- =============================================================================
local GRAVE = m_common.GRAVE -- U+0300
local ACUTE = m_common.ACUTE -- U+0301
local TILDE = m_common.TILDE -- U+0303
local MACRON = m_common.MACRON -- U+0304
local DOT_AB = m_common.DOTABOVE -- U+0307
local CARON = m_common.CARON -- U+030C
local OGONEK = m_common.OGONEK -- U+0328
local ANY_AC = m_common.ANY_ACCENT
-- Syllable separator emitted by lt-pron.hyphenate (U+2027 HYPHENATION POINT).
local HYPHEN_POINT = "‧"
-- =============================================================================
-- Output helper
-- =============================================================================
-- Convert an internal partial-NFD string to display-ready NFC, correctly
-- inserting dotabove between i/j and a following accent mark.
local function display(text)
return m_common.makeDisplayText(toNFC(text), lang, nil)
end
-- =============================================================================
-- Module-generated footnotes
-- =============================================================================
-- Footnotes added by the module, bracketed like user footnotes
-- (iut.show_forms gives identical texts one number). COLLOQ_NOTE: every
-- ending flagged `colloq = true` in the E.* tables and the matching
-- IRREGULAR_FORMS variants. IMPERS_NEUTER_NOTE: the neuter participles of
-- impersonal verbs and the passive neuters in -si of the -tis reflexives.
local COLLOQ_NOTE = "[colloquial short form]"
local IMPERS_NEUTER_NOTE = "[indeclinable neuter form used impersonally]"
-- =============================================================================
-- Input pipeline
-- =============================================================================
local to_stem_ac = m_common.to_stem_ac
local process_input = m_common.process_input
-- =============================================================================
-- Palatalization helpers (d -> dž, t -> č before i + back vowel)
-- =============================================================================
-- An ending palatalizes when it starts with i followed by a back vowel
-- (endings are NFC, so the class lists the precomposed letters too).
local function should_palatalize(ending)
return rfind(ending, "^i[aąouųū]") ~= nil
end
-- Returns (bare, ac) with a final d/t palatalized. A stem-final consonant
-- carries no accent mark, so both tracks end in the same character.
local function palatalize_stem(stem_bare, stem_ac)
local last = mw.ustring.sub(stem_bare, -1)
if last == "d" then
return mw.ustring.sub(stem_bare, 1, -2) .. "dž",
mw.ustring.sub(stem_ac, 1, -2) .. "dž"
elseif last == "t" then
return mw.ustring.sub(stem_bare, 1, -2) .. "č",
mw.ustring.sub(stem_ac, 1, -2) .. "č"
end
return stem_bare, stem_ac
end
-- Restore a final č → t, dž → d. Used for the 2sg of Class I -ia verbs: the
-- ending -i does not palatalize, but the present stem comes from the
-- palatalized present 3rd person (ver̃čia → ver̃č).
local function unpalatalize_stem(stem_bare, stem_ac)
if rlen(stem_bare) >= 2 and mw.ustring.sub(stem_bare, -2) == "dž" then
return mw.ustring.sub(stem_bare, 1, -3) .. "d",
mw.ustring.sub(stem_ac, 1, -3) .. "d"
end
if mw.ustring.sub(stem_bare, -1) == "č" then
return mw.ustring.sub(stem_bare, 1, -2) .. "t",
mw.ustring.sub(stem_ac, 1, -2) .. "t"
end
return stem_bare, stem_ac
end
-- =============================================================================
-- Form assembly
-- =============================================================================
-- Build one surface form from a two-track stem and a {naked, accented} pair.
-- is_end_stressed = true -> E-stress: drop stem accents, append accented ending.
-- is_end_stressed = false -> S-stress: keep stem accents, append naked ending.
-- When accent_e is nil the function always falls back to S-stress regardless of
-- is_end_stressed, so slots with no accented variant are handled safely.
local function combine(stem_bare, stem_ac, naked_e, accent_e, is_end_stressed)
if should_palatalize(naked_e) then
stem_bare, stem_ac = palatalize_stem(stem_bare, stem_ac)
end
if is_end_stressed and accent_e then
return display(stem_bare .. accent_e)
else
return display(stem_ac .. naked_e)
end
end
-- Convenience wrapper: always S-stressed (stem/infinitive accent preserved).
local function combine_S(stem_bare, stem_ac, naked_e)
return combine(stem_bare, stem_ac, naked_e, nil, false)
end
-- =============================================================================
-- Syllable quantity helper (operates on stem_ac representation)
-- =============================================================================
local LONG_V = {
["ą"]=true, ["ę"]=true, ["ė"]=true, ["į"]=true,
["ų"]=true, ["ū"]=true, ["y"]=true,
}
local SHORT_V = {
["a"]=true, ["e"]=true, ["i"]=true, ["u"]=true, ["o"]=true,
}
local ALL_V = {}
do
for k in pairs(LONG_V) do ALL_V[k] = true end
for k in pairs(SHORT_V) do ALL_V[k] = true end
end
-- True iff the syllable (stem_ac) contains exactly one vowel and it is a
-- plain short a/e/i/u/o; accent marks are not counted.
local function is_short_syllable_ac(syl)
local vowel_count = 0
for i = 1, rlen(syl) do
local ch = mw.ustring.sub(syl, i, i)
if LONG_V[ch] then return false end
if SHORT_V[ch] then vowel_count = vowel_count + 1 end
end
return vowel_count == 1
end
-- i and u have no acute sign of their own: the acute of a diphthong whose
-- first component is i or u (il, im, in, ir, ul, um, un, ur, ui) is written
-- as a grave on that component (dìrbti, jùngia, mùisto). Such a grave marks
-- a long, acute syllable, not a short vowel. In the mixed diphthongs it is
-- told apart from a short i/u by the resonant that closes the syllable
-- (dìr-ba, jùn-gia, but short kì-lo, kù-lia). Works on stem_ac text, a whole
-- form or a single syllable; a display dot above is ignored. `mixed_only`
-- leaves out ùi, whose acute does not hold the stress in the present and
-- past 1sg/2sg (muistaũ, muisčiaũ).
local function grave_marks_acute(ac, mixed_only)
ac = rsub(ac, DOT_AB, "")
return rfind(ac, "[iu]" .. GRAVE .. "[lmnr]$") ~= nil
or rfind(ac, "[iu]" .. GRAVE .. "[lmnr][^aeiouąęėįųūy]") ~= nil
or (not mixed_only and rfind(ac, "u" .. GRAVE .. "i") ~= nil)
end
-- =============================================================================
-- Accent paradigm detection
-- =============================================================================
-- Whether a tense has fixed (Pastovaus kirčio) or mobile (Kilnojamojo kirčio)
-- stress, from that tense's 3rd-person form (stem_ac). The paradigm is a
-- property of each tense, so the present and the past are tested separately.
--
-- Rules for un-prefixed verbs:
-- mobile – penultimate syllable has a circumflex (tilde) or is short
-- fixed – penultimate syllable has an acute (or the grave that writes the
-- acute of an i/u diphthong, dìrba), or
-- the accent falls on a non-penultimate (preceding) syllable
--
-- Syllables come from lt-pron.hyphenate.
local function detect_accent_paradigm(pres3_ac)
-- false: this is a stem fragment, not the page's headword; skip respelling detection.
local ok, result = pcall(lt_pron.hyphenate, toNFC(pres3_ac), false)
if not ok then
return "fixed" -- safe fallback if hyphenation fails
end
-- lt-pron.hyphenate returns either a table of syllables or one string
-- with the syllables joined by HYPHEN_POINT.
local syls
if type(result) == "table" then
syls = result
elseif type(result) == "string" then
syls = rsplit(result, HYPHEN_POINT, true)
else
return "fixed"
end
if #syls < 2 then
return "fixed" -- monosyllabic verb: treat as fixed
end
-- Convert the penultimate syllable to stem_ac so TILDE/ACUTE/GRAVE are
-- decomposed and individually detectable.
local penult_ac = to_stem_ac(syls[#syls - 1])
local has_tilde = rfind(penult_ac, TILDE) ~= nil
local has_acute = rfind(penult_ac, ACUTE) ~= nil
local has_grave = rfind(penult_ac, GRAVE) ~= nil
if has_tilde then
-- Circumflex on the penult: mobile.
return "mobile"
elseif has_acute then
-- Acute on the penult: fixed.
return "fixed"
elseif has_grave then
-- On the i/u of a mixed diphthong the grave writes the acute
-- (dìr-ba, jùn-gia) -> fixed. Otherwise (a short syllable, e.g.
-- vaišìna, or ùi: mùis-to) -> mobile.
if grave_marks_acute(penult_ac, true) then
return "fixed"
end
return "mobile"
elseif rfind(pres3_ac, ANY_AC) then
-- An accent exists in the word but not on the penult, so it must be on
-- a preceding syllable (e.g. džiùgina) -> fixed.
return "fixed"
elseif is_short_syllable_ac(penult_ac) then
-- No accent mark anywhere; short penult -> mobile (unusual input).
return "mobile"
else
return "fixed" -- default for long unaccented penult
end
end
-- =============================================================================
-- Static ending tables
-- =============================================================================
-- Each slot is a list of {naked_ending, accented_ending_or_nil} pairs.
-- naked_ending – appended to stem_ac for S-stressed forms.
-- accented_ending – appended to stem_bare for E-stressed forms, or nil when
-- the slot never takes ending stress.
-- Several pairs in a slot are variants, main form first. A pair flagged
-- `colloq = true` (the plural short forms without the final -e: indicative
-- -am/-at etc., subjunctive -tumėt) gets COLLOQ_NOTE from forms_for_slot;
-- the imperative -kim/-kit and the other subjunctive variants (-tumėm,
-- -tumei, -tumėme, -tute) are standard.
--
-- In the mobile paradigm only s1 and s2 are E-stressed.
--
-- Accented endings:
-- short vowel u -> grave: ù (U+00F9)
-- short vowel i -> grave: ì (U+00EC)
-- diphthong au -> tilde on u: aũ (a + ũ U+0169)
-- diphthong ai -> tilde on i: aĩ (a + ĩ U+0129) [display() adds dotabove to i]
-- diphthong iau -> tilde on u: iaũ
-- diphthong ei -> tilde on i: eĩ [display() adds dotabove to i]
local E = {}
-- Present tense – Class I -a (e.g. neš/a)
E.pres_I_a = {
s1 = { {"u", "ù"} },
s2 = { {"i", "ì"} },
s3 = { {"a", nil} },
p1 = { {"ame", nil}, {"am", nil, colloq = true} },
p2 = { {"ate", nil}, {"at", nil, colloq = true} },
}
-- Present tense – Class I -ia (e.g. dirb/ia)
E.pres_I_ia = {
s1 = { {"iu", "iù"} },
s2 = { {"i", "ì"} },
s3 = { {"ia", nil} },
p1 = { {"iame", nil}, {"iam", nil, colloq = true} },
p2 = { {"iate", nil}, {"iat", nil, colloq = true} },
}
-- Present tense – Class II -i (e.g. myl/i)
E.pres_II = {
s1 = { {"iu", "iù"} },
s2 = { {"i", "ì"} },
s3 = { {"i", nil} },
p1 = { {"ime", nil}, {"im", nil, colloq = true} },
p2 = { {"ite", nil}, {"it", nil, colloq = true} },
}
-- Present tense – Class III -o (e.g. važiav/o)
E.pres_III_o = {
s1 = { {"au", "aũ"} },
s2 = { {"ai", "aĩ"} },
s3 = { {"o", nil} },
p1 = { {"ome", nil}, {"om", nil, colloq = true} },
p2 = { {"ote", nil}, {"ot", nil, colloq = true} },
}
-- Past simple – o-stem (also used for -ėjo mixed verbs; see has_ejo_past flag)
E.past_o = {
s1 = { {"au", "aũ"} },
s2 = { {"ai", "aĩ"} },
s3 = { {"o", nil} },
p1 = { {"ome", nil}, {"om", nil, colloq = true} },
p2 = { {"ote", nil}, {"ot", nil, colloq = true} },
}
-- Past simple – ė-stem (e.g. nešė)
E.past_e = {
s1 = { {"iau", "iaũ"} },
s2 = { {"ei", "eĩ"} },
s3 = { {"ė", nil} },
p1 = { {"ėme", nil}, {"ėm", nil, colloq = true} },
p2 = { {"ėte", nil}, {"ėt", nil, colloq = true} },
}
-- Past frequentative (all S-stressed; infinitive accent always preserved).
-- Generator prepends the -dav- infix to the infinitive stem before use.
E.past_freq = {
s1 = { {"au", nil} },
s2 = { {"ai", nil} },
s3 = { {"o", nil} },
p1 = { {"ome", nil}, {"om", nil, colloq = true} },
p2 = { {"ote", nil}, {"ot", nil, colloq = true} },
}
-- Subjunctive mood (all S-stressed; the infinitive accent is always
-- preserved, in every variant). The main forms come first in each cell and
-- the less usual variants after them: 2sg -tum, -tumei; 1pl -tume, -tumėm,
-- -tumėme; 2pl -tumėte, -tumėt, -tute. -tumėt is the colloquial short form
-- of -tumėte, like the indicative plurals in -at, -ot.
E.subj = {
s1 = { {"čiau", nil} },
s2 = { {"tum", nil}, {"tumei", nil} },
s3 = { {"tų", nil} },
p1 = { {"tume", nil}, {"tumėm", nil}, {"tumėme", nil} },
p2 = { {"tumėte", nil}, {"tumėt", nil, colloq = true}, {"tute", nil} },
}
-- Imperative mood (all S-stressed; infinitive accent always preserved).
-- 1st sg has no imperative; 3rd person is built separately (te + pres_3).
E.imp = {
s2 = { {"k", nil}, {"ki", nil} },
p1 = { {"kime", nil}, {"kim", nil} },
p2 = { {"kite", nil}, {"kit", nil} },
}
-- -----------------------------------------------------------------------------
-- Reflexive (-tis) ending sets
--
-- Mobile-stress reflexive endings differ in tone from the non-reflexive set:
-- the present s1/s2 diphthongs uo/ie are ACUTE (prausiúosi, prausíesi), the
-- past ones circumflex (prausiaũsi, prausei̇̃si). Every form that ends in
-- the particle -si also has a colloquial short form in -s, with the same
-- stress and tone (prausiúos, prausiaũs, praũsiasi / praũsias, praũstųs);
-- the plural -mės, -tės and the future 3rd person -is have no -si to drop.
-- -----------------------------------------------------------------------------
-- Present tense – Class I -a reflexive (e.g. renk/asi)
E.pres_I_a_refl = {
s1 = { {"uosi", "úosi"}, {"uos", "úos", colloq = true} },
s2 = { {"iesi", "íesi"}, {"ies", "íes", colloq = true} },
s3 = { {"asi", nil}, {"as", nil, colloq = true} },
p1 = { {"amės", nil} },
p2 = { {"atės", nil} },
}
-- Present tense – Class I -ia reflexive (e.g. praus/iasi)
E.pres_I_ia_refl = {
s1 = { {"iuosi", "iúosi"}, {"iuos", "iúos", colloq = true} },
s2 = { {"iesi", "íesi"}, {"ies", "íes", colloq = true} },
s3 = { {"iasi", nil}, {"ias", nil, colloq = true} },
p1 = { {"iamės", nil} },
p2 = { {"iatės", nil} },
}
-- Present tense – Class II -i reflexive (e.g. tik/isi)
E.pres_II_refl = {
s1 = { {"iuosi", "iúosi"}, {"iuos", "iúos", colloq = true} },
s2 = { {"iesi", "íesi"}, {"ies", "íes", colloq = true} },
s3 = { {"isi", nil}, {"is", nil, colloq = true} },
p1 = { {"imės", nil} },
p2 = { {"itės", nil} },
}
-- Present tense – Class III -o reflexive (e.g. mok/osi)
E.pres_III_o_refl = {
s1 = { {"ausi", "aũsi"}, {"aus", "aũs", colloq = true} },
s2 = { {"aisi", "aĩsi"}, {"ais", "aĩs", colloq = true} },
s3 = { {"osi", nil}, {"os", nil, colloq = true} },
p1 = { {"omės", nil} },
p2 = { {"otės", nil} },
}
-- Past simple – o-stem reflexive
E.past_o_refl = {
s1 = { {"ausi", "aũsi"}, {"aus", "aũs", colloq = true} },
s2 = { {"aisi", "aĩsi"}, {"ais", "aĩs", colloq = true} },
s3 = { {"osi", nil}, {"os", nil, colloq = true} },
p1 = { {"omės", nil} },
p2 = { {"otės", nil} },
}
-- Past simple – ė-stem reflexive (e.g. praus/ėsi)
E.past_e_refl = {
s1 = { {"iausi", "iaũsi"}, {"iaus", "iaũs", colloq = true} },
s2 = { {"eisi", "eĩsi"}, {"eis", "eĩs", colloq = true} },
s3 = { {"ėsi", nil}, {"ės", nil, colloq = true} },
p1 = { {"ėmės", nil} },
p2 = { {"ėtės", nil} },
}
-- Past frequentative reflexive (all S-stressed; used on the -dav- stem).
E.past_freq_refl = {
s1 = { {"ausi", nil}, {"aus", nil, colloq = true} },
s2 = { {"aisi", nil}, {"ais", nil, colloq = true} },
s3 = { {"osi", nil}, {"os", nil, colloq = true} },
p1 = { {"omės", nil} },
p2 = { {"otės", nil} },
}
-- Subjunctive reflexive (all S-stressed with the infinitive accent): 2sg
-- -tumeisi, 1pl -tumės/-tumėmės (the shorter form is the main one), 2pl only
-- -tumėtės; the singular and the 3rd person add their short forms in -s.
E.subj_refl = {
s1 = { {"čiausi", nil}, {"čiaus", nil, colloq = true} },
s2 = { {"tumeisi", nil}, {"tumeis", nil, colloq = true} },
s3 = { {"tųsi", nil}, {"tųs", nil, colloq = true} },
p1 = { {"tumės", nil}, {"tumėmės", nil} },
p2 = { {"tumėtės", nil} },
}
-- Imperative reflexive (all S-stressed; 3rd person built separately:
-- te + si + present stem).
E.imp_refl = {
s2 = { {"kis", nil} },
p1 = { {"kimės", nil} },
p2 = { {"kitės", nil} },
}
-- =============================================================================
-- Conjugation class and past stem type detection
-- =============================================================================
-- Present conjugation class (I, II, III) and subtype from the bare present
-- 3rd person; -ia is tested before -a. n-infix and -ina presents (pjáuna,
-- tiñka, ramìna) are ordinary Class I -a: only the final -a is an ending, and
-- the n(a) stays in every present-stem form (pjáunąs, pjáunamas, pjáunant,
-- raminą̃s).
local function detect_conj_class(pres_bare)
if rmatch(pres_bare, "ia$") then return "I", "ia"
elseif rmatch(pres_bare, "a$") then return "I", "a"
elseif rmatch(pres_bare, "i$") then return "II", "i"
elseif rmatch(pres_bare, "o$") then return "III", "o"
end
error("lt-conj: cannot detect conjugation class from present 3rd \""
.. pres_bare .. "\". Expected ending: -a/-ia (I), -i (II), -o (III)")
end
-- Past stem type (o-stem or ė-stem) from the bare past 3rd person, in which
-- ė is a single codepoint.
local function detect_past_stem_type(past_bare)
if rmatch(past_bare, "ėjo$") then return "ė" end
if rmatch(past_bare, "ė$") then return "ė" end
if rmatch(past_bare, "o$") then return "o" end
error("lt-conj: cannot detect past stem type from past 3rd \""
.. past_bare .. "\". Expected ending: -o (o-stem) or -ė/-ėjo (ė-stem)")
end
-- =============================================================================
-- Stem extraction
-- =============================================================================
-- Remove the last suffix_len characters from both tracks. On stem_ac the cut
-- is found by counting base characters, since an accented vowel takes two
-- codepoints there (yrà loses the whole à, not just its accent).
local function strip_suffix(stem_bare, stem_ac, suffix_len)
local bare_result = mw.ustring.sub(stem_bare, 1, -(suffix_len + 1))
local target = rlen(bare_result)
if target == 0 then return "", "" end
-- Walk through stem_ac until `target` base characters are covered.
local base_count, pos = 0, 0
local total = rlen(stem_ac)
while pos < total and base_count < target do
pos = pos + 1
local ch = mw.ustring.sub(stem_ac, pos, pos)
if ch ~= GRAVE and ch ~= ACUTE and ch ~= TILDE then
base_count = base_count + 1
end
end
-- Absorb any combining accents that belong to the last base character.
while pos < total do
local nxt = mw.ustring.sub(stem_ac, pos + 1, pos + 1)
if nxt == GRAVE or nxt == ACUTE or nxt == TILDE then
pos = pos + 1
else
break
end
end
return bare_result, mw.ustring.sub(stem_ac, 1, pos)
end
-- Extract the infinitive stem by removing -ti or -tis.
-- Returns (bare, ac, is_reflexive).
local function extract_infinitive_stem(inf_bare, inf_ac)
if rmatch(inf_bare, "tis$") then
local b, a = strip_suffix(inf_bare, inf_ac, 3)
return b, a, true
elseif rmatch(inf_bare, "ti$") then
local b, a = strip_suffix(inf_bare, inf_ac, 2)
return b, a, false
end
error("lt-conj: infinitive \"" .. toNFC(inf_ac)
.. "\" does not end in -ti or -tis")
end
-- Extract the present stem by removing the conjugation ending.
-- Returns (bare, ac).
local function extract_present_stem(pres_bare, pres_ac, conj_class, conj_subtype)
-- Only the final vowel (or -ia) is an ending; everything else, including
-- an n-infix or -in-, stays in the stem.
local len = (conj_class == "I" and conj_subtype == "ia") and 2 or 1
return strip_suffix(pres_bare, pres_ac, len)
end
-- Extract the past stem by removing the past-tense ending.
-- Every past type loses exactly one final vowel: o-stem vil̃ko -> vil̃k-,
-- ė-stem nẽšė -> nẽš-, and -ėjo mixed pasts girdė́jo -> girdė́j- (which then
-- take the o-stem personal endings via has_ejo_past: girdė́jau, girdė́jęs,
-- girdė́jus). Returns (bare, ac).
local function extract_past_stem(past_bare, past_ac, past_stem_type)
return strip_suffix(past_bare, past_ac, 1)
end
-- =============================================================================
-- Future tense helpers
-- =============================================================================
-- Future stem: infinitive stem + formant -s-, with s/z + s -> s and
-- š/ž + s -> š. The result ends in the formant: person endings and
-- participle suffixes attach to it directly, and the bare 3rd person is the
-- stem itself (nèšti -> nèš, grį̃žti -> grį̃š, vèsti -> vès). Returns (bare, ac).
local function make_future_stem(stem_bare, stem_ac)
local last = mw.ustring.sub(stem_bare, -1)
if last == "s" or last == "z" then
-- Stem-final s/z fuses with the formant: one s remains.
return mw.ustring.sub(stem_bare, 1, -2) .. "s",
mw.ustring.sub(stem_ac, 1, -2) .. "s"
elseif last == "š" or last == "ž" then
-- Stem-final š/ž absorbs the formant: š remains, no s is added.
return mw.ustring.sub(stem_bare, 1, -2) .. "š",
mw.ustring.sub(stem_ac, 1, -2) .. "š"
end
return stem_bare .. "s", stem_ac .. "s"
end
-- Future 3rd-person shortening y -> i, ū -> u. The vowel becomes short and
-- takes a grave (ryti -> ri̇̀s, bū́ti -> bùs, lýti -> li̇̀s); the circumflex
-- metatonija does not apply to a shortened stem. Returns (bare, ac).
local function shorten_future_vowel(stem_bare, stem_ac)
local last = mw.ustring.sub(stem_bare, -1)
-- On the ac track the vowel may carry a combining accent (lý), so the
-- vowel and its accent are replaced together.
if last == "y" then
return mw.ustring.sub(stem_bare, 1, -2) .. "i",
rsub(stem_ac, "y" .. ANY_AC .. "?$", "i" .. GRAVE)
elseif last == "ū" then
return mw.ustring.sub(stem_bare, 1, -2) .. "u",
rsub(stem_ac, "ū" .. ANY_AC .. "?$", "u" .. GRAVE)
end
return stem_bare, stem_ac
end
-- Determine whether the future 3rd person requires vowel shortening.
-- Rules (all must be true):
-- 1. The verb is not reflexive: the affix blocks the shortening, and the
-- metatonija below applies instead (gýti -> gìs but gýtis -> gỹsis)
-- 2. The infinitive stem ends in -y or -ū
-- 3. The core infinitive stem (prefix-stripped, -ti/-tis removed) is monosyllabic
-- 4. The stem is not in the exclusion list {vy-, siū-} (ryti -> ris,
-- griūti -> grius, but vyti -> vys, siūti -> siūs)
local function should_shorten_future_3(stem_bare, inf_core_bare, is_reflexive)
-- Condition 1: reflexives keep the long vowel
if is_reflexive then
return false
end
-- Condition 2: infinitive stem ends in y/ū
local last = mw.ustring.sub(stem_bare, -1)
if last ~= "y" and last ~= "ū" then
return false
end
-- Condition 3: core infinitive stem (without -ti) is monosyllabic
local stem = rmatch(inf_core_bare, "^(.+)tis?$")
if not stem then return false end
-- false: stem fragment, not the page's headword; skip respelling detection.
local syls = lt_pron.get_syllables(toNFC(stem), false)
if not syls or #syls ~= 1 then
return false
end
-- Condition 4: not in exclusion list
if stem == "vy" or stem == "siū" then
return false
end
return true
end
-- =============================================================================
-- Parameter parsing
-- =============================================================================
-- -----------------------------------------------------------------------------
-- Prefix marker parsing
--
-- Prefixed verbs are entered with one `-` marker between the prefix/particle
-- chain and the root: at-nèšti, pér-traukti, nebepa-kliū́ti. In a prefixed
-- REFLEXIVE the internal reflexive affix ends the chain (nusi-praũsti); the
-- marker is what distinguishes it from a same-spelled plain verb
-- (nu-sir̃gti = nu + sirgti). Only the infinitive carries markers; the same
-- chain is stripped from present_3/past_3 automatically, tolerating a
-- retracted accent on the prefix or affix (àtneša, nusìneša) and the
-- always-stressed pér- (pérneša). A literal hyphen belonging to the word
-- itself can be escaped as `\-`.
-- -----------------------------------------------------------------------------
-- Closed inventory of verbal prefixes and preverbal particles. Longer
-- entries precede their own prefixes (nebe- before ne-/be-, api-/ati-
-- before ap-/at-, par- before pa-) so that greedy matching with
-- backtracking finds the canonical decomposition.
local PREFIX_ELEMENTS = {
"nebe", "tebe", "ne", "be", "te",
"api", "ati", "par", "per", "pra", "pri", "pa",
"ap", "at", "į", "iš", "nu", "su", "už",
}
-- Decompose a bare (accent-stripped) prefix chain into closed-inventory
-- elements. Returns an array of elements, or nil when the chain is not a
-- valid prefix/particle sequence.
local function decompose_chain(chain_bare)
if chain_bare == "" then return {} end
for _, p in ipairs(PREFIX_ELEMENTS) do
local plen = rlen(p)
if mw.ustring.sub(chain_bare, 1, plen) == p then
local rest = decompose_chain(mw.ustring.sub(chain_bare, plen + 1))
if rest then
insert(rest, 1, p)
return rest
end
end
end
return nil
end
-- Split the raw infinitive at its unescaped `-` marker. Returns
-- (display, chain_raw, core_raw): the marker-free infinitive, the
-- pre-root segment ("" when unprefixed), and the root segment.
local ESCAPED_HYPHEN = "\1"
local function parse_infinitive_markers(raw)
local s = raw:gsub("\\%-", ESCAPED_HYPHEN)
local segments = rsplit(s, "%-")
for i, seg in ipairs(segments) do
segments[i] = seg:gsub(ESCAPED_HYPHEN, "-")
end
if #segments == 1 then
return segments[1], "", segments[1]
end
if #segments > 2 then
error("lt-conj: \"" .. raw .. "\" has more than one \"-\"; the infinitive "
.. "takes one, before the root, with every prefix and the reflexive "
.. "affix in front of it (nusi-praũsti, nebepa-kliū́ti)")
end
local core = segments[2]
local chain = segments[1]
if chain == "" or core == "" then
error("lt-conj: malformed prefix marker in \"" .. raw
.. "\": empty segment next to \"-\"")
end
return chain .. core, chain, core
end
-- Classify the (first) accent mark carried by a stem_ac fragment.
local function accent_type_in(ac_fragment)
if rfind(ac_fragment, ACUTE) then return "acute" end
if rfind(ac_fragment, GRAVE) then return "grave" end
if rfind(ac_fragment, TILDE) then return "tilde" end
return nil
end
-- Remove the first n base characters (the prefix chain, with an internal
-- -si-) from a principal part. The removed part may carry an accent
-- (àtneša, nusìneša, pérneša), so the ac-track cut is found by counting base
-- characters, as in strip_suffix. Returns (core_bare, core_ac,
-- removed_accent_type).
local function strip_prefix_left(bare, ac, n)
local core_bare = mw.ustring.sub(bare, n + 1)
local base_count, pos = 0, 0
local total = rlen(ac)
while pos < total and base_count < n do
pos = pos + 1
local ch = mw.ustring.sub(ac, pos, pos)
if ch ~= GRAVE and ch ~= ACUTE and ch ~= TILDE then
base_count = base_count + 1
end
end
-- Absorb combining accents that belong to the last prefix character.
while pos < total do
local nxt = mw.ustring.sub(ac, pos + 1, pos + 1)
if nxt == GRAVE or nxt == ACUTE or nxt == TILDE then
pos = pos + 1
else
break
end
end
return core_bare, mw.ustring.sub(ac, pos + 1),
accent_type_in(mw.ustring.sub(ac, 1, pos))
end
-- Insert the retraction accent into an unaccented prefix chain: it lands on
-- the chain's LAST vowel — the syllable adjacent to the root, which is the
-- reflexive affix when present (nusì-: nusìpieštas) — as grave
-- (àt-, nù-, nebè-), or tilde on long į (į̃-: į̃kasamas).
local function accent_prefix_bare(prefix_bare)
for pos = rlen(prefix_bare), 1, -1 do
local ch = mw.ustring.sub(prefix_bare, pos, pos)
if ALL_V[ch] then
local mark = LONG_V[ch] and TILDE or GRAVE
return mw.ustring.sub(prefix_bare, 1, pos) .. mark
.. mw.ustring.sub(prefix_bare, pos + 1)
end
end
return prefix_bare
end
-- =============================================================================
-- Slot inventory
-- =============================================================================
-- Every slot with its accelerator tags, in iut.show_forms scan order. The
-- finite table and the participle box each have their own footnote block,
-- so the slots form two lists, rendered separately; numbering restarts in
-- the participle box. Within a list the order decides the numbering: the
-- indicative plural slots, which carry the colloquial variants, come first,
-- so that COLLOQ_NOTE takes the lowest number (only a whole-conjugation
-- footnote can precede it). The participle list is in table order.
-- Finite tags: no "ind"; the third person is "3|s//p" (one entry serves both
-- numbers), the past frequentative "freq|past", the subjunctive "sub".
-- Participle slots carry {{participle of}} tags, with "short"/"long" on the
-- active present and future pairs. transform_accel_obj in make_table sets
-- the accelerator pos, appends the "decl:" pseudo-tag (PART_DECL) and swaps
-- in IMPERS_NEUTER_TAGS.
local FINITE_SLOT_LIST = {
-- Colloquial-variant slots first (see COLLOQ_NOTE).
{"pres_1p", "1|p|pres"}, {"pres_2p", "2|p|pres"},
{"past_1p", "1|p|past"}, {"past_2p", "2|p|past"},
{"past_freq_1p", "1|p|freq|past"}, {"past_freq_2p", "2|p|freq|past"},
{"fut_1p", "1|p|fut"}, {"fut_2p", "2|p|fut"},
-- Remaining finite slots.
{"pres_1s", "1|s|pres"}, {"pres_2s", "2|s|pres"}, {"pres_3", "3|s//p|pres"},
{"past_1s", "1|s|past"}, {"past_2s", "2|s|past"}, {"past_3", "3|s//p|past"},
{"past_freq_1s", "1|s|freq|past"}, {"past_freq_2s", "2|s|freq|past"},
{"past_freq_3", "3|s//p|freq|past"},
{"fut_1s", "1|s|fut"}, {"fut_2s", "2|s|fut"}, {"fut_3", "3|s//p|fut"},
{"subj_1s", "1|s|sub"}, {"subj_2s", "2|s|sub"}, {"subj_3", "3|s//p|sub"},
{"subj_1p", "1|p|sub"}, {"subj_2p", "2|p|sub"},
{"imp_2s", "2|s|imp"}, {"imp_1p", "1|p|imp"}, {"imp_2p", "2|p|imp"},
{"imp_3", "3|s//p|imp"},
}
local PARTICIPLE_SLOT_LIST = {
-- Adjectival participles ({{participle of}} tags; long and short active
-- nominatives are distinguished with the standard short/long tags).
{"act_pres_short", "short|pres|act"}, {"act_pres_long", "long|pres|act"},
{"act_past", "past|act"}, {"act_past_freq", "freq|past|act"},
{"act_fut_short", "short|fut|act"}, {"act_fut_long", "long|fut|act"},
{"pass_pres", "pres|pass"}, {"pass_past", "past|pass"},
{"pass_fut", "fut|pass"}, {"pass_necess", "partnec"},
-- Adverbial forms (Module:form of/lang-data/lt native-term tags).
{"pusdalyvis", "adv|pusdalyvis"},
{"padalyvis_pres", "pres|adv|padalyvis"}, {"padalyvis_past", "past|adv|padalyvis"},
{"padalyvis_past_freq", "freq|past|adv|padalyvis"}, {"padalyvis_fut", "fut|adv|padalyvis"},
{"budinys_1", "adv|budinys"}, {"budinys_2", "adv|budinys"},
}
-- Membership set: participle slots get accel pos "participle", everything
-- else pos "verb" (see transform_accel_obj in make_table).
local PARTICIPLE_SLOT_SET = {}
for _, entry in ipairs(PARTICIPLE_SLOT_LIST) do
PARTICIPLE_SLOT_SET[entry[1]] = true
end
-- Declinable participle slots and how their {{lt-pdecl}} argument is made
-- (the "decl:" pseudo-tag, which Module:accel/lt turns into a Declension
-- section; "+" stands for the entry's own form):
-- * true — "+". act_past adds ".ius" for an -o-conjugation ė-stem past
-- (mãtęs → mãčiusio), as the past padalyvis takes -ius. The long
-- active present and future add ".snom:" with the readings of
-- their short slot (ACT_LONG_SHORT): lt-pdecl cannot derive that
-- accent, which depends on present_retracts.
-- * "AP" — passives: "+,AP", AP1 for a suffixed infinitive stem, AP3 for a
-- simple one, retracted prefixed forms included (àpskustas, "3b":
-- the AP3 stress map on the prefix-accented lemma gives them).
-- The short active nominatives are defective (nominative only) and have no
-- table of their own; they appear in the long form's table. Adverbial
-- slots and impersonal neuters are indeclinable. The adjectival slots of a
-- -tis reflexive pair an -is form (praũsiąsis) with a besi- form
-- (besipraũsiąs) and get their specs from compute_reflexive_decl_specs.
local PART_DECL = {
act_pres_long = true,
act_past = true,
act_past_freq = true,
act_fut_long = true,
pass_pres = "AP",
pass_past = "AP",
pass_fut = "AP",
pass_necess = "AP",
}
-- Long active present/future slot → its short-nominative slot, whose
-- reading(s) go into the long form's lt-pdecl spec as ".snom:".
local ACT_LONG_SHORT = {
act_pres_long = "act_pres_short",
act_fut_long = "act_fut_short",
}
-- Tags that replace those of a slot holding the indeclinable neuter (the
-- adjectival slots of impersonal verbs, lỹją, lỹjama; the passives of -tis
-- reflexives, praũsiamasi). No short/long: the neuter is the only form.
local IMPERS_NEUTER_TAGS = {
act_pres_short = "n|pres|act",
act_past = "n|past|act",
act_past_freq = "n|freq|past|act",
act_fut_short = "n|fut|act",
pass_pres = "n|pres|pass",
pass_past = "n|past|pass",
pass_fut = "n|fut|pass",
pass_necess = "n|partnec",
}
-- Combined inventory (override validation and anything slot-global).
local SLOT_LIST = {}
for _, entry in ipairs(FINITE_SLOT_LIST) do insert(SLOT_LIST, entry) end
for _, entry in ipairs(PARTICIPLE_SLOT_LIST) do insert(SLOT_LIST, entry) end
-- Slots the .SLOT:VALUE override syntax may target.
local OVERRIDE_SLOTS = {}
for _, entry in ipairs(SLOT_LIST) do
OVERRIDE_SLOTS[entry[1]] = true
end
-- =============================================================================
-- Template parameter parsing
-- =============================================================================
--
-- {{lt-conj|infinitive,present_3,past_3[.param1][.param2]...}}
--
-- Footnotes and variants (brackets isolated with
-- put.parse_balanced_segment_run, then m_common.fetch_specs/fetch_footnotes):
-- * Each principal part may carry [footnote]s and/or a colon-list of
-- variants (pū̃va:pū̃na). Every combination is conjugated and the
-- results are merged slot by slot. Infinitive footnotes become
-- headword-line qualifiers (the infinitive has no cell); present_3/past_3
-- footnotes go on the pres_3/past_3 cells.
-- * .SLOT:VALUE[note] — slot override (SLOT is a key of SLOT_LIST).
-- Values: "--" (no such form), "+" (keep the generated forms, e.g. to add
-- a footnote) or a full accented form. A colon-list is allowed, each
-- value with its own footnotes.
-- * .[note] — a lone bracket footnotes every form of the conjugation.
-- * .stem:VALUE and .impers are structural; a footnote on either is an
-- error.
-- * \, and \. escape a literal comma or dot; \- escapes a hyphen in the
-- infinitive.
-- Analyse one infinitive/present/past combination: strip prefix markers from
-- the infinitive and run all three principal parts through the full Unicode
-- input pipeline.
local function parse_one_combo(infinitive, present_3, past_3, params)
-- Prefix markers live only in the infinitive; strip and analyse them.
local inf_display, chain_raw, core_raw = parse_infinitive_markers(infinitive)
local has_prefix = chain_raw ~= ""
local has_si = false
local chain_bare, chain_ac = "", ""
if has_prefix then
chain_bare, chain_ac = process_input(chain_raw)
local decomp_target = chain_bare
if rmatch(chain_bare, "si$") then
-- No inventory element ends in -si, so a si-final chain always
-- marks the internal reflexive affix (nusi-praũsti).
has_si = true
decomp_target = mw.ustring.sub(chain_bare, 1, -3)
if decomp_target == "" then
error("lt-conj: the reflexive affix marker \"si-\" requires a prefix "
.. "in front of it (nusi-praũsti); a non-prefixed reflexive is "
.. "entered as a plain -tis infinitive (praũstis)")
end
end
if not decompose_chain(decomp_target) then
error("lt-conj: \"" .. toNFC(chain_ac) .. "-\" is not a recognizable "
.. "prefix/particle chain (combinations of ap(i)-, at(i)-, į-, iš-, "
.. "nu-, pa-, par-, per-, pra-, pri-, su-, už-, optionally preceded "
.. "by ne-/nebe-/be-/te-/tebe- and followed by -si-). If the hyphen "
.. "is part of the word itself, escape it as \"\\-\"")
end
end
-- Run all forms through the full input pipeline (markers already removed).
local inf_bare, inf_ac = process_input(inf_display)
local pres_bare, pres_ac = process_input(present_3)
local past_bare, past_ac = process_input(past_3)
-- Also process the core infinitive (without prefix/affix)
local inf_core_bare, inf_core_ac = process_input(core_raw)
return {
infinitive = inf_display,
present_3 = present_3,
past_3 = past_3,
inf_bare = inf_bare, inf_ac = inf_ac,
pres_bare = pres_bare, pres_ac = pres_ac,
past_bare = past_bare, past_ac = past_ac,
inf_core_bare = inf_core_bare,
inf_core_ac = inf_core_ac,
-- Prefix bookkeeping (chain includes the internal si when has_si).
has_prefix = has_prefix,
has_si = has_si,
prefix_bare = chain_bare,
prefix_ac = chain_ac,
inf_prefix_accent = accent_type_in(chain_ac),
params = params,
}
end
-- Parse the full template argument. Returns
-- { combos = {parsed, ...}, -- one per principal-part variant combination,
-- -- each carrying inf/pres/past_footnotes
-- params = {stem=, impers=, overrides=, whole_footnotes=}, -- shared
-- unescape = fn, parse_err = fn }
local function parse_params(args)
local input = args[1]
if not input then
error("lt-conj: missing required parameter. Usage: {{lt-conj|infinitive,present_3,past_3}}")
end
input = trim(input)
if input == "" then
error("lt-conj: missing required parameter. Usage: {{lt-conj|infinitive,present_3,past_3}}")
end
-- Protect escaped separators before any splitting; footnote-internal
-- commas/dots are protected structurally by the bracket isolation below.
local COMMA_PH, DOT_PH = "\2", "\3"
input = rsub(input, "\\,", COMMA_PH)
input = rsub(input, "\\%.", DOT_PH)
local function unescape(s)
if not s then return s end
return rsub(rsub(s, COMMA_PH, ","), DOT_PH, ".")
end
local function parse_err(msg)
error("lt-conj: " .. msg)
end
local segments = put.parse_balanced_segment_run(input, "[", "]")
local comma_groups = put.split_alternating_runs_and_strip_spaces(segments, ",")
if #comma_groups < 3 then
error("lt-conj: expected 3 principal parts (infinitive,present_3,past_3), got "
.. #comma_groups)
end
if #comma_groups > 3 then
error("lt-conj: expected 3 comma-separated principal parts, got "
.. #comma_groups .. " (escape a literal comma as \"\\,\")")
end
local inf_specs = m_common.fetch_specs(comma_groups[1], ":", "infinitive", nil, parse_err)
local pres_specs = m_common.fetch_specs(comma_groups[2], ":", "present 3rd person", nil, parse_err)
-- The third field carries the past_3 value plus dot-separated parameters.
local dot_groups = put.split_alternating_runs_and_strip_spaces(comma_groups[3], "%.")
local past_specs = m_common.fetch_specs(dot_groups[1], ":", "past 3rd person", nil, parse_err)
local params = { stem = nil, impers = false, overrides = nil, whole_footnotes = nil }
for i = 2, #dot_groups do
local group = dot_groups[i]
local part = group[1]
local has_footnote = #group > 1
if part == "" then
-- A bare bracket (nothing before it) footnotes the whole
-- conjugation.
if not has_footnote then
parse_err("blank parameter (empty dot-segment)")
end
params.whole_footnotes = iut.combine_footnotes(params.whole_footnotes,
m_common.fetch_footnotes(group, parse_err))
elseif rmatch(part, "^stem:") then
if has_footnote then
parse_err("footnotes not allowed on 'stem:' (structural override); "
.. "use a whole-conjugation footnote (a lone .[...]) instead")
end
-- Stored raw (unescaped); run through the pipeline in build_base_data.
params.stem = unescape(rmatch(part, "^stem:(.+)$"))
elseif part == "impers" then
if has_footnote then
parse_err("footnotes not allowed on 'impers' (structural switch); "
.. "use a whole-conjugation footnote (a lone .[...]) instead")
end
params.impers = true
else
local slot = rmatch(part, "^([a-z_0-9]+):")
if slot and OVERRIDE_SLOTS[slot] then
params.overrides = params.overrides or {}
if params.overrides[slot] then
parse_err("slot '" .. slot .. "' overridden twice")
end
-- Keep the value as a bracket-preserving run: the first text
-- piece minus the "slot:" prefix, then the rest of the group
-- (footnotes and colon-list tails), for fetch_specs later.
local val_run = {mw.ustring.sub(part, rlen(slot) + 2)}
for j = 2, #group do
insert(val_run, group[j])
end
params.overrides[slot] = val_run
elseif slot then
parse_err("unknown slot \"" .. slot .. "\" in override \""
.. part .. "\" (see SLOT_LIST in the module for valid slot keys)")
else
parse_err("unknown parameter \"" .. part .. "\"")
end
end
end
-- One conjugation pass per variant combination.
local combos = {}
for _, ispec in ipairs(inf_specs) do
for _, pspec in ipairs(pres_specs) do
for _, tspec in ipairs(past_specs) do
local parsed = parse_one_combo(unescape(ispec.form),
unescape(pspec.form), unescape(tspec.form), params)
parsed.inf_footnotes = ispec.footnotes
parsed.pres_footnotes = pspec.footnotes
parsed.past_footnotes = tspec.footnotes
insert(combos, parsed)
end
end
end
return { combos = combos, params = params, unescape = unescape, parse_err = parse_err }
end
-- =============================================================================
-- Main conjugation data structure builder
-- =============================================================================
local function build_base_data(parsed)
local params = parsed.params
local is_bare, is_ac, is_reflexive = extract_infinitive_stem(
parsed.inf_bare, parsed.inf_ac)
-- Reflexive verbs: the present/past 3rd-person principal parts carry the
-- reflexive affix -si (praũsiasi, praũsėsi). Strip it up front so class
-- detection, stem extraction, paradigm detection and retraction analysis
-- all see the plain forms (praũsia, praũsė).
local pres_bare, pres_ac = parsed.pres_bare, parsed.pres_ac
local past_bare, past_ac = parsed.past_bare, parsed.past_ac
-- Prefixed verbs: validate and strip the marked chain from the
-- present/past principal parts. The stripped CORE forms drive paradigm
-- detection and retraction analysis; the full forms remain the stems.
-- An accent inside the stripped portion is recorded: grave/tilde = the
-- stress retracted onto the prefix/affix (àtneša, nusìneša),
-- acute = the always-stressed pér- (pérneša).
local core_pres_bare, core_pres_ac
local core_past_bare, core_past_ac
local pres_prefix_accent, past_prefix_accent
if parsed.has_prefix then
if is_reflexive then
error("lt-conj: a prefixed reflexive carries the affix between prefix "
.. "and root; write the infinitive as e.g. nusi-praũsti, not as "
.. "a -tis form")
end
local n = rlen(parsed.prefix_bare)
if mw.ustring.sub(pres_bare, 1, n) ~= parsed.prefix_bare then
error("lt-conj: present_3 \"" .. toNFC(pres_ac) .. "\" does not begin "
.. "with the marked prefix chain \"" .. parsed.prefix_bare .. "-\"")
end
if mw.ustring.sub(past_bare, 1, n) ~= parsed.prefix_bare then
error("lt-conj: past_3 \"" .. toNFC(past_ac) .. "\" does not begin "
.. "with the marked prefix chain \"" .. parsed.prefix_bare .. "-\"")
end
core_pres_bare, core_pres_ac, pres_prefix_accent =
strip_prefix_left(pres_bare, pres_ac, n)
core_past_bare, core_past_ac, past_prefix_accent =
strip_prefix_left(past_bare, past_ac, n)
if parsed.has_si and rmatch(core_pres_bare, "si$") then
error("lt-conj: a prefixed reflexive takes plain endings "
.. "(nusipraũsia, not *nusipraũsiasi)")
end
end
if is_reflexive then
if not rmatch(pres_bare, "si$") or not rmatch(past_bare, "si$") then
error("lt-conj: reflexive infinitive \"" .. toNFC(parsed.inf_ac)
.. "\" requires reflexive present/past 3rd-person forms ending in -si")
end
pres_bare, pres_ac = strip_suffix(pres_bare, pres_ac, 2)
past_bare, past_ac = strip_suffix(past_bare, past_ac, 2)
end
-- For unprefixed verbs the core forms coincide with the (si-stripped)
-- full forms.
core_pres_bare = core_pres_bare or pres_bare
core_pres_ac = core_pres_ac or pres_ac
core_past_bare = core_past_bare or past_bare
core_past_ac = core_past_ac or past_ac
local conj_class, conj_subtype = detect_conj_class(pres_bare)
local past_stem_type = detect_past_stem_type(past_bare)
local ps_bare, ps_ac = extract_present_stem(
pres_bare, pres_ac, conj_class, conj_subtype)
local pa_bare, pa_ac = extract_past_stem(
past_bare, past_ac, past_stem_type)
-- The stem override goes through the full pipeline so it receives the same
-- canonicalization as the principal parts.
if params.stem then
local ob, oa = process_input(params.stem)
is_bare = ob; is_ac = oa
ps_bare = ob; ps_ac = oa
pa_bare = ob; pa_ac = oa
end
-- Flag for -ėjo mixed verbs: past stem type is "ė" but personal endings
-- are o-stem (au/ai/o/...) rather than ė-stem (iau/ei/ė/...).
local has_ejo_past = (rmatch(past_bare, "ėjo$") ~= nil)
-- The accent paradigm (mobile vs fixed) is read off each tense's own
-- 3rd-person penult: kélti is mobile in the present (kẽlia -> keliù) but
-- fixed in the past (kė́lė -> kė́liau); vìrti is the reverse (vérda ->
-- vérdu, vìrė -> viriaũ). In a prefixed verb any accent on the
-- prefix/affix fixes the whole tense on that syllable: pér- (pérnešu,
-- pértraukiau) and a retracted grave/tilde alike (nèvelku, àpskutu,
-- nusìnešu; àtplaukiau, nusìprausiau). The 1sg/2sg end stress remains
-- only where the core keeps its own accent (atplaukiù, nusiprausiù).
local function paradigm_of(prefix_accent, core_ac)
if prefix_accent then return "fixed" end
return detect_accent_paradigm(core_ac)
end
local pres_paradigm = paradigm_of(pres_prefix_accent, core_pres_ac)
local past_paradigm = paradigm_of(past_prefix_accent, core_past_ac)
return {
-- Original NFC strings kept for display in table headers and imp_3.
infinitive = parsed.infinitive,
present_3 = parsed.present_3,
past_3 = parsed.past_3,
-- Bare forms (for irregular verb lookup); reflexive -si already stripped.
pres_bare = pres_bare,
past_bare = past_bare,
inf_bare = parsed.inf_bare,
-- Accented present 3 (for retraction analysis and syllable counts);
-- reflexive -si already stripped.
pres_ac = pres_ac,
-- Two-track stems.
inf_stem_bare = is_bare, inf_stem_ac = is_ac,
pres_stem_bare = ps_bare, pres_stem_ac = ps_ac,
past_stem_bare = pa_bare, past_stem_ac = pa_ac,
-- Core infinitive (prefix/affix-stripped; future-tense shortening,
-- metatonija and suffixedness tests run on it).
inf_core_bare = parsed.inf_core_bare,
inf_core_ac = parsed.inf_core_ac,
-- Prefix bookkeeping. prefix_bare includes the internal
-- reflexive affix (nusi); the *_prefix_accent fields record the mark
-- found inside the stripped portion of each principal part.
has_prefix = parsed.has_prefix,
has_si = parsed.has_si,
prefix_bare = parsed.prefix_bare,
inf_prefix_accent = parsed.inf_prefix_accent,
pres_prefix_accent = pres_prefix_accent,
past_prefix_accent = past_prefix_accent,
-- Core (prefix-stripped) present/past 3rd-person forms; equal to the
-- si-stripped full forms for unprefixed verbs.
core_pres_bare = core_pres_bare, core_pres_ac = core_pres_ac,
core_past_bare = core_past_bare, core_past_ac = core_past_ac,
-- Classification.
conj_class = conj_class,
conj_subtype = conj_subtype,
past_stem_type = past_stem_type,
has_ejo_past = has_ejo_past,
pres_paradigm = pres_paradigm, -- "fixed" or "mobile"
past_paradigm = past_paradigm, -- "fixed" or "mobile"
accent_paradigm = pres_paradigm, -- alias of pres_paradigm
-- Properties.
is_reflexive = is_reflexive,
is_impersonal = params.impers,
forms = {},
}
end
-- =============================================================================
-- Form generator shared helpers
-- =============================================================================
-- True when a given slot takes ending stress in the mobile paradigm.
-- Only the 1st and 2nd person singular move the accent to the ending.
local function e_stressed(paradigm, slot)
return paradigm == "mobile" and (slot == "s1" or slot == "s2")
end
-- Build all surface-form objects for one person slot. Ending variants
-- flagged `colloq = true` in the E.* tables get the shared COLLOQ_NOTE.
local function forms_for_slot(stem_bare, stem_ac, slot_endings, end_stressed)
local list = {}
for _, pair in ipairs(slot_endings) do
local form_obj = {form = combine(stem_bare, stem_ac, pair[1], pair[2], end_stressed)}
if pair.colloq then
form_obj.footnotes = {COLLOQ_NOTE}
end
insert(list, form_obj)
end
return list
end
-- Populate base.forms from a complete ending table for all five personal slots.
-- prefix is prepended to each canonical slot name
-- (e.g. "pres_" -> "pres_1s", "pres_2s", "pres_3", "pres_1p", "pres_2p").
-- paradigm is the accent paradigm of THIS tense ("mobile" or "fixed"); it may
-- be omitted for ending tables whose slots carry no accented variants
-- (past frequentative, subjunctive), where E-stress can never trigger.
local function generate_from_table(base, stem_bare, stem_ac, end_table, prefix, paradigm)
paradigm = paradigm or "fixed"
local slot_keys = {
s1 = prefix .. "1s",
s2 = prefix .. "2s",
s3 = prefix .. "3",
p1 = prefix .. "1p",
p2 = prefix .. "2p",
}
for slot, key in pairs(slot_keys) do
if end_table[slot] then
base.forms[key] = forms_for_slot(
stem_bare, stem_ac,
end_table[slot],
e_stressed(paradigm, slot))
end
end
end
-- =============================================================================
-- Shared morphophonological predicates
-- =============================================================================
-- True when the core infinitive (prefix-stripped, -ti/-tis removed) carries a
-- derivational suffix (-yti, -ėti, -oti, -auti, -uoti, -enti, -inti, ...):
-- primary verbs have monosyllabic core stems (neš-, klaus-, pjau-).
-- Suffixed infinitives keep their accent in the būdinys and the passive
-- participles; non-suffixed ones take end stress or a mobile paradigm.
local function is_suffixed_infinitive(base)
local core = rmatch(base.inf_core_bare, "^(.+)tis?$")
if not core then return false end
-- false: stem fragment, not the page's headword; skip respelling detection.
local ok, syls = pcall(lt_pron.get_syllables, core, false)
return ok and syls ~= nil and #syls > 1
end
-- Lexical list: the few mixed a-conjugation verbs with al/am/an roots whose
-- present retracts (nùgarma, nèkalba, sùskamba).
local RETRACTING_AL_AM_AN = { garma = true, kalba = true, skamba = true }
-- True when the present-tense stress retracts onto a prefix or preverbal
-- particle (ne-, be-, te-, ...). Conditions:
-- * never for the -o conjugation; the stressed syllable must be the penult
-- of a disyllabic present-3 form (i.e. adjacent to the particle) and must
-- not be acute (tvirtapradė roots never yield their stress, including
-- those written with a grave on i/u: nedìrba, sujùngia);
-- * the penult nucleus must be a plain short or positionally-long vowel
-- a/e/i/u (sùveda, nèskuta, pàkasa, pàtiki), or an e-grade resonant
-- diphthong whose infinitive begins with the same onset in i-grade
-- (àtvelka ~ atvil̃kti, ìšskrenda ~ išskrìsti; but netem̃pia ~ tem̃pti),
-- or one of the lexical al/am/an verbs above. Long vowels and
-- non-alternating diphthongs keep their stress (neplaũkia, patiñka,
-- negir̃di).
-- * Not modelled: the netùri/negãli exception, which is specific to ne-/be-
-- and does not affect the te- imperative built here.
-- Besides the te- imperative, this predicate decides the shape of the short
-- active present participle (nešą̃s vs rašą̃s/rãšąs).
local function present_retracts(base)
-- In a prefixed present the input shows it: a grave/tilde on the
-- prefix/affix is the retraction (àtneša, nusìneša); an unaccented
-- (atplaũkia) or pér-stressed (pérneša) prefix means none. The analysis
-- below predicts the behaviour of te- with an unprefixed present.
if base.has_prefix then
return base.pres_prefix_accent == "grave"
or base.pres_prefix_accent == "tilde"
end
if base.conj_subtype == "o" then
return false
end
-- false: stem fragment, not the page's headword; skip respelling detection.
local ok, syls = pcall(lt_pron.get_syllables, toNFC(base.pres_ac), false)
if not ok or not syls or #syls ~= 2 then
return false
end
-- Syllables come back in display form (di̇̀r); the dot above is dropped so
-- that the coda analysis below sees the resonant.
local penult_ac = rsub(to_stem_ac(syls[1]), DOT_AB, "")
if rfind(penult_ac, ACUTE) or grave_marks_acute(penult_ac) then
return false
end
local penult_bare = rsub(penult_ac, ANY_AC, "")
local onset, nucleus, coda =
rmatch(penult_bare, "^([^aeiouąęėįųūy]*)([aeiouąęėįųūy]+)([^aeiouąęėįųūy]*)$")
if not nucleus or rlen(nucleus) > 1 then
return false
end
if not rfind(nucleus, "^[aeiu]$") then
return false -- long vowels (o ą ę ė į ų ū y) never retract
end
local coda_first = coda ~= "" and mw.ustring.sub(coda, 1, 1) or nil
if coda_first and rfind(coda_first, "^[lmnr]$") then
-- Resonant diphthong penult.
if nucleus == "e" then
-- e-grade: retracts only when the infinitive begins with the
-- same onset followed by i (vel~vil, ker~kir, skren~skri; not
-- tem~tem, el~el).
return mw.ustring.sub(base.inf_core_bare, 1, rlen(onset) + 1) == onset .. "i"
elseif nucleus == "a" then
return RETRACTING_AL_AM_AN[base.pres_bare] == true
end
return false -- il/im/in/ir, ul/um/un/ur keep their stress
end
return true -- open or obstruent-closed short/positional vowel
end
-- =============================================================================
-- Irregular (suppletive) verb forms
-- =============================================================================
-- Keyed by the bare infinitive and present 3rd person joined by a comma, so
-- that only the suppletive verb matches: bū́ti, yrà is "būti,yra", while
-- ìrti, ỹra and bū́ti with its other presents (bū̃na, bū̃va) are conjugated
-- regularly. Prefixed derivatives (atbūti, antbūti, užbūti …) do not match
-- and take their own principal parts.
--
-- Forms are NFC without the dot above an accented i/j, which display() adds
-- ("esì" → "esi̇̀"). A missing slot renders as "—".
local IRREGULAR_FORMS = {}
IRREGULAR_FORMS["būti,yra"] = {
-- Present tense: suppletive es- stem
pres_1s = {"esù"}, pres_2s = {"esì"}, pres_3 = {"yrà"},
pres_1p = {"ẽsame", "ẽsam"}, pres_2p = {"ẽsate", "ẽsat"},
-- Past simple: buv- stem
past_1s = {"buvaũ"}, past_2s = {"buvaĩ"}, past_3 = {"bùvo"},
past_1p = {"bùvome", "bùvom"}, past_2p = {"bùvote", "bùvot"},
-- Past frequentative: būdav- stem
past_freq_1s = {"bū́davau"}, past_freq_2s = {"bū́davai"}, past_freq_3 = {"bū́davo"},
past_freq_1p = {"bū́davome", "bū́davom"}, past_freq_2p = {"bū́davote", "bū́davot"},
-- Future: būs- stem
fut_1s = {"bū́siu"}, fut_2s = {"bū́si"}, fut_3 = {"bùs"},
fut_1p = {"bū́sime", "bū́sim"}, fut_2p = {"bū́site", "bū́sit"},
-- Subjunctive: bū- stem (same variant set as E.subj)
subj_1s = {"bū́čiau"}, subj_2s = {"bū́tum", "bū́tumei"}, subj_3 = {"bū́tų"},
subj_1p = {"bū́tume", "bū́tumėm", "bū́tumėme"}, subj_2p = {"bū́tumėte", "bū́tumėt", "bū́tute"},
-- Imperative: 3rd person uses tebū̃na (bū̃na is circumflex), not
-- te+yra. The relict tebūniẽ is a second variant.
imp_2s = {"bū́k", "bū́ki"}, imp_1p = {"bū́kime", "bū́kim"}, imp_2p = {"bū́kite", "bū́kit"},
imp_3 = {"tebū̃na", "tebūniẽ"},
-- Adjectival participles. esąs has two readings, end-stressed first.
act_pres_short = {"esą̃s", "ẽsąs"}, act_pres_long = {"ẽsantis"}, act_past = {"bùvęs"},
act_past_freq = {"bū́davęs"}, act_fut_short = {"bū́siąs"}, act_fut_long = {"bū́siantis"},
pass_pres = {"ẽsamas"}, pass_past = {"bū́tas"}, pass_fut = {"bū́simas"}, pass_necess = {"bū́tinas"},
-- Adverbial forms. Non-suffixed infinitive -> end-stressed būdinys
-- (būtè, būtinaĩ).
pusdalyvis = {"bū́damas"}, padalyvis_pres = {"ẽsant"}, padalyvis_past = {"bùvus"},
padalyvis_past_freq = {"bū́davus"}, padalyvis_fut = {"bū́siant"},
budinys_1 = {"būtè"}, budinys_2 = {"būtinaĩ"},
}
-- nebūti: the negative of būti, entered unhyphenated (nebū́ti,nėrà,nebùvo).
-- The present and its participles contract ne- with the es-/yr- stem (nesù,
-- nėrà, nẽsame; nesą̃s, nẽsąs, nẽsantis, nẽsamas, nẽsant); every other form is
-- ne- before the form of būti, unstressed (nebuvaũ, nebùvo, nebū́siu,
-- tenebū̃na). It has no būdinys.
IRREGULAR_FORMS["nebūti,nėra"] = {
pres_1s = {"nesù"}, pres_2s = {"nesì"}, pres_3 = {"nėrà"},
pres_1p = {"nẽsame", "nẽsam"}, pres_2p = {"nẽsate", "nẽsat"},
past_1s = {"nebuvaũ"}, past_2s = {"nebuvaĩ"}, past_3 = {"nebùvo"},
past_1p = {"nebùvome", "nebùvom"}, past_2p = {"nebùvote", "nebùvot"},
past_freq_1s = {"nebū́davau"}, past_freq_2s = {"nebū́davai"}, past_freq_3 = {"nebū́davo"},
past_freq_1p = {"nebū́davome", "nebū́davom"}, past_freq_2p = {"nebū́davote", "nebū́davot"},
fut_1s = {"nebū́siu"}, fut_2s = {"nebū́si"}, fut_3 = {"nebùs"},
fut_1p = {"nebū́sime", "nebū́sim"}, fut_2p = {"nebū́site", "nebū́sit"},
subj_1s = {"nebū́čiau"}, subj_2s = {"nebū́tum", "nebū́tumei"}, subj_3 = {"nebū́tų"},
subj_1p = {"nebū́tume", "nebū́tumėm", "nebū́tumėme"}, subj_2p = {"nebū́tumėte", "nebū́tumėt", "nebū́tute"},
imp_2s = {"nebū́k", "nebū́ki"}, imp_1p = {"nebū́kime", "nebū́kim"}, imp_2p = {"nebū́kite", "nebū́kit"},
imp_3 = {"tenebū̃na"},
act_pres_short = {"nesą̃s", "nẽsąs"}, act_pres_long = {"nẽsantis"}, act_past = {"nebùvęs"},
act_past_freq = {"nebū́davęs"}, act_fut_short = {"nebū́siąs"}, act_fut_long = {"nebū́siantis"},
pass_pres = {"nẽsamas"}, pass_past = {"nebū́tas"}, pass_fut = {"nebū́simas"}, pass_necess = {"nebū́tinas"},
pusdalyvis = {"nebū́damas"}, padalyvis_pres = {"nẽsant"}, padalyvis_past = {"nebùvus"},
padalyvis_past_freq = {"nebū́davus"}, padalyvis_fut = {"nebū́siant"},
}
-- =============================================================================
-- Form generators – individual tenses and moods
-- =============================================================================
local function generate_present(base)
local bare = base.pres_stem_bare
local ac = base.pres_stem_ac
local sub = base.conj_subtype
local tbl
if base.is_reflexive then
if base.conj_class == "I" then
tbl = (sub == "ia") and E.pres_I_ia_refl or E.pres_I_a_refl
elseif base.conj_class == "II" then
tbl = E.pres_II_refl
else
tbl = E.pres_III_o_refl
end
elseif base.conj_class == "I" then
tbl = (sub == "ia") and E.pres_I_ia or E.pres_I_a
elseif base.conj_class == "II" then
tbl = E.pres_II
else
tbl = E.pres_III_o
end
-- Class I -ia: the stem comes from the palatalized present (ver̃čia →
-- ver̃č), and the 2sg ending -i does not palatalize, so the 2sg is built
-- on the restored consonant (vertì, not verči̇̀). The other endings
-- begin with i + back vowel and keep the palatalized stem.
if base.conj_class == "I" and sub == "ia" then
local tbl_no_s2 = {}
for k, v in pairs(tbl) do
if k ~= "s2" then tbl_no_s2[k] = v end
end
generate_from_table(base, bare, ac, tbl_no_s2, "pres_", base.pres_paradigm)
local ubare, uac = unpalatalize_stem(bare, ac)
base.forms["pres_2s"] = forms_for_slot(
ubare, uac, tbl.s2,
e_stressed(base.pres_paradigm, "s2"))
else
generate_from_table(base, bare, ac, tbl, "pres_", base.pres_paradigm)
end
end
local function generate_past(base)
local bare = base.past_stem_bare
local ac = base.past_stem_ac
-- -ėjo mixed verbs: the past stem was extracted by stripping -ėjo, but
-- the personal endings are the o-stem set (au/ai/o/...) not the ė-stem set.
local is_o = (base.past_stem_type == "o" or base.has_ejo_past)
local tbl
if base.is_reflexive then
tbl = is_o and E.past_o_refl or E.past_e_refl
else
tbl = is_o and E.past_o or E.past_e
end
generate_from_table(base, bare, ac, tbl, "past_", base.past_paradigm)
end
local function generate_past_freq(base)
-- Past frequentative: infinitive stem + -dav- infix + o-stem endings.
-- Always S-stressed.
local bare = base.inf_stem_bare .. "dav"
local ac = base.inf_stem_ac .. "dav"
generate_from_table(base, bare, ac,
base.is_reflexive and E.past_freq_refl or E.past_freq, "past_freq_")
end
local function generate_future(base)
local bare0 = base.inf_stem_bare
local ac0 = base.inf_stem_ac
-- 3rd person vowel shortening (y -> i, ū -> u) for monosyllabic core
-- stems. The shortened vowel is short (grave); the circumflex
-- metatonija below never applies on top of it (lýti -> li̇̀s).
local s3_bare, s3_ac = bare0, ac0
local shortened = false
if should_shorten_future_3(bare0, base.inf_core_bare, base.is_reflexive) then
s3_bare, s3_ac = shorten_future_vowel(bare0, ac0)
shortened = true
end
-- 3rd person metatonija: a stressed heavy last syllable of the core
-- infinitive stem becomes circumflex (tráukti -> traũks, sėdė́ti ->
-- sėdė̃s, kélti -> kel̃s); a short one keeps its grave (nèšti -> nèš).
-- Reflexives alike (tikė́tis -> tikė̃sis).
if not shortened then
local should_change_accent = false
local inf_core_stem_ac = rmatch(base.inf_core_ac, "^(.+)tis?$")
if inf_core_stem_ac then
-- false: stem fragment, not the page's headword; skip respelling detection.
local syls = lt_pron.get_syllables(toNFC(inf_core_stem_ac), false)
if syls and #syls > 0 then
-- get_syllables returns NFC: an acute over a/o/u/y/e composes
-- into a single codepoint there, so the accent probe must run
-- on the stem_ac (partial NFD) form of the syllable.
local last_syl = syls[#syls]
local has_accent = rfind(to_stem_ac(last_syl), ANY_AC) ~= nil
if has_accent and lt_pron.last_syllable_is_heavy(toNFC(inf_core_stem_ac), false) then
should_change_accent = true
end
end
end
if should_change_accent then
local s3_syls = lt_pron.get_syllables(toNFC(s3_ac), false)
if s3_syls and #s3_syls > 0 then
local new_last_syl = lt_pron.change_accent(
s3_syls[#s3_syls], "tilde", false)
local new_stem_parts = {}
for i = 1, #s3_syls - 1 do
insert(new_stem_parts, s3_syls[i])
end
insert(new_stem_parts, new_last_syl)
s3_ac = to_stem_ac(toNFC(concat(new_stem_parts, "")))
end
end
end
-- The 3rd person is built on the metatonija/shortening-processed stem;
-- all other persons keep the plain infinitive-stem accent (kláusiu vs
-- klaũs, tikė́siuosi vs tikė̃sis).
local f3_bare, f3_ac = make_future_stem(s3_bare, s3_ac)
local fs_bare, fs_ac = make_future_stem(bare0, ac0)
-- Reflexive: 3rd person = future stem + -is (tikė̃sis, praũsis, mókysis);
-- other persons take -iuosi/-iesi/-imės/-itės, all S-stressed; the
-- singular also has the colloquial short form (praũsiuos, praũsies).
if base.is_reflexive then
base.forms["fut_3"] = { {form = combine_S(f3_bare, f3_ac, "is")} }
local other = {
{key = "fut_1s", endings = { {"iuosi", nil}, {"iuos", nil, colloq = true} }},
{key = "fut_2s", endings = { {"iesi", nil}, {"ies", nil, colloq = true} }},
{key = "fut_1p", endings = { {"imės", nil} }},
{key = "fut_2p", endings = { {"itės", nil} }},
}
for _, item in ipairs(other) do
base.forms[item.key] = forms_for_slot(fs_bare, fs_ac, item.endings, false)
end
return
end
-- Non-reflexive: the bare 3rd person IS the future stem (formant
-- included, with sibilant fusion: nèš, grį̃š, kel̃s).
base.forms["fut_3"] = { {form = display(f3_ac)} }
local other = {
{key = "fut_1s", endings = { {"iu", nil} }},
{key = "fut_2s", endings = { {"i", nil} }},
{key = "fut_1p", endings = { {"ime", nil}, {"im", nil, colloq = true} }},
{key = "fut_2p", endings = { {"ite", nil}, {"it", nil, colloq = true} }},
}
for _, item in ipairs(other) do
base.forms[item.key] = forms_for_slot(fs_bare, fs_ac, item.endings, false)
end
end
local function generate_subjunctive(base)
-- Subjunctive always preserves the infinitive accent.
generate_from_table(
base, base.inf_stem_bare, base.inf_stem_ac,
base.is_reflexive and E.subj_refl or E.subj, "subj_")
end
local function generate_imperative(base)
local bare = base.inf_stem_bare
local ac = base.inf_stem_ac
-- The imperative -k- fuses with a stem-final velar: tik+k -> tik (ti̇̀k),
-- veng+k -> venk.
local last = mw.ustring.sub(bare, -1)
if last == "k" or last == "g" then
bare = mw.ustring.sub(bare, 1, -2)
ac = mw.ustring.sub(ac, 1, -2)
end
-- 2sg, 1pl, 2pl: infinitive stem + -k- + person ending (all S-stressed).
local imp_tbl = base.is_reflexive and E.imp_refl or E.imp
for slot, key in pairs({s2 = "imp_2s", p1 = "imp_1p", p2 = "imp_2p"}) do
base.forms[key] = forms_for_slot(bare, ac, imp_tbl[slot], false)
end
-- 3rd person: te- + the present 3rd person. te- takes the stress of a
-- retracting present like a prefix (tèneša, tèkelia, tètiki); otherwise
-- the present keeps its accent (temiẽga, tever̃čia, terãšo).
-- Reflexive: te + si + present stem (tesipraũsia, tesimóko); a
-- retracting present puts the stress on the affix (tesìneša, as
-- nusìneša). Prefixed: te- goes in front of the prefixed present, whose
-- stress stays put, since retraction only reaches the syllable next to
-- the root (teàtneša, tenusìneša, tepérneša).
if base.has_prefix then
base.forms["imp_3"] = { {form = display("te" .. to_stem_ac(base.present_3))} }
elseif base.is_reflexive then
if present_retracts(base) then
base.forms["imp_3"] = { {form = display("tesi" .. GRAVE .. base.pres_bare)} }
else
base.forms["imp_3"] = { {form = display("tesi" .. base.pres_ac)} }
end
elseif present_retracts(base) then
base.forms["imp_3"] = { {form = display("te" .. GRAVE .. base.pres_bare)} }
else
base.forms["imp_3"] = { {form = display("te" .. to_stem_ac(base.present_3))} }
end
end
-- =============================================================================
-- Form generators – participle lemma forms
-- =============================================================================
-- The participle generators produce the masculine nominative singular.
-- Present-participle suffixes per conjugation class. A Class I -ia stem
-- lost its i with the ending, so the suffixes restore it: kẽlia -> kẽliąs,
-- kẽliantis (not *kẽląs); ver̃čia -> ver̃čiąs.
local function pres_participle_suffixes(base)
local is_cl2 = (base.conj_class == "II")
local is_ia = (base.conj_class == "I" and base.conj_subtype == "ia")
local short_sfx = is_cl2 and "įs" or (is_ia and "iąs" or "ąs")
local long_sfx = is_cl2 and "intis" or (is_ia and "iantis" or "antis")
local end_sfx = (is_cl2 and "į" or (is_ia and "ią" or "ą")) .. TILDE .. "s"
return short_sfx, long_sfx, end_sfx
end
-- Decide the accent shape of the short masc active present participle:
-- "end" – end-stressed circumflex only (retracting presents: nešą̃s,
-- kelią̃s, tikį̃s);
-- "both" – two readings, end-stressed first (other disyllabic presents
-- including the -o conjugation, and presents with the stressed
-- suffixes -ẽna/-ìja/-ìna: rašą̃s/rãšąs, gyveną̃s/gyvẽnąs);
-- "stem" – stem accent only (longer presents: dainúojąs).
-- The same split governs the besi- short form of reflexives
-- (besiprausią̃s/besipraũsiąs, besimoką̃s/besimókąs).
local function short_participle_mode(base)
-- pér- keeps its stress in every form, including the short participle
-- (péraugąs, péraugą).
if base.pres_prefix_accent == "acute" then
return "stem"
end
-- Syllable count and suffix probes run on the prefix-stripped CORE:
-- prefixed short participles behave like their unprefixed bases
-- (apkalbą̃s like kalbą̃s; suaugą̃s/suáugąs like augą̃s/áugąs).
-- false: stem fragment, not the page's headword; skip respelling detection.
local ok, syls = pcall(lt_pron.get_syllables, toNFC(base.core_pres_ac), false)
local n_syl = (ok and syls) and #syls or 0
local stressed_ena_ija_ina =
rfind(base.core_pres_ac, "e" .. TILDE .. "na$") ~= nil or
rfind(base.core_pres_ac, "i" .. GRAVE .. "ja$") ~= nil or
rfind(base.core_pres_ac, "i" .. GRAVE .. "na$") ~= nil
if present_retracts(base) then
return "end"
elseif n_syl == 2 or stressed_ena_ija_ina then
return "both"
else
return "stem"
end
end
local function generate_act_pres_participle(base)
local bare = base.pres_stem_bare
local ac = base.pres_stem_ac
local short_sfx, long_sfx, end_sfx = pres_participle_suffixes(base)
-- Long form: always keeps the present-3 accent.
base.forms["act_pres_long"] = { {form = combine_S(bare, ac, long_sfx)} }
local end_form = {form = display(bare .. end_sfx)}
local stem_form = {form = combine_S(bare, ac, short_sfx)}
local mode = short_participle_mode(base)
if mode == "end" then
base.forms["act_pres_short"] = { end_form }
elseif mode == "both" then
base.forms["act_pres_short"] = { end_form, stem_form }
else
base.forms["act_pres_short"] = { stem_form }
end
end
-- Past-stem derivatives (the -ęs participle and the past padalyvis) never
-- keep a retracted prefix stress: the accent returns to the core past
-- stem — circumflex on a heavy or positionally-lengthened a/e syllable,
-- grave on a plain short i/u — ìšnešė -> išnẽšęs, išnẽšus; àtplaukė ->
-- atplaũkęs; išsìnešė -> išsinẽšus. pér- (acute) does keep it: pértraukęs.
local function past_stem_unretracts(base)
return base.has_prefix and (base.past_prefix_accent == "grave"
or base.past_prefix_accent == "tilde")
end
local function unretracted_past_stem(base)
if base._unret_bare then
return base._unret_bare, base._unret_ac
end
-- Retraction implies a disyllabic core past, so the core past stem (one
-- final vowel stripped, cf. extract_past_stem) is a single unaccented
-- syllable. Try circumflex first; change_accent rejects it for plain
-- short i/u nuclei, which take grave instead (positionally lengthened
-- a/e and all heavy syllables take the tilde: nẽš-, bãr-, plaũk-).
local core_stem = mw.ustring.sub(base.core_past_bare, 1, -2)
local ok, accented = pcall(lt_pron.change_accent, core_stem, "tilde", false)
if not ok then
ok, accented = pcall(lt_pron.change_accent, core_stem, "grave", false)
end
local core_ac = ok and to_stem_ac(toNFC(accented)) or core_stem
base._unret_bare = base.prefix_bare .. core_stem
base._unret_ac = base.prefix_bare .. core_ac
return base._unret_bare, base._unret_ac
end
local function generate_act_past_participle(base)
local bare, ac = base.past_stem_bare, base.past_stem_ac
if past_stem_unretracts(base) then
bare, ac = unretracted_past_stem(base)
end
base.forms["act_past"] = { {form = combine_S(bare, ac, "ęs")} }
end
local function generate_act_past_freq_participle(base)
local bare = base.inf_stem_bare .. "dav"
local ac = base.inf_stem_ac .. "dav"
base.forms["act_past_freq"] = { {form = combine_S(bare, ac, "ęs")} }
end
local function generate_act_fut_participle(base)
local fb, fa = make_future_stem(base.inf_stem_bare, base.inf_stem_ac)
base.forms["act_fut_short"] = { {form = combine_S(fb, fa, "iąs")} }
base.forms["act_fut_long"] = { {form = combine_S(fb, fa, "iantis")} }
end
local function generate_pass_pres_participle(base)
local bare = base.pres_stem_bare
local ac = base.pres_stem_ac
-- -o presents take -omas (mãtomas, rãšomas); -i presents -imas; -ia
-- presents -iamas (kẽliamas, ver̃čiamas — the stripped i is restored);
-- the rest -amas.
local sfx
if base.conj_class == "II" then
sfx = "imas"
elseif base.conj_subtype == "o" then
sfx = "omas"
elseif base.conj_class == "I" and base.conj_subtype == "ia" then
sfx = "iamas"
else
sfx = "amas"
end
base.forms["pass_pres"] = { {form = combine_S(bare, ac, sfx)} }
end
local function generate_pass_past_participle(base)
local bare = base.inf_stem_bare
local ac = base.inf_stem_ac
local suffixed = is_suffixed_infinitive(base)
-- Prefixed, non-suffixed participles: an acute core root keeps its
-- stress (netráuktas 3, pasidìrbtas) and so does pér- (pértrauktas 1);
-- any other core root (circumflex or short) yields it to the syllable
-- directly before the root, the reflexive affix or else the last prefix
-- syllable: nèvilktas, àpskustas, nùpieštas, nusìpieštas 3b. No
-- rãstas-type lengthening here (apkàsti -> àpkastas, not *apkãstas).
if base.has_prefix and not suffixed
and base.inf_prefix_accent ~= "acute"
and not rfind(base.inf_core_ac, ACUTE)
and not grave_marks_acute(base.inf_core_ac) then
local core_stem_bare = mw.ustring.sub(bare, rlen(base.prefix_bare) + 1)
base.forms["pass_past"] = {
{form = display(accent_prefix_bare(base.prefix_bare)
.. core_stem_bare .. "tas")}
}
return
end
-- Non-suffixed stems lengthen a stressed short a/e in -tas (ràsti ->
-- rãstas, nèšti -> nẽštas); -simas and -tinas keep the short vowel
-- (nèšimas, nèštinas).
if not suffixed then
ac = rsub(ac, "([ae])" .. GRAVE, "%1" .. TILDE)
end
base.forms["pass_past"] = { {form = combine_S(bare, ac, "tas")} }
end
local function generate_pass_fut_participle(base)
local fb, fa = make_future_stem(base.inf_stem_bare, base.inf_stem_ac)
base.forms["pass_fut"] = { {form = combine_S(fb, fa, "imas")} }
end
local function generate_pass_necess_participle(base)
base.forms["pass_necess"] = {
{form = combine_S(base.inf_stem_bare, base.inf_stem_ac, "tinas")}
}
end
-- =============================================================================
-- Form generators – adverbial forms
-- =============================================================================
local function generate_pusdalyvis(base)
base.forms["pusdalyvis"] = {
{form = combine_S(base.inf_stem_bare, base.inf_stem_ac, "damas")}
}
end
local function generate_padalyvis_pres(base)
local bare = base.pres_stem_bare
local ac = base.pres_stem_ac
-- -ia presents restore the stripped i (kẽliant, ver̃čiant).
local sfx
if base.conj_class == "II" then
sfx = "int"
elseif base.conj_class == "I" and base.conj_subtype == "ia" then
sfx = "iant"
else
sfx = "ant"
end
base.forms["padalyvis_pres"] = { {form = combine_S(bare, ac, sfx)} }
end
local function generate_padalyvis_past(base)
-- -o-conjugation verbs with an ė-stem past take -ius (rãšius, sãkius;
-- matė -> mãčius with t -> č palatalization applied by combine); other
-- pasts take -us (nẽšus, kláusus), including -ėjo pasts (kalbė́jus).
-- A retracted prefix stress is undone here, as in the -ęs participle
-- (ìšnešė -> išnẽšus).
local bare, ac = base.past_stem_bare, base.past_stem_ac
if past_stem_unretracts(base) then
bare, ac = unretracted_past_stem(base)
end
local sfx = "us"
if base.conj_subtype == "o" and base.past_stem_type == "ė"
and not base.has_ejo_past then
sfx = "ius"
end
base.forms["padalyvis_past"] = { {form = combine_S(bare, ac, sfx)} }
end
local function generate_padalyvis_past_freq(base)
local bare = base.inf_stem_bare .. "dav"
local ac = base.inf_stem_ac .. "dav"
base.forms["padalyvis_past_freq"] = { {form = combine_S(bare, ac, "us")} }
end
local function generate_padalyvis_fut(base)
local fb, fa = make_future_stem(base.inf_stem_bare, base.inf_stem_ac)
base.forms["padalyvis_fut"] = { {form = combine_S(fb, fa, "iant")} }
end
local function generate_budinys(base)
-- The būdinys is not formed from reflexives. Prefixed reflexives
-- (internal -si-) run through the plain generators and stop here; -tis
-- reflexives never reach this function.
if base.has_si then
return
end
local bare = base.inf_stem_bare
local ac = base.inf_stem_ac
if base.inf_prefix_accent == "acute" or is_suffixed_infinitive(base) then
-- Suffixed infinitives keep their accent: sėdė́te, rašýtinai;
-- so does the always-stressed pér- (pértraukte).
base.forms["budinys_1"] = { {form = combine_S(bare, ac, "te")} }
base.forms["budinys_2"] = { {form = combine_S(bare, ac, "tinai")} }
else
-- Non-suffixed infinitives are end-stressed: neštè, neštinaĩ,
-- trauktè, vilktinaĩ.
base.forms["budinys_1"] = { {form = display(bare .. "te" .. GRAVE)} }
base.forms["budinys_2"] = { {form = display(bare .. "tinai" .. TILDE)} }
end
end
-- =============================================================================
-- Form generators – reflexive participles and adverbial forms
-- =============================================================================
--
-- Reflexive active participles have two forms: the -is form first
-- (praũsiąsis, praũsęsis), then the besi- form (besipraũsiąs, besipraũsęs).
-- The -is forms are never end-stressed; the besi- short present follows the
-- two-reading rule of the plain short participle (besiprausią̃s,
-- besipraũsiąs). The -is form has no long (-antis) variant, so the long
-- slots carry only the besi- form. The pusdalyvis and padalyviai use only
-- the -is forms. Non-prefixed reflexive passive participles exist only in
-- the neuter: the plain neuter + -si, same accent (praũsiamasi, praũstasi);
-- the present and the past are given. The būdinys is not formed.
local function generate_reflexive_participles(base)
local pb, pa = base.pres_stem_bare, base.pres_stem_ac
local short_sfx, long_sfx, end_sfx = pres_participle_suffixes(base)
-- Present: -is form (never end-stressed) + besi- forms.
local act_pres_short = { {form = combine_S(pb, pa, short_sfx .. "is")} }
local mode = short_participle_mode(base)
if mode == "end" or mode == "both" then
insert(act_pres_short, {form = display("besi" .. pb .. end_sfx)})
end
if mode == "stem" or mode == "both" then
insert(act_pres_short, {form = combine_S("besi" .. pb, "besi" .. pa, short_sfx)})
end
base.forms["act_pres_short"] = act_pres_short
-- Long form: retracting presents move the stress onto the reflexive
-- affix (besìrenkantis, besìtikintis), like prefixed reflexives
-- (nusìneša); others keep the present-stem accent (besipraũsiantis,
-- besimókantis).
if present_retracts(base) then
base.forms["act_pres_long"] = {
{form = display("besi" .. GRAVE .. pb .. long_sfx)}
}
else
base.forms["act_pres_long"] = {
{form = combine_S("besi" .. pb, "besi" .. pa, long_sfx)}
}
end
-- Past: past stem + -ęsis / besi- + -ęs.
local tb, ta = base.past_stem_bare, base.past_stem_ac
base.forms["act_past"] = {
{form = combine_S(tb, ta, "ęsis")},
{form = combine_S("besi" .. tb, "besi" .. ta, "ęs")},
}
-- Past frequentative: -dav- stem.
local db, da = base.inf_stem_bare .. "dav", base.inf_stem_ac .. "dav"
base.forms["act_past_freq"] = {
{form = combine_S(db, da, "ęsis")},
{form = combine_S("besi" .. db, "besi" .. da, "ęs")},
}
-- Future: future stem (formant included).
local fb, fa = make_future_stem(base.inf_stem_bare, base.inf_stem_ac)
base.forms["act_fut_short"] = {
{form = combine_S(fb, fa, "iąsis")},
{form = combine_S("besi" .. fb, "besi" .. fa, "iąs")},
}
base.forms["act_fut_long"] = {
{form = combine_S("besi" .. fb, "besi" .. fa, "iantis")},
}
-- Passive participles: the neuter in -si only (praũsiamasi, praũstasi).
generate_pass_pres_participle(base)
generate_pass_past_participle(base)
for _, slot in ipairs({"pass_pres", "pass_past"}) do
local neut = {}
for _, form_obj in ipairs(base.forms[slot]) do
insert(neut, {form = (form_obj.form:gsub("s$", "")) .. "si",
footnotes = {IMPERS_NEUTER_NOTE}})
end
base.forms[slot] = neut
end
end
local function generate_reflexive_adverbials(base)
local _, long_sfx = pres_participle_suffixes(base)
-- Pusdalyvis: -damasis (praũsdamasis, mókydamasis).
base.forms["pusdalyvis"] = {
{form = combine_S(base.inf_stem_bare, base.inf_stem_ac, "damasis")}
}
-- Present padalyvis: padalyvis + -is coincides with the long-participle
-- suffix shape (praũsiantis, mókantis).
base.forms["padalyvis_pres"] = {
{form = combine_S(base.pres_stem_bare, base.pres_stem_ac, long_sfx)}
}
-- Past padalyvis: -usis / -iusis (praũsusis, mókiusis); same -ius
-- condition as the non-reflexive form.
local sfx = "usis"
if base.conj_subtype == "o" and base.past_stem_type == "ė"
and not base.has_ejo_past then
sfx = "iusis"
end
base.forms["padalyvis_past"] = {
{form = combine_S(base.past_stem_bare, base.past_stem_ac, sfx)}
}
base.forms["padalyvis_past_freq"] = {
{form = combine_S(base.inf_stem_bare .. "dav", base.inf_stem_ac .. "dav", "usis")}
}
local fb, fa = make_future_stem(base.inf_stem_bare, base.inf_stem_ac)
base.forms["padalyvis_fut"] = { {form = combine_S(fb, fa, "iantis")} }
-- Būdinys: not formed from reflexives; slots stay empty ("—").
end
-- =============================================================================
-- Impersonal verbs (the impers parameter)
-- =============================================================================
--
-- Impersonal verbs have only 3rd-person finite forms, and their adjectival
-- participles only the indeclinable neuter (bevardė giminė): the passives of
-- intransitive verbs have no masculine or feminine, and the oblique mood
-- takes the active neuter (sako, ten lyją). The neuter is the masculine
-- nominative singular without the final -s, accent unchanged (lìję, lýdavę,
-- lýsią, lỹjama, lýta, lýtina, reikė́ta), except that the active present
-- neuter is always stem-stressed (lỹją, sniñgą, reĩkią), even where the
-- masculine is end-stressed only (retracting presents: gelią̃ masc/fem nom
-- pl, neuter gẽlią). The long (-antis) forms have no neuter and the
-- pusdalyvis agrees with a nominative subject, so these are dropped; the
-- padalyviai (lietui lyjant) and the būdinys (lyte lỹja type) stay.
-- Every neuter carries IMPERS_NEUTER_NOTE.
local IMPERSONAL_DROPPED_SLOTS = {
"pres_1s", "pres_2s", "pres_1p", "pres_2p",
"past_1s", "past_2s", "past_1p", "past_2p",
"past_freq_1s", "past_freq_2s", "past_freq_1p", "past_freq_2p",
"fut_1s", "fut_2s", "fut_1p", "fut_2p",
"subj_1s", "subj_2s", "subj_1p", "subj_2p",
"imp_2s", "imp_1p", "imp_2p",
"pusdalyvis", "act_pres_long", "act_fut_long",
}
-- Replace every variant in a participle slot with its neuter (final -s
-- stripped, accent unchanged), footnoted IMPERS_NEUTER_NOTE.
local function neuterize_slot(base, slot)
local forms = base.forms[slot]
if not forms then
return
end
local neut = {}
for _, form_obj in ipairs(forms) do
insert(neut, {form = (form_obj.form:gsub("s$", "")),
footnotes = iut.combine_footnotes(form_obj.footnotes, {IMPERS_NEUTER_NOTE})})
end
base.forms[slot] = neut
end
local function apply_impersonal(base)
if not base.is_impersonal then
return
end
if base.is_reflexive then
-- -tis reflexives: the -is/besi- active participles have no
-- neuter (nórįsi is the masculine nominative plural), so the
-- adjectival slots are emptied, the passive neuters in -si with
-- them; the padalyviai remain (nórintis, norė́jusis).
for _, slot in ipairs({"act_pres_short", "act_past",
"act_past_freq", "act_fut_short", "pass_pres", "pass_past"}) do
base.forms[slot] = nil
end
else
-- Active present neuter: the stem-stressed reading only (lỹją,
-- sniñgą, reĩkią, gẽlią), rebuilt from the present stem, since a
-- retracting present has only the end-stressed masculine (gelią̃).
if base.forms["act_pres_short"] then
local short_sfx = pres_participle_suffixes(base)
base.forms["act_pres_short"] = { {form = combine_S(
base.pres_stem_bare, base.pres_stem_ac, short_sfx)} }
end
for _, slot in ipairs({"act_pres_short", "act_past",
"act_past_freq", "act_fut_short", "pass_pres",
"pass_past", "pass_fut", "pass_necess"}) do
neuterize_slot(base, slot)
end
end
for _, slot in ipairs(IMPERSONAL_DROPPED_SLOTS) do
base.forms[slot] = nil
end
end
-- =============================================================================
-- Main form generation dispatcher
-- =============================================================================
local function generate_forms(base)
-- Suppletive verbs: every slot comes from IRREGULAR_FORMS, rendered
-- through display() like a regular form.
local irr = IRREGULAR_FORMS[base.inf_bare .. "," .. base.pres_bare]
if irr then
for slot, forms in pairs(irr) do
base.forms[slot] = {}
-- In the indicative plural slots and the subjunctive 2nd person
-- plural a variant without the final -e is the same colloquial
-- short form the E.* tables flag with `colloq` (ẽsam, bùvom,
-- bū́sit, bū́tumėt).
local short_pl = rfind(slot, "^pres_[12]p$")
or rfind(slot, "^past_[12]p$")
or rfind(slot, "^past_freq_[12]p$")
or rfind(slot, "^fut_[12]p$")
or slot == "subj_2p"
for _, f in ipairs(forms) do
local form_obj = {form = display(to_stem_ac(f))}
if short_pl and not rfind(f, "e$") then
form_obj.footnotes = {COLLOQ_NOTE}
end
insert(base.forms[slot], form_obj)
end
end
apply_impersonal(base)
return base
end
generate_present(base)
generate_past(base)
generate_past_freq(base)
generate_future(base)
generate_subjunctive(base)
generate_imperative(base)
if base.is_reflexive then
generate_reflexive_participles(base)
generate_reflexive_adverbials(base)
apply_impersonal(base)
return base
end
generate_act_pres_participle(base)
generate_act_past_participle(base)
generate_act_past_freq_participle(base)
generate_act_fut_participle(base)
generate_pass_pres_participle(base)
generate_pass_past_participle(base)
generate_pass_fut_participle(base)
generate_pass_necess_participle(base)
generate_pusdalyvis(base)
generate_padalyvis_pres(base)
generate_padalyvis_past(base)
generate_padalyvis_past_freq(base)
generate_padalyvis_fut(base)
generate_budinys(base)
apply_impersonal(base)
return base
end
-- =============================================================================
-- Conjugation pipeline (variant merge, slot overrides, whole footnotes)
-- =============================================================================
-- Merge a footnote list into every form of one slot.
local function attach_footnotes_to_slot(base, slot, footnotes)
if not footnotes then
return
end
for _, form_obj in ipairs(base.forms[slot] or {}) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes, footnotes)
end
end
-- Apply one .SLOT:VALUE override to the merged forms. Values: "--" (the
-- slot does not exist), "+" (keep the auto-generated forms, merging the
-- attached footnotes into each), or a full accented form run through the
-- standard input pipeline. A colon-list mixes "+" and explicit forms
-- freely, each value with its own footnotes.
local function apply_slot_override(base, slot, val_run, unescape, parse_err)
local specs = m_common.fetch_specs(val_run, ":", "slot override", nil, parse_err)
local list = {}
for _, spec in ipairs(specs) do
local v = unescape(spec.form)
if v == "--" then
if #specs > 1 then
parse_err("'--' cannot be combined with other values in slot '"
.. slot .. "'")
end
if spec.footnotes then
parse_err("footnotes not allowed on '--' (the slot is removed entirely)")
end
base.forms[slot] = nil
return
elseif v == "+" then
for _, form_obj in ipairs(base.forms[slot] or {}) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes, spec.footnotes)
iut.insert_form_into_list(list, form_obj)
end
else
local _, v_ac = process_input(v)
iut.insert_form_into_list(list, {form = display(v_ac), footnotes = spec.footnotes})
end
end
base.forms[slot] = list
end
-- Conjugate every principal-part variant combination and merge the results
-- slot by slot (iut.insert_form_into_list), then apply the slot overrides
-- and the whole-conjugation footnotes.
local function finish_conjugation(parsed_all)
local bases = {}
for _, parsed in ipairs(parsed_all.combos) do
local base = build_base_data(parsed)
generate_forms(base)
-- Principal-part footnotes go on the pres_3/past_3 cells; the
-- infinitive's go to the headword line (lemma_footnotes).
attach_footnotes_to_slot(base, "pres_3", parsed.pres_footnotes)
attach_footnotes_to_slot(base, "past_3", parsed.past_footnotes)
base.lemma_footnotes = parsed.inf_footnotes
insert(bases, base)
end
local base = bases[1]
local seen_inf = {[base.infinitive] = true}
for i = 2, #bases do
local other = bases[i]
for slot, forms in pairs(other.forms) do
if not base.forms[slot] then
base.forms[slot] = forms
else
for _, form_obj in ipairs(forms) do
iut.insert_form_into_list(base.forms[slot], form_obj)
end
end
end
base.lemma_footnotes = iut.combine_footnotes(base.lemma_footnotes,
other.lemma_footnotes)
if not seen_inf[other.infinitive] then
seen_inf[other.infinitive] = true
base.infinitive = base.infinitive .. " / " .. other.infinitive
end
end
local params = parsed_all.params
if params.overrides then
for slot, val_run in pairs(params.overrides) do
apply_slot_override(base, slot, val_run,
parsed_all.unescape, parsed_all.parse_err)
end
end
-- A lone .[note] footnotes every form, overrides included.
if params.whole_footnotes then
for _, form_list in pairs(base.forms) do
for _, form_obj in ipairs(form_list) do
form_obj.footnotes = iut.combine_footnotes(form_obj.footnotes,
params.whole_footnotes)
end
end
end
return base
end
-- =============================================================================
-- Wikitext table generation
-- =============================================================================
-- ".ius" in a {{lt-pdecl}} spec: the -ęs participle of an -o-conjugation
-- ė-stem past takes -ius- outside the masculine nominative (mãtęs →
-- mãčiusio), as the padalyvis takes -ius.
local function act_past_takes_ius(base)
return base.conj_subtype == "o" and base.past_stem_type == "ė"
and not base.has_ejo_past
end
-- Spec of a long active present/future slot: "+", the short nominative
-- reading(s) as ".snom:" (see PART_DECL), and on the present ".dvejopai"
-- when the present 3rd person is disyllabic (dìrba, gýdo, tìki; not gyvẽna,
-- važiúoja), which gives the definite forms a second, mobile reading.
local function long_active_spec(base, slot, short_readings)
local spec = "+"
if short_readings and short_readings[1] then
spec = spec .. ".snom:" .. table.concat(short_readings, ":")
end
if slot == "act_pres_long" then
local ok, syls = pcall(lt_pron.get_syllables, toNFC(base.core_pres_ac), false)
if ok and syls and #syls == 2 then
spec = spec .. ".dvejopai"
end
end
return spec
end
-- -tis reflexives: each adjectival slot pairs the -is form (praũsiąsis,
-- praũsęsis), whose {{lt-pdecl}} table is nominative-only, with the besi-
-- form (besipraũsiąs, besipraũsęs), which declines like any prefixed
-- participle. In the short present and future slots the spec is keyed by
-- form: the -is form gets "+" and ".stem:" with the plain long-participle
-- stem (pres stem + -ant/-int/-iant, fut stem + -iant), on which lt-pdecl
-- builds the feminine (praũsiantis, praũsiančiosi), since an end-stressed
-- -is lemma (nešą̃sis) would not show the long form's stress; several -is
-- readings also go in as ".snom:". The besi- short form gets none: its
-- readings go into the ".snom:" of the besi- long form. The past slots take
-- one spec for both forms.
local function compute_reflexive_decl_specs(base)
local specs = {}
local _, long_sfx = pres_participle_suffixes(base)
local fb, fa = make_future_stem(base.inf_stem_bare, base.inf_stem_ac)
local long_stem = {
act_pres_short = combine_S(base.pres_stem_bare, base.pres_stem_ac, (rsub(long_sfx, "is$", ""))),
act_fut_short = combine_S(fb, fa, "iant"),
}
for long_slot, short_slot in pairs(ACT_LONG_SHORT) do
local is_readings, besi_readings = {}, {}
if base.forms[short_slot] then
for _, fo in ipairs(base.forms[short_slot]) do
if rfind(fo.form, "sis$") then
insert(is_readings, fo.form)
else
insert(besi_readings, fo.form)
end
end
local spec = "+.stem:" .. long_stem[short_slot]
if #is_readings > 1 then
local shorts = {}
for _, f in ipairs(is_readings) do
insert(shorts, (rsub(f, "is$", "")))
end
spec = spec .. ".snom:" .. table.concat(shorts, ":")
end
local per_form = {}
for _, f in ipairs(is_readings) do
per_form[f] = spec
end
specs[short_slot] = per_form
end
if base.forms[long_slot] then
specs[long_slot] = long_active_spec(base, long_slot, besi_readings)
end
end
if base.forms["act_past"] then
specs["act_past"] = act_past_takes_ius(base) and "+.ius" or "+"
end
if base.forms["act_past_freq"] then
specs["act_past_freq"] = "+"
end
return specs
end
-- The {{lt-pdecl}} argument ("decl:" pseudo-tag) of every declinable
-- participle slot (see PART_DECL). Must run before iut.show_forms, while
-- the slots still hold form-object lists. specs[slot] is the argument, or a
-- table keyed by form where the forms of one slot differ
-- (compute_reflexive_decl_specs).
local function compute_decl_specs(base)
local specs = {}
if base.is_impersonal then
-- Impersonal neuters are indeclinable.
return specs
end
if base.is_reflexive then
return compute_reflexive_decl_specs(base)
end
for slot, mode in pairs(PART_DECL) do
if base.forms[slot] then
if mode == "AP" then
specs[slot] = "+," .. (is_suffixed_infinitive(base) and "1" or "3")
elseif slot == "act_past" then
specs[slot] = act_past_takes_ius(base) and "+.ius" or "+"
elseif ACT_LONG_SHORT[slot] then
local readings = {}
for _, fo in ipairs(base.forms[ACT_LONG_SHORT[slot]] or {}) do
insert(readings, fo.form)
end
specs[slot] = long_active_spec(base, slot, readings)
else
specs[slot] = "+"
end
end
end
return specs
end
local function make_table(base)
local frame = mw.getCurrentFrame()
local decl_specs = compute_decl_specs(base)
-- Without an explicit pos the creation gadget takes the section title
-- and makes {{head|lt|conjugation form}} entries, so finite slots get
-- pos "verb" and participle slots pos "participle" (Module:accel/lt
-- builds the Participle entry). The neuter tag swap and the "decl:"
-- pseudo-tag are added here as well.
local function transform_accel_obj(slot, form, accel_obj)
if not accel_obj then
return nil
end
if PARTICIPLE_SLOT_SET[slot] then
accel_obj.pos = "participle"
if IMPERS_NEUTER_TAGS[slot] and (base.is_impersonal
or base.is_reflexive and rfind(slot, "^pass_")) then
accel_obj.form = IMPERS_NEUTER_TAGS[slot]
else
local spec = decl_specs[slot]
if type(spec) == "table" then
spec = spec[form.form]
end
if spec then
accel_obj.form = accel_obj.form .. "|decl:" .. spec
end
end
else
accel_obj.pos = "verb"
end
return accel_obj
end
-- iut.show_forms rewrites base.forms[slot] in place (each form-object
-- list becomes one linked string with footnote markers) and puts the
-- footnote definitions in base.forms.footnote. The finite table and the
-- participle box get one pass each, with their own numbering.
local function render_forms(slot_list)
base.forms.footnote = nil
iut.show_forms(base.forms, {
lang = lang,
lemmas = {{form = base.infinitive}},
slot_list = slot_list,
transform_accel_obj = transform_accel_obj,
})
local notes = base.forms.footnote
return notes ~= "" and notes or nil
end
local finite_notes = render_forms(FINITE_SLOT_LIST)
local participle_notes = render_forms(PARTICIPLE_SLOT_LIST)
local title = frame:expandTemplate {
title = "m-self",
args = {"lt", "", base.infinitive},
}
local top = frame:expandTemplate {
title = "inflection-table-top",
args = {title = "Conjugation of " .. title, palette = "blue", tall = "yes"},
}
-- Footnotes of the finite slots go under the finite table itself.
local bot = frame:expandTemplate {
title = "inflection-table-bottom",
args = {notes = finite_notes or ""},
}
-- After show_forms, a populated slot holds its rendered wikitext string;
-- an absent slot is still nil and renders as "—".
local function make_cell(slot)
local s = base.forms[slot]
if type(s) ~= "string" or s == "" or s == "?" then return "—" end
return s
end
-- Join several slots into one physical cell, skipping absent ones.
local function join_cells(...)
local pieces = {}
for _, slot in ipairs({...}) do
local s = make_cell(slot)
if s ~= "—" then insert(pieces, s) end
end
if #pieces == 0 then return "—" end
return concat(pieces, ", ")
end
local parts = {}
insert(parts, [=[
! rowspan="2" | [[tiesioginė nuosaka|indicative]]
! singular
! plural
! singular
! plural
| class="separator" rowspan="9" |
! rowspan="2" |
! singular
! plural
|-
! colspan="2" class="secondary" | [[esamasis laikas|present]]
! colspan="2" class="secondary" | [[būsimasis laikas|future]]
! colspan="2" class="secondary" | [[tariamoji nuosaka|subjunctive]]]=])
insert(parts, "\n|-\n! 1<sup>st</sup> person")
insert(parts, "\n| " .. make_cell("pres_1s"))
insert(parts, "\n| " .. make_cell("pres_1p"))
insert(parts, "\n| " .. make_cell("fut_1s"))
insert(parts, "\n| " .. make_cell("fut_1p"))
insert(parts, "\n! 1<sup>st</sup> person")
insert(parts, "\n| " .. make_cell("subj_1s"))
insert(parts, "\n| " .. make_cell("subj_1p"))
insert(parts, "\n|-\n! 2<sup>nd</sup> person")
insert(parts, "\n| " .. make_cell("pres_2s"))
insert(parts, "\n| " .. make_cell("pres_2p"))
insert(parts, "\n| " .. make_cell("fut_2s"))
insert(parts, "\n| " .. make_cell("fut_2p"))
insert(parts, "\n! 2<sup>nd</sup> person")
insert(parts, "\n| " .. make_cell("subj_2s"))
insert(parts, "\n| " .. make_cell("subj_2p"))
insert(parts, "\n|-\n! 3<sup>rd</sup> person")
insert(parts, "\n| colspan=\"2\" | " .. make_cell("pres_3"))
insert(parts, "\n| colspan=\"2\" | " .. make_cell("fut_3"))
insert(parts, "\n! 3<sup>rd</sup> person")
insert(parts, "\n| colspan=\"2\" | " .. make_cell("subj_3"))
insert(parts, [=[
|-
!
! colspan="2" class="secondary" | [[būtasis kartinis laikas|past]]
! colspan="2" class="secondary" | [[būtasis dažninis laikas|past frequentative]]
!
! colspan="2" class="secondary" | [[liepiamoji nuosaka|imperative]]]=])
insert(parts, "\n|-\n! 1<sup>st</sup> person")
insert(parts, "\n| " .. make_cell("past_1s"))
insert(parts, "\n| " .. make_cell("past_1p"))
insert(parts, "\n| " .. make_cell("past_freq_1s"))
insert(parts, "\n| " .. make_cell("past_freq_1p"))
insert(parts, "\n! 1<sup>st</sup> person")
insert(parts, "\n| —")
insert(parts, "\n| " .. make_cell("imp_1p"))
insert(parts, "\n|-\n! 2<sup>nd</sup> person")
insert(parts, "\n| " .. make_cell("past_2s"))
insert(parts, "\n| " .. make_cell("past_2p"))
insert(parts, "\n| " .. make_cell("past_freq_2s"))
insert(parts, "\n| " .. make_cell("past_freq_2p"))
insert(parts, "\n! 2<sup>nd</sup> person")
insert(parts, "\n| " .. make_cell("imp_2s"))
insert(parts, "\n| " .. make_cell("imp_2p"))
insert(parts, "\n|-\n! 3<sup>rd</sup> person")
insert(parts, "\n| colspan=\"2\" | " .. make_cell("past_3"))
insert(parts, "\n| colspan=\"2\" | " .. make_cell("past_freq_3"))
insert(parts, "\n! 3<sup>rd</sup> person")
insert(parts, "\n| colspan=\"2\" | " .. make_cell("imp_3"))
insert(parts, "")
local rows = concat(parts, "\n")
local make_part_cell = make_cell
local box_top = frame:expandTemplate {
title = "inflection-box-top",
args = {title = "Phân từ của " .. title, flow = "vertical"},
}
local box_bot = frame:expandTemplate {title = "inflection-box-bottom", args = {}}
local top_adj = frame:expandTemplate {
title = "inflection-table-top", args = {palette = "blue", title = "-"},
}
local bot_adj = frame:expandTemplate {title = "inflection-table-bottom", args = {}}
-- The active present and future cells join the short and long slots;
-- an impersonal verb has no long slot, and the cell shows the neuter.
local act_pres_cell = join_cells("act_pres_short", "act_pres_long")
local act_fut_cell = join_cells("act_fut_short", "act_fut_long")
local parts_adj = {}
-- "adjectival" and "adverbial" are plain descriptions and carry no link.
-- The pusdalyvis and padalyvis rows use their English names
-- (half-participle, gerund); the būdinys has none and keeps its own.
insert(parts_adj, [=[! colspan="4" class="outer" | adjectival
|-
!
! active
! passive]=])
insert(parts_adj, "\n|-\n! present\n| " ..
act_pres_cell ..
"\n| " .. make_part_cell("pass_pres"))
insert(parts_adj, "\n|-\n! past\n| " ..
make_part_cell("act_past") .. "\n| " .. make_part_cell("pass_past"))
insert(parts_adj, "\n|-\n! past frequentative\n| " ..
make_part_cell("act_past_freq") .. "\n| —")
insert(parts_adj, "\n|-\n! future\n| " ..
act_fut_cell ..
"\n| " .. make_part_cell("pass_fut"))
insert(parts_adj, "\n|-\n! participle of necessity\n| —\n| " ..
make_part_cell("pass_necess"))
local top_adv = frame:expandTemplate {
title = "inflection-table-top", args = {palette = "blue", title = "-"},
}
-- Footnotes of the participle slots (adjectival + adverbial, one
-- numbering) go under the last sub-table of the box.
local bot_adv = frame:expandTemplate {
title = "inflection-table-bottom",
args = {notes = participle_notes or ""},
}
local parts_adv = {}
insert(parts_adv, [=[! colspan="3" class="outer" | adverbial]=])
insert(parts_adv, "\n|-\n! colspan=\"2\" | [[pusdalyvis|half-participle]]\n| " ..
make_part_cell("pusdalyvis"))
insert(parts_adv,
"\n|-\n! rowspan=\"4\" | [[padalyvis|gerund]]\n! present\n| " ..
make_part_cell("padalyvis_pres"))
insert(parts_adv, "\n|-\n! past\n| " .. make_part_cell("padalyvis_past"))
insert(parts_adv, "\n|-\n! past frequentative\n| " ..
make_part_cell("padalyvis_past_freq"))
insert(parts_adv, "\n|-\n! future\n| " .. make_part_cell("padalyvis_fut"))
insert(parts_adv, "\n|-\n! colspan=\"2\" | [[būdinys]]\n| " ..
join_cells("budinys_1", "budinys_2"))
return top .. rows .. bot .. "\n" ..
box_top .. "\n" ..
top_adj .. concat(parts_adj, "\n") .. "\n" .. bot_adj .. "\n" ..
top_adv .. concat(parts_adv, "\n") .. "\n" .. bot_adv .. "\n" ..
box_bot
end
-- =============================================================================
-- Compound (periphrastic) forms ({{lt-conj-compound}})
-- =============================================================================
--
-- A compound form pairs a form of bū́ti with a nominative participle of the
-- notional verb: the auxiliary carries person, number, tense and mood, the
-- participle voice and relative time, agreeing with the subject in gender and
-- number. Four participles give four series. The paradigms run to several
-- hundred cells and belong on an appendix page rather than in an entry,
-- hence an entry point of their own.
--
-- Reflexives (their -is participles are nominative-only) and impersonals
-- (whose participles exist only in the neuter, so the person and gender axes
-- do not apply) are rejected.
-- The auxiliary is the same for every verb and is listed rather than derived.
-- Plural subjunctive and imperative cells carry one form only, the first one
-- of the simple-tense table. The third person does not distinguish number,
-- but the participle beside it does, so both columns are filled from the one
-- form; there is no first person singular imperative.
local AUX_FINITE = {
pres = {s = {"esù", "esì", "yrà"}, p = {"ẽsame", "ẽsate", "yrà"}},
past = {s = {"buvaũ", "buvaĩ", "bùvo"}, p = {"bùvome", "bùvote", "bùvo"}},
past_freq = {s = {"bū́davau", "bū́davai", "bū́davo"}, p = {"bū́davome", "bū́davote", "bū́davo"}},
fut = {s = {"bū́siu", "bū́si", "bùs"}, p = {"bū́sime", "bū́site", "bùs"}},
subj = {s = {"bū́čiau", "bū́tum", "bū́tų"}, p = {"bū́tume", "bū́tumėte", "bū́tų"}},
imp = {s = {[2] = "bū́k", [3] = "tebūniẽ"}, p = {"bū́kime", "bū́kite", "tebūniẽ"}},
}
-- Oblique auxiliary: the nominative of būti's own active participles. This
-- mood has no person, so its blocks are two rows deep instead of six.
local AUX_OBLIQUE = {
pres = {m_s = "ẽsąs", m_p = "ẽsą", f_s = "ẽsanti", f_p = "ẽsančios"},
past = {m_s = "bùvęs", m_p = "bùvę", f_s = "bùvusi", f_p = "bùvusios"},
past_freq = {m_s = "bū́davęs", m_p = "bū́davę", f_s = "bū́davusi", f_p = "bū́davusios"},
fut = {m_s = "bū́siąs", m_p = "bū́sią", f_s = "bū́sianti", f_p = "bū́siančios"},
}
local INDICATIVE_TENSES = {
{key = "pres", label = "present"},
{key = "past", label = "past"},
{key = "past_freq", label = "past frequentative"},
{key = "fut", label = "future"},
}
-- The four series, in the order they are shown. `no_present` marks
-- the continuative, which has no present tense in any mood.
local COMPOUND_SERIES = {
{key = "perf_act", title = "Compound perfect tenses"},
{key = "cont", title = "Compound continuative tenses", no_present = true},
{key = "impf_pass", title = "Compound imperfect passive tenses"},
{key = "perf_pass", title = "Compound perfect passive tenses"},
}
-- Nominatives of the participle each series is built on, as {m_s, m_p, f_s,
-- f_p} lists of readings.
local function compound_participles(base)
local m_pdecl = require("Module:lt-participle")
local out = {}
local function first_form(slot)
local list = base.forms[slot]
return list and list[1] and list[1].form or nil
end
local function four(n, short)
return {
m_s = short and n.ms_s or n.m_s, m_p = short and n.ms_p or n.m_p,
f_s = n.f_s, f_p = n.f_p,
}
end
-- Perfect: the past active participle. An -o-conjugation ė-stem past
-- takes -ius- outside the masculine nominative, which the feminine
-- already shows (mãčiusi, not *mãtusi).
local past_part = first_form("act_past")
if past_part then
local has_ius = base.conj_subtype == "o" and base.past_stem_type == "ė"
and not base.has_ejo_past
out.perf_act = four(m_pdecl.nominatives(past_part, nil, {has_ius_tag = has_ius}))
end
-- Continuative: the present active participle with be-. The affix is
-- prefixed as is where something already precedes the root
-- (beàtnešantis); where the verb is unprefixed and its present
-- retracts, the affix takes the stress (bènešantis), as besi- does in a
-- reflexive. The masculine of this series is the short nominative, whose
-- accent depends on present_retracts and so comes from here, not from
-- lt-pdecl.
local pb, pa = base.pres_stem_bare, base.pres_stem_ac
local short_sfx, long_sfx, end_sfx = pres_participle_suffixes(base)
local be_long
if not base.has_prefix and present_retracts(base) then
be_long = display("be" .. GRAVE .. pb .. long_sfx)
else
be_long = "be" .. combine_S(pb, pa, long_sfx)
end
local be_short = {}
local mode = short_participle_mode(base)
if mode == "end" or mode == "both" then
insert(be_short, display("be" .. pb .. end_sfx))
end
if mode == "stem" or mode == "both" then
insert(be_short, "be" .. combine_S(pb, pa, short_sfx))
end
out.cont = four(m_pdecl.nominatives(be_long, nil, {snom = be_short}), true)
-- Passive: a non-suffixed infinitive gives a mobile paradigm (AP3), a
-- suffixed one keeps the infinitive accent (AP1).
local ap = is_suffixed_infinitive(base) and 1 or 3
for _, spec in ipairs({{"impf_pass", "pass_pres"}, {"perf_pass", "pass_past"}}) do
local form = first_form(spec[2])
if form then
out[spec[1]] = four(m_pdecl.nominatives(form, ap))
end
end
return out
end
-- One cell: the auxiliary before every reading of the participle slot.
local function compound_cell(aux, readings)
if not aux or not readings or not readings[1] then return "—" end
local pieces = {}
for _, reading in ipairs(readings) do
insert(pieces, display(aux) .. " " .. reading)
end
return table.concat(pieces, ", ")
end
local PERSON_LABELS = {"1st", "2nd", "3rd"}
-- The abbreviations of {{g}} (m, f, sg, pl), without categories.
local gender_abbr_cache = {}
local function gender_abbr(spec)
if not gender_abbr_cache[spec] then
gender_abbr_cache[spec] = require("Module:gender and number").format_genders({spec})
end
return gender_abbr_cache[spec]
end
-- The header rows shared by both blocks: the mood across the whole table when
-- `mood` is given, then the tense of each column pair over its two numbers.
local function compound_head(lead, tenses, mood)
local parts = {}
if mood then
insert(parts, '! colspan="' .. (#lead + 2 * #tenses) .. '" class="outer" | ' .. mood .. "\n|-\n")
end
local head1, head2 = {}, {}
for _, cell in ipairs(lead) do
insert(head1, 'rowspan="2" | ' .. cell)
end
for _, t in ipairs(tenses) do
insert(head1, 'colspan="2" | ' .. t.label)
insert(head2, 'class="secondary" | ' .. gender_abbr("s"))
insert(head2, 'class="secondary" | ' .. gender_abbr("p"))
end
insert(parts, "! " .. table.concat(head1, " !! ") ..
"\n|-\n! " .. table.concat(head2, " !! "))
return table.concat(parts)
end
-- A person block: six rows (three persons, each masculine over feminine) with
-- one singular and one plural column per tense listed in `tenses`.
local function compound_person_block(nom, tenses, mood)
local parts = {}
insert(parts, compound_head({"person", "gender"}, tenses, mood))
for person = 1, 3 do
for _, gender in ipairs({"m", "f"}) do
local row = {}
if gender == "m" then
insert(row, '! rowspan="2" | ' .. PERSON_LABELS[person] .. "\n! " .. gender_abbr("m"))
else
insert(row, "! " .. gender_abbr("f"))
end
local cells = {}
for _, t in ipairs(tenses) do
local aux = t.aux
insert(cells, compound_cell(aux.s[person], nom[gender .. "_s"]))
insert(cells, compound_cell(aux.p[person], nom[gender .. "_p"]))
end
insert(parts, "\n|-\n" .. row[1] .. "\n| " .. table.concat(cells, "\n| "))
end
end
return table.concat(parts)
end
-- The oblique block: no person axis, so two rows and one column pair per tense.
local function compound_oblique_block(nom, tenses, mood)
local parts = {}
insert(parts, compound_head({"gender"}, tenses, mood))
for _, gender in ipairs({"m", "f"}) do
local cells = {}
for _, t in ipairs(tenses) do
local aux = AUX_OBLIQUE[t.key]
insert(cells, compound_cell(aux[gender .. "_s"], nom[gender .. "_s"]))
insert(cells, compound_cell(aux[gender .. "_p"], nom[gender .. "_p"]))
end
insert(parts, "\n|-\n! " .. gender_abbr(gender) ..
"\n| " .. table.concat(cells, "\n| "))
end
return table.concat(parts)
end
local MOOD_INDICATIVE = "[[tiesioginė nuosaka|indicative]]"
local MOOD_OBLIQUE = "[[netiesioginė nuosaka|oblique mood]]"
local function make_compound_tables(base)
local frame = mw.getCurrentFrame()
local all_nom = compound_participles(base)
local title = frame:expandTemplate {
title = "m-self",
args = {"lt", "", base.infinitive},
}
local sub_top = frame:expandTemplate {
title = "inflection-table-top", args = {palette = "blue", title = "-"},
}
local sub_bot = frame:expandTemplate {title = "inflection-table-bottom", args = {}}
local output = {}
for _, series in ipairs(COMPOUND_SERIES) do
local nom = all_nom[series.key]
if nom and (nom.m_s or nom.f_s) then
-- Indicative, split in two so neither table grows past four form
-- columns; the continuative has no present, so its first table
-- carries the future alone.
local ind = {}
for _, t in ipairs(INDICATIVE_TENSES) do
if not (series.no_present and t.key == "pres") then
insert(ind, {key = t.key, label = t.label, aux = AUX_FINITE[t.key]})
end
end
-- Group as (present, future) and (past, past frequentative), or
-- the surviving subset of each.
local groupA, groupB = {}, {}
for _, t in ipairs(ind) do
if t.key == "pres" or t.key == "fut" then insert(groupA, t) else insert(groupB, t) end
end
local tables = {}
-- The indicative and the oblique mood share their tense names, so
-- their tables carry the mood above them; the subjunctive and the
-- imperative name it in their column header.
if #groupA > 0 then insert(tables, compound_person_block(nom, groupA, MOOD_INDICATIVE)) end
if #groupB > 0 then insert(tables, compound_person_block(nom, groupB, MOOD_INDICATIVE)) end
insert(tables, compound_person_block(nom,
{{key = "subj", label = "subjunctive", aux = AUX_FINITE.subj}}))
insert(tables, compound_person_block(nom,
{{key = "imp", label = "imperative", aux = AUX_FINITE.imp}}))
local obl = {}
for _, t in ipairs(INDICATIVE_TENSES) do
if not (series.no_present and t.key == "pres") then
insert(obl, {key = t.key, label = t.label})
end
end
insert(tables, compound_oblique_block(nom, obl, MOOD_OBLIQUE))
local box_top = frame:expandTemplate {
title = "inflection-box-top",
args = {title = series.title .. " of " .. title, flow = "vertical"},
}
local box_bot = frame:expandTemplate {title = "inflection-box-bottom", args = {}}
insert(output, box_top)
for _, body in ipairs(tables) do
insert(output, sub_top .. body .. "\n" .. sub_bot)
end
insert(output, box_bot)
end
end
return table.concat(output, "\n")
end
-- =============================================================================
-- Public interface
-- =============================================================================
-- Main entry point for {{lt-conj}}.
function export.show(frame)
-- {{lt-conj}} passes legacy=lt-conj: a call of the legacy table goes to
-- Template:lt-conj/old.
if frame.args.legacy and m_common.is_legacy_conj(frame:getParent().args) then
return m_common.render_legacy(frame, frame.args.legacy)
end
local raw_input = frame:getParent().args[1] or "kalbė́ti,kal̃ba,kalbė́jo"
local base = finish_conjugation(parse_params({[1] = raw_input}))
return make_table(base)
end
-- Main entry point for {{lt-conj-compound}}: the full compound paradigm, for
-- an appendix rather than an entry. Same three principal parts as
-- {{lt-conj}}.
function export.show_compound(frame)
local raw_input = frame:getParent().args[1] or "at-nèšti,àtneša,àtnešė"
local base = finish_conjugation(parse_params({[1] = raw_input}))
if base.is_reflexive then
error("lt-conj-compound: reflexive verbs are not supported; their -is " ..
"participles are nominative-only and the compound paradigm of a -tis " ..
"verb is not laid out here")
end
if base.is_impersonal then
error("lt-conj-compound: impersonal verbs have no compound paradigm of " ..
"this shape, their participles being confined to the neuter")
end
return make_compound_tables(base)
end
-- Testing interface for the compound forms: the participle nominatives each
-- series is built on, without the auxiliary or the table markup.
function export.compound_for_testing(infinitive, present_3, past_3, params)
local input = infinitive .. "," .. present_3 .. "," .. past_3
local parsed_all = parse_params({[1] = input})
if params then
for k, v in pairs(params) do parsed_all.params[k] = v end
end
return compound_participles(finish_conjugation(parsed_all))
end
-- Testing interface: the merged base, with base.forms still form-object
-- lists ({form=, footnotes=}); nothing is rendered.
function export.conjugate_for_testing(infinitive, present_3, past_3, params)
local input = infinitive .. "," .. present_3 .. "," .. past_3
local parsed_all = parse_params({[1] = input})
if params then
for k, v in pairs(params) do parsed_all.params[k] = v end
end
return finish_conjugation(parsed_all)
end
-- Testing interface for the accel declension specs: slot → {{lt-pdecl}}
-- argument, or form → argument for the mixed slots of a -tis reflexive
-- (see compute_decl_specs).
function export.decl_specs_for_testing(infinitive, present_3, past_3, params)
local input = infinitive .. "," .. present_3 .. "," .. past_3
local parsed_all = parse_params({[1] = input})
if params then
for k, v in pairs(params) do parsed_all.params[k] = v end
end
return compute_decl_specs(finish_conjugation(parsed_all))
end
-- =============================================================================
-- Table cells as tag sets (used by {{lt-head|verb form|…}})
-- =============================================================================
-- The finite slots in the order of the table (tense by tense).
local FINITE_TABLE_ORDER = {}
do
local tags = {}
for _, entry in ipairs(FINITE_SLOT_LIST) do
tags[entry[1]] = entry[2]
end
for _, tense in ipairs({"pres", "past", "past_freq", "fut", "subj", "imp"}) do
for _, person in ipairs({"1s", "2s", "3", "1p", "2p"}) do
local slot = tense .. "_" .. person
if tags[slot] then
insert(FINITE_TABLE_ORDER, {slot, tags[slot]})
end
end
end
end
-- Every filled finite cell of the {{lt-conj}} table of `pattern_str`, in
-- table order, as {tags = {…}, forms = <form-object list>}, with the
-- accelerator tags of the table. The participles and the adverbial forms are
-- entries of their own and are not included.
function export.form_cells(pattern_str)
local base = finish_conjugation(parse_params({[1] = pattern_str}))
local cells = {}
for _, entry in ipairs(FINITE_TABLE_ORDER) do
local list = base.forms[entry[1]]
if list and list[1] then
insert(cells, {tags = mw.text.split(entry[2], "|", true), forms = list})
end
end
return {lemma = base.infinitive, cells = cells}
end
-- =============================================================================
-- Headword data interface (used by Module:lt-headword)
-- =============================================================================
function export.get_headword_data(pattern_str)
local base = finish_conjugation(parse_params({[1] = pattern_str}))
-- pres_3/past_3 are form-object lists ({form=, footnotes=}, several after
-- a colon-list merge), so that lt-headword can show per-form qualifiers;
-- lemma_footnotes are the infinitive's. The colloquial short forms
-- (praũsias beside praũsiasi) are not principal parts.
local function principal(forms)
if not forms then
return nil
end
local out = {}
for _, form_obj in ipairs(forms) do
local colloq = false
for _, note in ipairs(form_obj.footnotes or {}) do
if note == COLLOQ_NOTE then
colloq = true
end
end
if not colloq then
insert(out, form_obj)
end
end
return out
end
return {
lemma = base.infinitive,
lemma_footnotes = base.lemma_footnotes,
pres_3 = principal(base.forms.pres_3),
past_3 = principal(base.forms.past_3),
-- a -tis verb, or a prefixed one with -si- in its chain (nusi-praũsti)
reflexive = base.is_reflexive or base.has_si or nil,
}
end
return export
lf9xatzkz1sxq0hghtkcfewipd3e18g
gemoette
0
422457
2576493
2026-11-09T10:17:23Z
Hiyuune
50834
Trang mới: “=={{langname|nl}}== ==={{section|v}}=== {{head|nl|vf}} # {{infl of|nl|gemoeten||past-sg}} ==={{section|ana}}=== * {{l|nl|tegemoet}}”
2576493
wikitext
text/x-wiki
=={{langname|nl}}==
==={{section|v}}===
{{head|nl|vf}}
# {{infl of|nl|gemoeten||past-sg}}
==={{section|ana}}===
* {{l|nl|tegemoet}}
b91lb5nk0j2n37kg5f509d3dfzx500f
gemoet
0
422458
2576494
2026-11-09T10:33:08Z
Hiyuune
50834
Trang mới: “=={{langname|nl}}== ==={{section|etym}}=== Từ {{m|nl|gemoeten}}. ==={{section|pron}}=== * {{rhymes|nl|ut|s=2}} ==={{section|n}}=== {{nl-noun|n|-|-}} # {{lb|nl|obsolete}} Cuộc [[gặp gỡ]], cuộc [[hội họp]], [[hội nghị]]. ===={{section|drv}}==== * {{l|nl|tegemoet}} ==={{section|v}}=== {{head|nl|vf}} # {{infl of|nl|gemoeten||bare-ten-verb}} ==={{section|ptcp}}=== {{nl-past-ptc}} # {{past participle of|nl|gemoeten}} ====Declension==== {{nl-decl-past…”
2576494
wikitext
text/x-wiki
=={{langname|nl}}==
==={{section|etym}}===
Từ {{m|nl|gemoeten}}.
==={{section|pron}}===
* {{rhymes|nl|ut|s=2}}
==={{section|n}}===
{{nl-noun|n|-|-}}
# {{lb|nl|obsolete}} Cuộc [[gặp gỡ]], cuộc [[hội họp]], [[hội nghị]].
===={{section|drv}}====
* {{l|nl|tegemoet}}
==={{section|v}}===
{{head|nl|vf}}
# {{infl of|nl|gemoeten||bare-ten-verb}}
==={{section|ptcp}}===
{{nl-past-ptc}}
# {{past participle of|nl|gemoeten}}
====Declension====
{{nl-decl-past-ptc}}
ciqu8oucz0qvb8wveu00a0t4tckc8or
иллинойсский
0
422459
2576496
2026-11-09T11:49:32Z
Hiyuune
50834
/* */
2576496
wikitext
text/x-wiki
=={{langname|ru}}==
==={{section|pron}}===
* {{ru-IPA|иллино́йс(с)кий}}
==={{section|adj}}===
{{ru-adj|иллино́йсский}}
# {{alt of|ru|иллино́йский}}
===={{section|decl}}====
{{ru-decl-adj|иллино́йсский}}
ai8d5m346u5z9d58733lk4hlve9d79u
хеллоуинский
0
422460
2576497
2026-11-09T11:51:31Z
Hiyuune
50834
/* */
2576497
wikitext
text/x-wiki
=={{langname|ru}}==
==={{section|pron}}===
* {{ru-IPA|phon=хэллоуи́нский}}
==={{section|adj}}===
{{ru-adj|хеллоуи́нский<tr:xɛllouínskij>}}
# {{alt of|ru|хэллоуи́нский}}
===={{section|decl}}====
{{ru-decl-adj|хеллоуи́нский//xɛllouínskij}}
33ql61zmevxn3d5goer8c5v73ss1j1d