From c764c94cc2abb1b6bfd4003afb9c56fcc64c25d5 Mon Sep 17 00:00:00 2001 From: Hyperzlib Date: Sat, 16 Aug 2025 11:18:26 +0000 Subject: [PATCH] Init --- CODE_OF_CONDUCT.md | 1 + COPYING | 339 ++++++++++++++++++++ composer.json | 27 ++ extension.json | 77 +++++ i18n/api/ar.json | 21 ++ i18n/api/ast.json | 20 ++ i18n/api/de.json | 24 ++ i18n/api/en.json | 21 ++ i18n/api/es.json | 15 + i18n/api/fa.json | 8 + i18n/api/fr.json | 29 ++ i18n/api/gl.json | 19 ++ i18n/api/he.json | 24 ++ i18n/api/hu.json | 16 + i18n/api/ia.json | 23 ++ i18n/api/it.json | 12 + i18n/api/ja.json | 11 + i18n/api/ko.json | 10 + i18n/api/ksh.json | 14 + i18n/api/mk.json | 23 ++ i18n/api/nb.json | 24 ++ i18n/api/nl.json | 23 ++ i18n/api/pl.json | 21 ++ i18n/api/pt-br.json | 24 ++ i18n/api/pt.json | 20 ++ i18n/api/qqq.json | 23 ++ i18n/api/roa-tara.json | 23 ++ i18n/api/ru.json | 21 ++ i18n/api/sl.json | 23 ++ i18n/api/sr-ec.json | 14 + i18n/api/sr-el.json | 10 + i18n/api/sv.json | 21 ++ i18n/api/tr.json | 21 ++ i18n/api/uk.json | 24 ++ i18n/api/zh-hans.json | 27 ++ i18n/api/zh-hant.json | 23 ++ i18n/ar.json | 8 + i18n/ast.json | 8 + i18n/ce.json | 8 + i18n/cs.json | 8 + i18n/de.json | 8 + i18n/dsb.json | 8 + i18n/en.json | 6 + i18n/es.json | 10 + i18n/fa.json | 9 + i18n/fr.json | 11 + i18n/gl.json | 10 + i18n/he.json | 9 + i18n/hsb.json | 8 + i18n/hu.json | 8 + i18n/ia.json | 8 + i18n/id.json | 8 + i18n/it.json | 8 + i18n/ja.json | 9 + i18n/ko.json | 9 + i18n/ksh.json | 8 + i18n/mk.json | 8 + i18n/ml.json | 8 + i18n/nb.json | 9 + i18n/nl.json | 10 + i18n/oc.json | 8 + i18n/pl.json | 10 + i18n/pt-br.json | 11 + i18n/pt.json | 10 + i18n/qqq.json | 8 + i18n/roa-tara.json | 8 + i18n/ru.json | 8 + i18n/scn.json | 8 + i18n/sl.json | 8 + i18n/sr-ec.json | 9 + i18n/sr-el.json | 6 + i18n/sv.json | 8 + i18n/tr.json | 8 + i18n/uk.json | 10 + i18n/vi.json | 8 + i18n/zh-hans.json | 9 + i18n/zh-hant.json | 8 + includes/ApiQueryExtracts.php | 408 +++++++++++++++++++++++++ includes/ExtractFormatter.php | 109 +++++++ includes/Hooks.php | 145 +++++++++ includes/TextTruncator.php | 111 +++++++ tests/phpunit/ApiQueryExtractsTest.php | 274 +++++++++++++++++ tests/phpunit/ExtractFormatterTest.php | 108 +++++++ tests/phpunit/TextTruncatorTest.php | 178 +++++++++++ 84 files changed, 2758 insertions(+) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 COPYING create mode 100644 composer.json create mode 100644 extension.json create mode 100644 i18n/api/ar.json create mode 100644 i18n/api/ast.json create mode 100644 i18n/api/de.json create mode 100644 i18n/api/en.json create mode 100644 i18n/api/es.json create mode 100644 i18n/api/fa.json create mode 100644 i18n/api/fr.json create mode 100644 i18n/api/gl.json create mode 100644 i18n/api/he.json create mode 100644 i18n/api/hu.json create mode 100644 i18n/api/ia.json create mode 100644 i18n/api/it.json create mode 100644 i18n/api/ja.json create mode 100644 i18n/api/ko.json create mode 100644 i18n/api/ksh.json create mode 100644 i18n/api/mk.json create mode 100644 i18n/api/nb.json create mode 100644 i18n/api/nl.json create mode 100644 i18n/api/pl.json create mode 100644 i18n/api/pt-br.json create mode 100644 i18n/api/pt.json create mode 100644 i18n/api/qqq.json create mode 100644 i18n/api/roa-tara.json create mode 100644 i18n/api/ru.json create mode 100644 i18n/api/sl.json create mode 100644 i18n/api/sr-ec.json create mode 100644 i18n/api/sr-el.json create mode 100644 i18n/api/sv.json create mode 100644 i18n/api/tr.json create mode 100644 i18n/api/uk.json create mode 100644 i18n/api/zh-hans.json create mode 100644 i18n/api/zh-hant.json create mode 100644 i18n/ar.json create mode 100644 i18n/ast.json create mode 100644 i18n/ce.json create mode 100644 i18n/cs.json create mode 100644 i18n/de.json create mode 100644 i18n/dsb.json create mode 100644 i18n/en.json create mode 100644 i18n/es.json create mode 100644 i18n/fa.json create mode 100644 i18n/fr.json create mode 100644 i18n/gl.json create mode 100644 i18n/he.json create mode 100644 i18n/hsb.json create mode 100644 i18n/hu.json create mode 100644 i18n/ia.json create mode 100644 i18n/id.json create mode 100644 i18n/it.json create mode 100644 i18n/ja.json create mode 100644 i18n/ko.json create mode 100644 i18n/ksh.json create mode 100644 i18n/mk.json create mode 100644 i18n/ml.json create mode 100644 i18n/nb.json create mode 100644 i18n/nl.json create mode 100644 i18n/oc.json create mode 100644 i18n/pl.json create mode 100644 i18n/pt-br.json create mode 100644 i18n/pt.json create mode 100644 i18n/qqq.json create mode 100644 i18n/roa-tara.json create mode 100644 i18n/ru.json create mode 100644 i18n/scn.json create mode 100644 i18n/sl.json create mode 100644 i18n/sr-ec.json create mode 100644 i18n/sr-el.json create mode 100644 i18n/sv.json create mode 100644 i18n/tr.json create mode 100644 i18n/uk.json create mode 100644 i18n/vi.json create mode 100644 i18n/zh-hans.json create mode 100644 i18n/zh-hant.json create mode 100644 includes/ApiQueryExtracts.php create mode 100644 includes/ExtractFormatter.php create mode 100644 includes/Hooks.php create mode 100644 includes/TextTruncator.php create mode 100644 tests/phpunit/ApiQueryExtractsTest.php create mode 100644 tests/phpunit/ExtractFormatterTest.php create mode 100644 tests/phpunit/TextTruncatorTest.php diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..498acf7 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1 @@ +The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct). diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a1edd38 --- /dev/null +++ b/composer.json @@ -0,0 +1,27 @@ +{ + "require-dev": { + "mediawiki/mediawiki-codesniffer": "45.0.0", + "mediawiki/mediawiki-phan-config": "0.14.0", + "mediawiki/minus-x": "1.1.3", + "php-parallel-lint/php-console-highlighter": "1.0.0", + "php-parallel-lint/php-parallel-lint": "1.4.0" + }, + "scripts": { + "fix": [ + "minus-x fix .", + "phpcbf" + ], + "test": [ + "parallel-lint . --exclude vendor --exclude node_modules", + "@phpcs", + "minus-x check ." + ], + "phan": "phan -d . --long-progress-bar", + "phpcs": "phpcs -sp --cache" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/extension.json b/extension.json new file mode 100644 index 0000000..590e240 --- /dev/null +++ b/extension.json @@ -0,0 +1,77 @@ +{ + "name": "IsekaiTextExtracts", + "author": [ + "Max Semenik" + ], + "requires": { + "MediaWiki": ">= 1.43" + }, + "url": "https://git.isekai.cn/hyperzlib/IsekaiTextExtracts", + "descriptionmsg": "textextracts-desc", + "license-name": "GPL-2.0-or-later", + "type": "other", + "ConfigRegistry": { + "textextracts": "GlobalVarConfig::newInstance" + }, + "APIPropModules": { + "extracts": { + "class": "MediaWiki\\Extension\\TextExtracts\\ApiQueryExtracts", + "services": [ + "ConfigFactory", + "MainWANObjectCache", + "LanguageConverterFactory", + "WikiPageFactory", + "TitleFormatter" + ] + } + }, + "MessagesDirs": { + "TextExtracts": [ + "i18n", + "i18n/api" + ] + }, + "AutoloadNamespaces": { + "MediaWiki\\Extension\\TextExtracts\\": "includes/" + }, + "Hooks": { + "ApiOpenSearchSuggest": "main", + "SearchResultProvideDescription": "main" + }, + "HookHandlers": { + "main": { + "class": "MediaWiki\\Extension\\TextExtracts\\Hooks", + "services": [ + "ConfigFactory" + ] + } + }, + "config": { + "ExtractsRemoveClasses": { + "value": [ + "table", + "div", + "figure", + "script", + "input", + "style", + "ul.gallery", + ".mw-editsection", + "sup.reference", + "ol.references", + ".error", + ".nomobile", + ".noprint", + ".noexcerpt", + ".sortkey" + ] + }, + "ExtractsExtendOpenSearchXml": { + "value": false + }, + "ExtractsExtendRestSearch": { + "value": false + } + }, + "manifest_version": 2 +} diff --git a/i18n/api/ar.json b/i18n/api/ar.json new file mode 100644 index 0000000..22faec7 --- /dev/null +++ b/i18n/api/ar.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [ + "ديفيد", + "Meno25" + ] + }, + "apihelp-query+extracts-summary": "يعرض نصا عاديا أو مقتطفات HTML محدودة من الصفحات المعينة.", + "apihelp-query+extracts-param-chars": "كم عدد شخصيات للعودة؟ قد يكون النص الفعلي المرتجع أطول قليلا.", + "apihelp-query+extracts-param-sentences": "كم عدد الجمل للعودة.", + "apihelp-query+extracts-param-limit": "كم عدد المقتطفات للعودة. (يمكن فقط إرجاع المقتطفات المتعددة إذا تم تعيين exintro إلى true.)", + "apihelp-query+extracts-param-intro": "إرجاع المحتوى فقط قبل القسم الأول.", + "apihelp-query+extracts-param-plaintext": "عودة ال مقتطفات كنص عادي بدلا من HTML محدود.", + "apihelp-query+extracts-param-sectionformat": "كيفية تنسيق الأقسام في وضع النص البسيط:", + "apihelp-query+extracts-example-1": "الحصول على استخراج 175 حرفا", + "apiwarn-textextracts-limit": "كان exlimit كبيرا جدا للحصول على طلب مقتطفات لمقالة بأكملها; انخفض إلى $1.", + "apiwarn-textextracts-unsupportedmodel": "يحتوي $1 على نموذج محتوى $2، وهو غير مدعوم; إرجاع مستخلص فارغ.", + "apiwarn-textextracts-title-in-file-namespace": "تم طلب استخراج عنوان في نطاق الملف، ولم يتم إرجاع أي شيء.", + "apiwarn-textextracts-sentences-and-html": "قد يحتوي الوسيط $1sentences على نتائج غير متوقعة عند استخدامها في وضع HTML.", + "apiwarn-textextracts-malformed-html": "قد يكون HTML غير صحيح و/أو غير متوازن وقد يحذف الصور المضمنة، استخدم على مسؤوليتك الخاصة. يتم سرد المشاكل المعروفة في https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/ast.json b/i18n/api/ast.json new file mode 100644 index 0000000..0d8ef09 --- /dev/null +++ b/i18n/api/ast.json @@ -0,0 +1,20 @@ +{ + "@metadata": { + "authors": [ + "Xuacu" + ] + }, + "apihelp-query+extracts-summary": "Devuelve testu planu o estractos en HTML parciales de les páxines indicaes.", + "apihelp-query+extracts-param-chars": "Cuántos caráuteres hai que devolver. El testu real devueltu puede ser un poco más llargu.", + "apihelp-query+extracts-param-sentences": "Cuántes frases hai que devolver.", + "apihelp-query+extracts-param-limit": "Cuántos estractos van devolvese. (Sólo pueden devolvese estractos múltiples s'establez «exintro» como verdadero.)", + "apihelp-query+extracts-param-intro": "Devolver sólo el conteníu anterior a la primera seición.", + "apihelp-query+extracts-param-plaintext": "Devolver estractos como testu planu en llugar de HTML parcial.", + "apihelp-query+extracts-param-sectionformat": "Como dar formatu a les seiciones en mou testu planu:\n;plain:Sin formatu.\n;wiki:Formatu d'estilu testu wiki (== como esto ==).\n;raw:Representación interna d'esti módulu (títulos de sección prefixaos con <ASCII 1><ASCII 2><nivel de seición><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Recibir un estractu de 175 caráuteres", + "apiwarn-textextracts-limit": "exlimit yera grande enforma pa una solicitú completa d'estractos del artículu, baxóse a $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 tien el modelu de conteníu $2, que nun ye compatible; devolveráse un estractu vacíu.", + "apiwarn-textextracts-title-in-file-namespace": "Pidióse l'estractu d'un títulu del espaciu de nomes Ficheru, nun se devolvió nada.", + "apiwarn-textextracts-sentences-and-html": "El parámetru $1sentences puede tener resultaos inesperaos cuando s'usa en mou HTML.", + "apiwarn-textextracts-malformed-html": "El HTML puede tar mal escritu y/o nun tar equilibráu y puede omitir les imáxenes en llinia. Úsalu so la to responsabilidá. Los problemes conocíos recuéyense'n https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/de.json b/i18n/api/de.json new file mode 100644 index 0000000..048938c --- /dev/null +++ b/i18n/api/de.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "Justman10000", + "Metalhead64" + ] + }, + "apihelp-query+extracts-summary": "Gibt den Klartext oder beschränkte HTML-Auszüge der angegebenen Seiten zurück.", + "apihelp-query+extracts-param-chars": "Wie viele Zeichen zurückgegeben werden sollen. Der tatsächlich zurückgegebene Text kann etwas länger sein.", + "apihelp-query+extracts-param-sentences": "Wie viele Sätze zurückgegeben werden sollen.", + "apihelp-query+extracts-param-limit": "Wie viele Auszüge zurückgegeben werden sollen (mehrere Auszüge können nur zurückgegeben werden, wenn exintro auf true gesetzt ist).", + "apihelp-query+extracts-param-intro": "Gibt nur den Inhalt vor dem ersten Abschnitt zurück.", + "apihelp-query+extracts-param-plaintext": "Gibt Auszüge als Klartext anstatt in beschränktem HTML zurück.", + "apihelp-query+extracts-param-sectionformat": "So formatierst du Abschnitte im Klartextmodus:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Keine Formatierung.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Formatierung im Wikitext-Stil (== wie hier ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Die interne Darstellung dieses Moduls (Abschnittstitel mit vorangestelltem <ASCII 1><ASCII 2><Abschnittsebene><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Ruft einen 175-Zeichen-Auszug ab", + "apiwarn-textextracts-limit": "exlimit war zu groß für eine ganze Artikelauszugsabfrage, begrenzt auf $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 hat das Inhaltsmodell $2, das nicht unterstützt wird. Es wird ein leerer Auszug zurückgegeben.", + "apiwarn-textextracts-title-in-file-namespace": "Es wurde ein Auszug für einen Titel im Dateinamensraum angefordert, jedoch wurde nichts zurückgegeben.", + "apiwarn-textextracts-sentences-and-html": "Der Parameter $1sentences könnte unerwartete Ergebnisse aufweisen, wenn er im HTML-Modus verwendet wird.", + "apiwarn-textextracts-malformed-html": "HTML könnte beschädigt und/oder unausgeglichen sein und Inline-Bilder weglassen. Verwendung auf eigene Gefahr. Bekannte Probleme sind unter https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats aufgelistet." +} diff --git a/i18n/api/en.json b/i18n/api/en.json new file mode 100644 index 0000000..01feb1c --- /dev/null +++ b/i18n/api/en.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [] + }, + "apihelp-query+extracts-summary": "Returns plain-text or limited HTML extracts of the given pages.", + "apihelp-query+extracts-param-chars": "How many characters to return. Actual text returned might be slightly longer.", + "apihelp-query+extracts-param-sentences": "How many sentences to return.", + "apihelp-query+extracts-param-limit": "How many extracts to return. (Multiple extracts can only be returned if exintro is set to true.)", + "apihelp-query+extracts-param-intro": "Return only content before the first section.", + "apihelp-query+extracts-param-plaintext": "Return extracts as plain text instead of limited HTML.", + "apihelp-query+extracts-param-sectionformat": "How to format sections in plaintext mode:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "No formatting.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Wikitext-style formatting (== like this ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "This module's internal representation (section titles prefixed with <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Get a 175-character extract", + "apiwarn-textextracts-limit": "exlimit was too large for a whole article extracts request, lowered to $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 has content model $2, which is not supported; returning an empty extract.", + "apiwarn-textextracts-title-in-file-namespace": "Extract for a title in File namespace was requested, none returned.", + "apiwarn-textextracts-sentences-and-html": "The $1sentences parameter may have unexpected results when used in HTML mode.", + "apiwarn-textextracts-malformed-html": "HTML may be malformed and/or unbalanced and may omit inline images. Use at your own risk. Known problems are listed at https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/es.json b/i18n/api/es.json new file mode 100644 index 0000000..3d4a2c6 --- /dev/null +++ b/i18n/api/es.json @@ -0,0 +1,15 @@ +{ + "@metadata": { + "authors": [ + "Dgstranz", + "Macofe" + ] + }, + "apihelp-query+extracts-param-chars": "Cuántos caracteres devolver. El texto real devuelto puede ser un poco más largo.", + "apihelp-query+extracts-param-sentences": "Cuántas oraciones se devolverán.", + "apihelp-query+extracts-param-limit": "Cuántos extractos se devolverán. (Los extractos múltiples sólo pueden devolverse si se estable 'exintro' como verdadero.)", + "apihelp-query+extracts-param-intro": "Devolver sólo el contenido antes de la primera sección.", + "apihelp-query+extracts-param-plaintext": "Devuelve extractos como texto sin formato en lugar de HTML limitado.", + "apihelp-query+extracts-example-1": "Obtener un extracto de 175 caracteres", + "apiwarn-textextracts-unsupportedmodel": "El modelo de contenido de $1 es $2, que no es compatible; se devolverá un extracto vacío." +} diff --git a/i18n/api/fa.json b/i18n/api/fa.json new file mode 100644 index 0000000..0e714a1 --- /dev/null +++ b/i18n/api/fa.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Ladsgroup" + ] + }, + "apihelp-query+extracts-param-sentences": "چند جمله بازگرداند." +} diff --git a/i18n/api/fr.json b/i18n/api/fr.json new file mode 100644 index 0000000..b6a58f8 --- /dev/null +++ b/i18n/api/fr.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "Amire80", + "Gomoko", + "McDutchie", + "Thibaut120094", + "Urhixidur", + "Verdy p", + "Wladek92" + ] + }, + "apihelp-query+extracts-summary": "Renvoie des extraits en texte brut ou en HTML limité des pages données.", + "apihelp-query+extracts-param-chars": "Nombre de caractères à retourner. Le texte courant retourné peut être légèrement plus long.", + "apihelp-query+extracts-param-sentences": "Combien de phrases renvoyer.", + "apihelp-query+extracts-param-limit": "Combien d’extraits à retourner (des extraits multiples peuvent être retournés si « exintro » est mis à « true »).", + "apihelp-query+extracts-param-intro": "Retourner uniquement le contenu précédant la première section.", + "apihelp-query+extracts-param-plaintext": "Retourner les extraits au format texte brut au lieu de HTML limité.", + "apihelp-query+extracts-param-sectionformat": "Comment mettre en forme les sections en mode texte brut:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Pas de formatage.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Formatage de style Wikitext (== comme ceci ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "La représentation de ce module (section titres préfixée avec <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Obtenir un extrait de 175 caractères", + "apiwarn-textextracts-limit": "exlimit était trop grand pour une requête d'extraction d'article complet, réduit à $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 a le modèle de contenu $2, qui n’est pas pris en charge ; renvoi d’un extrait vide.", + "apiwarn-textextracts-title-in-file-namespace": "L’extraction pour un titre dans l’espace de noms Fichier a été demandée, rien n’a été renvoyé.", + "apiwarn-textextracts-sentences-and-html": "Le paramètre $1sentences peut avoir des résultats inattendus quand il est utilisé en mode HTML.", + "apiwarn-textextracts-malformed-html": "Le HTML peut être malformé ou non équilibré et peut omettre des images en ligne. À utiliser à vos risques et périls. Les problèmes connus sont listés sur https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/gl.json b/i18n/api/gl.json new file mode 100644 index 0000000..75a30e8 --- /dev/null +++ b/i18n/api/gl.json @@ -0,0 +1,19 @@ +{ + "@metadata": { + "authors": [ + "Banjo", + "Elisardojm" + ] + }, + "apihelp-query+extracts-summary": "Devolve texto plano ou extractos limitados en HTML das páxinas indicadas.", + "apihelp-query+extracts-param-chars": "Cantos caracteres devolver. O texto devolto actual pode ser un pouco máis longo.", + "apihelp-query+extracts-param-sentences": "Cantas frases devolver.", + "apihelp-query+extracts-param-limit": "Cantos extractos devolver. (Os extractos múltiples só se poden devolver se exintro ten valor ''true'', verdadeiro)", + "apihelp-query+extracts-param-intro": "Só devolver contido antes da primeira sección.", + "apihelp-query+extracts-param-plaintext": "Devolver extractos como texto plano no canto de HTML limitado.", + "apihelp-query+extracts-param-sectionformat": "Como formatear seccións en modo texto plano:\n;plain:Sen formato.\n;wiki:Formateo en estilo wiki (== como isto ==).\n;raw:Representación interna deste módulo (títulos de sección prefixados con <ASCII 1><ASCII 2><nivel de sección><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Devolver un extracto de 175 caracteres", + "apiwarn-textextracts-limit": "exlimit era demasiado grande para unha petición de extracción do artigo completo, reducida a $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 ten o modelo de contido $2, que non está soportado; devolvendo un extracto baleiro.", + "apiwarn-textextracts-title-in-file-namespace": "Pediuse un extracto para un título no espazo de nomes Ficheiro, non se obtivo ningún." +} diff --git a/i18n/api/he.json b/i18n/api/he.json new file mode 100644 index 0000000..99ae553 --- /dev/null +++ b/i18n/api/he.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "Amire80", + "Guycn2" + ] + }, + "apihelp-query+extracts-summary": "החזרת קטעים של הדפים הנתונים בטקסט רגיל או ב־HTML מוגבל.", + "apihelp-query+extracts-param-chars": "כמה תווים להחזיר. הטקסט האמתי עשוי להיות ארוך קצת יותר.", + "apihelp-query+extracts-param-sentences": "כמה משפטים להחזיר.", + "apihelp-query+extracts-param-limit": "כמה מובאות להחזיר. (מובאות מרובות יכולות להיות מוחזרות אם הערך של exintro הוא true.)", + "apihelp-query+extracts-param-intro": "להחזיר רק תוכן לפני הפרק הראשון.", + "apihelp-query+extracts-param-plaintext": "להחזיר מובאות בתור טקסט רגיל במקום HTML מוגבל.", + "apihelp-query+extracts-param-sectionformat": "איך לעצב פרקים במצב טקסט רגיל:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "ללא עיצוב.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "עיצוב בסגנון קוד ויקי (== ככה ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "הייצוג הפנימי של המודול הזה (לכותרות פרקים תהיה תחילית <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "קבלת מובאה של 175 תווים", + "apiwarn-textextracts-limit": "ה־exlimit היה גדול מדי בשביל בקשת מובאות מערך שלם, הונמך ל־$1.", + "apiwarn-textextracts-unsupportedmodel": "ל־$1 יש דגם תוכן $2, שאינו נתמך; מוחזרת מובאה ריקה.", + "apiwarn-textextracts-title-in-file-namespace": "נשלחה בקשה לקטע במרחב הקבצים, לא הוחזר דבר.", + "apiwarn-textextracts-sentences-and-html": "לפרמטר $1sentences עלולות להיות תוצאות בלתי־צפויות בעת שימוש במצב HTML.", + "apiwarn-textextracts-malformed-html": "ה־HTML עלול להיות פגום או בלתי־מאוזן, והוא עלול להשמיט תמונות מוטבעות. השימוש באפשרות זו הוא באחריותך. רשימה של בעיות ידועות מופיעה בדף https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/hu.json b/i18n/api/hu.json new file mode 100644 index 0000000..2c0aa5c --- /dev/null +++ b/i18n/api/hu.json @@ -0,0 +1,16 @@ +{ + "@metadata": { + "authors": [ + "Tacsipacsi" + ] + }, + "apihelp-query+extracts-param-chars": "A visszaadandó karakterek száma. A tényleges visszaadott szöveg lehet valamivel hosszabb.", + "apihelp-query+extracts-param-sentences": "A visszaadandó mondatok száma.", + "apihelp-query+extracts-param-limit": "A visszaadandó kivonatok száma. (Több kivonat csak akkor adható vissza, ha az exintro meg van adva.)", + "apihelp-query+extracts-param-intro": "Csak az első szakasz előtti tartalom visszaadása.", + "apihelp-query+extracts-param-plaintext": "A kivonatok visszaadása egyszerű szövegként korlátozott HTML helyett.", + "apihelp-query+extracts-param-sectionformat": "A szakaszcímek formázása egyszerű szöveges módban:\n;plain: Nincs formázás.\n;wiki: Wikiszöveg-formázás (== így ==).\n;raw: Ezen modul belső reprezentációja (a szakaszcímek előtagja <ASCII 1><ASCII 2><szakaszszint><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Egy 175 karakteres kivonat lekérése", + "apiwarn-textextracts-limit": "exlimit túl nagy teljes szócikk kivonatához, csökkentve $1 darabra.", + "apiwarn-textextracts-unsupportedmodel": "$1 tartalommodellje $2, ami nem támogatott; üres kivonat visszaadva." +} diff --git a/i18n/api/ia.json b/i18n/api/ia.json new file mode 100644 index 0000000..e977920 --- /dev/null +++ b/i18n/api/ia.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "McDutchie" + ] + }, + "apihelp-query+extracts-summary": "Restitue extractos del paginas date in forma de texto simple o HTML limitate.", + "apihelp-query+extracts-param-chars": "Quante characteres restituer. Le texto effectivemente restituite pote esser un poco plus longe.", + "apihelp-query+extracts-param-sentences": "Quante phrases restituer.", + "apihelp-query+extracts-param-limit": "Quante extractos restituer. (Plure extractos pote esser restituite solmente si exintro es mittite a true (ver).)", + "apihelp-query+extracts-param-intro": "Restituer solmente le contento ante le prime section.", + "apihelp-query+extracts-param-plaintext": "Restituer extractos in forma de texto simple in loco de HTML limitate.", + "apihelp-query+extracts-param-sectionformat": "Como formatar sectiones in modo de texto simple:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Non formatar.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Formatar in stilo de wikitexto (== como isto ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Usar le representation interne de iste modulo (titulos de section con prefixos <ASCII 1><ASCII 2><nivello de section><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Obtener un extracto de 175 characteres", + "apiwarn-textextracts-limit": "exlimit esseva troppo grande pro un requesta de extractos de un articulo complete; reducite a $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 ha le modello de contento $2, que non es supportate; se restitue un extracto vacue.", + "apiwarn-textextracts-title-in-file-namespace": "Un extracto pro un titulo in le spatio de nomines File ha essite requestate, nihil restituite.", + "apiwarn-textextracts-sentences-and-html": "Le parametro $1sentences pote producer resultatos inexpectate quando es usate in modo HTML.", + "apiwarn-textextracts-malformed-html": "Le codice HTML pote esser mal formate e/o non equilibrate e pote omitter imagines in linea. Usar a proprie risco. Le problemas cognoscite es listate sur https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/it.json b/i18n/api/it.json new file mode 100644 index 0000000..591c329 --- /dev/null +++ b/i18n/api/it.json @@ -0,0 +1,12 @@ +{ + "@metadata": { + "authors": [ + "Beta16" + ] + }, + "apihelp-query+extracts-param-chars": "Quanti caratteri restituire. Il testo effettivo restituito potrebbe essere leggermente più lungo.", + "apihelp-query+extracts-param-sentences": "Quante frasi restituire.", + "apihelp-query+extracts-param-limit": "Quanti estratti restituire. (Più estratti possono essere restituiti solo se 'exintro' è impostato su 'true'.)", + "apihelp-query+extracts-param-intro": "Restituisci solo il contenuto prima della prima sezione.", + "apihelp-query+extracts-example-1": "Ottieni un estratto di 175 caratteri" +} diff --git a/i18n/api/ja.json b/i18n/api/ja.json new file mode 100644 index 0000000..5ba6eef --- /dev/null +++ b/i18n/api/ja.json @@ -0,0 +1,11 @@ +{ + "@metadata": { + "authors": [ + "Yusuke1109" + ] + }, + "apihelp-query+extracts-summary": "指定されたページのプレーンテキストまたは制限付きHTMLを返します。", + "apihelp-query+extracts-param-chars": "返す文字数。返される実際の本文はわずかに長くなる場合があります。", + "apihelp-query+extracts-param-sentences": "返す文の数。", + "apihelp-query+extracts-param-intro": "最初の節の前の内容のみ返す。" +} diff --git a/i18n/api/ko.json b/i18n/api/ko.json new file mode 100644 index 0000000..34d8b9e --- /dev/null +++ b/i18n/api/ko.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Ykhwong" + ] + }, + "apihelp-query+extracts-summary": "주어진 문서의 플레인 텍스트 또는 제한된 HTML 추출 정보를 반환합니다.", + "apiwarn-textextracts-sentences-and-html": "$1sentences 변수는 HTML 모드에서 사용할 때 예측하지 못한 결과가 있을 수 있습니다.", + "apiwarn-textextracts-malformed-html": "HTML이 잘못 구성되었거나 균형을 잃었거나 인라인 이미지가 누락된 상태일 수 있습니다. 자신의 책임 하에 사용하십시오. 알려진 문제는 [https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats 여기]에 나열되어 있습니다." +} diff --git a/i18n/api/ksh.json b/i18n/api/ksh.json new file mode 100644 index 0000000..9257fb3 --- /dev/null +++ b/i18n/api/ksh.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Purodha" + ] + }, + "apihelp-query+extracts-param-chars": "Wi vill Zeische ußjävve? Wat dann kütt, künnd e klei beßje länger sin.", + "apihelp-query+extracts-param-sentences": "Wi vell Säz ußjävve?", + "apihelp-query+extracts-param-limit": "Wi vell Ußzöhsch ußjävve?", + "apihelp-query+extracts-param-intro": "Jif blohß dat Schtök vör de eezde Övverschrevv uß.", + "apihelp-query+extracts-param-plaintext": "Donn Ußzöhsch als eijnfache Täx ußjävve, un nidd als bejränz HTML.", + "apihelp-query+extracts-param-sectionformat": "Wi sulle Affschnedde em nommahle Täx ußjejovve wähde:\n;plain:Kein Fommahd.\n;wiki:Als Wikkitäx (== allsu esu ==).\n;raw:Heh däm Moduhl singe eije Aat (Övverschreffte met „<ASCII 1><ASCII 2><de Ennröckong als Zahl><ASCII 2><ASCII 1>“ dovör).", + "apihelp-query+extracts-example-1": "Holl ene Ußzoch met 175 Zeijsche dren." +} diff --git a/i18n/api/mk.json b/i18n/api/mk.json new file mode 100644 index 0000000..0357ace --- /dev/null +++ b/i18n/api/mk.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Bjankuloski06" + ] + }, + "apihelp-query+extracts-summary": "Дава извадоци од дадените страници во прост текст или ограничен HTML.", + "apihelp-query+extracts-param-chars": "Колку знаци да има извадокот. Самиот текст што ќе се даде може да биде малку подолг.", + "apihelp-query+extracts-param-sentences": "Колку реченици да има извадокот.", + "apihelp-query+extracts-param-limit": "Колку извадоци да се дадат. (Ќе се дадат повеќе извадоци само exintro е наместен на true)", + "apihelp-query+extracts-param-intro": "Дај го само воведниот дел пред првиот оддел.", + "apihelp-query+extracts-param-plaintext": "Давај ги извадоците како прост текс или ограничен HTML.", + "apihelp-query+extracts-param-sectionformat": "Како да се форматираат одделите во прост текст:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Без форматирање.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Викитекстуално форматирање (== вака ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Внатрешната претстава на овој модул (насловите на одделните со претставка <ASCII 1><ASCII 2><ниво на насловот><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Дај извадок во 175 знаци", + "apiwarn-textextracts-limit": "exlimit е преголемо за точно барање од цела статија. Го намалив на $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 го има содржинскиот модел $2, кој не е поддржан. Давам празен извадок.", + "apiwarn-textextracts-title-in-file-namespace": "Беше побаран извадок за наслов во именскиот простор „Податотека“, но не добив ништо.", + "apiwarn-textextracts-sentences-and-html": "Параметарот $1sentences може да има неочекуван исход кога се користи во HTML-режим.", + "apiwarn-textextracts-malformed-html": "HTML може да е погрешно срочено и/или неурамнотежено, па затоа може да се изоставени слики во редовите. Користете го на сопствен ризик. Познатите проблеми се наведени на https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/nb.json b/i18n/api/nb.json new file mode 100644 index 0000000..7737dbb --- /dev/null +++ b/i18n/api/nb.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "Amire80", + "Jon Harald Søby" + ] + }, + "apihelp-query+extracts-summary": "Returnerer tekstutdrag fra de gitte sidene i rentekst eller begrenset HTML.", + "apihelp-query+extracts-param-chars": "Hvor mange tegn som skal returneres. Den faktiske teksten som returneres kan være litt lenger.", + "apihelp-query+extracts-param-sentences": "Hvor mange setninger som skal returneres.", + "apihelp-query+extracts-param-limit": "Hvor mange utdrag som skal returneres. (Flere utdrag kan kun returneres om exintro er satt til sann.)", + "apihelp-query+extracts-param-intro": "Returner kun innholdet foran første seksjon.", + "apihelp-query+extracts-param-plaintext": "Returner utdrag som ren tekst i stedet for HTML.", + "apihelp-query+extracts-param-sectionformat": "Hvordan seksjoner formateres i rentekstmodus:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Ingen formatering.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Formatering i wikitekststil (== som dette ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Denne modulens interne representasjon (seksjonstittel med prefiks <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Hent et utdrag på 175 tegn", + "apiwarn-textextracts-limit": "exlimit var for stor for en forespørsel om full artikkeluthenting, senket til $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 har innholdsmodellen $2, som ikke støttes; returnerer en tom uthenting.", + "apiwarn-textextracts-title-in-file-namespace": "Utdrag for en tittel i filnavnerommet ble bedt om, ingen ble returnert.", + "apiwarn-textextracts-sentences-and-html": "Parameteren $1sentences kan ha uventede resultater om den brukes i HTML-modus.", + "apiwarn-textextracts-malformed-html": "HTML kan være misformet og/eller ubalansert, og kan utelate bilder. Bruk på egen risiko. Kjente problemer listes opp på https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/nl.json b/i18n/api/nl.json new file mode 100644 index 0000000..b7d577d --- /dev/null +++ b/i18n/api/nl.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "McDutchie" + ] + }, + "apihelp-query+extracts-summary": "Retourneert uittreksels van de opgegeven pagina’s in platte tekst of in beperkte HTML.", + "apihelp-query+extracts-param-chars": "Aantal te retourneren tekens. De daadwerkelijk geretourneerde tekst kan iets langer zijn.", + "apihelp-query+extracts-param-sentences": "Aantal te retourneren zinnen.", + "apihelp-query+extracts-param-limit": "Aantal te retourneren uittreksels. (Alleen als ‘exintro’ op ‘true’ staat kunnen meerdere uittreksels worden geretourneerd.)", + "apihelp-query+extracts-param-intro": "Alleen de inhoud vóór de eerste sectie retourneren.", + "apihelp-query+extracts-param-plaintext": "Uittreksels retourneren als platte tekst in plaats van beperkte HTML.", + "apihelp-query+extracts-param-sectionformat": "Opmaak van secties in platte-tekstmodus:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Geen opmaak.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Opmaak in wikitekst-stijl (== zoals dit ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "De interne representatie van deze module (sectietitels voorafgegaan door <ASCII 1><ASCII 2><sectieniveau><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Een uittreksel van 175 tekens opvragen", + "apiwarn-textextracts-limit": "exlimit was te groot om van een heel artikel uittreksels te maken en is verlaagd tot $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 heeft inhoudsmodel $2, dat niet wordt ondersteund; er wordt een leeg uittreksel geretourneerd.", + "apiwarn-textextracts-title-in-file-namespace": "Er is een uittreksel voor een titel in de naamruimte Bestand (File) aangevraagd, maar er is er geen teruggestuurd.", + "apiwarn-textextracts-sentences-and-html": "De parameter $1sentences kan onverwachte resultaten opleveren bij gebruik in de HTML-modus.", + "apiwarn-textextracts-malformed-html": "De HTML-code is mogelijk verkeerd opgemaakt en/of onevenwichtig. Ingevoegde afbeeldingen kunnen eruit zijn weggelaten. Gebruik op eigen risico. Bekende problemen worden vermeld op https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/pl.json b/i18n/api/pl.json new file mode 100644 index 0000000..2d99e91 --- /dev/null +++ b/i18n/api/pl.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [ + "DeRudySoulStorm", + "SemanticPioneer" + ] + }, + "apihelp-query+extracts-summary": "Zwraca zwykły tekst lub fragmenty HTML podanych stron.", + "apihelp-query+extracts-param-chars": "Ile znaków ma zostać zwróconych. Rzeczywisty zwracany tekst może być nieco dłuższy.", + "apihelp-query+extracts-param-sentences": "Jak wiele zdań ma zostać zwróconych.", + "apihelp-query+extracts-param-limit": "Jak wiele fragmentów ma być zwróconych. (Wiele fragmentów może zostać zwróconych tylko wtedy, gdy parametr exintro ma wartość true).", + "apihelp-query+extracts-param-intro": "Zwróć tylko zawartość przed pierwszą sekcją.", + "apihelp-query+extracts-param-plaintext": "Zwróć fragmenty jako zwykły tekst zamiast ograniczonego kodu HTML.", + "apihelp-query+extracts-param-sectionformat": "Jak formatować sekcje w trybie zwykłego tekstu:\n;plain:Bez formatowania.\n;wiki:Formatowanie w stylu Wikitext (==jak to==).\n;raw:Wewnętrzna reprezentacja tego modułu (tytuły sekcji z prefiksem <ASCII 1><ASCII 2><poziom sekcji><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Zdobądź 175-znakowy fragment", + "apiwarn-textextracts-limit": "Wartość exlimit była za duża dla żądania fragmentu z całego artykułu, obniżono do $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 ma model zawartości $2, który nie jest obsługiwany; zwracam pusty fragment.", + "apiwarn-textextracts-title-in-file-namespace": "Zażądano wyodrębnienia tytułu z przestrzeni nazw plików, żaden nie został zwrócony.", + "apiwarn-textextracts-sentences-and-html": "Parametr $1sentences może mieć nieoczekiwane wyniki, jeśli jest używany w trybie HTML.", + "apiwarn-textextracts-malformed-html": "HTML może być zniekształcony i/lub niezrównoważony i może ominąć obrazy śród-liniowe. Używaj na własne ryzyko. Znane problemy są wymienione na stronie https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/pt-br.json b/i18n/api/pt-br.json new file mode 100644 index 0000000..080ef56 --- /dev/null +++ b/i18n/api/pt-br.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "!Silent", + "Araceletorres", + "Eduardo Addad de Oliveira", + "Eduardoaddad", + "Felipe L. Ewald" + ] + }, + "apihelp-query+extracts-summary": "Retorna texto simples ou extratos de HTML limitados das páginas dadas.", + "apihelp-query+extracts-param-chars": "Quantos caracteres retornar. O texto real retornado pode ser um pouco mais longo.", + "apihelp-query+extracts-param-sentences": "Quantas sentenças retornar.", + "apihelp-query+extracts-param-limit": "Quantos extratos retornar (múltiplos extratos somente podem ser retornados \"exintro\" estiver definido como verdadeiro).", + "apihelp-query+extracts-param-intro": "Retornar apenas o conteúdo antes da primeira seção.", + "apihelp-query+extracts-param-plaintext": "Retornar extratos como texto simples em vez de HTML limitado.", + "apihelp-query+extracts-param-sectionformat": "Como formatar as seções no modo de texto simples:\n;plain: sem formato\n;wiki: formato no estilo wiki (== dessa forma ==)\n;raw: representação interna deste módulo (títulos de seção prefixados com <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Obter um extrato de 175 caracteres", + "apiwarn-textextracts-limit": "exlimit foi muito grande para um pedido completo de extrato de artigo, reduzido para $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 tem o modelo de conteúdo $2, que não é suportado; devolvendo um extrato vazio.", + "apiwarn-textextracts-title-in-file-namespace": "Foi solicitado um extrato para um título no espaço nominal do arquivo, nenhum retornou.", + "apiwarn-textextracts-sentences-and-html": "O parâmetro $1sentences pode gerar resultados inesperados quando é usado em modo HTML.", + "apiwarn-textextracts-malformed-html": "O HTML pode estar incorreto ou desequilibrado (ter etiquetas abertas e não fechadas) e pode omitir imagens em linha. Use por sua conta e risco. Os problemas conhecidos são listados em https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/pt.json b/i18n/api/pt.json new file mode 100644 index 0000000..5a2a9f5 --- /dev/null +++ b/i18n/api/pt.json @@ -0,0 +1,20 @@ +{ + "@metadata": { + "authors": [ + "Hamilton Abreu" + ] + }, + "apihelp-query+extracts-summary": "Fornece extratos do conteúdo das páginas indicadas, em texto simples ou HTML limitado.", + "apihelp-query+extracts-param-chars": "Quantos caracteres devem ser devolvidos. O texto devolvido pode ser ligeiramente mais longo.", + "apihelp-query+extracts-param-sentences": "Quantas frases devem ser devolvidas.", + "apihelp-query+extracts-param-limit": "Quantos extratos devem ser devolvidos. (Se pode ser devolvido mais do que um extrato se 'exintro' tiver o valor \"true\", verdadeiro).", + "apihelp-query+extracts-param-intro": "Devolver só o conteúdo antes da primeira secção.", + "apihelp-query+extracts-param-plaintext": "Devolver extratos em texto simples em vez de HTML limitado.", + "apihelp-query+extracts-param-sectionformat": "Como formatar as secções no modo de texto simples:\n;plain:Sem formatação.\n;wiki:Formatação ao estilo de texto wiki (== assim ==)\n;raw:A representação interna deste módulo (títulos de secção com os prefixos <ASCII 1><ASCII 2><nível de secção><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Obter um extrato de 175 caracteres", + "apiwarn-textextracts-limit": "exlimit era demasiado grande para um pedido de extrato de um artigo completo; reduzido para $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 tem o modelo de conteúdo $2, que não é suportado; a devolver um extrato vazio.", + "apiwarn-textextracts-title-in-file-namespace": "Foi pedido um extrato para um título no espaço nominal Ficheiro, não foi devolvido nenhum.", + "apiwarn-textextracts-sentences-and-html": "O parâmetro $1sentences pode gerar resultados inesperados quando é usado em modo HTML.", + "apiwarn-textextracts-malformed-html": "O HTML pode estar incorreto ou desequilibrado (ter etiquetas abertas e não fechadas) e pode omitir imagens em linha. Use por sua conta e risco. Os problemas conhecidos são listados em https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/qqq.json b/i18n/api/qqq.json new file mode 100644 index 0000000..6fd95f2 --- /dev/null +++ b/i18n/api/qqq.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Umherirrender" + ] + }, + "apihelp-query+extracts-summary": "{{doc-apihelp-summary|query+extracts}}", + "apihelp-query+extracts-param-chars": "{{doc-apihelp-param|query+extracts|chars}}", + "apihelp-query+extracts-param-sentences": "{{doc-apihelp-param|query+extracts|sentences}}", + "apihelp-query+extracts-param-limit": "{{doc-apihelp-param|query+extracts|limit}}", + "apihelp-query+extracts-param-intro": "{{doc-apihelp-param|query+extracts|intro}}", + "apihelp-query+extracts-param-plaintext": "{{doc-apihelp-param|query+extracts|plaintext}}", + "apihelp-query+extracts-param-sectionformat": "{{doc-apihelp-param|query+extracts|sectionformat}}", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "{{doc-apihelp-paramvalue|query+extracts|sectionformat|plain}}", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "{{doc-apihelp-paramvalue|query+extracts|sectionformat|wiki}}", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "{{doc-apihelp-paramvalue|query+extracts|sectionformat|raw}}", + "apihelp-query+extracts-example-1": "{{doc-apihelp-example|query+extracts}}", + "apiwarn-textextracts-limit": "{{doc-apierror}}\n\nParameters:\n* $1 - Limit that will be used", + "apiwarn-textextracts-unsupportedmodel": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title\n* $2 - Content model", + "apiwarn-textextracts-title-in-file-namespace": "{{doc-apierror}}\n\nWarning message displayed when an extract for a title in File namespace is requested.", + "apiwarn-textextracts-sentences-and-html": "{{doc-apierror}}\n\nWarning message displayed documenting a known issue with sentence parameter used.", + "apiwarn-textextracts-malformed-html": "{{doc-apierror}}\n\nWarning message displayed documented known issues with the TextExtracts API." +} diff --git a/i18n/api/roa-tara.json b/i18n/api/roa-tara.json new file mode 100644 index 0000000..09e1293 --- /dev/null +++ b/i18n/api/roa-tara.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Joetaras" + ] + }, + "apihelp-query+extracts-summary": "Dèje stuèzze jndr'à 'u teste semblice o HTML limitate da le pàggene specificate.", + "apihelp-query+extracts-param-chars": "Quanda carattere adda restituì. 'U teste de mò turnate pò essere 'nu picche cchiù luènghe.", + "apihelp-query+extracts-param-sentences": "Quanda frase adda turnà.", + "apihelp-query+extracts-param-limit": "Quanda stuèzze adda restituì. (Cchiù stuèzze ponne sulamende essere date ce exintro jè 'msotate a true.)", + "apihelp-query+extracts-param-intro": "Tuèrne sulamende 'u condenute apprime d'a prima selezione.", + "apihelp-query+extracts-param-plaintext": "Torne le stuèzze cumme teste semblice invece ca cumme HTML limitate.", + "apihelp-query+extracts-param-sectionformat": "Accume formattà le seziune jndr'à 'nu mode de teste semblice:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Nisicuna formattazzione.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Formattazzione stile Uicchiteste (== cumme a quiste ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Sta rappresendazione d'u module 'nderne (titole d'a sezione cu prefisse <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Pigghie 'nu stuèzze da 175 carattere", + "apiwarn-textextracts-limit": "exlimit jè troppe granne pa richieste de le stuèzze d'a vôsce, avasciate a $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 ave 'nu modelle de condenute $2, 'u quale non g'è supportate; e dèje 'nu stuèzze vacande.", + "apiwarn-textextracts-title-in-file-namespace": "Ha state cercate 'n'estrazione pe 'nu titole jndr'à 'u namespace, no amme acchiate ninde.", + "apiwarn-textextracts-sentences-and-html": "'U parametre $1sentences pò avè resultate inaspettate quanne avène ausate cu 'u mode HTML.", + "apiwarn-textextracts-malformed-html": "HTML pò essere malformate e/o sbilangiate e pò zumbà le immaggine inline. Ce l'ause jè a rischie tune. Le probbleme canusciute so elengate sus a https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/ru.json b/i18n/api/ru.json new file mode 100644 index 0000000..b35d032 --- /dev/null +++ b/i18n/api/ru.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [ + "Facenapalm", + "Okras" + ] + }, + "apihelp-query+extracts-summary": "Возвращает фрагменты указанных страниц в виде обычного текста или ограниченного HTML.", + "apihelp-query+extracts-param-chars": "Сколько символов возвращать. Возвращаемый в действительности текст может быть немного длиннее.", + "apihelp-query+extracts-param-sentences": "Сколько предложений возвращать.", + "apihelp-query+extracts-param-limit": "Сколько фрагментов возвращать. (Несколько фрагментов можно запрашивать только в том случае, если для exintro установлено значение true)", + "apihelp-query+extracts-param-intro": "Возвращаться только содержимое, идущее до первого раздела.", + "apihelp-query+extracts-param-plaintext": "Возвращать фрагменты в виде обычного текста вместо ограниченного HTML.", + "apihelp-query+extracts-param-sectionformat": "Как форматировать секции в режиме обычного текста:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Без форматирования.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Вики-текстовое форматрирование (== вот так ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Внутреннее представление данного модуля (перед названием секций будет <ASCII 1><ASCII 2><уровень секции><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Получить 175-символьный фрагмент", + "apiwarn-textextracts-limit": "exlimit был слишком велик для запроса фрагмента всей статьи, поэтому он был снижен до $1.", + "apiwarn-textextracts-unsupportedmodel": "Модель содержимого $2, установленная для странице $1, не поддерживается; возвращён пустой фрагмент." +} diff --git a/i18n/api/sl.json b/i18n/api/sl.json new file mode 100644 index 0000000..13a6a3e --- /dev/null +++ b/i18n/api/sl.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Eleassar" + ] + }, + "apihelp-query+extracts-summary": "Vrne golo besedilo ali omejene izvlečke HTML predloženih strani.", + "apihelp-query+extracts-param-chars": "Koliko znakov naj bo vrnjenih. Dejansko vrnjeno besedilo je lahko nekoliko daljše.", + "apihelp-query+extracts-param-sentences": "Koliko stavkov naj bo vrnjenih.", + "apihelp-query+extracts-param-limit": "Koliko izvlečkov naj bo vrnjenih (Več izvlečkov je mogoče vrniti le, če je »exintro« nastavljen na »true«.)", + "apihelp-query+extracts-param-intro": "Vrne samo vsebino pred prvim razdelkom.", + "apihelp-query+extracts-param-plaintext": "Vrne izvlečke kot navadno besedilo namesto omejenega HTML-ja.", + "apihelp-query+extracts-param-sectionformat": "Kako oblikovati razdelke v načinu navadnega besedila:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Brez oblikovanja.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Oblikovanje v slogu vikibesedila (== tako ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Notranja predstavitev tega modula (naslovi razdelkov s predpono <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Pridobite izvleček s 175 znaki", + "apiwarn-textextracts-limit": "exlimit je bil prevelik za zahtevek za izvlečke celotnega članka; zmanjšano na $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 ima vsebinski model $2, ki ni podprt; vrnitev praznega izvlečka.", + "apiwarn-textextracts-title-in-file-namespace": "Zahtevan je bil izvleček za naslov v imenskem prostoru datotek; vrnjen ni bil noben.", + "apiwarn-textextracts-sentences-and-html": "Parameter $1sentences lahko vrne nepričakovane zadetke, če se uporablja v načinu HTML.", + "apiwarn-textextracts-malformed-html": "HTML je morda napačno oblikovan in/ali neuravnotežen in morda izpusti vstavljene slike. Uporabljajte na lastno odgovornost. Znane težave so navedene na https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/sr-ec.json b/i18n/api/sr-ec.json new file mode 100644 index 0000000..4ae4216 --- /dev/null +++ b/i18n/api/sr-ec.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Kizule", + "Prevodim", + "Zoranzoki21" + ] + }, + "apihelp-query+extracts-summary": "Враћа сажетке датих страница у облику чистог текста или ограниченог HTML-а.", + "apihelp-query+extracts-param-chars": "Колико слова треба вратити. Текст који се заправо враћа може бити мало дужи.", + "apihelp-query+extracts-param-sentences": "Колико реченица треба вратити.", + "apihelp-query+extracts-param-intro": "Врати само садржај пре прве секције.", + "apiwarn-textextracts-unsupportedmodel": "$1 има модел садржаја $2, који није подржан; враћа се празан сажетак." +} diff --git a/i18n/api/sr-el.json b/i18n/api/sr-el.json new file mode 100644 index 0000000..afe7e90 --- /dev/null +++ b/i18n/api/sr-el.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [] + }, + "apihelp-query+extracts-summary": "Vraća sažetke datih stranica u obliku čistog teksta ili ograničenog HTML-a.", + "apihelp-query+extracts-param-chars": "Koliko slova treba vratiti. Tekst koji se zapravo vraća može biti malo duži.", + "apihelp-query+extracts-param-sentences": "Koliko rečenica treba vratiti.", + "apihelp-query+extracts-param-intro": "Vrati samo sadržaj pre prve sekcije.", + "apiwarn-textextracts-unsupportedmodel": "$1 ima model sadržaja $2, koji nije podržan; vraća se prazan sažetak." +} diff --git a/i18n/api/sv.json b/i18n/api/sv.json new file mode 100644 index 0000000..04da974 --- /dev/null +++ b/i18n/api/sv.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [ + "Dhallin", + "Lokal Profil" + ] + }, + "apihelp-query+extracts-summary": "Returnerar ren text eller begränsade HTML-utdrag av de angivna sidorna.", + "apihelp-query+extracts-param-chars": "Antalet tecken att returnera. Den faktiska text som returneras kan vara något längre.", + "apihelp-query+extracts-param-sentences": "Antalet meningar som ska returneras.", + "apihelp-query+extracts-param-limit": "Hur många utdrag som ska returneras. (Flera extrakt kan endast returneras om exintro är satt till true.)", + "apihelp-query+extracts-param-intro": "Returnera bara innehåll före första avsnittet.", + "apihelp-query+extracts-param-plaintext": "Returnera extrakt som ren text eller begränsad HTML.", + "apihelp-query+extracts-param-sectionformat": "Hur stycken formateras i ren-text-läge:\n;plain:Ingen formatering.\n;wiki:Wikitext-stil formatering (== som detta ==).\n;raw:Denna moduls interna representation (avsnittstitlar med prefixet <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "FÅ ett extrakt på 175 tecken", + "apiwarn-textextracts-limit": "exlimit var för stor för en begäran om hela artikelutdrag, sänkt till $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 har innehållsmodell $2, som inte stöds; returnerar ett tomt utdrag.", + "apiwarn-textextracts-title-in-file-namespace": "Extrakt för en titel i filnamnutrymme begärdes, inget returnerades.", + "apiwarn-textextracts-sentences-and-html": "$1sentences Parametern kan ha oväntade resultat när den används i HTML-läge.", + "apiwarn-textextracts-malformed-html": "HTML kan vara missbildad och/eller obalanserad och kan utelämna inline bilder. Använd på egen risk. Kända problem listas på https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/tr.json b/i18n/api/tr.json new file mode 100644 index 0000000..b2c5b91 --- /dev/null +++ b/i18n/api/tr.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [ + "BaRaN6161 TURK", + "SaldırganSincap" + ] + }, + "apihelp-query+extracts-summary": "Verilen sayfaların düz metin veya sınırlı HTML alıntılarını döndürür.", + "apihelp-query+extracts-param-chars": "Döndürülecek karakter sayısı. Döndürülen gerçek metin biraz daha uzun olabilir.", + "apihelp-query+extracts-param-sentences": "Geri döndürecek birçok cümle.", + "apihelp-query+extracts-param-limit": "Geri döndürecek alıntı. (Birden fazla alıntı yalnızca exintro true olarak ayarlanmışsa döndürülebilir.)", + "apihelp-query+extracts-param-intro": "Yalnızca ilk bölümden önceki içeriği döndürün.", + "apihelp-query+extracts-param-plaintext": "Özetleri sınırlı HTML yerine düz metin olarak döndürün.", + "apihelp-query+extracts-param-sectionformat": "Bölümleri düz metin modunda biçimlendirme:\n;plain:Biçimlendirme yok.\n;wiki:Vikimetin tarzı biçimlendirme (== bunun gibi ==).\n;raw:Bu modülün dahili gösterimi (<ASCII 1><ASCII 2><bölüm düzeyi><ASCII 2><ASCII 1> önekli bölüm başlıkları).", + "apihelp-query+extracts-example-1": "175 karakterlik bir alıntı edinin", + "apiwarn-textextracts-limit": "exlimit, tüm madde alıntıları isteği için çok büyüktü ve $1 düşürüldü.", + "apiwarn-textextracts-unsupportedmodel": "$1, desteklenmeyen $2 içerik modeline sahiptir; boş bir özü döndürme.", + "apiwarn-textextracts-title-in-file-namespace": "Dosya ad alanında bir başlık için ayıklama istendi, hiçbiri döndürülmedi.", + "apiwarn-textextracts-sentences-and-html": "$1sentences parametresi, HTML modunda kullanıldığında beklenmeyen sonuçlara sahip olabilir.", + "apiwarn-textextracts-malformed-html": "HTML hatalı biçimlendirilmiş ve/veya dengesiz olabilir ve satır içi resimleri atlayabilir. Kendi sorumluluğunuzdadır kullanın. Bilinen sorunlar https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats adresinde listelenmiştir." +} diff --git a/i18n/api/uk.json b/i18n/api/uk.json new file mode 100644 index 0000000..ca1d8c8 --- /dev/null +++ b/i18n/api/uk.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "Piramidion", + "Ата" + ] + }, + "apihelp-query+extracts-summary": "Видає звичайний текст або обмежені уривки HTML заданих сторінок.", + "apihelp-query+extracts-param-chars": "Скільки символів виводити. Дійсно виданий текст може бути дещо довшим.", + "apihelp-query+extracts-param-sentences": "Скільки речень виводити.", + "apihelp-query+extracts-param-limit": "Скільки уривків виводити. (Кілька уривків може виводитися, тільки якщо exintro має значення true.)", + "apihelp-query+extracts-param-intro": "Виводити лише вміст до першого розділу.", + "apihelp-query+extracts-param-plaintext": "Виводити уривки у вигляді звичайного тексту замість обмеженого HTML.", + "apihelp-query+extracts-param-sectionformat": "Як форматувати розділи у режимі звичайного тексту:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "Без форматування.", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Форматування у вікістилі (== отак ==).", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "Зовнішнє представлення цього модуля (назви розділів матимуть префікс <ASCII 1><ASCII 2><section level><ASCII 2><ASCII 1>).", + "apihelp-query+extracts-example-1": "Отримати 175-символьний уривок", + "apiwarn-textextracts-limit": "exlimit був надто великим для виконання запиту з видобування цілої статті; понижено до $1.", + "apiwarn-textextracts-unsupportedmodel": "$1 має контентну модель $2, яка не підтримується; повертаємо порожній витяг.", + "apiwarn-textextracts-title-in-file-namespace": "Подано запит на витяг для назви з простору назв Файл; не отримано нічого.", + "apiwarn-textextracts-sentences-and-html": "Параметр $1sentences може видати неочікувані результаті, якщо його використати в режимі HTML.", + "apiwarn-textextracts-malformed-html": "Код HTML може бути неправильно сформованим та/або незбалансованим і може пропускати вбудовані зображення. Використовуйте на свій власний ризик. Відомі проблеми перелічено на сторінці https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats." +} diff --git a/i18n/api/zh-hans.json b/i18n/api/zh-hans.json new file mode 100644 index 0000000..50d55df --- /dev/null +++ b/i18n/api/zh-hans.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "GuoPC", + "LittlePaw365", + "Liuxinyu970226", + "Xiplus", + "Yfdyh000" + ] + }, + "apihelp-query+extracts-summary": "返回指定页面的纯文本或有限HTML格式摘录。", + "apihelp-query+extracts-param-chars": "返回字符数。实际返回的文本可能比这稍长。", + "apihelp-query+extracts-param-sentences": "返回句子数。", + "apihelp-query+extracts-param-limit": "返回摘录数。(当exintro设为true时才能返回多段摘录。)", + "apihelp-query+extracts-param-intro": "只返回首个章节前的内容。", + "apihelp-query+extracts-param-plaintext": "以纯文本而非有限HTML返回摘录。", + "apihelp-query+extracts-param-sectionformat": "纯文本模式下格式化章节方式:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "无格式。", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "wikitext样式的格式(== 像这样 ==)。", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "此模块的内部表示方法(章节标题前缀<ASCII 1><ASCII 2><章节级别><ASCII 2><ASCII 1>)", + "apihelp-query+extracts-example-1": "获取175个字符的摘录", + "apiwarn-textextracts-limit": "exlimit对于完整条目摘录请求而言过大,已降低为$1。", + "apiwarn-textextracts-unsupportedmodel": "$1有不受支持的内容模型$2,将返回空摘录。", + "apiwarn-textextracts-title-in-file-namespace": "请求了文件命名空间内标题的摘录,因此没有返回。", + "apiwarn-textextracts-sentences-and-html": "当用在HTML模式时,$1sentences参数可能有意外结果。", + "apiwarn-textextracts-malformed-html": "HTML可能有缺陷和/或不稳定,并可能忽略行内图片。使用时请自行承担风险。已知问题在https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats列出。" +} diff --git a/i18n/api/zh-hant.json b/i18n/api/zh-hant.json new file mode 100644 index 0000000..4f45229 --- /dev/null +++ b/i18n/api/zh-hant.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Kly" + ] + }, + "apihelp-query+extracts-summary": "回傳純文字或受限的指定頁面 HTML 匯出。", + "apihelp-query+extracts-param-chars": "要回傳的字元數量。實際回傳的文字可能會稍多。", + "apihelp-query+extracts-param-sentences": "要回傳的文句數量。", + "apihelp-query+extracts-param-limit": "要回傳的匯出數量。(若 exintro 設定成 true 可回傳多個提取。)", + "apihelp-query+extracts-param-intro": "僅回傳在首個段落前的內容。", + "apihelp-query+extracts-param-plaintext": "回傳匯出為純文字而非受限的 HTML 內容", + "apihelp-query+extracts-param-sectionformat": "在純文字模式如何格式化段落:", + "apihelp-query+extracts-paramvalue-sectionformat-plain": "無格式。", + "apihelp-query+extracts-paramvalue-sectionformat-wiki": "Wikitext 樣式格式(== 例如像這樣 ==)。", + "apihelp-query+extracts-paramvalue-sectionformat-raw": "此模組的內建呈現方法(帶有 <ASCII 1><ASCII 2><段落層級><ASCII 2><ASCII 1> 的段落標題前綴)。", + "apihelp-query+extracts-example-1": "取得 175-字元匯出內容", + "apiwarn-textextracts-limit": "exlimit 對於整個條目提取請求太大,已降為 $1。", + "apiwarn-textextracts-unsupportedmodel": "$1 含有內容模組 $2,這並不被支援,且會回傳空白匯出內容。", + "apiwarn-textextracts-title-in-file-namespace": "已請求匯出在檔案命名空間的標題,但未有內容回傳。", + "apiwarn-textextracts-sentences-and-html": "當使用 HTML 模式時,$1sentences 參數可能會產生預期外的結果。", + "apiwarn-textextracts-malformed-html": "HTML 可能不完整/或不穩定,並可能會忽略行內的圖片。使用時請自行承擔風險。已知問題則列在 https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats 裡。" +} diff --git a/i18n/ar.json b/i18n/ar.json new file mode 100644 index 0000000..65766ea --- /dev/null +++ b/i18n/ar.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "ديفيد" + ] + }, + "textextracts-desc": "يوفر نصا عاديا أو مقتطفات HTML محدودة من محتوى الصفحة" +} diff --git a/i18n/ast.json b/i18n/ast.json new file mode 100644 index 0000000..f24db8f --- /dev/null +++ b/i18n/ast.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Xuacu" + ] + }, + "textextracts-desc": "Ufre estractos del conteníu de la páxina en testu simple o HTML llimitáu" +} diff --git a/i18n/ce.json b/i18n/ce.json new file mode 100644 index 0000000..3d05985 --- /dev/null +++ b/i18n/ce.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Умар" + ] + }, + "textextracts-desc": "АгӀонийн чулацаман дешнаш лата до йозан йа HTML-форматехь" +} diff --git a/i18n/cs.json b/i18n/cs.json new file mode 100644 index 0000000..66b6dea --- /dev/null +++ b/i18n/cs.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Mormegil" + ] + }, + "textextracts-desc": "Poskytuje extrakty obsahu stránky v čistém textu nebo omezeném HTML" +} diff --git a/i18n/de.json b/i18n/de.json new file mode 100644 index 0000000..2f869b0 --- /dev/null +++ b/i18n/de.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Metalhead64" + ] + }, + "textextracts-desc": "Stellt Auszüge aus Seiten in Klartext oder beschränktem HTML zur Verfügung" +} diff --git a/i18n/dsb.json b/i18n/dsb.json new file mode 100644 index 0000000..5e4ec09 --- /dev/null +++ b/i18n/dsb.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Michawiki" + ] + }, + "textextracts-desc": "Staja wupise wopsimjeśa boka w lutnem teksće abo wobgranicowanem HTML k dispoziciji" +} diff --git a/i18n/en.json b/i18n/en.json new file mode 100644 index 0000000..16954cb --- /dev/null +++ b/i18n/en.json @@ -0,0 +1,6 @@ +{ + "@metadata": { + "authors": [] + }, + "textextracts-desc": "Provides plain-text or limited HTML extracts of page content" +} diff --git a/i18n/es.json b/i18n/es.json new file mode 100644 index 0000000..fa9f3d9 --- /dev/null +++ b/i18n/es.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Dgstranz", + "Fitoschido", + "Macofe" + ] + }, + "textextracts-desc": "Proporciona extractos del contenido de una página en texto sencillo o HTML limitado" +} diff --git a/i18n/fa.json b/i18n/fa.json new file mode 100644 index 0000000..cfe0468 --- /dev/null +++ b/i18n/fa.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Armin1392", + "Ladsgroup" + ] + }, + "textextracts-desc": "ارائه متن ساده یا اچ‌تی‌ام‌ال محدود شده، محتوای صفحه را بیرون می‌کشد" +} diff --git a/i18n/fr.json b/i18n/fr.json new file mode 100644 index 0000000..086d325 --- /dev/null +++ b/i18n/fr.json @@ -0,0 +1,11 @@ +{ + "@metadata": { + "authors": [ + "Gomoko", + "Thibaut120094", + "Urhixidur", + "Wladek92" + ] + }, + "textextracts-desc": "Fournit des extraits en texte brut ou en HTML limité du contenu de la page" +} diff --git a/i18n/gl.json b/i18n/gl.json new file mode 100644 index 0000000..dc5d5f2 --- /dev/null +++ b/i18n/gl.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Banjo", + "Elisardojm", + "Toliño" + ] + }, + "textextracts-desc": "Proporciona extractos de texto do contido da páxina sen formato ou con HTML limitado" +} diff --git a/i18n/he.json b/i18n/he.json new file mode 100644 index 0000000..52da68e --- /dev/null +++ b/i18n/he.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Amire80", + "Guycn2" + ] + }, + "textextracts-desc": "אספקת מובאות של תוכן הדפים טקסט בפשוט או ב־HTML מוגבל" +} diff --git a/i18n/hsb.json b/i18n/hsb.json new file mode 100644 index 0000000..35b4fb1 --- /dev/null +++ b/i18n/hsb.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Michawiki" + ] + }, + "textextracts-desc": "Staja wupisy wobsaha strony w lutym teksće abo wobmjezowanym HTML k dispoziciji" +} diff --git a/i18n/hu.json b/i18n/hu.json new file mode 100644 index 0000000..3cadfb5 --- /dev/null +++ b/i18n/hu.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Tacsipacsi" + ] + }, + "textextracts-desc": "Egy lap tartalmának egyszerű szöveges vagy korlátozott HTML kivonatát készíti el" +} diff --git a/i18n/ia.json b/i18n/ia.json new file mode 100644 index 0000000..210db39 --- /dev/null +++ b/i18n/ia.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "McDutchie" + ] + }, + "textextracts-desc": "Forni extractos del contento de paginas in forma de texto simple o HTML limitate" +} diff --git a/i18n/id.json b/i18n/id.json new file mode 100644 index 0000000..744f8d2 --- /dev/null +++ b/i18n/id.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Daud I.F. Argana" + ] + }, + "textextracts-desc": "Menyediakan ekstrak teks polos atau HTML terbatas dari konten halaman" +} diff --git a/i18n/it.json b/i18n/it.json new file mode 100644 index 0000000..24c55b0 --- /dev/null +++ b/i18n/it.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Beta16" + ] + }, + "textextracts-desc": "Fornisce estratti in testo semplice o HTML dal contenuto della pagina" +} diff --git a/i18n/ja.json b/i18n/ja.json new file mode 100644 index 0000000..eee18d1 --- /dev/null +++ b/i18n/ja.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Shirayuki", + "Yusuke1109" + ] + }, + "textextracts-desc": "ページ本文を抽出したプレーンテキストまたは制限付き HTML を提供する" +} diff --git a/i18n/ko.json b/i18n/ko.json new file mode 100644 index 0000000..efe9726 --- /dev/null +++ b/i18n/ko.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Priviet", + "Ykhwong" + ] + }, + "textextracts-desc": "문서 내용을 추출한 일반 텍스트나 제한된 HTML을 제공" +} diff --git a/i18n/ksh.json b/i18n/ksh.json new file mode 100644 index 0000000..a86ff1b --- /dev/null +++ b/i18n/ksh.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Purodha" + ] + }, + "textextracts-desc": "Määt bejränz Ußzööje vun Sigge em HTML udder als Täx möjjelesch." +} diff --git a/i18n/mk.json b/i18n/mk.json new file mode 100644 index 0000000..e86b03f --- /dev/null +++ b/i18n/mk.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Bjankuloski06" + ] + }, + "textextracts-desc": "Дава извадоци од содржината на страницата во прост текст или ограничен HTML" +} diff --git a/i18n/ml.json b/i18n/ml.json new file mode 100644 index 0000000..e4a9459 --- /dev/null +++ b/i18n/ml.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Praveenp" + ] + }, + "textextracts-desc": "താളിന്റെ ഉള്ളടക്കം വെറും-എഴുത്തായോ, ഭാഗികമായി എച്ച്.റ്റി.എം.എൽ. ആയോ എടുക്കൽ അനുവദിക്കുന്നു" +} diff --git a/i18n/nb.json b/i18n/nb.json new file mode 100644 index 0000000..4ececa7 --- /dev/null +++ b/i18n/nb.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Danmichaelo", + "Jon Harald Søby" + ] + }, + "textextracts-desc": "Tilbyr et kort utdrag av sideinnholdet som ren tekst eller begrenset HTML" +} diff --git a/i18n/nl.json b/i18n/nl.json new file mode 100644 index 0000000..5b16842 --- /dev/null +++ b/i18n/nl.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Arent", + "McDutchie", + "Siebrand" + ] + }, + "textextracts-desc": "Maakt uittreksels van pagina-inhoud in platte tekst of in beperkte HTML" +} diff --git a/i18n/oc.json b/i18n/oc.json new file mode 100644 index 0000000..80dc73f --- /dev/null +++ b/i18n/oc.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Cedric31" + ] + }, + "textextracts-desc": "Provesís d'extraits en tèxte brut o en HTML limitat del contengut de la pagina" +} diff --git a/i18n/pl.json b/i18n/pl.json new file mode 100644 index 0000000..376cd61 --- /dev/null +++ b/i18n/pl.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "DeRudySoulStorm", + "Rail", + "Railfail536" + ] + }, + "textextracts-desc": "Wprowadza wyodrębnianie czystego tekstu, lub pewnych elementów HTML z zawartości strony" +} diff --git a/i18n/pt-br.json b/i18n/pt-br.json new file mode 100644 index 0000000..8bc2d3c --- /dev/null +++ b/i18n/pt-br.json @@ -0,0 +1,11 @@ +{ + "@metadata": { + "authors": [ + "!Silent", + "Araceletorres", + "Eduardo Addad de Oliveira", + "Felipe L. Ewald" + ] + }, + "textextracts-desc": "Fornece texto simples ou extratos de HTML limitados de conteúdo da página" +} diff --git a/i18n/pt.json b/i18n/pt.json new file mode 100644 index 0000000..4369448 --- /dev/null +++ b/i18n/pt.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Hamilton Abreu", + "Waldir", + "Waldyrious" + ] + }, + "textextracts-desc": "Fornece extratos do conteúdo de páginas em texto simples ou HTML limitado" +} diff --git a/i18n/qqq.json b/i18n/qqq.json new file mode 100644 index 0000000..51738d3 --- /dev/null +++ b/i18n/qqq.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Umherirrender" + ] + }, + "textextracts-desc": "{{desc|name=TextExtracts|url=https://www.mediawiki.org/wiki/Extension:TextExtracts}}" +} diff --git a/i18n/roa-tara.json b/i18n/roa-tara.json new file mode 100644 index 0000000..8458572 --- /dev/null +++ b/i18n/roa-tara.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Joetaras" + ] + }, + "textextracts-desc": "Dèje stuèzze jndr'à 'u teste semblice o HTML da 'u condenute d'a pàgene" +} diff --git a/i18n/ru.json b/i18n/ru.json new file mode 100644 index 0000000..1f61b16 --- /dev/null +++ b/i18n/ru.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Okras" + ] + }, + "textextracts-desc": "Предоставляет фрагмент содержимого страниц в текстовом или ограниченном HTML-формате" +} diff --git a/i18n/scn.json b/i18n/scn.json new file mode 100644 index 0000000..e13460a --- /dev/null +++ b/i18n/scn.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Ajeje Brazorf" + ] + }, + "textextracts-desc": "Furnisci stratti n testu sìmpruci o HTML dû cuntinutu dâ pàggina" +} diff --git a/i18n/sl.json b/i18n/sl.json new file mode 100644 index 0000000..2788440 --- /dev/null +++ b/i18n/sl.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Eleassar" + ] + }, + "textextracts-desc": "Zagotavlja izvlečke vsebine strani v navadnem besedilu ali omejenem jeziku HTML" +} diff --git a/i18n/sr-ec.json b/i18n/sr-ec.json new file mode 100644 index 0000000..8922da8 --- /dev/null +++ b/i18n/sr-ec.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Prevodim", + "Zoranzoki21" + ] + }, + "textextracts-desc": "Пружа сажетак садржаја странице у облику чистог текста или ограниченог HTML-а" +} diff --git a/i18n/sr-el.json b/i18n/sr-el.json new file mode 100644 index 0000000..faf2c06 --- /dev/null +++ b/i18n/sr-el.json @@ -0,0 +1,6 @@ +{ + "@metadata": { + "authors": [] + }, + "textextracts-desc": "Pruža sažetak sadržaja stranice u obliku čistog teksta ili ograničenog HTML-a" +} diff --git a/i18n/sv.json b/i18n/sv.json new file mode 100644 index 0000000..56210b0 --- /dev/null +++ b/i18n/sv.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Lokal Profil" + ] + }, + "textextracts-desc": "Erbjuder extrakt, i oformaterad text eller begränsad HTML, av sidinnehåll" +} diff --git a/i18n/tr.json b/i18n/tr.json new file mode 100644 index 0000000..bb7e4b5 --- /dev/null +++ b/i18n/tr.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "BaRaN6161 TURK" + ] + }, + "textextracts-desc": "Sayfa içeriğinin düz metin veya sınırlı HTML özetini sağlar" +} diff --git a/i18n/uk.json b/i18n/uk.json new file mode 100644 index 0000000..ae0721c --- /dev/null +++ b/i18n/uk.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Andriykopanytsia", + "Piramidion", + "Ата" + ] + }, + "textextracts-desc": "Забезпечує видобування звичайного текст або обмеженого HTML із вмісту сторінки" +} diff --git a/i18n/vi.json b/i18n/vi.json new file mode 100644 index 0000000..d977741 --- /dev/null +++ b/i18n/vi.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Minh Nguyen" + ] + }, + "textextracts-desc": "Tóm lược nội dung trang dưới dạng văn bản thuần hoặc HTML đơn giản" +} diff --git a/i18n/zh-hans.json b/i18n/zh-hans.json new file mode 100644 index 0000000..98e63bd --- /dev/null +++ b/i18n/zh-hans.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Liuxinyu970226", + "Yfdyh000" + ] + }, + "textextracts-desc": "提供纯文本或有限的HTML页面内容提取" +} diff --git a/i18n/zh-hant.json b/i18n/zh-hant.json new file mode 100644 index 0000000..e2af869 --- /dev/null +++ b/i18n/zh-hant.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Kly" + ] + }, + "textextracts-desc": "提供純文字或受限的頁面內容 HTML 匯出" +} diff --git a/includes/ApiQueryExtracts.php b/includes/ApiQueryExtracts.php new file mode 100644 index 0000000..c83b8f7 --- /dev/null +++ b/includes/ApiQueryExtracts.php @@ -0,0 +1,408 @@ +config = $configFactory->makeConfig( 'textextracts' ); + $this->cache = $cache; + $this->langConvFactory = $langConvFactory; + $this->wikiPageFactory = $wikiPageFactory; + $this->titleFormatter = $titleFormatter; + } + + /** + * Evaluates the parameters, performs the requested extraction of text, + * and sets up the result + */ + public function execute() { + $titles = $this->getPageSet()->getGoodPages(); + if ( $titles === [] ) { + return; + } + $isXml = $this->getMain()->isInternalMode() + || $this->getMain()->getPrinter()->getFormat() == 'XML'; + $result = $this->getResult(); + $params = $this->params = $this->extractRequestParams(); + $this->requireMaxOneParameter( $params, 'chars', 'sentences' ); + $continue = 0; + $limit = intval( $params['limit'] ); + if ( $limit > 1 && !$params['intro'] && count( $titles ) > 1 ) { + $limit = 1; + $this->addWarning( [ 'apiwarn-textextracts-limit', $limit ] ); + } + if ( isset( $params['continue'] ) ) { + $continue = intval( $params['continue'] ); + $this->dieContinueUsageIf( $continue < 0 || $continue > count( $titles ) ); + $titles = array_slice( $titles, $continue, null, true ); + } + $count = 0; + $titleInFileNamespace = false; + /** @var PageIdentity $t */ + foreach ( $titles as $id => $t ) { + if ( ++$count > $limit ) { + $this->setContinueEnumParameter( 'continue', $continue + $count - 1 ); + break; + } + + if ( $t->getNamespace() === NS_FILE ) { + $text = ''; + $titleInFileNamespace = true; + } else { + $params = $this->params; + $text = $this->getExtract( $t ); + $text = $this->truncate( $text ); + if ( $params['plaintext'] ) { + $text = $this->doSections( $text ); + } else { + if ( $params['sentences'] ) { + $this->addWarning( $this->msg( 'apiwarn-textextracts-sentences-and-html', self::PREFIX ) ); + } + $this->addWarning( 'apiwarn-textextracts-malformed-html' ); + } + } + + if ( $isXml ) { + $fit = $result->addValue( [ 'query', 'pages', $id ], 'extract', [ '*' => $text ] ); + } else { + $fit = $result->addValue( [ 'query', 'pages', $id ], 'extract', $text ); + } + if ( !$fit ) { + $this->setContinueEnumParameter( 'continue', $continue + $count - 1 ); + break; + } + } + if ( $titleInFileNamespace ) { + $this->addWarning( 'apiwarn-textextracts-title-in-file-namespace' ); + } + } + + /** + * @param array $params Ignored parameters + * @return string + */ + public function getCacheMode( $params ) { + return 'public'; + } + + /** + * Returns a processed, but not trimmed extract + * @param PageIdentity $title + * @return string + */ + private function getExtract( PageIdentity $title ) { + $page = $this->wikiPageFactory->newFromTitle( $title ); + + $contentModel = $page->getContentModel(); + if ( !in_array( $contentModel, $this->supportedContentModels, true ) ) { + $this->addWarning( [ + 'apiwarn-textextracts-unsupportedmodel', + wfEscapeWikiText( $this->titleFormatter->getPrefixedText( $title ) ), + $contentModel + ] ); + return ''; + } + + $introOnly = $this->params['intro']; + $text = false; // $this->getFromCache( $page, $introOnly ); + // if we need just first section, try retrieving full page and getting first section out of it + if ( $text === false && $introOnly ) { + $text = false; // $this->getFromCache( $page, false ); + if ( $text !== false ) { + $text = $this->getFirstSection( $text, $this->params['plaintext'] ); + } + } + if ( $text === false ) { + $text = $this->parse( $page ); + $text = $this->convertText( $text ); + $this->setCache( $page, $text ); + } + return $text; + } + + /** + * @param WANObjectCache $cache + * @param WikiPage $page + * @param bool $introOnly + * @return string + */ + private function cacheKey( WANObjectCache $cache, WikiPage $page, $introOnly ) { + $langConv = $this->langConvFactory->getLanguageConverter( $page->getTitle()->getPageLanguage() ); + return $cache->makeKey( 'textextracts', self::CACHE_VERSION, + $page->getId(), $page->getTouched(), + $langConv->getPreferredVariant(), + $this->params['plaintext'] ? 'plaintext' : 'html', + $introOnly ? 'intro' : 'full' + ); + } + + /** + * @param WikiPage $page + * @param bool $introOnly + * @return string|false + */ + private function getFromCache( WikiPage $page, $introOnly ) { + $cache = $this->cache; + // @TODO: replace with getWithSetCallback() + $key = $this->cacheKey( $cache, $page, $introOnly ); + return $cache->get( $key ); + } + + /** + * @param WikiPage $page + * @param string $text + */ + private function setCache( WikiPage $page, $text ) { + $cache = $this->cache; + // @TODO: replace with getWithSetCallback() + $key = $this->cacheKey( $cache, $page, $this->params['intro'] ); + $cache->set( $key, $text, $this->getConfig()->get( 'ParserCacheExpireTime' ) ); + } + + /** + * @param string $text + * @param bool $plainText + * @return string + */ + private function getFirstSection( $text, $plainText ) { + // Remove headers + if ( $plainText ) { + $text = preg_replace( '/^(]*>.*?<\/h[1-6]>|\n)*/s', '', $text ); + } else { + $text = preg_replace( '/^(]*>.*?<\/h[1-6]>|\n)*/s', '', $text ); + } + + if ( $plainText ) { + $regexp = '/^.*?(?=' . ExtractFormatter::SECTION_MARKER_START . + '(?!.' . ExtractFormatter::SECTION_MARKER_END . '

getParserOutputAccess(); + $status = $parserOutputAccess->getParserOutput( + $page->toPageRecord(), + ParserOptions::newFromAnon() + ); + if ( $status->isOK() ) { + $pout = $status->getValue(); + $text = $pout->getText( [ 'unwrap' => true ] ); + if ( $this->params['intro'] ) { + $text = $this->getFirstSection( $text, false ); + } + return $text; + } else { + LoggerFactory::getInstance( 'textextracts' )->warning( + 'Parse attempt failed while generating text extract', [ + 'title' => $page->getTitle()->getFullText(), + 'url' => $this->getRequest()->getFullRequestURL(), + 'reason' => $status->getWikiText( false, false, 'en' ) + ] ); + $this->dieStatus( $status ); + } + } + + /** + * Converts page HTML into an extract + * @param string $text + * @return string + */ + private function convertText( $text ) { + $fmt = new ExtractFormatter( $text, $this->params['plaintext'] ); + $fmt->remove( $this->config->get( 'ExtractsRemoveClasses' ) ); + $text = $fmt->getText(); + return $text; + } + + /** + * Truncate the given text to a certain number of characters or sentences + * @param string $text The text to truncate + * @return string + */ + private function truncate( $text ) { + $useTidy = !$this->params['plaintext']; + $truncator = new TextTruncator( $useTidy ); + + if ( $this->params['chars'] ) { + $truncatedText = $truncator->getFirstChars( $text, $this->params['chars'] ); + if ( $truncatedText !== $text ) { + $text = $truncatedText . $this->msg( 'ellipsis' )->text(); + } + } elseif ( $this->params['sentences'] ) { + $text = $truncator->getFirstSentences( $text, $this->params['sentences'] ); + } + return $text; + } + + /** + * @param string $text + * @return string + */ + private function doSections( $text ) { + $pattern = '/' . + ExtractFormatter::SECTION_MARKER_START . '(\d)' . + ExtractFormatter::SECTION_MARKER_END . '(.*)/'; + + switch ( $this->params['sectionformat'] ) { + case 'raw': + return $text; + + case 'wiki': + return preg_replace_callback( $pattern, static function ( $matches ) { + $bars = str_repeat( '=', $matches[1] ); + return "\n$bars " . trim( $matches[2] ) . " $bars"; + }, $text ); + + case 'plain': + return preg_replace_callback( $pattern, static function ( $matches ) { + return "\n" . trim( $matches[2] ); + }, $text ); + + default: + throw new \LogicException( 'Invalid sectionformat' ); + } + } + + /** + * @inheritDoc + */ + public function getAllowedParams() { + return [ + 'chars' => [ + ApiBase::PARAM_TYPE => 'integer', + ApiBase::PARAM_MIN => 1, + ApiBase::PARAM_MAX => 1200, + ], + 'sentences' => [ + ApiBase::PARAM_TYPE => 'integer', + ApiBase::PARAM_MIN => 1, + ApiBase::PARAM_MAX => 10, + ], + 'limit' => [ + ParamValidator::PARAM_DEFAULT => 20, + ApiBase::PARAM_TYPE => 'limit', + ApiBase::PARAM_MIN => 1, + ApiBase::PARAM_MAX => 20, + ApiBase::PARAM_MAX2 => 20, + ], + 'intro' => false, + 'plaintext' => false, + 'sectionformat' => [ + ApiBase::PARAM_TYPE => [ 'plain', 'wiki', 'raw' ], + ParamValidator::PARAM_DEFAULT => 'wiki', + ApiBase::PARAM_HELP_MSG_PER_VALUE => [], + ], + 'continue' => [ + ApiBase::PARAM_TYPE => 'integer', + ApiBase::PARAM_HELP_MSG => 'api-help-param-continue', + ], + ]; + } + + /** + * @inheritDoc + */ + protected function getExamplesMessages() { + return [ + 'action=query&prop=extracts&exchars=175&titles=Therion' + => 'apihelp-query+extracts-example-1', + ]; + } + + /** + * @inheritDoc + */ + public function getHelpUrls() { + return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#API'; + } + +} diff --git a/includes/ExtractFormatter.php b/includes/ExtractFormatter.php new file mode 100644 index 0000000..28fccd1 --- /dev/null +++ b/includes/ExtractFormatter.php @@ -0,0 +1,109 @@ +"; + public const SECTION_MARKER_END = "<|endofsection|>"; + + /** + * @var bool + */ + private $plainText; + + /** + * @param string $text Text to convert + * @param bool $plainText Whether extract should be plaintext + */ + public function __construct( $text, $plainText ) { + parent::__construct( HtmlFormatter::wrapHTML( $text ) ); + $this->plainText = $plainText; + + $this->setRemoveMedia( true ); + + if ( $plainText ) { + $this->flattenAllTags(); + } else { + $this->flatten( [ 'a' ] ); + } + } + + /** + * Performs final transformations (such as newline replacement for plaintext + * option) and returns resulting HTML. + * + * @param DOMElement|string|null $element ID of element to get HTML from. + * Ignored + * @return string Processed HTML + */ + public function getText( $element = null ): string { + $this->filterContent(); + $text = parent::getText(); + if ( $this->plainText ) { + $text = html_entity_decode( $text ); + // replace nbsp with space + $text = str_replace( "\u{00A0}", ' ', $text ); + // for Windows + $text = str_replace( "\r", "\n", $text ); + // normalise newlines + $text = preg_replace( "/\n{3,}/", "\n\n", $text ); + } + return trim( $text ); + } + + /** + * @param string $html HTML string to process + * @return string Processed HTML + */ + public function onHtmlReady( string $html ): string { + if ( $this->plainText ) { + $html = preg_replace( '/\s*(getDoc(); + + // Headings in a DIV wrapper may get removed by $wgExtractsRemoveClasses, + // move it outside the header to rescue it (T363445) + // https://www.mediawiki.org/wiki/Heading_HTML_changes + $headings = DOMCompat::querySelectorAll( $doc->documentElement, 'h1, h2, h3, h4, h5, h6' ); + foreach ( $headings as $heading ) { + // @phan-suppress-next-line PhanTypeMismatchArgumentSuperType + if ( DOMCompat::getClassList( $heading->parentNode )->contains( 'mw-heading' ) ) { + $heading->parentNode->parentNode->insertBefore( $heading, $heading->parentNode ); + } + } + + $removed = parent::filterContent(); + + $spans = $doc->getElementsByTagName( 'span' ); + + /** @var DOMElement $span */ + foreach ( $spans as $span ) { + $span->removeAttribute( 'class' ); + $span->removeAttribute( 'style' ); + } + + return $removed; + } +} diff --git a/includes/Hooks.php b/includes/Hooks.php new file mode 100644 index 0000000..251160c --- /dev/null +++ b/includes/Hooks.php @@ -0,0 +1,145 @@ +config = $configFactory->makeConfig( 'textextracts' ); + } + + /** + * Trim an extract to a sensible length. + * + * Adapted from Extension:OpenSearchXml, which adapted it from + * Extension:ActiveAbstract. + * + * @param string $text + * @param int $length Target length; actual result will continue to the end of a sentence. + * @return string + */ + private static function trimExtract( $text, $length ) { + static $regex = null; + if ( $regex === null ) { + $endchars = [ + // regular ASCII + '([^\d])\.\s', '\!\s', '\?\s', + // full-width ideographic full-stop + '。', + // double-width roman forms + '.', '!', '?', + // half-width ideographic full stop + '。', + ]; + $endgroup = implode( '|', $endchars ); + $end = "(?:$endgroup)"; + $sentence = ".{{$length},}?$end+"; + $regex = "/^($sentence)/u"; + } + $matches = []; + if ( preg_match( $regex, $text, $matches ) ) { + return trim( $matches[1] ); + } else { + // Just return the first line + return trim( explode( "\n", $text )[0] ); + } + } + + /** + * Retrieves extracts data for the given page IDs from the TextExtract API. + * The page IDs are chunked into the max limit of exlimit of the TextExtract API + * + * @param array $pageIds An array of page IDs to retrieve extracts for + * @return Generator Yields the result data from the API request + * $data = [ + * 'pageId' => [ + * 'ns' => int of the namespace + * 'title' => string of the title of the page + * 'extract' => string of the text extracts of the page + * ] + * ] + */ + private function getExtractsData( array $pageIds ) { + foreach ( array_chunk( $pageIds, 20 ) as $chunkedPageIds ) { + $api = new ApiMain( new FauxRequest( + [ + 'action' => 'query', + 'prop' => 'extracts', + 'explaintext' => true, + 'exintro' => true, + 'exlimit' => count( $chunkedPageIds ), + 'pageids' => implode( '|', $chunkedPageIds ), + ] + ) ); + $api->execute(); + yield $api->getResult()->getResultData( [ 'query', 'pages' ] ); + } + } + + /** + * ApiOpenSearchSuggest hook handler + * @param array &$results Array of search results + */ + public function onApiOpenSearchSuggest( &$results ) { + if ( !$this->config->get( 'ExtractsExtendOpenSearchXml' ) || $results === [] ) { + return; + } + + $pageIds = array_keys( $results ); + foreach ( $this->getExtractsData( $pageIds ) as $data ) { + foreach ( $pageIds as $id ) { + $contentKey = $data[$id]['extract'][ApiResult::META_CONTENT] ?? '*'; + if ( isset( $data[$id]['extract'][$contentKey] ) ) { + $results[$id]['extract'] = $data[$id]['extract'][$contentKey]; + $results[$id]['extract trimmed'] = false; + } + } + } + } + + /** + * Used to update Search Results with descriptions for Search Engine. + * @param array $pageIdentities Array (string=>SearchResultPageIdentity) where key is pageId + * @param array &$descriptions Output array (string=>string|null) + * where key is pageId and value is either a description for given page or null + */ + public function onSearchResultProvideDescription( + array $pageIdentities, + &$descriptions + ): void { + if ( !$this->config->get( 'ExtractsExtendRestSearch' ) || $pageIdentities === [] ) { + return; + } + + $pageIds = array_map( static function ( $identity ) { + return $identity->getId(); + }, $pageIdentities ); + foreach ( $this->getExtractsData( $pageIds ) as $data ) { + foreach ( $pageIds as $id ) { + $contentKey = $data[$id]['extract'][ApiResult::META_CONTENT] ?? '*'; + if ( isset( $data[$id]['extract'][$contentKey] ) ) { + $descriptions[$id] = self::trimExtract( $data[$id]['extract'][$contentKey], 150 ); + } + } + } + } +} diff --git a/includes/TextTruncator.php b/includes/TextTruncator.php new file mode 100644 index 0000000..c89bacc --- /dev/null +++ b/includes/TextTruncator.php @@ -0,0 +1,111 @@ +useTidy = $useTidy; + } + + /** + * Returns no more than the given number of sentences + * + * @param string $text Source text to extract from + * @param int $requestedSentenceCount Maximum number of sentences to extract + * @return string + */ + public function getFirstSentences( $text, $requestedSentenceCount ) { + if ( $requestedSentenceCount <= 0 ) { + return ''; + } + + // Based on code from OpenSearchXml by Brion Vibber + $endchars = [ + // regular ASCII + '\P{Lu}\.(?=[ \n]|$)', + '[!?](?=[ \n]|$)', + // full-width ideographic full-stop + '。', + // double-width roman forms + '.', + '!', + '?', + // half-width ideographic full stop + '。', + ]; + + $regexp = '/(?:' . implode( '|', $endchars ) . ')+/u'; + $res = preg_match_all( $regexp, $text, $matches, PREG_OFFSET_CAPTURE ); + + if ( !$res ) { + // Just return the first line + $lines = explode( "\n", $text, 2 ); + return trim( $lines[0] ); + } + + $index = min( $requestedSentenceCount, $res ) - 1; + [ $tail, $length ] = $matches[0][$index]; + // PCRE returns raw offsets, so using substr() instead of mb_substr() + $text = substr( $text, 0, $length ) . $tail; + + return $this->tidy( $text ); + } + + /** + * Returns no more than a requested number of characters, preserving words + * + * @param string $text Source text to extract from + * @param int $requestedLength Maximum number of characters to return + * @return string + */ + public function getFirstChars( $text, $requestedLength ) { + if ( $requestedLength <= 0 ) { + return ''; + } + + $length = mb_strlen( $text ); + if ( $length <= $requestedLength ) { + return $text; + } + + // This ungreedy pattern always matches, just might return an empty string + $pattern = '/^[\w\/]*>?/su'; + preg_match( $pattern, mb_substr( $text, $requestedLength ), $m ); + $truncatedText = mb_substr( $text, 0, $requestedLength ) . $m[0]; + if ( $truncatedText === $text ) { + return $text; + } + + return $this->tidy( $truncatedText ); + } + + /** + * @param string $text + * @return string + */ + private function tidy( $text ) { + if ( $this->useTidy ) { + $text = MediaWikiServices::getInstance()->getTidy()->tidy( $text ); + } + + return trim( $text ); + } + +} diff --git a/tests/phpunit/ApiQueryExtractsTest.php b/tests/phpunit/ApiQueryExtractsTest.php new file mode 100644 index 0000000..1f11fb8 --- /dev/null +++ b/tests/phpunit/ApiQueryExtractsTest.php @@ -0,0 +1,274 @@ + ExpirationAwareness::TTL_INDEFINITE, + ] ); + + $configFactory = $this->createMock( ConfigFactory::class ); + $configFactory->method( 'makeConfig' ) + ->with( 'textextracts' ) + ->willReturn( $config ); + + $cache = new WANObjectCache( [ 'cache' => new HashBagOStuff() ] ); + + $context = $this->createMock( IContextSource::class ); + $context->method( 'getConfig' ) + ->willReturn( $config ); + $context->method( 'msg' ) + ->willReturnCallback( function ( $key, ...$params ) { + $msg = $this->createMock( Message::class ); + $msg->method( 'text' )->willReturn( "($key)" ); + return $msg; + } ); + + $main = $this->createMock( ApiMain::class ); + $main->expects( $this->once() ) + ->method( 'getContext' ) + ->willReturn( $context ); + + $query = $this->createMock( ApiQuery::class ); + $query->expects( $this->once() ) + ->method( 'getMain' ) + ->willReturn( $main ); + + $langConv = $this->createMock( ILanguageConverter::class ); + $langConv->method( 'getPreferredVariant' ) + ->willReturn( 'en' ); + $langConvFactory = $this->createMock( LanguageConverterFactory::class ); + $langConvFactory->method( 'getLanguageConverter' ) + ->willReturn( $langConv ); + + return new ApiQueryExtracts( + $query, + '', + $configFactory, + $cache, + $langConvFactory, + $this->getServiceContainer()->getWikiPageFactory(), + $this->getServiceContainer()->getTitleFormatter() + ); + } + + public function testMemCacheHelpers() { + $title = $this->createMock( Title::class ); + $title->method( 'getPageLanguage' ) + ->willReturn( $this->createMock( Language::class ) ); + + $page = $this->createMock( \WikiPage::class ); + $page->method( 'getTitle' ) + ->willReturn( $title ); + $page->method( 'getId' ) + ->willReturn( 123 ); + $page->method( 'getTouched' ) + ->willReturn( '20010101000000' ); + + $text = 'Text to cache'; + + /** @var ApiQueryExtracts $instance */ + $instance = TestingAccessWrapper::newFromObject( $this->newInstance() ); + // Default param values for this API module + $instance->params = [ 'intro' => false, 'plaintext' => false ]; + + $this->assertFalse( $instance->getFromCache( $page, false ), 'is not cached yet' ); + + $instance->setCache( $page, $text ); + $instance->cache->clearProcessCache(); + $this->assertSame( $text, $instance->getFromCache( $page, false ) ); + } + + public function testSelfDocumentation() { + /** @var ApiQueryExtracts $instance */ + $instance = TestingAccessWrapper::newFromObject( $this->newInstance() ); + + $this->assertIsString( $instance->getCacheMode( [] ) ); + $this->assertNotEmpty( $instance->getExamplesMessages() ); + $this->assertIsString( $instance->getHelpUrls() ); + + $params = $instance->getAllowedParams(); + $this->assertIsArray( $params ); + + $this->assertSame( 1, $params['chars'][ApiBase::PARAM_MIN] ); + $this->assertSame( 1200, $params['chars'][ApiBase::PARAM_MAX] ); + + $this->assertSame( 20, $params['limit'][ApiBase::PARAM_DFLT] ); + $this->assertSame( 'limit', $params['limit'][ApiBase::PARAM_TYPE] ); + $this->assertSame( 1, $params['limit'][ApiBase::PARAM_MIN] ); + $this->assertSame( 20, $params['limit'][ApiBase::PARAM_MAX] ); + $this->assertSame( 20, $params['limit'][ApiBase::PARAM_MAX2] ); + } + + /** + * @dataProvider provideFirstSectionsToExtract + */ + public function testGetFirstSection( $text, $isPlainText, $expected ) { + /** @var ApiQueryExtracts $instance */ + $instance = TestingAccessWrapper::newFromObject( $this->newInstance() ); + + $this->assertSame( $expected, $instance->getFirstSection( $text, $isPlainText ) ); + } + + public static function provideFirstSectionsToExtract() { + return [ + 'Plain text match' => [ + "First\nsection \1\2... \1\2...", + true, + "First\nsection ", + ], + 'Plain text without a match' => [ + 'Example\1\2...', + true, + 'Example\1\2...', + ], + + 'HTML match' => [ + "First\nsection

...

...", + false, + "First\nsection ", + ], + 'HTML without a match' => [ + 'Example ...', + false, + 'Example ...', + ], + '__TOC__ before intro (HTML)' => [ + '

Contents

Intro

Actual heading

...', + false, + '

Contents

Intro', + ], + '__TOC__ before intro (plaintext)' => [ + "\1\2_\2\1

Contents

Intro\1\2_\2\1

Actual heading

...", + true, + "\1\2_\2\1

Contents

Intro", + ], + ]; + } + + /** + * @dataProvider provideTextsToTruncate + */ + public function testTruncate( $text, array $params, $expected ) { + /** @var ApiQueryExtracts $instance */ + $instance = TestingAccessWrapper::newFromObject( $this->newInstance() ); + $instance->params = $params + [ 'chars' => null, 'sentences' => null, 'plaintext' => true ]; + + $this->assertSame( $expected, $instance->truncate( $text ) ); + } + + public static function provideTextsToTruncate() { + return [ + [ '', [], '' ], + [ 'abc', [], 'abc' ], + [ + 'abc', + [ 'chars' => 1 ], + 'abc' + ], + [ + 'abc', + [ 'chars' => 1, 'plaintext' => false ], + 'abc' + ], + [ + 'abc', + [ 'sentences' => 1 ], + 'abc' + ], + [ + 'abc abc. xyz xyz.', + [ 'chars' => 1 ], + 'abc(ellipsis)' + ], + [ + 'abc abc. xyz xyz.', + [ 'sentences' => 1 ], + 'abc abc.' + ], + [ + 'abc abc. xyz xyz.', + [ 'chars' => 1000 ], + 'abc abc. xyz xyz.' + ], + [ + 'abc abc. xyz xyz.', + [ 'chars' => 1000, 'plaintext' => false ], + 'abc abc. xyz xyz.' + ], + [ + 'abc abc. xyz xyz.', + [ 'sentences' => 10 ], + 'abc abc. xyz xyz.' + ], + ]; + } + + /** + * @dataProvider provideSectionsToFormat + */ + public function testDoSections( $text, $format, $expected ) { + /** @var ApiQueryExtracts $instance */ + $instance = TestingAccessWrapper::newFromObject( $this->newInstance() ); + $instance->params = [ 'sectionformat' => $format ]; + + $this->assertSame( $expected, $instance->doSections( $text ) ); + } + + public static function provideSectionsToFormat() { + $level = 3; + $marker = "\1\2$level\2\1"; + + return [ + 'Raw' => [ + "$marker Headline\t\nNext line", + 'raw', + "$marker Headline\t\nNext line", + ], + 'Wiki text' => [ + "$marker Headline\t\nNext line", + 'wiki', + "\n=== Headline ===\nNext line", + ], + 'Plain text' => [ + "$marker Headline\t\nNext line", + 'plain', + "\nHeadline\nNext line", + ], + + 'Multiple matches' => [ + "{$marker}First\n{$marker}Second", + 'wiki', + "\n=== First ===\n\n=== Second ===", + ], + ]; + } + +} diff --git a/tests/phpunit/ExtractFormatterTest.php b/tests/phpunit/ExtractFormatterTest.php new file mode 100644 index 0000000..35bc7d8 --- /dev/null +++ b/tests/phpunit/ExtractFormatterTest.php @@ -0,0 +1,108 @@ +remove( [ 'div', 'figure', '.metadata' ] ); + $text = $fmt->getText(); + $this->assertSame( $expected, $text ); + } + + public static function provideExtracts() { + // phpcs:ignore Generic.Files.LineLength + $dutch = 'Dutch (About this sound Nederlands ) is a West Germanic language and the native language of most of the population of the Netherlands'; + $tocText = 'Lead
TOC goes here
+

Section

+

Section text

'; + // phpcs:ignore Generic.Files.LineLength + $figureText = 'Test 123beforetext
About this sound
Very loud speaker
aftertext'; + + return [ + [ + 'Dutch ( Nederlands ) is a West Germanic language and the native language of ' . + 'most of the population of the Netherlands', + $dutch, + true, + ], + + 'HTML cleanup in HTML mode' => [ + "\u{00A0}A & B", + "  A & B\r\n", + false + ], + 'HTML cleanup in plain text mode' => [ + 'A & B', + "  A & B\r\n", + true + ], + + [ + "qux", + 'qux', + false, + ], + [ + "qux", + 'qux', + false, + ], + [ + "quux", + 'quux', + false, + ], + [ + // New heading markup from T13555 (T363445) + "

hello

heading

bye

", + '

hello

' . + '
' . + '

heading

' . + 'xxx' . + '
' . + '

bye

', + false, + ], + [ + // Verify that TOC is properly removed (HTML mode) + "Lead\n

Section

\n

Section text

", + $tocText, + false, + ], + [ + // Verify that TOC is properly removed (plain text mode) + "Lead\n\n\x01\x021\2\1Section\nSection text", + $tocText, + true, + ], + [ + // Verify that text in figures is removed (plain) + 'Test 123beforetextaftertext', + $figureText, + true, + ], + [ + // Verify that text in figures is removed (html) + 'Test 123beforetextaftertext', + $figureText, + false, + ] + ]; + } + +} diff --git a/tests/phpunit/TextTruncatorTest.php b/tests/phpunit/TextTruncatorTest.php new file mode 100644 index 0000000..873e854 --- /dev/null +++ b/tests/phpunit/TextTruncatorTest.php @@ -0,0 +1,178 @@ +assertSame( $expected, $truncator->getFirstSentences( $text, $sentences ) ); + } + + public static function provideGetFirstSentences() { + $longLine = str_repeat( 'word ', 1000000 ); + return [ + [ + 'Foo is a bar. Such a smart boy. But completely useless.', + 2, + 'Foo is a bar. Such a smart boy.', + ], + [ + 'Foo is a bar. Such a smart boy. But completely useless.', + 1, + 'Foo is a bar.', + ], + [ + 'Foo is a bar. Such a smart boy.', + 2, + 'Foo is a bar. Such a smart boy.', + ], + [ + 'Foo is a bar.', + 1, + 'Foo is a bar.', + ], + [ + 'Foo is a bar.', + 2, + 'Foo is a bar.', + ], + [ + '', + 1, + '', + ], + '0 sentences mean empty result' => [ + 'Foo is a bar. Such a smart boy.', + 0, + '', + ], + "Don't explode on negative input" => [ + 'Foo is a bar. Such a smart boy.', + -1, + '', + ], + 'More sentences requested than is available' => [ + 'Foo is a bar. Such a smart boy.', + 3, + 'Foo is a bar. Such a smart boy.', + ], + // Exclamation points too!!! + [ + 'Foo is a bar! Such a smart boy! But completely useless!', + 1, + 'Foo is a bar!', + ], + // A tricky one + [ + "Acid phosphatase (EC 3.1.3.2) is a chemical you don't want to mess with. " . + "Polyvinyl acetate, however, is another story.", + 1, + "Acid phosphatase (EC 3.1.3.2) is a chemical you don't want to mess with.", + ], + // No clear sentences + [ + "foo\nbar\nbaz", + 2, + 'foo', + ], + // Bug T118621 + [ + 'Foo was born in 1977. He enjoys listening to Siouxsie and the Banshees.', + 1, + 'Foo was born in 1977.', + ], + // Bug T115795 - Test no cropping after initials + [ + 'P.J. Harvey is a singer. She is awesome!', + 1, + 'P.J. Harvey is a singer.', + ], + // Bug T115817 - Non-breaking space is not a delimiter + [ + html_entity_decode( 'Pigeons (lat. Columbidae) are birds. ' . + 'They primarily feed on seeds.' ), + 1, + html_entity_decode( 'Pigeons (lat. Columbidae) are birds.' ), + ], + // Bug T145231 - various problems with regexes + [ + $longLine, + 3, + trim( $longLine ), + ], + [ + str_repeat( 'Sentence. ', 70000 ), + 65536, + trim( str_repeat( 'Sentence. ', 65536 ) ), + ], + + 'Preserve whitespace before end character' => [ + 'Aa . Bb', + 1, + 'Aa .', + ], + ]; + } + + /** + * @dataProvider provideGetFirstChars + * @param string $text + * @param string $chars + * @param string $expected + */ + public function testGetFirstChars( $text, $chars, $expected ) { + $truncator = new TextTruncator( false ); + $this->assertSame( $expected, $truncator->getFirstChars( $text, $chars ) ); + } + + public static function provideGetFirstChars() { + $text = 'Lullzy lulz are lullzy!'; + $html = 'foobar'; + $longText = str_repeat( 'тест ', 50000 ); + $longTextExpected = trim( str_repeat( 'тест ', 13108 ) ); + + return [ + [ $text, -8, '' ], + [ $text, 0, '' ], + [ $text, 100, $text ], + [ $text, 1, 'Lullzy' ], + [ $text, 6, 'Lullzy' ], + // [ $text, 7, 'Lullzy' ], + [ $text, 8, 'Lullzy lulz' ], + // HTML processing + [ $html, 1, 'foo' ], + // let HTML sanitizer clean it up later + [ $html, 4, 'foo' ], + [ $html, 12, 'foobar' ], + [ $html, 13, 'foobar' ], + [ $html, 16, 'foobar' ], + [ $html, 17, 'foobar' ], + // T143178 - previously, characters were extracted using regexps which failed when + // requesting 64K chars or more. + [ $longText, 65536, $longTextExpected ], + ]; + } + + public function testTidyIntegration() { + $truncator = new TextTruncator( true ); + + $text = 'Aa. Bb.'; + $this->assertSame( '

Aa.

', $truncator->getFirstSentences( $text, 1 ) ); + $this->assertSame( '

Aa

', $truncator->getFirstChars( $text, 4 ) ); + } + +}