From: jenkins-bot Date: Mon, 14 May 2018 04:17:15 +0000 (+0000) Subject: Merge "Initial support for Content Security Policy, disabled by default" X-Git-Tag: 1.34.0-rc.0~5438 X-Git-Url: http://git.cyclocoop.org/%22%2C%20generer_url_ecrire%28?a=commitdiff_plain;h=8e6496aaa3713424fe16b71e433c6b253afbf451;hp=70941efd35562dcb7003229b56c91a98a67de7a9;p=lhc%2Fweb%2Fwiklou.git Merge "Initial support for Content Security Policy, disabled by default" --- diff --git a/README b/README deleted file mode 100644 index ad9b9d9d83..0000000000 --- a/README +++ /dev/null @@ -1,33 +0,0 @@ -== MediaWiki == - -MediaWiki is a free and open-source wiki software package written in PHP. It -serves as the platform for Wikipedia and the other Wikimedia projects, used -by hundreds of millions of people each month. MediaWiki is localised in over -350 languages and its reliability and robust feature set have earned it a large -and vibrant community of third-party users and developers. - -MediaWiki is: - -* feature-rich and extensible, both on-wiki and with hundreds of extensions; -* scalable and suitable for both small and large sites; -* simple to install, working on most hardware/software combinations; and -* available in your language. - -For system requirements, installation, and upgrade details, see the files -RELEASE-NOTES, INSTALL, and UPGRADE. - -* Ready to get started? -** https://www.mediawiki.org/wiki/Special:MyLanguage/Download -* Looking for the technical manual? -** https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents -* Seeking help from a person? -** https://www.mediawiki.org/wiki/Special:MyLanguage/Communication -* Looking to file a bug report or a feature request? -** https://bugs.mediawiki.org/ -* Interested in helping out? -** https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute - -MediaWiki is the result of global collaboration and cooperation. The CREDITS -file lists technical contributors to the project. The COPYING file explains -MediaWiki's copyright and license (GNU General Public License, version 2 or -later). Many thanks to the Wikimedia community for testing and suggestions. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..ca703dbc0f --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +MediaWiki +=========== + +MediaWiki is a free and open-source wiki software package written in PHP. It +serves as the platform for Wikipedia and the other Wikimedia projects, used +by hundreds of millions of people each month. MediaWiki is localised in over +350 languages and its reliability and robust feature set have earned it a large +and vibrant community of third-party users and developers. + +MediaWiki is: + +* feature-rich and extensible, both on-wiki and with hundreds of extensions; +* scalable and suitable for both small and large sites; +* simple to install, working on most hardware/software combinations; and +* available in your language. + +For system requirements, installation, and upgrade details, see the files +RELEASE-NOTES, INSTALL, and UPGRADE. + +* Ready to get started? +** https://www.mediawiki.org/wiki/Special:MyLanguage/Download +* Looking for the technical manual? +** https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents +* Seeking help from a person? +** https://www.mediawiki.org/wiki/Special:MyLanguage/Communication +* Looking to file a bug report or a feature request? +** https://bugs.mediawiki.org/ +* Interested in helping out? +** https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute + +MediaWiki is the result of global collaboration and cooperation. The CREDITS +file lists technical contributors to the project. The COPYING file explains +MediaWiki's copyright and license (GNU General Public License, version 2 or +later). Many thanks to the Wikimedia community for testing and suggestions. diff --git a/README.mediawiki b/README.mediawiki deleted file mode 120000 index 100b93820a..0000000000 --- a/README.mediawiki +++ /dev/null @@ -1 +0,0 @@ -README \ No newline at end of file diff --git a/autoload.php b/autoload.php index 6aa832c0b2..6e123a10b0 100644 --- a/autoload.php +++ b/autoload.php @@ -225,6 +225,7 @@ $wgAutoloadLocalClasses = [ 'CapsCleanup' => __DIR__ . '/maintenance/cleanupCaps.php', 'CategoriesRdf' => __DIR__ . '/includes/CategoriesRdf.php', 'Category' => __DIR__ . '/includes/Category.php', + 'CategoryChangesAsRdf' => __DIR__ . '/maintenance/categoryChangesAsRdf.php', 'CategoryFinder' => __DIR__ . '/includes/CategoryFinder.php', 'CategoryMembershipChange' => __DIR__ . '/includes/changes/CategoryMembershipChange.php', 'CategoryMembershipChangeJob' => __DIR__ . '/includes/jobqueue/jobs/CategoryMembershipChangeJob.php', diff --git a/composer.json b/composer.json index 8de402561b..833e3bfd0e 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "mediawiki/core", "description": "Free software wiki application developed by the Wikimedia Foundation and others", + "type": "mediawiki-core", "keywords": ["mediawiki", "wiki"], "homepage": "https://www.mediawiki.org/", "authors": [ diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 72375fbfaf..87ca0168bd 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -7864,10 +7864,6 @@ $wgActionFilteredLogs = [ 'autocreate' => [ 'autocreate' ], 'byemail' => [ 'byemail' ], ], - 'patrol' => [ - 'patrol' => [ 'patrol' ], - 'autopatrol' => [ 'autopatrol' ], - ], 'protect' => [ 'protect' => [ 'protect' ], 'modify' => [ 'modify' ], diff --git a/includes/api/i18n/he.json b/includes/api/i18n/he.json index 097d510625..d044ecb16d 100644 --- a/includes/api/i18n/he.json +++ b/includes/api/i18n/he.json @@ -475,7 +475,7 @@ "apihelp-query+allimages-param-sha1base36": "גיבוב SHA1 של התמונה בבסיס 36 (הבסיס בו נעשה שימוש במדיה־ויקי).", "apihelp-query+allimages-param-user": "להחזיר רק קבצים שהועלו על־ידי המשתמש הזה. יכול לשמש רק עם $1sort=timestamp. לא יכול לשמש יחד עם $1filterbots.", "apihelp-query+allimages-param-filterbots": "איך לסנן קבצים שמעלים בוטים. יכול לשמש רק עם $1sort=timestamp. לא יכול לשמש יחד עם $1user.", - "apihelp-query+allimages-param-mime": "אילו סוגי MIME לחבפש, למשל image/jpeg.", + "apihelp-query+allimages-param-mime": "אילו סוגי MIME לחפש, למשל image/jpeg.", "apihelp-query+allimages-param-limit": "כמה תמונות להחזיר בסך הכול.", "apihelp-query+allimages-example-B": "הצגת רשימה של קבצים שמתחילים באות B.", "apihelp-query+allimages-example-recent": "הצגת רשימת קבצים שהועלו לאחרונה, דומה ל־[[Special:NewFiles]].", @@ -642,7 +642,7 @@ "apihelp-query+categories-paramvalue-prop-hidden": "תיוג קטגוריות שהוסתרו באמצעות __HIDDENCAT__.", "apihelp-query+categories-param-show": "איזה סוג של קטגוריות להציג.", "apihelp-query+categories-param-limit": "כמה קטגוריות להחזיר.", - "apihelp-query+categories-param-categories": "לרשום רק את הקטגוריות האלו. שימושי לבדיקה עם דף מסוים נמצא בקטגוריה מסוימת.", + "apihelp-query+categories-param-categories": "לרשום רק את הקטגוריות האלו. שימושי לבדיקה אם דף מסוים נמצא בקטגוריה מסוימת.", "apihelp-query+categories-param-dir": "באיזה כיוון לרשום.", "apihelp-query+categories-example-simple": "קבלת רשימת קטגוריות שהם Albert Einstein שייך אליהן.", "apihelp-query+categories-example-generator": "קבלת מידע על כל הקטגוריות שמשמשות בדף Albert Einstein.", @@ -799,7 +799,7 @@ "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "משמש את Special:Upload כדי לקבל מידע על קובץ קיים. לא נועד לשימוש מחוץ לליבת MediaWiki.", "apihelp-query+imageinfo-paramvalue-prop-badfile": "מוסיף האם הקובץ נמצא ב־[[MediaWiki:Bad image list]]", "apihelp-query+imageinfo-param-limit": "כמה גרסאות של קובץ לכל קובץ.", - "apihelp-query+imageinfo-param-start": "מאיז חותם־זמן להתחיל רשימה.", + "apihelp-query+imageinfo-param-start": "מאילו תאריך ושעה להתחיל את הרשימה.", "apihelp-query+imageinfo-param-end": "באיזה חותם־זמן לסיים את הרשימה.", "apihelp-query+imageinfo-param-urlwidth": "אם מוגדר $2prop=url, יוחזר URL לתמונה שגודלה הותאם לרוחב הזה.\nמסיבות של ביצועים, אם האפשרות הזאת משמשת, לא יוחזרו יותר מ־$1 תמונות.", "apihelp-query+imageinfo-param-urlheight": "דומה ל־$1urlwidth.", @@ -987,7 +987,7 @@ "apihelp-query+recentchanges-param-end": "באיזה חותם זמן להפסיק לרשום.", "apihelp-query+recentchanges-param-namespace": "לסנן את השינויים רק למרחבי השם האלה.", "apihelp-query+recentchanges-param-user": "לרשום רק שינויים של המשתמש הזה.", - "apihelp-query+recentchanges-param-excludeuser": "Don't list changes by this user", + "apihelp-query+recentchanges-param-excludeuser": "לא לרשום שינויים ממשתמש זה.", "apihelp-query+recentchanges-param-tag": "לרשום רק שינויים שמתויגים עם התג הזה.", "apihelp-query+recentchanges-param-prop": "לכלול פריטי מידע נוספים:", "apihelp-query+recentchanges-paramvalue-prop-user": "הוספת המשתמש האחראי על העריכה ותיוג אם זאת כתובת IP.", @@ -1098,7 +1098,7 @@ "apihelp-query+siteinfo-paramvalue-prop-namespacealiases": "רשימת כינויי מרחבי שם רשומים.", "apihelp-query+siteinfo-paramvalue-prop-specialpagealiases": "רשימת כינויים דפים מיוחדים.", "apihelp-query+siteinfo-paramvalue-prop-magicwords": "רשימות מילות קסם וכינוייהן.", - "apihelp-query+siteinfo-paramvalue-prop-statistics": "החזרזת סטטיסטיקות אתר.", + "apihelp-query+siteinfo-paramvalue-prop-statistics": "החזרת סטטיסטיקות של האתר.", "apihelp-query+siteinfo-paramvalue-prop-interwikimap": "החזרת מפת בינוויקי (אפשר שתהיה מסוננת, אפשר שתהיה מותאמת מקומית באמצעות $1inlanguagecode).", "apihelp-query+siteinfo-paramvalue-prop-dbrepllag": "החזרת שרת מסד־נתונים עם שיהוי השכפול הגבוה ביותר.", "apihelp-query+siteinfo-paramvalue-prop-usergroups": "החזרת קבוצות משתמשים וההרשאות המשויכות.", @@ -1233,7 +1233,7 @@ "apihelp-query+watchlist-param-end": "באיזה חותם זמן להפסיק לרשום.", "apihelp-query+watchlist-param-namespace": "סינון שינויים רק למרחבי השם שניתנו.", "apihelp-query+watchlist-param-user": "לרשום רק שינויים של המשתמש הזה.", - "apihelp-query+watchlist-param-excludeuser": "Don't list changes by this user", + "apihelp-query+watchlist-param-excludeuser": "לא לרשום שינויים ממשתמש זה.", "apihelp-query+watchlist-param-limit": "כמה תוצאות סך הכול להחזיר בכל בקשה.", "apihelp-query+watchlist-param-prop": "אילו מאפיינים נוספים לקבל:", "apihelp-query+watchlist-paramvalue-prop-ids": "הוספת מזהי גסה ומזהי דף.", @@ -1302,7 +1302,7 @@ "apihelp-rollback-param-title": "שם הדף לשחזור. לא יכול לשמש יחד עם $1pageid.", "apihelp-rollback-param-pageid": "מזהה הדף לשחזור. לא יכול לשמש יחד עם $1title.", "apihelp-rollback-param-tags": "אילו תגים להחיל על השחזור.", - "apihelp-rollback-param-user": "שם המשתמשים שהעריכות שלו תשוחזרנה.", + "apihelp-rollback-param-user": "שם המשתמש שהעריכות שלו תשוחזרנה.", "apihelp-rollback-param-summary": "תקציר עריכה מותאם. אם ריק, ישמש תקציר לפי בררת מחדל.", "apihelp-rollback-param-markbot": "לסמן את העריכות ששוחזרו ואת השחזור בתור עריכות בוט.", "apihelp-rollback-param-watchlist": "הוספה או הסרה של הדף ללא תנאי מרשימת המעקב של המשתמש הנוכחי, להשתמש בהעדפות או לא לשנות את המעקב.", @@ -1320,8 +1320,8 @@ "apihelp-setnotificationtimestamp-example-page": "אתחול מצב ההודעה עבור Main Page.", "apihelp-setnotificationtimestamp-example-pagetimestamp": "הגדרת חותם־הזמן להודעה ל־Main page כך שכל העריכות מאז 1 בינואר 2012 מוגדרות בתור כאלה שלא נצפו.", "apihelp-setnotificationtimestamp-example-allpages": "אתחול מצב ההודעה עבור דפים במרחב השם {{ns:user}}.", - "apihelp-setpagelanguage-summary": "שנה את השפה של דף", - "apihelp-setpagelanguage-extended-description-disabled": "שינוי השפה של דף לא מורשה בוויקי זה.\n\nהפעל את [[mw:Special:MyLanguage/Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]] על מנת להשתמש בפעולה זו", + "apihelp-setpagelanguage-summary": "שינוי השפה של דף.", + "apihelp-setpagelanguage-extended-description-disabled": "לא ניתן לשנות שפות של דפים באתר הוויקי הזה.\n\nיש להפעיל את [[mw:Special:MyLanguage/Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]] על־מנת להשתמש בפעולה זו.", "apihelp-setpagelanguage-param-title": "כותרת הדף שאת שפתו ברצונך לשנות. לא אפשרי להשתמש באפשרות עם $1pageid.", "apihelp-setpagelanguage-param-pageid": "מזהה הדף שאת שפתו ברצונך לשנות. לא אפשרי להשתמש באפשרות עם $1title.", "apihelp-setpagelanguage-param-lang": "קוד השפה של השפה שאליה צריך לשנות את הדף. יש להשתמש ב־default כדי לאתחל את הדף לשפת בררת המחדל של הוויקי.", @@ -1435,7 +1435,7 @@ "apihelp-phpfm-summary": "לפלוט נתונים בתסדיר PHP מוסדר (עם הדפסה יפה ב־HTML).", "apihelp-rawfm-summary": "לפלוט את הנתונים, כולל אלמנטים לניפוי שגיאות, בתסדיר JSON (עם הדפסה יפה ב־HTML).", "apihelp-xml-summary": "לפלוט נתונים בתסדיר XML.", - "apihelp-xml-param-xslt": "אם צוין, יש להוסיף את שם הדף כגיליון עיצוב XSL. על הערך להיות כותרת ב {{ns:MediaWiki}} במרחב שם המשתמש, המסתיים ב- .xsl.", + "apihelp-xml-param-xslt": "אם צוין, הדף יתווסף כגיליון XSL. הערך חייב להיות כותרת במרחב השם \"{{ns:MediaWiki}}\" שמסתיימת ב־.xsl.", "apihelp-xml-param-includexmlnamespace": "אם זה צוין, מוסיף מרחב שם של XML.", "apihelp-xmlfm-summary": "לפלוט נתונים בתסדיר XML (עם הדפסה יפה ב־HTML).", "api-format-title": "תוצאה של API של מדיה־ויקי", @@ -1718,7 +1718,7 @@ "apierror-writeapidenied": "אין לך הרשאה לערוך את הוויקי הזה דרך ה־API.", "apiwarn-alldeletedrevisions-performance": "לביצועים טובים יותר בעת יצירת כותרת, יש להשתמש ב־$1dir=newer.", "apiwarn-badurlparam": "לא היה אפשר לפענח את $1urlparam עבור $2. משתמשים רק ב־width ו־height.", - "apiwarn-badutf8": "הערך הערך שהועבר ל־$1 מכיל נתונים בלתי־תקינים או בלתי־מנורמלים. נתונים טקסט אמורים להיות תקינים, מנורמלי NFC ללא תווי בקרה C0 למעט HT (\\t)‏, LF (\\n), ו־CR (\\r).", + "apiwarn-badutf8": "הערך שהועבר ל־$1 מכיל נתונים בלתי־תקינים או בלתי־מנורמלים. נתונים טקסט אמורים להיות תקינים, מנורמלי NFC וללא תווי בקרה C0 למעט HT (\\t)‏, LF (\\n)‏ ו־CR (\\r).", "apiwarn-checktoken-percentencoding": "נא לבדוק שסימנים כמו \"+\" באסימון מקודדים עם אחוזים בצורה נכונה ב־URL.", "apiwarn-compare-nocontentmodel": "לא היה אפשר לקבוע את מודל התוכן, נניח שזה $1.", "apiwarn-deprecation-deletedrevs": "list=deletedrevs הוצהר בתור מיושן. נא להשתמש ב־ prop=deletedrevisions או ב־list=alldeletedrevisions במקום זה.", @@ -1736,7 +1736,7 @@ "apiwarn-errorprinterfailed-ex": "מדפיס השגיאות לא עבד (ינסה שוב ללא פרמטרים): $1", "apiwarn-invalidcategory": "\"$1\" אינה קטגוריה.", "apiwarn-invalidtitle": "\"$1\" אינה כותרת תקינה.", - "apiwarn-invalidxmlstylesheetext": "לגיליון הסגנונות אמור להיות הסיומת .xsl.", + "apiwarn-invalidxmlstylesheetext": "לגיליון הסגנונות אמורה להיות הסיומת .xsl.", "apiwarn-invalidxmlstylesheet": "ניתן גיליון סגנונות שאינו תקין או אינו קיים.", "apiwarn-invalidxmlstylesheetns": "גיליון הסגנונות אמור להיות במרחב השם {{ns:MediaWiki}}.", "apiwarn-moduleswithoutvars": "המאפיין modules לא הוגדר, אבל לא jsconfigvars או encodedjsconfigvars. משתני הגדרות נחוצים בשביל שימוש נכון במודולים.", @@ -1751,7 +1751,7 @@ "apiwarn-toomanyvalues": "יותר מדי ערכים סופקו לפרמטר $1. המגבלה היא $2.", "apiwarn-truncatedresult": "התוצאה נחתכה כי אחרת היא הייתה ארוכה מהמגבלה של $1 בתים.", "apiwarn-unclearnowtimestamp": "העברת \"$2\" בתור פרמטר חותם־זמן $1 הוצהרה בתור מיושנת. אם מסיבה כלשהי אתם צריכים להגדיר במפורש את הזמן הנוכחי ללא חישובו בצד הלקוח, יש להשתמש ב־now.", - "apiwarn-unrecognizedvalues": "לפרמטר $1 היתנ ג{{PLURAL:$3|ניתן ערך בלתי־ידוע|ניתנו ערכים בלתי־ידועים}}: $2.", + "apiwarn-unrecognizedvalues": "לפרמטר $1 {{PLURAL:$3|ניתן ערך בלתי־ידוע|ניתנו ערכים בלתי־ידועים}}: $2.", "apiwarn-unsupportedarray": "הפרמטר $1 משתמש בתחביר מערכים שאינו נתמך ב־PHP.", "apiwarn-urlparamwidth": "התעלמות מרוחב (width) שהוגדר ב־$1urlparam (ערך: $2) לטובת רוחב שנגזר מ־$1urlwidth/$1urlheight (ערך: $3).", "apiwarn-validationfailed-badchars": "תווים בלתי־תקינים במפתח (מותרים רק a-z‏, A-Z‏, 0-9‏, _, ו־-).", diff --git a/includes/collation/IcuCollation.php b/includes/collation/IcuCollation.php index 36efdb379b..9ac81ae01e 100644 --- a/includes/collation/IcuCollation.php +++ b/includes/collation/IcuCollation.php @@ -384,9 +384,17 @@ class IcuCollation extends Collation { foreach ( $letters as $letter ) { $key = $this->getPrimarySortKey( $letter ); if ( isset( $letterMap[$key] ) ) { - // Primary collision - // Keep whichever one sorts first in the main collator - if ( $this->mainCollator->compare( $letter, $letterMap[$key] ) < 0 ) { + // Primary collision (two characters with the same sort position). + // Keep whichever one sorts first in the main collator. + $comp = $this->mainCollator->compare( $letter, $letterMap[$key] ); + wfDebug( "Primary collision '$letter' '{$letterMap[$key]}' (comparison: $comp)\n" ); + // If that also has a collision, use codepoint as a tiebreaker. + if ( $comp === 0 ) { + // TODO Use <=> operator when PHP 7 is allowed. + $comp = UtfNormal\Utils::utf8ToCodepoint( $letter ) - + UtfNormal\Utils::utf8ToCodepoint( $letterMap[$key] ); + } + if ( $comp < 0 ) { $letterMap[$key] = $letter; } } else { diff --git a/includes/libs/rdbms/lbfactory/LBFactory.php b/includes/libs/rdbms/lbfactory/LBFactory.php index 38c7a5c7e9..955c28de16 100644 --- a/includes/libs/rdbms/lbfactory/LBFactory.php +++ b/includes/libs/rdbms/lbfactory/LBFactory.php @@ -95,6 +95,8 @@ abstract class LBFactory implements ILBFactory { const ROUND_BEGINNING = 'within-begin'; const ROUND_COMMITTING = 'within-commit'; const ROUND_ROLLING_BACK = 'within-rollback'; + const ROUND_COMMIT_CALLBACKS = 'within-commit-callbacks'; + const ROUND_ROLLBACK_CALLBACKS = 'within-rollback-callbacks'; private static $loggerFields = [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ]; @@ -170,28 +172,28 @@ abstract class LBFactory implements ILBFactory { /** * @see ILBFactory::newMainLB() * @param bool $domain - * @return LoadBalancer + * @return ILoadBalancer */ abstract public function newMainLB( $domain = false ); /** * @see ILBFactory::getMainLB() * @param bool $domain - * @return LoadBalancer + * @return ILoadBalancer */ abstract public function getMainLB( $domain = false ); /** * @see ILBFactory::newExternalLB() * @param string $cluster - * @return LoadBalancer + * @return ILoadBalancer */ abstract public function newExternalLB( $cluster ); /** * @see ILBFactory::getExternalLB() * @param string $cluster - * @return LoadBalancer + * @return ILoadBalancer */ abstract public function getExternalLB( $cluster ); @@ -261,6 +263,7 @@ abstract class LBFactory implements ILBFactory { // Actually perform the commit on all master DB connections and revert DBO_TRX $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] ); // Run all post-commit callbacks in a separate step + $this->trxRoundStage = self::ROUND_COMMIT_CALLBACKS; $e = $this->executePostTransactionCallbacks(); $this->trxRoundStage = self::ROUND_CURSORY; // Throw any last post-commit callback error @@ -275,6 +278,7 @@ abstract class LBFactory implements ILBFactory { // Actually perform the rollback on all master DB connections and revert DBO_TRX $this->forEachLBCallMethod( 'rollbackMasterChanges', [ $fname ] ); // Run all post-commit callbacks in a separate step + $this->trxRoundStage = self::ROUND_ROLLBACK_CALLBACKS; $this->executePostTransactionCallbacks(); $this->trxRoundStage = self::ROUND_CURSORY; } @@ -547,10 +551,18 @@ abstract class LBFactory implements ILBFactory { } /** - * Base parameters to LoadBalancer::__construct() + * Base parameters to ILoadBalancer::__construct() * @return array */ final protected function baseLoadBalancerParams() { + if ( $this->trxRoundStage === self::ROUND_COMMIT_CALLBACKS ) { + $initStage = ILoadBalancer::STAGE_POSTCOMMIT_CALLBACKS; + } elseif ( $this->trxRoundStage === self::ROUND_ROLLBACK_CALLBACKS ) { + $initStage = ILoadBalancer::STAGE_POSTROLLBACK_CALLBACKS; + } else { + $initStage = null; + } + return [ 'localDomain' => $this->localDomain, 'readOnlyReason' => $this->readOnlyReason, @@ -570,7 +582,8 @@ abstract class LBFactory implements ILBFactory { // Defer ChronologyProtector construction in case setRequestInfo() ends up // being called later (but before the first connection attempt) (T192611) $this->getChronologyProtector()->initLB( $lb ); - } + }, + 'roundStage' => $initStage ]; } diff --git a/includes/libs/rdbms/loadbalancer/ILoadBalancer.php b/includes/libs/rdbms/loadbalancer/ILoadBalancer.php index 850f9afab8..81ce4baeaf 100644 --- a/includes/libs/rdbms/loadbalancer/ILoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/ILoadBalancer.php @@ -89,6 +89,11 @@ interface ILoadBalancer { /** @var int Alias for CONN_TRX_AUTOCOMMIT for b/c; deprecated since 1.31 */ const CONN_TRX_AUTO = 1; + /** @var string Manager of ILoadBalancer instances is running post-commit callbacks */ + const STAGE_POSTCOMMIT_CALLBACKS = 'stage-postcommit-callbacks'; + /** @var string Manager of ILoadBalancer instances is running post-rollback callbacks */ + const STAGE_POSTROLLBACK_CALLBACKS = 'stage-postrollback-callbacks'; + /** * Construct a manager of IDatabase connection objects * @@ -112,6 +117,7 @@ interface ILoadBalancer { * - perfLogger: PSR-3 logger instance. [optional] * - errorLogger : Callback that takes an Exception and logs it. [optional] * - deprecationLogger: Callback to log a deprecation warning. [optional] + * - roundStage: STAGE_POSTCOMMIT_* class constant; for internal use [optional] * @throws InvalidArgumentException */ public function __construct( array $params ); diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancer.php b/includes/libs/rdbms/loadbalancer/LoadBalancer.php index 405ed14160..360be4256e 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancer.php @@ -261,6 +261,14 @@ class LoadBalancer implements ILoadBalancer { if ( isset( $params['chronologyCallback'] ) ) { $this->chronologyCallback = $params['chronologyCallback']; } + + if ( isset( $params['roundStage'] ) ) { + if ( $params['roundStage'] === self::STAGE_POSTCOMMIT_CALLBACKS ) { + $this->trxRoundStage = self::ROUND_COMMIT_CALLBACKS; + } elseif ( $params['roundStage'] === self::STAGE_POSTROLLBACK_CALLBACKS ) { + $this->trxRoundStage = self::ROUND_ROLLBACK_CALLBACKS; + } + } } /** diff --git a/includes/logging/LogEventsList.php b/includes/logging/LogEventsList.php index 93a81cff8e..9e4a630bd0 100644 --- a/includes/logging/LogEventsList.php +++ b/includes/logging/LogEventsList.php @@ -97,7 +97,7 @@ class LogEventsList extends ContextSource { * @param array|string $types * @param string $user * @param string $page - * @param string $pattern + * @param bool $pattern * @param int|string $year Use 0 to start with no year preselected. * @param int|string $month A month in the 1..12 range. Use 0 to start with no month * preselected. @@ -105,7 +105,7 @@ class LogEventsList extends ContextSource { * @param string $tagFilter Tag to select by default * @param string $action */ - public function showOptions( $types = [], $user = '', $page = '', $pattern = '', $year = 0, + public function showOptions( $types = [], $user = '', $page = '', $pattern = false, $year = 0, $month = 0, $filter = null, $tagFilter = '', $action = null ) { global $wgScript, $wgMiserMode; @@ -289,7 +289,7 @@ class LogEventsList extends ContextSource { } /** - * @param string $pattern + * @param bool $pattern * @return string Checkbox */ private function getTitlePattern( $pattern ) { diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php index c047e96ea3..84653b1ba1 100644 --- a/includes/logging/LogPager.php +++ b/includes/logging/LogPager.php @@ -36,8 +36,8 @@ class LogPager extends ReverseChronologicalPager { /** @var string|Title Events limited to those about Title when set */ private $title = ''; - /** @var string */ - private $pattern = ''; + /** @var bool */ + private $pattern = false; /** @var string */ private $typeCGI = ''; @@ -59,7 +59,7 @@ class LogPager extends ReverseChronologicalPager { * @param string|array $types Log types to show * @param string $performer The user who made the log entries * @param string|Title $title The page title the log entries are for - * @param string $pattern Do a prefix search rather than an exact title match + * @param bool $pattern Do a prefix search rather than an exact title match * @param array $conds Extra conditions for the query * @param int|bool $year The year to start from. Default: false * @param int|bool $month The month to start from. Default: false @@ -68,7 +68,7 @@ class LogPager extends ReverseChronologicalPager { * @param int $logId Log entry ID, to limit to a single log entry. */ public function __construct( $list, $types = [], $performer = '', $title = '', - $pattern = '', $conds = [], $year = false, $month = false, $tagFilter = '', + $pattern = false, $conds = [], $year = false, $month = false, $tagFilter = '', $action = '', $logId = false ) { parent::__construct( $list->getContext() ); @@ -194,7 +194,7 @@ class LogPager extends ReverseChronologicalPager { * (For the block and rights logs, this is a user page.) * * @param string|Title $page Title name - * @param string $pattern + * @param bool $pattern * @return void */ private function limitTitle( $page, $pattern ) { @@ -398,6 +398,9 @@ class LogPager extends ReverseChronologicalPager { return $this->title; } + /** + * @return bool + */ public function getPattern() { return $this->pattern; } diff --git a/includes/search/SearchEngine.php b/includes/search/SearchEngine.php index 7e6e8e6d0d..0f65711bf6 100644 --- a/includes/search/SearchEngine.php +++ b/includes/search/SearchEngine.php @@ -335,12 +335,25 @@ abstract class SearchEngine { return false; } $extractedNamespace = null; + $allkeywords = []; - $allkeyword = wfMessage( 'searchall' )->inContentLanguage()->text() . ":"; - if ( strncmp( $query, $allkeyword, strlen( $allkeyword ) ) == 0 ) { - $extractedNamespace = null; - $parsed = substr( $query, strlen( $allkeyword ) ); - } elseif ( strpos( $query, ':' ) !== false ) { + $allkeywords[] = wfMessage( 'searchall' )->inContentLanguage()->text() . ":"; + // force all: so that we have a common syntax for all the wikis + if ( !in_array( 'all:', $allkeywords ) ) { + $allkeywords[] = 'all:'; + } + + $allQuery = false; + foreach ( $allkeywords as $kw ) { + if ( strncmp( $query, $kw, strlen( $kw ) ) == 0 ) { + $extractedNamespace = null; + $parsed = substr( $query, strlen( $kw ) ); + $allQuery = true; + break; + } + } + + if ( !$allQuery && strpos( $query, ':' ) !== false ) { // TODO: should we unify with PrefixSearch::extractNamespace ? $prefix = str_replace( ' ', '_', substr( $query, 0, strpos( $query, ':' ) ) ); $index = $wgContLang->getNsIndex( $prefix ); diff --git a/includes/specials/SpecialPreferences.php b/includes/specials/SpecialPreferences.php index f67fe9f757..1cfcffa85d 100644 --- a/includes/specials/SpecialPreferences.php +++ b/includes/specials/SpecialPreferences.php @@ -36,8 +36,6 @@ class SpecialPreferences extends SpecialPage { function __construct() { parent::__construct( 'Preferences' ); - - $this->oouiEnabled = self::isOouiEnabled( $this->getContext() ); } /** @@ -56,6 +54,8 @@ class SpecialPreferences extends SpecialPage { } public function execute( $par ) { + $this->oouiEnabled = static::isOouiEnabled( $this->getContext() ); + $this->setHeaders(); $this->outputHeader(); $out = $this->getOutput(); diff --git a/languages/i18n/as.json b/languages/i18n/as.json index 81b6d0f239..e118a0ceec 100644 --- a/languages/i18n/as.json +++ b/languages/i18n/as.json @@ -25,7 +25,7 @@ ] }, "tog-underline": "সংযোগসমূহ অধোৰেখিত কৰক:", - "tog-hideminor": "সাম্প্ৰতিক সাল-সলনিত অগুৰুত্বপূৰ্ণ সম্পাদনা নেদেখুৱাব", + "tog-hideminor": "শেহতীয়া সাল-সলনিত অগুৰুত্বপূৰ্ণ সম্পাদনা নেদেখুৱাব", "tog-hidepatrolled": "সাম্প্ৰতিক সাল-সলনিত তহলদাৰী সম্পাদনা নেদেখুৱাব", "tog-newpageshidepatrolled": "নতুন পৃষ্ঠা তালিকাত তহলদাৰী পৃষ্ঠাসমূহ নেদেখুৱাব", "tog-hidecategorization": "পৃষ্ঠাবোৰৰ শ্ৰেণীকৰণ লুকুৱাওক", @@ -1151,6 +1151,7 @@ "recentchanges-legend-plusminus": "(''±১২৩'')", "rcfilters-legend-heading": "সংক্ষিপ্ত ৰূপৰ তালিকা:", "rcfilters-other-review-tools": "আন পুনৰীক্ষণ সঁজুলি", + "rcfilters-filter-humans-label": "মানুহ (ব'ট নহয়)", "rcnotefrom": "$2ৰ পৰা হোৱা পৰিৱৰ্তনসমূহ (সৰ্বোচ্চ $1টা দেখুৱা হৈছে)।", "rclistfrom": "$3 $2ৰ পৰা নতুন সালসলনি দেখুৱাওক", "rcshowhideminor": "$1 -সংখ্যক নগণ্য সম্পাদনা", diff --git a/languages/i18n/azb.json b/languages/i18n/azb.json index f7e226557f..d6fb71661b 100644 --- a/languages/i18n/azb.json +++ b/languages/i18n/azb.json @@ -1220,7 +1220,7 @@ "recentchangeslinked-feed": "باغلی دَییشیکلیک‌لر", "recentchangeslinked-toolbox": "باغلی دَییشیکلیک‌لر", "recentchangeslinked-title": "''$1'' ایله باغلی دییشیکلر", - "recentchangeslinked-summary": "آشاغیداکی سیياهی، قئيد اوْلونان صحیفه‌‌يه (و يا قئيد اوْلونان کاتئقوْرياداکی صحیفه‌‌لره) داخیلی کئچید وئرن صحیفه‌‌لرده ائدیلمیش سوْن ديَیشیکلیکلرین سیياهیسیدیر. \n[[Special:Watchlist|ایزله‌مه سیياهینیزداکی]] صحیفه‌‌لر '''قالین''' شریفتله گؤستریلمیشدیر.", + "recentchangeslinked-summary": "آشاغیداکی ژورنال، قئيد اوْلونان صفحه‌‌يه (و يا قئيد اوْلونان بؤلمه‌ده‌کی صفحه‌‌لره) داخیلی کئچید وئرن صفحه‌‌لرده ائدیلمیش سوْن ديَیشیکلیکلرین لیستیدیر. \n[[Special:Watchlist|ایزله‌مه لیستینیزده]]‌کی صفحه‌‌لر '''قالین''' شریفتله گؤستریلمیشدیر.", "recentchangeslinked-page": "صفحه آدی:", "recentchangeslinked-to": "قئيد اوْلونان صحیفه‌‌ده‌کی دئيیل، اوْنا داخیلی کئچید وئرن صحیفه‌‌لرده‌کی ديَیشیکلیکلری گؤستر", "upload": "فایل یوکله‌", diff --git a/languages/i18n/be-tarask.json b/languages/i18n/be-tarask.json index df3cd07674..4365fb4ab5 100644 --- a/languages/i18n/be-tarask.json +++ b/languages/i18n/be-tarask.json @@ -540,6 +540,7 @@ "botpasswords-restriction-failed": "Уваход ня выкананы праз абмежаваньні на пароль робата", "botpasswords-invalid-name": "Пададзенае імя ўдзельніка ня ўтрымлівае падзяляльнік для паролю робата («$1»).", "botpasswords-not-exist": "Удзельнік «$1» ня мае паролю для робата з назвай «$2».", + "botpasswords-needs-reset": "Пароль для робата зь імем «$2» {{GENDER:$1|удзельніка|удзельніцы}} «$1» мусіць быць скінуты.", "resetpass_forbidden": "Пароль ня можа быць зьменены", "resetpass_forbidden-reason": "Паролі ня могуць быць зьмененыя: $1", "resetpass-no-info": "Для непасрэднага доступу да гэтай старонкі Вам неабходна ўвайсьці ў сыстэму.", @@ -635,8 +636,8 @@ "subject-preview": "Папярэдні прагляд загалоўку:", "previewerrortext": "Адбылася памылка пры спробе папярэдняга прагляду вашых зьменаў.", "blockedtitle": "Удзельнік заблякаваны", - "blockedtext": "Ваш рахунак удзельніка ці IP-адрас быў заблякаваны.\n\nБлякаваньне выканаў $1.\nПрычына гэтага: $2.\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне. Заўважце, што Вы ня зможаце ўжыць магчымасьць «даслаць ліст па электроннай пошце», пакуль не пазначыце сапраўдны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах]], і калі гэта Вам не было забаронена.\nВаш IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што Вы будзеце рабіць.", - "autoblockedtext": "Ваш IP-адрас быў аўтаматычна заблякаваны, таму што ён ужываўся іншым удзельнікам, які быў заблякаваны $1.\nПрычына гэтага:\n\n:$2\n\n* Блякаваньне пачалося: $8\n* Блякаваньне скончыцца: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці з адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне.\n\nЗаўважце, што Вы ня зможаце ўжываць магчымасьць «даслаць ліст праз электронную пошту», пакуль ня будзе пазначаны дзейны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах удзельніка]], і калі гэта Вам не было забаронена.\n\nВаш цяперашні IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што Вы будзеце рабіць.", + "blockedtext": "Ваш рахунак удзельніка ці IP-адрас быў заблякаваны.\n\nБлякаваньне выканаў $1.\nПрычына гэтага: $2.\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне. Заўважце, што вы ня зможаце ўжыць магчымасьць «{{int:emailuser}}», пакуль не пазначыце сапраўдны адрас электроннай пошты ў вашых [[Special:Preferences|наладах]], і калі гэта вам не было забаронена.\nВаш IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што вы будзеце рабіць.", + "autoblockedtext": "Ваш IP-адрас быў аўтаматычна заблякаваны, таму што ён ужываўся іншым удзельнікам, які быў заблякаваны $1.\nПрычына гэтага:\n\n:$2\n\n* Блякаваньне пачалося: $8\n* Блякаваньне скончыцца: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці з адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне.\n\nЗаўважце, што вы ня зможаце ўжываць магчымасьць «{{int:emailuser}}», пакуль ня будзе пазначаны дзейны адрас электроннай пошты ў вашых [[Special:Preferences|наладах удзельніка]], і калі гэта вам не было забаронена.\n\nВаш цяперашні IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што вы будзеце рабіць.", "systemblockedtext": "Вашае імя ўдзельніка ці IP-адрас былі аўтаматычна заблякаваныя MediaWiki.\nЗ наступнай прычыны:\n\n:$2\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Мэта блякаваньня: $7\n\nВаш цяперашні IP-адрас — $3.\nКалі ласка, уключайце ўсе пададзеныя вышэй дэталі ва ўсе запыты, што вы робіце.", "blockednoreason": "прычына не пазначана", "whitelistedittext": "Вам трэба $1, каб рэдагаваць старонкі.", @@ -1497,14 +1498,14 @@ "upload": "Загрузіць файл", "uploadbtn": "Загрузіць файл", "reuploaddesc": "Скасаваць загрузку і вярнуцца да формы загрузкі", - "upload-tryagain": "Даслаць зьмененае апісаньне файла", + "upload-tryagain": "Даслаць зьмененае апісаньне файлу", "upload-tryagain-nostash": "Даслаць паўторна загружаны файл і зьмененае апісаньне", "uploadnologin": "Вы не ўвайшлі ў сыстэму", "uploadnologintext": "Вам трэба $1, каб загружаць файлы.", "upload_directory_missing": "Загрузачная дырэкторыя ($1) адсутнічае і ня можа быць створаная сэрвэрам.", "upload_directory_read_only": "Сэрвэр ня мае правоў на запіс у дырэкторыю загружаных файлаў ($1).", "uploaderror": "Памылка загрузкі", - "upload-recreate-warning": "'''Увага: файл з такой назвай быў выдалены альбо перанесены.'''\n\nЖурнал выдаленьняў і пераносаў гэтай старонкі для зручнасьці пададзены тут:", + "upload-recreate-warning": "Увага: файл з такой назвай быў выдалены альбо перанесены.\n\nЖурнал выдаленьняў і пераносаў гэтай старонкі для зручнасьці пададзены тут:", "uploadtext": "Ужывайце форму ніжэй для загрузкі файлаў.\nКаб паглядзець ці адшукаць раней загружаныя файлы, глядзіце [[Special:FileList|сьпіс загружаных файлаў]], загрузкі таксама запісваюцца ў [[Special:Log/upload|журнал загрузак]], а выдаленьні — у [[Special:Log/delete|журнал выдаленьняў]].\n\nКаб улучыць файл у старонку, ужывайце адзін з наступных варыянтаў:\n* '''[[{{ns:file}}:File.jpg]]''' для поўнай вэрсіі файла\n* '''[[{{ns:file}}:File.png|200px|thumb|left|Подпіс да выявы]]''' для выявы шырынёй 200 піксэляў у рамцы і тэкстам «Подпіс да выявы» ў якасьці подпісу\n* '''[[{{ns:media}}:File.ogg]]''' для простай спасылкі на файл безь яго адлюстраваньня.", "upload-permitted": "{{PLURAL:$2|Дазволены тып|Дазволеныя тыпы}} файлаў: $1.", "upload-preferred": "{{PLURAL:$2|Пажаданы тып|Пажаданыя тыпы}} файлаў: $1.", diff --git a/languages/i18n/be.json b/languages/i18n/be.json index 0333b61464..c7d9bf62e0 100644 --- a/languages/i18n/be.json +++ b/languages/i18n/be.json @@ -1023,7 +1023,7 @@ "recentchangesdays-max": "(найбольш $1 {{PLURAL:$1|дзень|дзён}})", "recentchangescount": "Перадвызначаная колькасць правак для паказу:", "prefs-help-recentchangescount": "Максімальная колькасць: 1000", - "prefs-help-watchlist-token2": "Гэта сакрэтны ключ да сеціўнай стужкі з Вашага спіса назірання.\nКожны, хто ведае гэты ключ, будзе мець магчымасць чытаць Ваш спіс назірання, таму не дзяліцеся ім.\nКалі трэба, можна [[Special:ResetTokens|скінуць яго]].", + "prefs-help-watchlist-token2": "Гэта сакрэтны ключ да сеціўнай стужкі з Вашага спісу назірання.\nКожны, хто ведае гэты ключ, будзе мець магчымасць чытаць Ваш спіс назірання, таму не дзяліцеся ім.\nКалі трэба, можна [[Special:ResetTokens|скінуць яго]].", "savedprefs": "Настройкі замацаваныя.", "savedrights": "Групы {{GENDER:$1|ўдзельніка|ўдзельніцы}} $1 захаваныя.", "timezonelegend": "Часавы пояс:", @@ -1576,7 +1576,7 @@ "uploaded-event-handler-on-svg": "Устаноўка атрыбутаў апрацоўшчыка падзей $1=\"$2\" у SVG файле не дазваляецца.", "uploaded-href-attribute-svg": "у SVG файлах атрыбутам href дазволены толькі мэты віду http:// або https://, знойдзена <$1 $2=\"$3\">.", "uploaded-href-unsafe-target-svg": "У ўкладзеным SVG файле знойдзена спасылка на небяспечныя звесткі: URI мэты <$1 $2=\"$3\">.", - "uploaded-animate-svg": "У ўкладзеным SVG файле знойдзены тэг \"animate\", здольны змяніць спасылку з дапамогай атрыбута \"from\" <$1 $2=\"$3\">.", + "uploaded-animate-svg": "Ва ўкладзеным SVG файле знойдзены тэг \"animate\", здольны змяніць спасылку з дапамогай атрыбута \"from\" <$1 $2=\"$3\">.", "uploaded-setting-event-handler-svg": "Устаноўка атрыбутаў апрацоўкі падзей заблакавана, у ўкладзеным SVG-файле знойдзены код <$1 $2=\"$3\">.", "uploaded-setting-href-svg": "Выкарыстанне тэга \"set\" для дадання атрыбута \"href\" у бацькоўскі элемент заблакавана.", "uploaded-wrong-setting-svg": "Ужыванне тэга \"set\" для задання ў якасці мэты аддаленага адраса/звестак/сцэнарыя для любога атрыбута заблакавана. У ўкладзеным SVG-файле знойдзены <set to=\"$1\">.", @@ -2663,7 +2663,7 @@ "tooltip-ca-undelete": "Аднавіць праўкі, зробленыя на гэтай старонцы перад тым, як яна была сцёрта", "tooltip-ca-move": "Перанесці гэтую старонку пад іншую назву", "tooltip-ca-watch": "Дадаць гэтую старонку да свайго спісу назіраных старонак", - "tooltip-ca-unwatch": "Выняць гэту старонку з вашага спіса назірання", + "tooltip-ca-unwatch": "Выняць гэтую старонку з Вашага спісу назірання", "tooltip-search": "Знайсці ў {{SITENAME}}", "tooltip-search-go": "Перайсці да старонкі з дакладна такой назвай, калі такая наогул існуе", "tooltip-search-fulltext": "Знайсці гэты тэкст у тэкстах старонак", @@ -3249,7 +3249,7 @@ "confirm-watch-button": "ОК", "confirm-watch-top": "Дабавіць старонку ў спіс назірання", "confirm-unwatch-button": "ОК", - "confirm-unwatch-top": "Выняць гэту старонку з вашага спіса назірання?", + "confirm-unwatch-top": "Выняць гэту старонку з Вашага спісу назірання?", "confirm-rollback-button": "Добра", "confirm-rollback-top": "Адкаціць праўкі гэтай старонкі?", "quotation-marks": "«$1»", @@ -3274,6 +3274,7 @@ "autosumm-replace": "Замена старонкі на '$1'", "autoredircomment": "Перасылае да [[$1]]", "autosumm-removed-redirect": "Выдаленае перенаправление на [[$1]]", + "autosumm-changed-redirect-target": "Мэта перасылкі зменена з [[$1]] на [[$2]]", "autosumm-new": "Новая старонка: '$1'", "autosumm-newblank": "Створана пустая старонка", "size-bytes": "$1 {{PLURAL:$1|байт|байты|байтаў}}", @@ -3283,7 +3284,7 @@ "watchlistedit-normal-legend": "Выдаленне складнікаў са спісу назірання", "watchlistedit-normal-explain": "Назвы старонак з ліку назіраных паказаныя ніжэй. Каб нешта выдаліць, адзначце клетку побач з адпаведным радком, пасля чаго націсніце \"Выняць складнікі\". Таксама можна правіць гэты спіс непасрэдна, [[Special:EditWatchlist/raw|без афармлення]].", "watchlistedit-normal-submit": "Выняць складнікі", - "watchlistedit-normal-done": "З вашага спіса назірання {{PLURAL:$1|быў выдалены|былі выдалены|было выдалена}} $1 {{PLURAL:$1|складнік|складнікі|складнікаў}}:", + "watchlistedit-normal-done": "З Вашага спісу назірання {{PLURAL:$1|быў выдалены|былі выдалены|было выдалена}} $1 {{PLURAL:$1|складнік|складнікі|складнікаў}}:", "watchlistedit-raw-title": "Нефарматаваны спіс назірання", "watchlistedit-raw-legend": "Правіць нефарматаваны спіс назірання", "watchlistedit-raw-explain": "Назвы старонак з ліку назіраных паказаныя ніжэй, без афармлення, адна назва на адзін радок; такім чынам, спіс можна правіць як звычайны тэкст. Па сканчэнні націсніце \"{{int:Watchlistedit-raw-submit}}\". Таксама гэта можна зрабіць праз [[Special:EditWatchlist|стандартны інтэрфейс]].", @@ -3544,6 +3545,7 @@ "logentry-delete-delete": "$1 {{GENDER:$2|выдаліў|выдаліла}} старонку $3", "logentry-delete-delete_redir": "$1 {{GENDER:$2|выдаліў|выдаліла}} перанакіраванне $3 шляхам перазапісу", "logentry-delete-restore": "$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3 ($4)", + "restore-count-revisions": "{{PLURAL:$1|1 версія|$1 версіі|$1 версій}}", "logentry-delete-event": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|запісу журнала|$5 запісаў журнала}} $3: $4", "logentry-delete-revision": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|версіі|$5 версій|$5 версій}} старонкі $3: $4", "logentry-delete-event-legacy": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць запісаў журнала $3", diff --git a/languages/i18n/bg.json b/languages/i18n/bg.json index b4b31f2b46..07b224c8e3 100644 --- a/languages/i18n/bg.json +++ b/languages/i18n/bg.json @@ -628,6 +628,9 @@ "savechanges": "Съхраняване на промените", "publishpage": "Публикуване на страницата", "publishchanges": "Публикуване на промените", + "savearticle-start": "Съхраняване на страницата...", + "savechanges-start": "Съхраняване на промените...", + "publishpage-start": "Публикуване на страницата...", "publishchanges-start": "Публикуване на промените...", "preview": "Предварителен преглед", "showpreview": "Предварителен преглед", @@ -636,6 +639,7 @@ "anoneditwarning": "Внимание: Не сте влезли в системата. Ако направите редакция IP-адресът Ви ще бъде публично видим. Ако [$1 влезете] или си [$2 създадете акаунт], редакциите Ви ще бъдат свързани с потребителското Ви име, заедно с други преимущества.", "anonpreviewwarning": "Не сте влезли в системата. Ако съхраните редакцията си, тя ще бъде записана в историята на страницата с вашия IP-адрес.", "missingsummary": "Напомняне: Не е въведено кратко описание на промените.\nПри повторно натискане на бутона „$1“, редакцията ще бъде съхранена без резюме.", + "selfredirect": "Внимание: Пренасочвате страница към самата нея.\nМоже би сте посочили грешна цел за пренасочването или може би сте редактирали грешната страница.\nАко натиснете „$1“ отново, пренасочването ще бъде създадено.", "missingcommenttext": "Моля, въведете коментар.", "missingcommentheader": "Напомняне: Не е въведено заглавие на коментара.\nПри повторно натискане на „$1“, редакцията ще бъде записана без коментар.", "summary-preview": "Предварителен преглед на резюмето:", @@ -644,6 +648,7 @@ "blockedtitle": "Потребителят е блокиран", "blockedtext": "'''Вашето потребителско име (или IP-адрес) беше блокирано.'''\n\nБлокирането е извършено от $1. Посочената причина е: ''$2''\n\n*Начало на блокирането: $8\n*Край на блокирането: $6\n*Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата ѝ и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nВашият IP адрес е $3, а номерът на блокирането е $5. Включвайте едно от двете или и двете във всяко запитване, което правите.", "autoblockedtext": "IP-адресът ви беше блокиран автоматично, защото е бил използван от друг потребител, който е бил блокиран от $1.\nПосочената причина е:\n\n:''$2''\n\n* Начало на блокирането: $8\n* Край на блокирането: $6\n* Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата ѝ и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nТекущият ви IP-адрес е $3, а номерът на блокирането ви е $5. Включвайте ги във всяко питане, което правите.", + "systemblockedtext": "Вашето потребителско име или IP адрес беше автоматично блокирано от Медия Уики.\nПосочената причина е:\n\n:$2\n\n* Начало на блокирането: $8\n* Край на блокирането: $6\n* Блокирането се отнася за: $7\n\nВашият текущ IP адрес е $3.\nМоля, включете всичките детайли по-горе, ако правите каквито и да е запитвания.", "blockednoreason": "не е указана причина", "whitelistedittext": "Редактирането на страници изисква $1 в системата.", "confirmedittext": "Необходимо е да потвърдите електронната си поща, преди да редактирате страници.\nВъведете и потвърдете адреса си на [[Special:Preferences|страницата с настройките]].", @@ -1059,6 +1064,7 @@ "prefs-dateformat": "Формат на датата", "prefs-timeoffset": "Часово отместване", "prefs-advancedediting": "Общи настройки", + "prefs-developertools": "Инструменти за разработчици", "prefs-editor": "Редактор", "prefs-preview": "Преглед", "prefs-advancedrc": "Разширени настройки", @@ -1361,6 +1367,8 @@ "rcfilters-filter-humans-description": "Редакции, направени от редактори.", "rcfilters-filtergroup-reviewstatus": "Проверка на статуса", "rcfilters-filter-reviewstatus-unpatrolled-label": "Непатрулирано", + "rcfilters-filter-reviewstatus-manual-label": "Ръчно патрулирани", + "rcfilters-filter-reviewstatus-auto-label": "Автоматично патрулирани", "rcfilters-filtergroup-significance": "Значимост", "rcfilters-filter-minor-label": "Малки промени", "rcfilters-filter-minor-description": "Редакции, които не са отбелязани като малки промени.", @@ -1698,10 +1706,10 @@ "filedelete-intro-old": "Изтривате версията на [[Media:$1|$1]] към [$4 $3, $2].", "filedelete-comment": "Причина:", "filedelete-submit": "Изтриване", - "filedelete-success": "Файлът '''$1''' беше изтрит.", + "filedelete-success": "Файлът $1 беше изтрит.", "filedelete-success-old": "Версията на [[Media:$1|$1]] към $3, $2 е била изтрита.", "filedelete-nofile": "Файлът $1 не съществува.", - "filedelete-nofile-old": "Не съществува архивна версия на '''$1''' с указаните параметри.", + "filedelete-nofile-old": "Не съществува архивна версия на $1 с указаните параметри.", "filedelete-otherreason": "Друга/допълнителна причина:", "filedelete-reason-otherlist": "Друга причина", "filedelete-reason-dropdown": "*Общи причини за изтриване\n** Нарушение на авторските права\n** Файлът се повтаря", @@ -2157,7 +2165,7 @@ "protect-othertime": "Друг срок:", "protect-othertime-op": "друг срок", "protect-existing-expiry": "Оставащо време: $2, $3", - "protect-existing-expiry-infinity": "Existing expiration time: безсрочно", + "protect-existing-expiry-infinity": "Оставащо време: безсрочно", "protect-otherreason": "Друга/допълнителна причина:", "protect-otherreason-op": "Друга причина", "protect-dropdown": "* Стандартни причини за защита на страници\n** Чест обект на вандализъм\n** Чест обект на спам\n** Редакторска война\n** Страница, изискваща много сървърни ресурси", @@ -2177,7 +2185,7 @@ "restriction-level-all": "всички", "undelete": "Преглед на изтрити страници", "undeletepage": "Преглед и възстановяване на изтрити страници", - "undeletepagetitle": "'''По-долу е показан списък на изтритите версии на [[:$1|$1]]'''.", + "undeletepagetitle": "По-долу е показан списък на изтритите версии на [[:$1|$1]]/strong>.", "viewdeletedpage": "Преглед на изтрити страници", "undeletepagetext": "{{PLURAL:$1|Следната страница беше изтрита, но все още се намира в архива и може да бъде възстановена|Следните $1 страници бяха изтрити, но все още се намират в архива и могат да бъдат възстановени}}. Архивът може да се почиства от време на време.", "undelete-fieldset-title": "Възстановяване на версии", diff --git a/languages/i18n/ca.json b/languages/i18n/ca.json index f4158eae86..a8a60d559e 100644 --- a/languages/i18n/ca.json +++ b/languages/i18n/ca.json @@ -586,6 +586,7 @@ "botpasswords-restriction-failed": "Les restriccions de contrasenyes de bots impedeixen aquest inici de sessió.", "botpasswords-invalid-name": "El nom d'usuari especificat no conté el separador de contrasenya de bot («$1»).", "botpasswords-not-exist": "L'usuari «$1» no té una contrasenya de bot anomenada «$2».", + "botpasswords-needs-reset": "Cal reinicialitzar la contrasenya del robot «$2» que pertany a {{GENDER:$1|l’usuari|la usuària}} «$1».", "resetpass_forbidden": "No poden canviar-se les contrasenyes", "resetpass_forbidden-reason": "Les contrasenyes no es poden canviar: $1", "resetpass-no-info": "Heu d'estar registrats en un compte per a poder accedir directament a aquesta pàgina.", diff --git a/languages/i18n/ckb.json b/languages/i18n/ckb.json index 79f2b2b5b5..b23fbabc29 100644 --- a/languages/i18n/ckb.json +++ b/languages/i18n/ckb.json @@ -1174,6 +1174,8 @@ "rcfilters-limit-and-date-label": "$1 گۆڕانکاری، $2", "rcfilters-days-show-days": "$1 {{PLURAL:$1|ڕۆژ}}", "rcfilters-quickfilters": "پاڵوێنە پاشەکەوتکراوەکان", + "rcfilters-quickfilters-placeholder-title": "ھیچ پاڵوێنەیەک پاشەکەوت نەکراوە", + "rcfilters-quickfilters-placeholder-description": "بۆ پاشەکەوتکردنی ھەڵبژاردەی پاڵوێنەکان و دووبارە بەکارھێنانەوەیان، کرتە لەسەر نیشانی نیشانەی کتێبەکە بکە.", "rcfilters-savedqueries-defaultlabel": "پاڵوێنە پاشەکەوتکراوەکان", "rcfilters-savedqueries-setdefault": "بە بنەڕەتی کارای بکە", "rcfilters-savedqueries-new-name-label": "ناو", diff --git a/languages/i18n/cs.json b/languages/i18n/cs.json index a37e90a0bb..0ca1120976 100644 --- a/languages/i18n/cs.json +++ b/languages/i18n/cs.json @@ -659,8 +659,8 @@ "subject-preview": "Náhled předmětu:", "previewerrortext": "Při pokusu o zobrazení náhledu vaÅ¡ich změn doÅ¡lo k chybě.", "blockedtitle": "Uživatel zablokován", - "blockedtext": "Vaší IP adrese či uživatelskému jménu byla zablokována možnost editace.\n\nZablokování {{GENDER:$4|provedl|provedla}} $1.\nUdaným důvodem bylo $2.\n\n* Začátek blokování: $8\n* Zablokování vyprší: $6\n* Blokovaný uživatel: $7\n\nPokud chcete zablokování prodiskutovat, můžete kontaktovat {{GENDER:$4|uživatele|uživatelku}} $1 či jiného [[{{MediaWiki:Grouppage-sysop}}|správce]].\nUvědomte si, že nemůžete použít funkci „Poslat e-mail“, jestliže nemáte ve svém [[Special:Preferences|nastavení]] uvedenu platnou e-mailovou adresu nebo pokud vám byla tato možnost zakázána.\nVaÅ¡e IP adresa je $3 a identifikační číslo bloku je #$5; tyto údaje uvádějte ve vÅ¡ech dotazech na správce.", - "autoblockedtext": "VaÅ¡e IP adresa byla automaticky zablokována, protože ji používal jiný uživatel, kterého zablokoval $1.\nUdaný důvod blokování:\n\n:$2\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nZablokování můžete prodiskutovat se správcem $1 nebo některým z dalších [[{{MediaWiki:Grouppage-sysop}}|správců]].\n\nUvědomte si vÅ¡ak, že funkci „Poslat e-mail tomuto uživateli“ nemůžete použít, pokud nemáte ve svém [[Special:Preferences|uživatelském nastavení]] zadaný platný e-mail a nebylo vám zablokováno jeho užívání.\n\nVaÅ¡e současná IP adresa je $3, číslo vaÅ¡eho zablokování je #$5.\nProsíme, uveďte tyto údaje při komunikaci se správci.", + "blockedtext": "Vaší IP adrese či uživatelskému jménu byla zablokována možnost editace.\n\nZablokování {{GENDER:$4|provedl|provedla}} $1.\nUdaným důvodem bylo $2.\n\n* Začátek blokování: $8\n* Zablokování vyprší: $6\n* Blokovaný uživatel: $7\n\nPokud chcete zablokování prodiskutovat, můžete kontaktovat {{GENDER:$4|uživatele|uživatelku}} $1 či jiného [[{{MediaWiki:Grouppage-sysop}}|správce]].\nUvědomte si, že nemůžete použít funkci „{{int:emailuser}}“, jestliže nemáte ve svém [[Special:Preferences|nastavení]] uvedenu platnou e-mailovou adresu nebo pokud vám byla tato možnost zakázána.\nVaÅ¡e IP adresa je $3 a identifikační číslo bloku je #$5; tyto údaje uvádějte ve vÅ¡ech dotazech na správce.", + "autoblockedtext": "VaÅ¡e IP adresa byla automaticky zablokována, protože ji používal jiný uživatel, kterého zablokoval $1.\nUdaný důvod blokování:\n\n:$2\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nZablokování můžete prodiskutovat se správcem $1 nebo některým z dalších [[{{MediaWiki:Grouppage-sysop}}|správců]].\n\nUvědomte si vÅ¡ak, že funkci „{{int:emailuser}}“ nemůžete použít, pokud nemáte ve svém [[Special:Preferences|uživatelském nastavení]] zadaný platný e-mail a nebylo vám zablokováno jeho užívání.\n\nVaÅ¡e současná IP adresa je $3, číslo vaÅ¡eho zablokování je #$5.\nProsíme, uveďte tyto údaje při komunikaci se správci.", "systemblockedtext": "VaÅ¡e IP adresa byla automaticky zablokována softwarem MediaWiki.\nUdaný důvod blokování:\n\n:$2\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nVaÅ¡e současná IP adresa je $3.\nProsíme, uveďte tyto údaje při komunikaci se správci.", "blockednoreason": "důvod nebyl zadán", "whitelistedittext": "Pro editaci se musíte $1.", diff --git a/languages/i18n/cv.json b/languages/i18n/cv.json index 946c6c97f4..4de9d8c640 100644 --- a/languages/i18n/cv.json +++ b/languages/i18n/cv.json @@ -885,10 +885,10 @@ "tooltip-pt-logout": "Сеансне пĕтер", "tooltip-pt-createaccount": "Аккаунт ту та системӑна кӗр. Паллах, унсӑрах та юрать, анчах та аккаунтпа кӗни лайӑхрах.", "tooltip-ca-talk": "Статьяна сӳтсе явасси", - "tooltip-ca-edit": "Эле тӳрлет", + "tooltip-ca-edit": "Кăна тӳрлет", "tooltip-ca-addsection": "Çĕнĕ пай ту", "tooltip-ca-viewsource": "Ку страницӑна эсир улӑштарма пултараймастӑр. Ӑна мӗнле ҫырнине кӑна пӑхма пултаратӑр.", - "tooltip-ca-history": "Эле улӑштарнин кун-ҫулӗ", + "tooltip-ca-history": "Кунăн улӑшăннисем", "tooltip-ca-protect": "Улӑшратусенчен сыхласси", "tooltip-ca-delete": "Страницӑна кӑларса пӑрахмалли", "tooltip-ca-move": "Страницӑна урӑх ҫӗре куҫарасси", diff --git a/languages/i18n/de.json b/languages/i18n/de.json index 0470691a0e..a820ad592f 100644 --- a/languages/i18n/de.json +++ b/languages/i18n/de.json @@ -712,8 +712,8 @@ "subject-preview": "Vorschau der Zusammenfassungszeile:", "previewerrortext": "Beim Versuch, eine Vorschau deiner Änderungen anzuzeigen, ist ein Fehler aufgetreten.", "blockedtitle": "Benutzer ist gesperrt", - "blockedtext": "'''Dein Benutzername oder deine IP-Adresse wurde gesperrt.'''\n\nDie Sperrung wurde vom Administrator $1 durchgeführt.\nAls Grund wurde ''$2'' angegeben.\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\nDu kannst die „E-Mail an diesen Benutzer“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\nDeine aktuelle IP-Adresse ist $3 und die Sperrkennung lautet $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", - "autoblockedtext": "Deine IP-Adresse wurde automatisch gesperrt, da sie von einem anderen Benutzer genutzt wurde, der von $1 gesperrt wurde.\nAls Grund wurde angegeben:\n\n:''$2''\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\n\nDu kannst die „E-Mail an diesen Benutzer“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\n\nDeine aktuelle IP-Adresse ist $3, und die Sperr-ID ist $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", + "blockedtext": "'''Dein Benutzername oder deine IP-Adresse wurde gesperrt.'''\n\nDie Sperrung wurde vom Administrator $1 durchgeführt.\nAls Grund wurde ''$2'' angegeben.\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\nDu kannst die „{{int:emailuser}}“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\nDeine aktuelle IP-Adresse ist $3 und die Sperrkennung lautet $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", + "autoblockedtext": "Deine IP-Adresse wurde automatisch gesperrt, da sie von einem anderen Benutzer genutzt wurde, der von $1 gesperrt wurde.\nAls Grund wurde angegeben:\n\n:''$2''\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\n\nDu kannst die „{{int:emailuser}}“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\n\nDeine aktuelle IP-Adresse ist $3, und die Sperr-ID ist $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.", "systemblockedtext": "Dein Benutzername oder deine IP-Adresse wurde von MediaWiki automatisch gesperrt.\nDer angegebene Grund ist:\n\n:$2\n\n* Beginn der Sperre: $8\n* Ablauf der Sperre: $6\n* Sperre betrifft: $7\n\nDeine aktuelle IP-Adresse ist $3.\nBitte gib alle oben stehenden Details in jeder Anfrage an.", "blockednoreason": "keine Begründung angegeben", "whitelistedittext": "Du musst dich $1, um Seiten bearbeiten zu können.", diff --git a/languages/i18n/diq.json b/languages/i18n/diq.json index 2ad2c5a77d..1a80395594 100644 --- a/languages/i18n/diq.json +++ b/languages/i18n/diq.json @@ -1226,31 +1226,31 @@ "rcnotefrom": "Cêr de $2 ra nata {{PLURAL:$5|vurnayışiyê}} asenê (tewr vêşi $1 asenê) $3, $4", "rclistfrom": "$3 sehat $2 ra tepiya vurnayışanê neweyan bımotne", "rcshowhideminor": "Vırnayışê werdiy $1", - "rcshowhideminor-show": "Bımotne", + "rcshowhideminor-show": "Bımocne", "rcshowhideminor-hide": "Bınımne", "rcshowhidebots": "botan $1", - "rcshowhidebots-show": "Bımotne", + "rcshowhidebots-show": "Bımocne", "rcshowhidebots-hide": "Bınımne", "rcshowhideliu": "karberê qeydbiyay $1", "rcshowhideliu-show": "Bımocne", "rcshowhideliu-hide": "Bınımne", "rcshowhideanons": "$1 karberê bênamey", - "rcshowhideanons-show": "Bımotne", + "rcshowhideanons-show": "Bımocne", "rcshowhideanons-hide": "Bınımne", "rcshowhidepatr": "$1 vurnayışê ke dewriya geyrayê", "rcshowhidepatr-show": "Bımocne", "rcshowhidepatr-hide": "Bınımne", "rcshowhidemine": "vırnayışê mı $1", - "rcshowhidemine-show": "Bımotne", + "rcshowhidemine-show": "Bımocne", "rcshowhidemine-hide": "Bınımne", "rcshowhidecategorization": "kategorizasyoni $1", - "rcshowhidecategorization-show": "Bımotné", + "rcshowhidecategorization-show": "Bımocne", "rcshowhidecategorization-hide": "Bınımne", "rclinks": "$1 vurnayışê peyênê ke $2 rocanê peyênan de biyê, inan bımocne", "diff": "ferq", "hist": "verên", "hide": "Bınımne", - "show": "Bımotne", + "show": "Bımocne", "minoreditletter": "q", "newpageletter": "N", "boteditletter": "b", @@ -1583,7 +1583,7 @@ "withoutinterwiki": "Perrê ke zıwananê binan rê gıreyê cı çıni yo", "withoutinterwiki-summary": "Enê pelî ke versiyonê ziwanî binî ra link nidano.", "withoutinterwiki-legend": "Verole", - "withoutinterwiki-submit": "Bımotne", + "withoutinterwiki-submit": "Bımocne", "fewestrevisions": "Perrê kı tewr tayn timaryayê", "nbytes": "$1 {{PLURAL:$1|bayt|bayti}}", "ncategories": "$1 {{PLURAL:$1|Kategori|Kategoriy}}", @@ -1650,7 +1650,7 @@ "usereditcount": "$1 {{PLURAL:$1|vurnayîş|vurnayîşî}}", "usercreated": "$2 de $1 {{GENDER:$3|viraziya}}", "newpages": "Perrê newey", - "newpages-submit": "Bımotne", + "newpages-submit": "Bımocne", "newpages-username": "Nameyê karberi:", "ancientpages": "Tewr pelê kıhani", "move": "Bıkırışe", @@ -1689,7 +1689,7 @@ "specialloguserlabel": "Kerdoğ:", "speciallogtitlelabel": "Meqsed (sername ya zi {{ns:user}}:karberi rê nameyê karberi):", "log": "Qeydi", - "logeventslist-submit": "Bımotne", + "logeventslist-submit": "Bımocne", "all-logs-page": "Heme qeydê pêroyi", "alllogstext": "qey {{SITENAME}}i mocnayişê heme rocaneyani.\ntipa rocaneyi, nameyê karberi (herfa pil u qıci re hessas a), ya zi peli (reyna hessasiyê herfa pil u qıciyi) bıweçine u esayiş qıc kerê.", "logempty": "Qeydan dı malumato unasin çıni yo.", @@ -1730,7 +1730,7 @@ "linksearch-line": "$1, $2 ra link biya", "linksearch-error": "jokeri têna nameyê makina ya serekini de aseni/eseni.", "listusersfrom": "karber ê ke pey ıney detpêkeni ramocın:", - "listusers-submit": "Bımotne", + "listusers-submit": "Bımocne", "listusers-noresult": "karber nêdiyayo/a.", "listusers-blocked": "(blok biy)", "activeusers": "Lista karberanê aktifan", @@ -1820,7 +1820,7 @@ "wlnote": "$3 saete $4 ra dıme {{PLURAL:$2|yew saete de|'''$2''' saetan de}} {{PLURAL:$1|vurnayışo peyên|vurnayışê '''$1''' peyêni}} cêrderê.", "wlshowlast": "Peyni de $1 seata u $2 roca bıasne", "watchlist-hide": "Bınımne", - "watchlist-submit": "Bımotne", + "watchlist-submit": "Bımocne", "wlshowtime": "Periyoda zemani asenayışi:", "wlshowhideminor": "vırnayışê werdiy", "wlshowhidebots": "boti", @@ -1859,7 +1859,7 @@ "delete-confirm": "\"$1\" bestere", "delete-legend": "Bestere", "historywarning": "'''Teme:''' Pela ke şıma esterenê tede yew viyarte be teqriben $1 {{PLURAL:$1|versiyon esto|versiyoni estê}}:", - "historyaction-submit": "Bımotne", + "historyaction-submit": "Bımocne", "confirmdeletetext": "Tı ho yew pele u tarixê pele wederneno.\nTı ra rica keno, tı zani tı ho sekeno, tı zani neticeyanê eno wedarnayışi u tı zani tı ser [[{{MediaWiki:Policy-url}}|poliçe]] kar keno.", "actioncomplete": "Kar bi temam", "actionfailed": "kar nêbı", diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 4befdc5331..43f9386c79 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -660,8 +660,8 @@ "subject-preview": "Preview of subject:", "previewerrortext": "An error occurred while attempting to preview your changes.", "blockedtitle": "User is blocked", - "blockedtext": "Your username or IP address has been blocked.\n\nThe block was made by $1.\nThe reason given is $2.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"email this user\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", - "autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"email this user\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", + "blockedtext": "Your username or IP address has been blocked.\n\nThe block was made by $1.\nThe reason given is $2.\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.\nYou cannot use the \"{{int:emailuser}}\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", + "autoblockedtext": "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.\nThe reason given is:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYou may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.\n\nNote that you may not use the \"{{int:emailuser}}\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.\n\nYour current IP address is $3, and the block ID is #$5.\nPlease include all above details in any queries you make.", "systemblockedtext": "Your username or IP address has been automatically blocked by MediaWiki.\nThe reason given is:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYour current IP address is $3.\nPlease include all above details in any queries you make.", "blockednoreason": "no reason given", "whitelistedittext": "Please $1 to edit pages.", diff --git a/languages/i18n/eo.json b/languages/i18n/eo.json index 7353f90242..58cf7ddcb1 100644 --- a/languages/i18n/eo.json +++ b/languages/i18n/eo.json @@ -548,6 +548,7 @@ "botpasswords-existing": "Ekzistantaj robotaj pasvortoj", "botpasswords-createnew": "Krei novan robotan pasvorton", "botpasswords-editexisting": "Redakti ekzistantan robotan pasvorton", + "botpasswords-label-needsreset": "(oni devas rekomencigi la pasvorton)", "botpasswords-label-appid": "Robota nomo:", "botpasswords-label-create": "Krei", "botpasswords-label-update": "Ĝisdatigi", diff --git a/languages/i18n/es.json b/languages/i18n/es.json index 7199df934a..8360c61565 100644 --- a/languages/i18n/es.json +++ b/languages/i18n/es.json @@ -667,6 +667,7 @@ "botpasswords-existing": "Contraseñas de bots existentes", "botpasswords-createnew": "Crear una contraseña de robot nueva", "botpasswords-editexisting": "Editar una contraseña de robot existente", + "botpasswords-label-needsreset": "(la contraseña debe restablecerse)", "botpasswords-label-appid": "Nombre del robot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Actualizar", @@ -690,6 +691,7 @@ "botpasswords-restriction-failed": "Las restricciones de la contraseña de bot impiden este inicio de sesión.", "botpasswords-invalid-name": "El nombre de usuario especificado no contiene el separador de contraseña de bot (\"$1\").", "botpasswords-not-exist": "El usuario \"$1\" no tiene una contraseña de bot llamada \"$2\".", + "botpasswords-needs-reset": "Se debe restablecer la contraseña del robot «$2», propiedad {{GENDER:$1|del usuario|de la usuaria}} «$1».", "resetpass_forbidden": "No se pueden cambiar las contraseñas", "resetpass_forbidden-reason": "Las contraseñas no pueden cambiarse: $1", "resetpass-no-info": "Debes iniciar sesión para acceder directamente a esta página.", @@ -786,7 +788,7 @@ "previewerrortext": "Se ha producido un error al intentar la vista previa de los cambios.", "blockedtitle": "El usuario está bloqueado", "blockedtext": "Tu nombre de usuario o dirección IP ha sido bloqueada.\n\nEl bloqueo lo hizo $1.\nLa razón dada es $2.\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar a $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\nNo puedes utilizar la función «enviar correo electrónico a este usuario» a menos que tengas una dirección de correo electrónico válida registrada en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es #$5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.", - "autoblockedtext": "Tu dirección IP ha sido bloqueada automáticamente porque fue utilizada por otro usuario, que resultó bloqueado por $1.\nEl motivo dado es el siguiente:\n\n:$2\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar con $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\n\nTen en cuenta que no puedes utilizar la función «enviar correo electrónico a este usuario» a menos que tengas una dirección de correo electrónico válida registrada en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es #$5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.", + "autoblockedtext": "Tu dirección IP ha sido bloqueada automáticamente porque fue utilizada por otro usuario, que resultó bloqueado por $1.\nEl motivo dado es el siguiente:\n\n:$2\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar con $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\n\nObserva que no puedes utilizar la función «{{int:emailuser}}» a menos que hayas registrado una dirección de correo electrónico válida en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es n.º $5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.", "systemblockedtext": "Tu nombre de usuario o dirección IP ha sido bloqueado automáticamente por el software MediaWiki.\nLa razón dada es:\n\n:$2\n\n* Inicio del bloqueo: $8\n* Caducidad de bloqueo: $6\n* Destinatario del bloqueo: $7\n\nTu dirección IP actual es $3.\nPor favor, incluye todos los datos aquí mostrados en cualquier consulta que hagas.", "blockednoreason": "no se ha especificado el motivo", "whitelistedittext": "Tienes que $1 para editar páginas.", diff --git a/languages/i18n/fi.json b/languages/i18n/fi.json index 0e22f6fed7..3c5ef67517 100644 --- a/languages/i18n/fi.json +++ b/languages/i18n/fi.json @@ -671,8 +671,8 @@ "subject-preview": "Aiheotsikon esikatselu:", "previewerrortext": "Muokkaustesi esikatselun toteuttamisessa on tapahtunut virhe.", "blockedtitle": "Käyttäjä on estetty", - "blockedtext": "'''Käyttäjätunnuksesi tai IP-osoitteesi on estetty.'''\n\nEston on asettanut $1.\nSyy: '''$2'''\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", - "autoblockedtext": "IP-osoitteesi on estetty automaattisesti, koska sitä on käyttänyt toinen käyttäjä, jonka on estänyt ylläpitäjä $1.\nEston syy on:\n\n:''$2''\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\n\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\n\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", + "blockedtext": "Käyttäjätunnuksesi tai IP-osoitteesi on estetty.\n\nEston on asettanut $1.\nAnnettu syy on $2.\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", + "autoblockedtext": "IP-osoitteesi on estetty automaattisesti, koska sitä on käyttänyt toinen käyttäjä, jonka on estänyt ylläpitäjä $1.\nAnnettu syy on:\n\n:$2\n\n* Eston alkamisaika: $8\n* Eston päättymisaika: $6\n* Kohde: $7\n\nVoit keskustella ylläpitäjän $1 tai toisen [[{{MediaWiki:Grouppage-sysop}}|ylläpitäjän]] kanssa estosta.\n\nHuomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassa olevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] tai jos esto on asetettu koskemaan myös sähköpostin lähettämistä.\n\nIP-osoitteesi on $3 ja estotunnus on #$5.\nLiitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", "systemblockedtext": "Käyttäjätunnuksesi tai IP-osoitteesi on automaattisesti estetty MediaWikin toimesta.\nAnnettu syy on:\n\n:$2\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nTämänhetkinen IP-osoitteesi on $3.\nOle hyvä ja liitä kaikki yllä olevat tiedot mahdollisiin kyselyihisi.", "blockednoreason": "(syytä ei annettu)", "whitelistedittext": "Sinun täytyy $1, jotta voisit muokata sivuja.", diff --git a/languages/i18n/fr.json b/languages/i18n/fr.json index 783a778bed..5748adfd6a 100644 --- a/languages/i18n/fr.json +++ b/languages/i18n/fr.json @@ -693,7 +693,7 @@ "botpasswords-restriction-failed": "Les restrictions de mot de passe de robots empêchent cette connexion.", "botpasswords-invalid-name": "Le nom d’utilisateur spécifié ne contient pas de séparateur de mot de passe de robots (« $1 »).", "botpasswords-not-exist": "L’{{GENDER:$1|utilisateur|utilisatrice}} « $1 » n’a pas de mot de passe de robot nommé « $2 ».", - "botpasswords-needs-reset": "Le mot de passe du robot de nom \"$2\" de l'utilisat{{GENDER:$1|eur}} \"$1\" doit être réinitialisé.", + "botpasswords-needs-reset": "Le mot de passe du robot de nom « $2 » de l’utilisat{{GENDER:$1|eur|rice}} « $1 » doit être réinitialisé.", "resetpass_forbidden": "Les mots de passe ne peuvent pas être changés", "resetpass_forbidden-reason": "Les mots de passe ne peuvent pas être modifiés : $1", "resetpass-no-info": "Vous devez être connecté(e) pour accéder directement à cette page.", diff --git a/languages/i18n/gcr.json b/languages/i18n/gcr.json index 584759be91..abe2cb3a7a 100644 --- a/languages/i18n/gcr.json +++ b/languages/i18n/gcr.json @@ -182,7 +182,7 @@ "unprotect": "Chanjé protèksyon-an", "newpage": "Nouvèl paj", "talkpagelinktext": "diskisyon", - "specialpage": "Paj spésyal", + "specialpage": "Paj èspésyal", "personaltools": "Zouti pèrsonèl", "talk": "Diskisyon", "views": "Afichaj", @@ -273,7 +273,7 @@ "nstab-main": "Paj", "nstab-user": "Paj di {{GENDER:{{ROOTPAGENAME}}|itilizatò|itilizatris}}", "nstab-media": "Médja", - "nstab-special": "Paj spésyal", + "nstab-special": "Paj èspésyal", "nstab-project": "À propo", "nstab-image": "Fiché", "nstab-mediawiki": "Mésaj", @@ -283,8 +283,8 @@ "mainpage-nstab": "Paj prensipal", "nosuchaction": "Aksyon enkonèt", "nosuchactiontext": "Aksyon-an spésifyé andan URL-a sa envalid.\nZòt pitèt mal antré URL-a ou swivi roun lyen éroné.\nLi pé égalman endiké oun anomali andan logisyèl itilizé pa {{SITENAME}}.", - "nosuchspecialpage": "Paj spésyal inègzistant", - "nospecialpagetext": "Zòt doumandé oun paj spésyal ki pa ka ègzisté.\n\nOun lis dé paj spésyal valid ka trouvé so kò asou [[Special:SpecialPages|{{int:specialpages}}]].", + "nosuchspecialpage": "Paj èspésyal inègzistant", + "nospecialpagetext": "Zòt doumandé oun paj èspésyal ki pa ka ègzisté.\n\nOun lis dé paj èspésyal valid ka trouvé so kò asou [[Special:SpecialPages|{{int:specialpages}}]].", "error": "Érò", "databaseerror": "Érò di baz di doné", "databaseerror-text": "Oun érò di rékèt di baz di doné aparèt.\nSala pé provini di roun anomali annan lojisyèl-a.", @@ -353,7 +353,7 @@ "mycustomjsprotected": "Zòt pa gen drwè di modifyé sa paj JavaScript.", "myprivateinfoprotected": "Zòt pa gen drwè di modifyé zòt enfòrmasyon pèrsonèl.", "mypreferencesprotected": "Zòt pa gen drwè di modifyé zòt préférans.", - "ns-specialprotected": "Paj spésyal-ya pa pouvé sa modifyé.", + "ns-specialprotected": "Paj èspésyal-ya pa pouvé fika modifyé.", "titleprotected": "Sa tit té protéjé kont tout kréyasyon pa [[User:$1|$1]].\nMotif fourni sa $2.", "filereadonlyerror": "Enposib di modifyé fiché-a « $1 » pas répèrtwar-a di fiché « $2 » sa an lèktir sèl.\n\nAdministratò sistèm ki li vérouyé té fourni sa motif : « $3 ».", "invalidtitle-knownnamespace": "Tit pa valid ké lèspas di non « $2 » é entitilé-a « $3 »", @@ -593,7 +593,7 @@ "showpreview": "Prévizwalizé", "showdiff": "Wè modifikasyon-yan", "anoneditwarning": "Panga : zòt pa konèkté. Zòt adrès IP ké sa vizib di tout moun si zòt ka fè dé modifikasyon. Si zòt [$1 ka konèkté zòt kò] ou [$2 kréyé roun kont], zòt modifikasyon ké sq atribwé à zòt pròp non di itilizatò(ris) é zòt ké gen dé ròt avantaj.", - "blockedtext": "Zòt kont itilizatò ou zòt adrès IP bloké.\n\nBlokaj té éfèktchwé pa $1.\nRézon-an évoké sa swivant : $2.\n\n* Koumansman di blokaj : $8\n* Èkspirasyon di blokaj : $6\n* Kont bloké : $7.\n\nZòt pé kontakté $1 ou rounòt [[{{MediaWiki:Grouppage-sysop}}|administratò]] pou an diskité.\nZòt pa pé itilizé fonksyon-an « {{int:emailuser}} » sèlman si oun adrès di kouryé valid sa spésifyé andan zòt [[Special:Preferences|préférans]] é sèlman si sa fonksyonalité pa bloké.\nZòt adrèd IP atchwèl sa $3 é zòt idantifyan di blokaj sa $5.\nSouplé, enkli tout détay-ya lasou'l annan chakin dé rékèt ki zòt ké fè.", + "blockedtext": "Zòt kont itilizatò oben zòt adrès IP bloké.\n\nBlokaj té éfèktchwé pa $1.\nRézon-an évoké sa swivant : $2.\n\n* Koumansman di blokaj : $8\n* Èspirasyon di blokaj : $6\n* Kont bloké : $7.\n\nZòt pé kontakté $1 oben rounòt [[{{MediaWiki:Grouppage-sysop}}|administratò]] pou an diskité.\nZòt pa pouvé itilizé fonksyon-an « {{int:emailuser}} » rounso si oun adrès di kouryé valid sa èspésifyé andan zòt [[Special:Preferences|préférans]] é rounso si sa fonksyonalité pa bloké.\nZòt adrès IP atchwèl sa $3 é zòt idantifyan di blokaj sa $5.\nSouplé, enkli tout détay-ya lasou'l annan chakin dé rékèt ki zòt ké fè.", "loginreqlink": "konèkté so kò", "newarticletext": "Zòt té ka swiv roun lyen vèr roun paj ki pa ka ègzisté òkò. \nAtò di kréyé sa paj, antré zòt tèks annan bwat ki aprè (zòt pé konsilté [$1 paj d'èd-a] pou plis enfòrmasyon).\nSi zòt pa rivé{{GENDER:|}} isi pa éròr, kliké asou bouton Routour di zòt navigatò.", "anontalkpagetext": "----\nZòt asou paj di diskisyon di oun itilizatò anonim ki pa òkò kréyé di kont ou ki pa ka an itilizé.\nPou sa rézon, nou divèt itilizé so adrès IP pou idantifyé li.\nOun adrès IP pé sa partajé pa plizyò itilizatò.\nSi zòt roun itiliza{{GENDER:|ò|ris}} anonim é si zòt ka kontasté ki dé koumantèr ki pa ka konsèrné zòt sa adrèsé à zòt, zòt pé [[Special:CreateAccount|kréyé roun kont]] ou [[Special:UserLogin|konèkté zòt kò]] atò di évité tout konfizyon fitir ké ròt kontribitò anonim.", @@ -725,7 +725,7 @@ "recentchangeslinked-feed": "Swivi dé paj lyé", "recentchangeslinked-toolbox": "Swivi dé paj lyé", "recentchangeslinked-title": "Swivi dé paj asosyé à « $1 »", - "recentchangeslinked-summary": "Antré roun non di paj pou wè modifikasyon-yan ki fè résaman asou dé paj lyé dipi ou vèr sa paj (pou wè manm-yan di oun katégori, antré Katégori:Non di katégori). Modifikasyon-yan dé paj di [[Special:Watchlist|zòt lis di swivi]] sa an gra.", + "recentchangeslinked-summary": "Antré roun non di paj pou wè modifikasyon-yan ki fè résaman asou dé paj lyé dipi oben bò'd sa paj (pou wè manm-yan di oun katégori, antré {{ns:category}}:Non di katégori). Modifikasyon-yan dé paj di [[Special:Watchlist|zòt lis di swivi]] sa an gra.", "recentchangeslinked-page": "Non di paj :", "recentchangeslinked-to": "Afiché modifikasyon-yan dé paj ki ka konpòrté roun lyen vèr paj ki bay plito ki envèrs", "upload": "Enpòrté roun fiché", @@ -892,12 +892,12 @@ "tooltip-t-contributions": "Wè lis dé kontribisyon di {{GENDER:$1|sa itilizatò|sa itilizatris}}", "tooltip-t-emailuser": "Voyé roun kouryé à {{GENDER:$1|sa itilizatò|sa itilizatris}}", "tooltip-t-upload": "Télévèrsé dé fiché", - "tooltip-t-specialpages": "Lis di tout paj spésyal", + "tooltip-t-specialpages": "Lis di tout paj èspésyal", "tooltip-t-print": "Vèrsyon enprimab di sa paj", "tooltip-t-permalink": "Adrès pèrmanant di sa vèrsyon di paj-a", "tooltip-ca-nstab-main": "Wè kontni di paj-a", "tooltip-ca-nstab-user": "Wè paj di itilizatò", - "tooltip-ca-nstab-special": "A roun paj spésyal, é li pa pé sa modifyé.", + "tooltip-ca-nstab-special": "A roun paj èspésyal, é li pa pouvé fika modifyé.", "tooltip-ca-nstab-project": "Wè paj-a di projè", "tooltip-ca-nstab-image": "Wè paj-a di fiché", "tooltip-ca-nstab-mediawiki": "Wè mésaj sistèm-a", @@ -984,7 +984,7 @@ "watchlisttools-raw": "Modifyé lis di swivi an mòd brout", "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|diskisyon]])", "redirect": "Roudirijé pa ID di fiché, itilizatò, paj, révizyon ou journal", - "redirect-summary": "Sa paj spésyal ka roudirijé vèr roun fiché (non di fiché fourni), oun paj (ID di révizyon ou di paj fourni), oun paj di itilizatò (idantifyan nimérik di itilizatò fourni), ou roun antré di journal (ID di journal fourni). Itilizasyon : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].", + "redirect-summary": "Sa paj èspésyal ka roudirijé bò'd roun fiché (non di fiché fourni), oun paj (ID di révizyon oben di paj fourni), oun paj di itilizatò (idantifyan nimérik di itilizatò fourni), oben roun antré di journal (ID di journal fourni). Itilizasyon : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], oben [[{{#Special:Redirect}}/logid/186]].", "redirect-submit": "Validé", "redirect-lookup": "Sasé :", "redirect-value": "Valò :", @@ -992,7 +992,7 @@ "redirect-page": "ID di paj", "redirect-revision": "Révizyon di paj-a", "redirect-file": "Non di fiché", - "specialpages": "Paj spésyal", + "specialpages": "Paj èspésyal", "tag-filter": "Filtré [[Special:Tags|baliz]] :", "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Baliz}}]] : $2)", "tags-active-yes": "Wi", diff --git a/languages/i18n/gl.json b/languages/i18n/gl.json index 633d84dcbb..4fb87e7042 100644 --- a/languages/i18n/gl.json +++ b/languages/i18n/gl.json @@ -26,7 +26,8 @@ "Luan", "Hamilton Abreu", "Athena in Wonderland", - "Navhy" + "Navhy", + "PokéDex Nacional" ] }, "tog-underline": "Subliñar as ligazóns:", @@ -63,7 +64,7 @@ "tog-watchlisthideminor": "Agochar as edicións pequenas na lista de vixilancia", "tog-watchlisthideliu": "Agochar as edicións dos usuarios rexistrados na lista de vixilancia", "tog-watchlistreloadautomatically": "Recargar a lista de vixilancia automaticamente cando se produza un cambio nun filtro (necesítase JavaScript)", - "tog-watchlistunwatchlinks": "Engadir ligazóns directos para vixiar ou deixar de vixiar as entradas da lista de páxinas vixiadas (é necesario JavaScript para activar a funcionalidade)", + "tog-watchlistunwatchlinks": "Engadir ligazóns directos para vixiar ou deixar de vixiar ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) as entradas da lista de páxinas vixiadas (é preciso JavaScript para activar a funcionalidade)", "tog-watchlisthideanons": "Agochar as edicións dos usuarios anónimos na lista de vixilancia", "tog-watchlisthidepatrolled": "Agochar as edicións patrulladas na lista de vixilancia", "tog-watchlisthidecategorization": "Agochar a categorización das páxinas", @@ -532,6 +533,7 @@ "botpasswords-existing": "Contrasinais de bots existentes", "botpasswords-createnew": "Crear un novo contrasinal de bot", "botpasswords-editexisting": "Editar un contrasinal de bot xa existente", + "botpasswords-label-needsreset": "(o contrasinal precisa ser redefinido)", "botpasswords-label-appid": "Nome do bot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Actualizar", diff --git a/languages/i18n/he.json b/languages/i18n/he.json index 0946de246b..740ae29ba0 100644 --- a/languages/i18n/he.json +++ b/languages/i18n/he.json @@ -491,7 +491,7 @@ "noemail": "לא רשומה כתובת דואר אלקטרוני עבור ה{{GENDER:$1|משתמש|משתמשת}} \"$1\".", "noemailcreate": "יש לספק כתובת דואר אלקטרוני תקינה.", "passwordsent": "סיסמה חדשה נשלחה לכתובת הדואר האלקטרוני הרשומה עבור \"$1\".\nאנא היכנסו חזרה לאתר אחרי שתקבלו אותה.", - "blocked-mailpassword": "כתובת ה־IP שלך נחסמה מעריכה. כדי למנוע ניצול לרעה, אינך מורשה להשתמש באפשרות שחזור הסיסמה.", + "blocked-mailpassword": "כתובת ה־IP שלך נחסמה מעריכה. כדי למנוע ניצול לרעה, אין באפשרותך להשתמש באפשרות שחזור הסיסמה.", "eauthentsent": "דוא\"ל אימות נשלח לכתובת הדוא\"ל שצוינה.\nלפני שדברי דוא\"ל אחרים יישלחו לחשבון הזה, יהיה {{GENDER:|עליך|עלייך}} לפעול לפי ההוראות בדוא\"ל, כדי לאשר שהחשבון אכן שייך לך.", "throttled-mailpassword": "כבר נשלח דוא\"ל לאיפוס הסיסמה ב{{PLURAL:$1|שעה האחרונה|שעתיים האחרונות|Ö¾$1 השעות האחרונות}}.\nכדי למנוע ניצול לרעה, יכול להישלח רק דוא\"ל אחד כזה בכל {{PLURAL:$1|שעה|שעתיים|$1 שעות}}.", "mailerror": "שגיאה בשליחת דוא\"ל: $1", @@ -656,8 +656,8 @@ "subject-preview": "תצוגה מקדימה של הנושא:", "previewerrortext": "אירעה שגיאה בעת הניסיון להציג תצוגה מקדימה של השינויים שלך.", "blockedtitle": "המשתמש חסום", - "blockedtext": "שם המשתמש או כתובת ה־IP שלך נחסמו.\n\nהחסימה בוצעה על ידי $1.\nהסיבה שניתנה לכך היא $2.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\nאין באפשרותך להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", - "autoblockedtext": "כתובת ה־IP שלך נחסמה באופן אוטומטי כיוון שמשתמש אחר, שנחסם על־ידי $1, השתמש בה.\nהסיבה שניתנה לחסימה היא:\n\n:$2\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\n\nאין באפשרותך להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\n\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", + "blockedtext": "שם המשתמש או כתובת ה־IP שלך נחסמו.\n\nהחסימה בוצעה על־ידי $1.\nהסיבה שניתנה לכך היא $2.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\nכמו־כן, באפשרותך להשתמש בתכונת \"{{int:emailuser}}\", אלא אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", + "autoblockedtext": "כתובת ה־IP שלך נחסמה באופן אוטומטי כיוון שמשתמש אחר, שנחסם על־ידי $1, השתמש בה.\nהסיבה שניתנה לחסימה היא:\n\n:$2\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\n\nכמו־כן, באפשרותך להשתמש בתכונת \"{{int:emailuser}}\", אלא אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\n\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", "systemblockedtext": "שם המשתמש או כתובת ה־IP שלך נחסמו באופן אוטומטי על־ידי תוכנת מדיה־ויקי.\nהסיבה שניתנה לחסימה היא:\n\n:$2\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nכתובת ה־IP הנוכחית שלך היא $3.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.", "blockednoreason": "לא ניתנה סיבה", "whitelistedittext": "נדרשת $1 כדי לערוך דפים.", @@ -1837,7 +1837,7 @@ "listduplicatedfiles-summary": "זוהי רשימה של קבצים שהגרסה החדשה ביותר שלהם זהה לגרסה החדשה ביותר של קובץ אחר כלשהו. רק קבצים מקומיים נבדקים לצורך זה.", "listduplicatedfiles-entry": "לקובץ [[:File:$1|$1]] יש [[$3|{{PLURAL:$2|עותק זהה|$2 עותקים זהים}}]].", "unusedtemplates": "תבניות שאינן בשימוש", - "unusedtemplatestext": "דף זה מכיל רשימה של כל הדפים במרחב השם {{ns:template}} שאינם נכללים בדף אחר. אנא זכרו לבדוק את הקישורים האחרים לתבניות לפני שתמחקו אותן.", + "unusedtemplatestext": "דף זה מכיל רשימה של כל הדפים במרחב השם \"{{ns:template}}\" שאינם נכללים בדף אחר.\nיש לזכור לבדוק את הקישורים האחרים לתבניות לפני מחיקתן.", "unusedtemplateswlh": "קישורים אחרים", "randompage": "דף אקראי", "randompage-nopages": "אין דפים {{PLURAL:$2|במרחב השם הבא|במרחבי השם הבאים}}: $1.", @@ -1882,22 +1882,22 @@ "brokenredirects-edit": "עריכה", "brokenredirects-delete": "מחיקה", "withoutinterwiki": "דפים ללא קישורי שפה", - "withoutinterwiki-summary": "הדפים הבאים אינם מקשרים לגרסאות שלהם בשפות אחרות:", + "withoutinterwiki-summary": "הדפים הבאים אינם מקשרים לגרסאות שלהם בשפות אחרות.", "withoutinterwiki-legend": "תחילית", "withoutinterwiki-submit": "הצגה", "fewestrevisions": "הדפים בעלי מספר העריכות הנמוך ביותר", "nbytes": "{{PLURAL:$1|בית אחד|$1 בתים}}", "ncategories": "{{PLURAL:$1|קטגוריה אחת|$1 קטגוריות}}", - "ninterwikis": "{{PLURAL:$1|קישור בינוויקי קחד|$1 קישורי בינוויקי}}", + "ninterwikis": "{{PLURAL:$1|קישור בינוויקי אחד|$1 קישורי בינוויקי}}", "nlinks": "{{PLURAL:$1|קישור אחד|$1 קישורים}}", "nmembers": "{{PLURAL:$1|דף אחד|$1 דפים}}", "nmemberschanged": "$1 ← {{PLURAL:$2|חבר אחד|$2 חברים}}", "nrevisions": "{{PLURAL:$1|גרסה אחת|$1 גרסאות}}", "nimagelinks": "בשימוש {{PLURAL:$1|בדף אחד|ב־$1 דפים}}", "ntransclusions": "בשימוש {{PLURAL:$1|בדף אחד|ב־$1 דפים}}", - "specialpage-empty": "אין תוצאות.", + "specialpage-empty": "אין תוצאות בדיווח התחזוקה הזה.", "lonelypages": "דפים יתומים", - "lonelypagestext": "הדפים הבאים אינם מקושרים ואינם מוכללים בדפים אחרים באתר {{SITENAME}}.", + "lonelypagestext": "הדפים הבאים אינם מקושרים מדפים אחרים ב{{GRAMMAR:תחילית|{{SITENAME}}}} ואינם מוכללים בהם.", "uncategorizedpages": "דפים חסרי קטגוריה", "uncategorizedcategories": "קטגוריות חסרות קטגוריה", "uncategorizedimages": "קבצים חסרי קטגוריה", @@ -1907,11 +1907,11 @@ "unusedimages": "קבצים שאינם בשימוש", "wantedcategories": "קטגוריות מבוקשות", "wantedpages": "דפים מבוקשים", - "wantedpages-summary": "רשימת דפים לא קיימים שמספר הקישורים אליהם הוא הגדול ביותר, למעט דפים שרק הפניות מקשרות אליהם. לרשימת דפים לא קיימים שיש הפניות המקשרות אליהם, ר' [[{{#special:BrokenRedirects}}|רשימת ההפניות הבלתי־תקינות]].", + "wantedpages-summary": "רשימת דפים לא קיימים שמספר הקישורים אליהם הוא הגדול ביותר, למעט דפים שרק הפניות מקשרות אליהם. לרשימת דפים לא קיימים שיש הפניות המקשרות אליהם, ניתן לעיין ב[[{{#special:BrokenRedirects}}|רשימת ההפניות הבלתי־תקינות]].", "wantedpages-badtitle": "כותרת בלתי תקינה ברשימת התוצאות: $1", "wantedfiles": "קבצים מבוקשים", "wantedfiletext-cat": "הקבצים הבאים נמצאים בשימוש, אך אינם קיימים. ייתכן שקבצים ממאגרים חיצוניים יהיו רשומים אף על פי שהם קיימים, אך שגיאות כאלה יהיו מחוקות. בנוסף, דפים שמטביעים קבצים שאינם קיימים רשומים בדף [[:$1]].", - "wantedfiletext-cat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים. כמו־כן, דפים שמשתמשים בקבצים שאינם קיימים רשומים בדף [[:$1]].", + "wantedfiletext-cat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים. כמו־כן, דפים שמטביעים קבצים שאינם קיימים רשומים בדף [[:$1]].", "wantedfiletext-nocat": "הקבצים הבאים נמצאים בשימוש, אך אינם קיימים. ייתכן שקבצים ממאגרים חיצוניים יהיו רשומים אף על פי שהם קיימים, אך שגיאות כאלה יהיו מחוקות.", "wantedfiletext-nocat-noforeign": "הקבצים הבאים נמצאים בשימוש, אבל אינם קיימים.", "wantedtemplates": "תבניות מבוקשות", @@ -1923,7 +1923,7 @@ "mostinterwikis": "הדפים עם המספר הרב ביותר של קישורי בינוויקי", "mostrevisions": "הדפים עם מספר העריכות הגבוה ביותר", "prefixindex": "כל הדפים עם התחילית", - "prefixindex-namespace": "כל הדפים עם התחילית (במרחב השם $1)", + "prefixindex-namespace": "כל הדפים עם התחילית (במרחב השם \"$1\")", "prefixindex-submit": "הצגה", "prefixindex-strip": "הסתרת התחילית ברשימה", "shortpages": "דפים קצרים", @@ -1931,9 +1931,9 @@ "deadendpages": "דפים ללא קישורים", "deadendpagestext": "הדפים הבאים אינם מקשרים לדפים אחרים באתר {{SITENAME}}.", "protectedpages": "דפים מוגנים", - "protectedpages-filters": "מסננים:", + "protectedpages-filters": "סינון:", "protectedpages-indef": "הגנות ללא הגבלת זמן בלבד", - "protectedpages-summary": "בדף זה רשומים הדפים הקיימים שמוגנים כרגע. לרשימת הכותרות שמוגנות מפני יצירה, ראו [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].", + "protectedpages-summary": "בדף זה רשומים הדפים הקיימים שמוגנים כרגע. רשימת הכותרות שמוגנות מפני יצירה מופיעה בדף [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].", "protectedpages-cascade": "הגנות מדורגות בלבד", "protectedpages-noredirect": "הסתרת הפניות", "protectedpagesempty": "אין כרגע דפים מוגנים עם הפרמטרים הללו.", @@ -1947,7 +1947,7 @@ "protectedpages-unknown-timestamp": "לא ידוע", "protectedpages-unknown-performer": "משתמש לא ידוע", "protectedtitles": "כותרות מוגנות", - "protectedtitles-summary": "בדף זה רשומות הכותרות של הדפים שמוגנים כעת מפני יצירה. לרשימת הדפים הקיימים שמוגנים, {{GENDER:|ראה|ראי|ראו}} [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].", + "protectedtitles-summary": "בדף זה רשומות הכותרות של הדפים שמוגנים כעת מפני יצירה. רשימת הדפים הקיימים שמוגנים מופיעה בדף [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].", "protectedtitlesempty": "אין כרגע כותרות מוגנות עם הפרמטרים האלה.", "protectedtitles-submit": "הצגת הדפים", "listusers": "רשימת משתמשים", @@ -1962,7 +1962,7 @@ "ancientpages": "דפים מוזנחים", "move": "העברה", "movethispage": "העברת דף זה", - "unusedimagestext": "הקבצים הבאים קיימים אך אינם מוטבעים בשום דף.\nשימו לב שאתרי אינטרנט אחרים עשויים לקשר לקובץ באמצעות כתובת URL ישירה, ולכן הוא עלול להופיע כאן למרות היותו בשימוש פעיל.", + "unusedimagestext": "הקבצים הבאים קיימים, אך אינם מוטבעים בשום דף.\nיש לשים לב לכך שאתרי אינטרנט אחרים עשויים לקשר לקובץ באמצעות כתובת URL ישירה, ולכן הוא עלול להופיע כאן למרות היותו בשימוש פעיל.", "unusedcategoriestext": "הקטגוריות הבאות קיימות, אבל לא נעשה שימוש בהן בשום דף או קטגוריה.", "notargettitle": "אין דף מטרה", "notargettext": "לא ציינת דף מטרה או משתמש לגביו תבוצע פעולה זו.", @@ -1970,14 +1970,14 @@ "nopagetext": "דף המטרה שציינת אינו קיים.", "pager-newer-n": "{{PLURAL:$1|הבאה|$1 הבאות}}", "pager-older-n": "{{PLURAL:$1|הקודמת|$1 הקודמות}}", - "suppress": "הסתרה", + "suppress": "העלמה", "querypage-disabled": "דף מיוחד זה מבוטל עקב בעיות ביצועים.", "apihelp": "עזרה עבור ה־API", "apihelp-no-such-module": "המודול \"$1\" לא נמצא.", "apisandbox": "ארגז החול של ה־API", "apisandbox-jsonly": "דרוש JavaScript כדי להשתמש בארגז החול של ה־API.", "apisandbox-api-disabled": "API אינו פעיל באתר הזה.", - "apisandbox-intro": "השתמשו בדף הזה כדי להתנסות בשימוש בשירות ה־API המבוסס Web של מדיה־ויקי.\nעיינו ב[[mw:API:Main page|תיעוד של ה־API]] (באנגלית) למידע נוסף של שימוש ב־API. למשל: [https://www.mediawiki.org/wiki/API#A_simple_example איך לקבל את התוכן של העמוד הראשי]. בחרו באחת הפעולות (actions) לדוגמאות נוספות.\n\nשימו לב שאף שמדובר ב\"ארגז חול\", פעולות שנעשות כאן עשויות לשנות את התוכן של אתר הוויקי.", + "apisandbox-intro": "ניתן להשתמש בדף הזה כדי להתנסות בשימוש בשירות ה־API המבוסס Web של מדיה־ויקי.\nאפשר לעיין ב[[mw:API:Main page|תיעוד של ה־API]] (באנגלית) למידע נוסף על שימוש ב־API. למשל: [https://www.mediawiki.org/wiki/API#A_simple_example איך לקבל את התוכן של העמוד הראשי]. יש לבחור באחת הפעולות (actions) לדוגמאות נוספות.\n\nלתשומת לבך: אף על פי שמדובר ב\"ארגז חול\", פעולות שנעשות כאן עשויות לשנות את התוכן של אתר הוויקי.", "apisandbox-submit": "ביצוע הבקשה", "apisandbox-reset": "ניקוי", "apisandbox-retry": "ניסיון נוסף", @@ -1994,7 +1994,7 @@ "apisandbox-fetch-token": "מילוי אוטומטי של האסימון", "apisandbox-add-multi": "הוספה", "apisandbox-submit-invalid-fields-title": "חלק מהשדות אינם תקינים", - "apisandbox-submit-invalid-fields-message": "אנא תקנו את השדות המסומנים ונסו שוב.", + "apisandbox-submit-invalid-fields-message": "נא לתקן את השדות המסומנים ולנסות שוב.", "apisandbox-results": "תוצאות", "apisandbox-sending-request": "בקשת ה־API בשליחה...", "apisandbox-loading-results": "תוצאות ה־API בתהליך קבלה...", @@ -2005,7 +2005,7 @@ "apisandbox-request-url-label": "כתובת ה־URL של הבקשה:", "apisandbox-request-json-label": "ייצוג הבקשה כ־JSON:", "apisandbox-request-time": "זמן הבקשה: {{PLURAL:$1|מילישנייה אחת|$1 מילישניות}}", - "apisandbox-results-fixtoken": "אנא תקנו את האסימון ושלחו שוב", + "apisandbox-results-fixtoken": "יש לתקן את האסימון ולשלוח שוב", "apisandbox-results-fixtoken-fail": "קבלת האסימון \"$1\" נכשלה.", "apisandbox-alert-page": "שדות בדף זה אינם תקינים.", "apisandbox-alert-field": "הערך של שדה זה אינו תקין.", @@ -2019,8 +2019,8 @@ "booksources-search-legend": "חיפוש משאבי ספרות חיצוניים", "booksources-isbn": "מסת\"ב (ISBN):", "booksources-search": "חיפוש", - "booksources-text": "להלן רשימת קישורים לאתרים אחרים המוכרים ספרים חדשים ויד־שנייה, ושבהם עשוי להיות מידע נוסף לגבי ספרים שאתם מחפשים:", - "booksources-invalid-isbn": "המסת\"ב שניתן כנראה אינו תקין; אנא בדקו אם ביצעתם טעויות בהעתקה מהמידע המקורי.", + "booksources-text": "להלן רשימת קישורים לאתרים אחרים המוכרים ספרים חדשים ויד־שנייה, ושבהם עשוי להיות מידע נוסף לגבי ספרים שמעניינים אותך:", + "booksources-invalid-isbn": "המסת\"ב שניתן כנראה אינו תקין; יש לבדוק אם נעשו טעויות בהעתקה מהמידע המקורי.", "magiclink-tracking-rfc": "דפים שמשתמשים בקישורי קסם ל־RFC", "magiclink-tracking-rfc-desc": "דף זה משתמש בקישורי קסם ל־RFC. באתר [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] מוסבר כיצד יש לשנותם.", "magiclink-tracking-pmid": "דפים שמשתמשים בקישורי קסם ל־PMID", diff --git a/languages/i18n/hu.json b/languages/i18n/hu.json index f82859f398..53241d4d39 100644 --- a/languages/i18n/hu.json +++ b/languages/i18n/hu.json @@ -728,7 +728,7 @@ "longpageerror": "'''HIBA: Az általad beküldött szöveg {{PLURAL:$1|egy kilobájt|$1 kilobájt}} hosszú, ami több az engedélyezett {{PLURAL:$2|egy kilobájtnál|$2 kilobájtnál}}.\nA szerkesztést nem lehet elmenteni.'''", "readonlywarning": "FIGYELMEZTETÉS: A wiki adatbázisát karbantartás miatt zárolták, ezért most nem fogod tudni elmenteni a szerkesztéseidet!\nA lap szövegét másold egy szövegfájlba, amit később felhasználhatsz!\n\nAz adatbázist lezáró rendszeradminisztrátor az alábbi magyarázatot adta: $1", "protectedpagewarning": "Figyelem: Ez a lap védett, így csak adminisztrátori jogosultságokkal rendelkező szerkesztők módosíthatják.\nA legutolsó ide vonatkozó naplóbejegyzés alább látható:", - "semiprotectedpagewarning": "'''Megjegyzés:''' ez a lap védett, így regisztrálatlan vagy újonnan regisztrált szerkesztők nem módosíthatják.", + "semiprotectedpagewarning": "Megjegyzés: ez a lap védett, így regisztrálatlan vagy újonnan regisztrált szerkesztők nem módosíthatják.\nA lapra vonatkozó utolsó naplóbejegyzés alább látható:", "cascadeprotectedwarning": "Figyelem: ez a lap le van zárva, csak [[Special:ListGroupRights|megfelelő jogosultságú]] felhasználók szerkeszthetik, mert a következő kaszkádvédelemmel ellátott {{PLURAL:$1|lapon|lapokon}} be van illesztve:", "titleprotectedwarning": "'''Figyelem: Ez a lap le van védve, így csak a [[Special:ListGroupRights|megfelelő jogosultságokkal]] rendelkező szerkesztők hozhatják létre.'''\nA legutolsó ide vonatkozó naplóbejegyzés alább látható:", "templatesused": "A lapon használt {{PLURAL:$1|sablon|sablonok}}:", diff --git a/languages/i18n/ia.json b/languages/i18n/ia.json index 3efb8cac29..3bd7b9e90e 100644 --- a/languages/i18n/ia.json +++ b/languages/i18n/ia.json @@ -54,7 +54,7 @@ "tog-watchlisthideminor": "Celar modificationes minor in le observatorio", "tog-watchlisthideliu": "Celar modificationes de usatores registrate in le observatorio", "tog-watchlistreloadautomatically": "Recargar automaticamente le observatorio quando un filtro es cambiate (JavaScript requirite)", - "tog-watchlistunwatchlinks": "Adjunger ligamines directe pro disobservar/observar al entratas del observatorio (JavaScript es necessari pro le functionalitate de alternar)", + "tog-watchlistunwatchlinks": "Adjunger marcatores directe pro disobservar/observar ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) al paginas sub observation que ha cambiate (JavaScript es necessari pro le functionalitate de alternar)", "tog-watchlisthideanons": "Celar modificationes de usatores anonyme in le observatorio", "tog-watchlisthidepatrolled": "Celar le modificationes patruliate in le observatorio", "tog-watchlisthidecategorization": "Celar le categorisation de paginas", @@ -362,8 +362,10 @@ "cascadeprotected": "Iste pagina ha essite protegite contra modificationes perque illo es transcludite in le sequente {{PLURAL:$1|pagina, le qual|paginas, le quales}} es protegite usante le option \"cascada\":\n$2", "namespaceprotected": "Tu non ha le permission de modificar paginas in le spatio de nomines '''$1'''.", "customcssprotected": "Tu non ha le permission de modificar iste pagina de CSS perque illo contine le configuration personal de un altere usator.", + "customjsonprotected": "Tu non ha le permission de modificar iste pagina JSON perque illo contine le configuration personal de un altere usator.", "customjsprotected": "Tu non ha le permission de modificar iste pagina de JavaScript perque illo contine le configuration personal de un altere usator.", "mycustomcssprotected": "Tu non ha le permission de modificar iste pagina de CSS.", + "mycustomjsonprotected": "Tu non ha le permission de modificar iste pagina JSON.", "mycustomjsprotected": "Tu non ha le permission de modificar iste pagina de JavaScript.", "myprivateinfoprotected": "Tu non ha le permission de modificar le proprie information private.", "mypreferencesprotected": "Tu non ha le permission de modificar le proprie preferentias.", @@ -458,12 +460,12 @@ "wrongpasswordempty": "Tu non entrava un contrasigno. Per favor reprova.", "passwordtooshort": "Le contrasignos debe continer al minus {{PLURAL:$1|1 character|$1 characteres}}.", "passwordtoolong": "Le contrasignos non pote esser plus longe de {{PLURAL:$1|1 character|$1 characteres}}.", - "passwordtoopopular": "Contrasignos habitual non pote esser usate. Per favor, elige un contrasigno plus unic.", + "passwordtoopopular": "Contrasignos habitual non pote esser usate. Per favor, elige un contrasigno plus difficile a divinar.", "password-name-match": "Tu contrasigno debe esser differente de tu nomine de usator.", "password-login-forbidden": "Le uso de iste nomine de usator e contrasigno ha essite prohibite.", "mailmypassword": "Reinitialisar contrasigno", "passwordremindertitle": "Nove contrasigno temporari pro {{SITENAME}}", - "passwordremindertext": "Alcuno (probabilemente tu, ab le adresse IP $1) requestava un nove\ncontrasigno pro {{SITENAME}} ($4).\nUn contrasigno temporari pro le usator \"$2\" ha essite create; iste\ncontrasigno es \"$3\". Si isto esseva le intention, tu debe ora\naperir un session e eliger un nove contrasigno. Le contrasigno temporari\nexpirara post {{PLURAL:$5|un die|$5 dies}}.\n\nSi un altere persona ha facite iste requesta, o si tu te ha rememorate\nle contrasigno e non plus vole cambiar lo, tu pote ignorar iste message\ne continuar a usar le contrasigno original.", + "passwordremindertext": "Alcuno (ab le adresse IP $1) requestava un nove\ncontrasigno pro {{SITENAME}} ($4).\nUn contrasigno temporari pro le usator \"$2\" ha essite create; iste\ncontrasigno es \"$3\". Si isto esseva le intention, tu debe ora\naperir un session e eliger un nove contrasigno. Le contrasigno temporari\nexpirara post {{PLURAL:$5|un die|$5 dies}}.\n\nSi un altere persona ha facite iste requesta, o si tu te ha rememorate\nle contrasigno e non plus vole cambiar lo, tu pote ignorar iste message\ne continuar a usar le contrasigno original.", "noemail": "Il non ha un adresse de e-mail registrate pro le usator \"$1\".", "noemailcreate": "Es necessari fornir un adresse de e-mail valide", "passwordsent": "Un nove contrasigno ha essite inviate al adresse de e-mail registrate pro \"$1\".\nPer favor aperi session de novo post reciper lo.", @@ -514,6 +516,7 @@ "botpasswords-existing": "Contrasignos de robot existente", "botpasswords-createnew": "Crear un nove contrasigno de robot", "botpasswords-editexisting": "Modificar un contrasigno de robot existente", + "botpasswords-label-needsreset": "(contrasigno debe esser reinitialisate)", "botpasswords-label-appid": "Nomine del robot:", "botpasswords-label-create": "Crear", "botpasswords-label-update": "Actualisar", @@ -537,6 +540,7 @@ "botpasswords-restriction-failed": "Session impedite per restrictiones de contrasigno de robot.", "botpasswords-invalid-name": "Iste nomine de usator non contine le separator pro contrasigno de robot (\"$1\").", "botpasswords-not-exist": "Le usator \"$1\" non ha un contrasigno de robot del nomine \"$2\".", + "botpasswords-needs-reset": "Le contrasigno pro le robot \"$2\" del {{GENDER:$1|usator}} \"$1\" debe esser reinitialisate.", "resetpass_forbidden": "Le contrasignos non pote esser cambiate", "resetpass_forbidden-reason": "Le contrasignos non pote esser cambiate: $1", "resetpass-no-info": "Tu debe aperir un session pro poter acceder directemente a iste pagina.", @@ -614,6 +618,10 @@ "savechanges": "Salveguardar modificationes", "publishpage": "Publicar pagina", "publishchanges": "Publicar modificationes", + "savearticle-start": "Salveguardar pagina…", + "savechanges-start": "Salveguardar modificationes…", + "publishpage-start": "Publicar pagina…", + "publishchanges-start": "Publicar modificationes…", "preview": "Previsualisation", "showpreview": "Monstrar previsualisation", "showdiff": "Detaliar modificationes", diff --git a/languages/i18n/ig.json b/languages/i18n/ig.json index d652bd1d6b..2a1d6320c2 100644 --- a/languages/i18n/ig.json +++ b/languages/i18n/ig.json @@ -153,7 +153,7 @@ "history": "Ịta ihüá", "history_short": "Ịta", "updatedmarker": "ihe gáráníru ké mgbe m byàrà nga mbu", - "printableversion": "Ùdì ǹke mbifụ̀", + "printableversion": "Ùdì ǹke mbipụ̀", "permalink": "Jikodo ekechịrị", "print": "Dotié", "view": "Lèzí", @@ -300,8 +300,10 @@ "logout": "Fwuör", "userlogout": "Fwuör", "notloggedin": "I bátà bò", + "userlogin-joinproject": "Bàkọ {{SITENAME}}", "createaccount": "Ké otụ buwa", "createaccountmail": "na e-mail", + "createacct-benefit-heading": "{{SITENAME}} sì nà aka ndị dị kà gị.", "createacct-benefit-body1": "{{PLURAL:$1|ḿmezi}}", "badretype": "Mkpurụ okwu ejị a gafẹ é jëghị.", "userexists": "Áhè ọ'bànifé tírí di na áká onye ozor.\nBíkó nwèré áhà nke ozor.", @@ -1055,6 +1057,7 @@ "pageinfo-header-edits": "Mèzí ịta", "pageinfo-length": "Ogologo ihü (na baitusu)", "pageinfo-article-id": "ID Ihü", + "pageinfo-toolboxlink": "Nkàta ihu", "pageinfo-redirectsto-info": "ọ́márí", "pageinfo-contentpage-yes": "Eeh", "pageinfo-protect-cascading-yes": "Eeh", @@ -1242,7 +1245,7 @@ "special-characters-group-latin": "Latin", "special-characters-group-latinextended": "Latin dọsàrà", "special-characters-group-ipa": "IPA", - "special-characters-group-symbols": "Nkárí", + "special-characters-group-symbols": "Akàrà", "special-characters-group-greek": "Greek", "special-characters-group-cyrillic": "Cyrillic", "special-characters-group-arabic": "Arabiki", diff --git a/languages/i18n/inh.json b/languages/i18n/inh.json index 80cf726cb6..110c031362 100644 --- a/languages/i18n/inh.json +++ b/languages/i18n/inh.json @@ -396,11 +396,11 @@ "userpage-userdoesnotexist-view": "«$1» яха дагара йоазув долаш дац.", "clearyourcache": "Теркал де. Хетаргахьа, оагIув дIаязъяь яьлча шоай браузера кэш IоцIанъе езаргья шун, даь хувцамаш гургдолаш.\n* Firefox / Safari: Shift яха лак тоIояь лоаттаеш инструментий цхьа дакъа тIа тоIае Обновить е Ctrl-F5 тоIае е Ctrl-R (⌘-R Mac тIа)\n* Google Chrome: ТоIае Ctrl-Shift-R (⌘-Shift-R Mac тIа)\n* Internet Explorer: Ctrl яха лак тоIояь лоаттаеш, тоIае Обновить е Ctrl-F5 тоIае\n* Opera: ДехьагIо Menu → Настройки (Opera → Настройки Mac тIа), тIаккха Безопасность → Очистить историю посещений → Кэшированные изображения и файлы", "note": "'''Белгалдоахар:'''", - "previewnote": "'''Теркам бе, ер хьалххе бIаргтохар мара бац.'''\nХьа хувцамаш хIанза а дIаяздаь дац!", - "continue-editing": "Хувцар кхы дIахо де", + "previewnote": "'''Теркам бе! Ер хьалххе бIаргтохар мара бац.'''\nХьа хувцамаш хIанзехьа кхы а дIаяздаь дац!", + "continue-editing": "Хувцам бергболаш дIахо дехьавáла", "editing": "Хувцам: $1", - "creating": "«$1» оагIув хьакхоллар", - "editingsection": "Хувцам: $1 (оагӀон дáкъа)", + "creating": "«$1» яха оагIув хьакхоллар", + "editingsection": "Хувцар: $1 (оагӀон дáкъа)", "editingcomment": "Хувцам: $1 (оагӀон керда дáкъа)", "editconflict": "Хувцама вIашдухьалъоттам: $1", "yourtext": "Хьа текст", diff --git a/languages/i18n/io.json b/languages/i18n/io.json index 8032223eea..e8626942cc 100644 --- a/languages/i18n/io.json +++ b/languages/i18n/io.json @@ -696,6 +696,7 @@ "rev-deleted-user-contribs": "[Uzero od IP-adreso eliminita - la redakto celesis de la kontributaji]", "rev-delundel": "montrar/celar", "rev-showdeleted": "montrar", + "revisiondelete": "Efacar/Restaurar revizi", "revdelete-show-file-submit": "Yes", "revdelete-hide-image": "Celar kontenajo dil arkivo", "revdelete-hide-comment": "Rezumo di redakto", @@ -873,6 +874,7 @@ "right-upload": "Adkargar arkivi", "right-writeapi": "Uzez API por skribar", "right-delete": "Efacar pagini", + "right-deleterevision": "Efacar e restaurar specifika revizi de la pagini", "right-browsearchive": "Serchar pagini efacita", "right-suppressrevision": "Vidar, celar e deskovrar specifika revizi di pagini de irga uzero", "right-blockemail": "Blokusar uzero pri sendar e-posto", @@ -1276,13 +1278,20 @@ "restriction-upload": "Adkargar", "undelete": "Vidar efacita pagini", "undeletepage": "Vidar e restaurar efacita pagini", + "undeletepagetitle": "Yen la efacita versioni di la pagino [[:$1|$1]].", + "viewdeletedpage": "Vidar pagini efacita", "undeletepagetext": "La sequanta {{PLURAL:$1|pagino|pagini}} efacesis ma {{PLURAL:$1|ol|li}} ankore esas en la arkivo ed esas restaurebla. La arkivo povas netigesar periodale.", + "undelete-fieldset-title": "Restaurar revizi", + "undeleteextrahelp": "Por restaurar omna historio de la pagino, desselektez omna buxi e kliktez {{int:undeletebtn}}.\nPor selektar quala modifiki restauresos, markizez la buxi korespondanta a la revizi por restaurar, e kliktez {{int:undeletebtn}}.", "undeleterevisions": "$1 {{PLURAL:$1|revizo|revizi}} efacita", "undeletehistory": "Se vu restauros la pagino, omna antea revizi restauresos en la korespondanta historiala pagino.\nSe nova pagino kun la sama titulo kreesis pos l'efaco, la restaurita revizuri aparos en lua historiala pagino.", + "undeleterevdel": "La restauro ne facesos se to produktos partala o totala efaco de la maxim recenta revizo.\nCa kazi, vu mustas desselektar o trovar la maxim recenta versiono efacita.", + "undeletehistorynoadmin": "Ica pagino efacesis.\nLa motivo por l'efaco montresas en la rezumo adinfre, kune la detaligo dil uzeri qui redaktis la pagino ante lua efaco.\nLa kompleta texto di ca revizi efacita esas videbla nur por l'administreri.", "undeleterevision-missing": "Nevalida o mankanta revizo.\nSive vu skribis la ligilo nekorekte, sive la revizo restauresis o removesis del arkivo.", "undeletebtn": "Restaurar", "undeletelink": "vidar/restaurar", "undeleteviewlink": "videz", + "undeleteinvert": "Inversigar selektajo", "undeletecomment": "Motivo:", "undeletedpage": "$1 restauresis\n\nVidez la [[Special:Log/delete|'log' pri efaci]] por vidar omna recenta efaci e restauri.", "undelete-search-box": "Serchez efacita pagini", @@ -1678,6 +1687,7 @@ "tags-hitcount": "$1 {{PLURAL:$1|chanjo|chanji}}", "tags-create-explanation": "Segun predefino, la nova etiketi kreita divenos disponebla por uzado, sive da uzeri, sive da informatikoprogrami 'bot'.", "tags-create-warnings-above": "La sequanta {{PLURAL:$2|avizo|avizi}} renkontresis, probante kreir l'etiketo \"$1\":", + "tags-delete-not-found": "L'etiketo \"$1\" ne existas.", "tags-delete-too-many-uses": "L'etiketo \"$1\" uzesas en plua kam $2 {{PLURAL:$2|revizo|revizi}}, do ol ne povas eskartesar.", "tags-delete-warnings-after-delete": "L'etiketo \"$1\" efacesis, ma la sequanta {{PLURAL:$2|avizo|avizi}} renkontresis:", "tags-activate-not-found": "L'etiketo \"$1\" ne existas.", @@ -1701,6 +1711,7 @@ "logentry-protect-modify-cascade": "$1 {{GENDER:$2|modifikis}} la nivelo di protekto di $3 $4 [kaskade]", "logentry-upload-upload": "$1 {{GENDER:$2|uploaded}} $3", "logentry-upload-overwrite": "$1 {{GENDER:$2|parsendis}} nova versiono di $3", + "log-name-tag": "Protokolo di etiketi", "rightsnone": "(nula)", "searchsuggest-search": "Serchez en {{SITENAME}}", "searchsuggest-containing": "quan kontenas...", diff --git a/languages/i18n/ja.json b/languages/i18n/ja.json index 3e5182e527..321c4eb692 100644 --- a/languages/i18n/ja.json +++ b/languages/i18n/ja.json @@ -1473,6 +1473,9 @@ "rcfilters-filter-reviewstatus-unpatrolled-description": "手動または自動で巡回されていない編集。", "rcfilters-filter-reviewstatus-unpatrolled-label": "未巡回", "rcfilters-filter-reviewstatus-manual-description": "巡回済みと手動でマークされた編集。", + "rcfilters-filter-reviewstatus-manual-label": "手動巡回", + "rcfilters-filter-reviewstatus-auto-description": "巡回済みと自動でマークされた編集。", + "rcfilters-filter-reviewstatus-auto-label": "自動巡回", "rcfilters-filtergroup-significance": "重要度", "rcfilters-filter-minor-label": "細部の編集", "rcfilters-filter-minor-description": "編集者が細部の編集とマークしたもの。", diff --git a/languages/i18n/jv.json b/languages/i18n/jv.json index 0d85f3bfa0..f4aa034f79 100644 --- a/languages/i18n/jv.json +++ b/languages/i18n/jv.json @@ -17,7 +17,8 @@ "아라", "Macofe", "Matma Rex", - "Fitoschido" + "Fitoschido", + "Notanotheramy" ] }, "tog-underline": "Garis ngisori pranala:", @@ -575,6 +576,7 @@ "savechanges": "Simpen owahan", "publishpage": "Babar kaca", "publishchanges": "Babar owahan", + "publishchanges-start": "Babar owahan...", "preview": "Pratuduh", "showpreview": "Deleng pratuduh", "showdiff": "Tuduhaké owahan", diff --git a/languages/i18n/lb.json b/languages/i18n/lb.json index 8bea39a651..d3bc002f50 100644 --- a/languages/i18n/lb.json +++ b/languages/i18n/lb.json @@ -510,6 +510,7 @@ "botpasswords-existing": "Aktuell Botpasswierder.", "botpasswords-createnew": "En neit Botpasswuert uleeën", "botpasswords-editexisting": "E Botpasswuert änneren", + "botpasswords-label-needsreset": "(Passwuert muss zréckgesat ginn)", "botpasswords-label-appid": "Numm vum Bot:", "botpasswords-label-create": "Uleeën", "botpasswords-label-update": "Aktualiséieren", @@ -1420,7 +1421,7 @@ "recentchangeslinked-feed": "Ännerungen op verlinkt Säiten", "recentchangeslinked-toolbox": "Ännerungen op verlinkt Säiten", "recentchangeslinked-title": "Ännerungen a Verbindung mat \"$1\"", - "recentchangeslinked-summary": "Gitt den Numm vun enger Säit a fir Ännerungen Säiten ze gesinn op déi oder vun deene gelinkt gëtt. Ännerungen op Säite vun [[Special:Watchlist|Ärer Iwwerwaachungslëscht]] si fett geschriwwen.", + "recentchangeslinked-summary": "Gitt den Numm vun enger Säit a fir Ännerungen op Säiten ze gesinn op déi oder vun deene gelinkt gëtt. (Fir d'Membere vun enger Kategorie ze gesinn gitt {{ns:category}}:Numm vun der Kategorie, an.) Ännerungen op Säite vun [[Special:Watchlist|Ärer Iwwerwaachungslëscht]] si fett geschriwwen.", "recentchangeslinked-page": "Säitennumm:", "recentchangeslinked-to": "Weis Ännerungen zu de verlinkte Säiten aplaz vun der gefroter Säit", "recentchanges-page-added-to-category": "[[:$1]] an d'Kategorie dobäigesat", diff --git a/languages/i18n/lfn.json b/languages/i18n/lfn.json index bad0415525..4f61fd5532 100644 --- a/languages/i18n/lfn.json +++ b/languages/i18n/lfn.json @@ -10,7 +10,8 @@ "Katxis", "Chabi", "Angel Blaise", - "Fitoschido" + "Fitoschido", + "Robin van der Vliet" ] }, "tog-underline": "Sulini de lias:", @@ -232,7 +233,7 @@ "disclaimerpage": "Project:Renunsia jeneral", "edithelp": "Aida sur edita", "helppage-top-gethelp": "Aida", - "mainpage": "Paje Xef", + "mainpage": "Paje xef", "mainpage-description": "Paje xef", "policy-url": "Project:Politica", "portal": "Porton de comunia", @@ -618,7 +619,7 @@ "subject-preview": "Previde de tema:", "previewerrortext": "Un era ia aveni en atenta previde tua cambias.", "blockedtitle": "Usor es impedida", - "blockedtext": "Tua nom de usor o adirije IP es impedida.\n\nLa impedi ia es fada par $1.\nLa razona donada es ''$2''.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\n\nTu pote contata $1 o un otra [[{{MediaWiki:Grouppage-sysop}}|dirijor]] per discute esta impedi.\nTu no pote usa la funsiona \"envia un eposta a esta usor\" estra si un adirije valida\nde eposta es spesifada en tua [[Special:Preferences|preferes de conta]] e tu no es impedida de usa lo.\nTua adirije IP presente es $3, e la numero de impedi es #$5.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", + "blockedtext": "Tua nom de usor o adirije IP es impedida.\n\nLa impedi ia es fada par $1.\nLa razona donada es $2.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\n\nTu pote contata $1 o un otra [[{{MediaWiki:Grouppage-sysop}}|dirijor]] per discute esta impedi.\nTu no pote usa la funsiona \"{{int:emailuser}}\" estra si un adirije valida\nde eposta es spesifada en tua [[Special:Preferences|preferes de conta]] e tu no es impedida de usa lo.\nTua adirije IP presente es $3, e la numero de impedi es #$5.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", "autoblockedtext": "Tua adirije IP ia es automata impedida car lo ia es usada par un otra usor, ci ia es impedida par $1.\nLa razona donada es ''$2''.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\n\nTu pote contata $1 o un otra [[{{MediaWiki:Grouppage-sysop}}|dirijor]] per discute esta impedi.\nTu no pote usa la funsiona \"envia un eposta a esta usor\" estra si un adirije valida de eposta es spesifada en tua [[Special:Preferences|preferes de conta]] e tu no es impedida de usa lo.\nTua adirije IP presente es $3, e la numero de impedi es #$5.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", "systemblockedtext": "Tua nom de usor o adirije IP ia es automata impedida par MediaWiki.\nLa razona donada es $2.\n\n* Comensa de impedi: $8\n* Fini de impedi: $6\n* Conta impedida: $7\nTua adirije IP presente es $3.\nInclui tota esta detalias en cualce demandas cual tu fa, per favore.", "blockednoreason": "no razona donada", @@ -1451,7 +1452,7 @@ "recentchangeslinked-feed": "Cambias relatada", "recentchangeslinked-toolbox": "Cambias relatada", "recentchangeslinked-title": "Cambias relatada a \"$1\"", - "recentchangeslinked-summary": "Tape un nom de paje per vide cambias en pajes liada a o de acel paje. (Per vide membros de un categoria, tape bold.) Cambias a pajes en [[Special:Watchlist|tua lista monitorida]] es spesa.", + "recentchangeslinked-summary": "Tape un nom de paje per vide cambias en pajes liada a o de acel paje. (Per vide membros de un categoria, tape {{ns:category}}:Nom de categoria.) Cambias a pajes en [[Special:Watchlist|tua lista monitorida]] es spesa.", "recentchangeslinked-page": "Nom de paje:", "recentchangeslinked-to": "Mostra cambias a pajes cual lia a la paje indicada, en loca", "recentchanges-page-added-to-category": "[[:$1]] ajuntada a categoria", @@ -1931,6 +1932,7 @@ "apisandbox-dynamic-error-exists": "Un parametre nomida \"$1\" esiste ja.", "apisandbox-deprecated-parameters": "Parametres desaprobada", "apisandbox-fetch-token": "Autopleni la marca", + "apisandbox-add-multi": "Ajunta", "apisandbox-submit-invalid-fields-title": "Alga campos es nonvalida", "apisandbox-submit-invalid-fields-message": "Coreti la campos indicada, per favore, e reatenta.", "apisandbox-results": "Resultas", @@ -3705,6 +3707,7 @@ "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|bait|baites}}", "limitreport-expansiondepth": "Profondia la plu grande de despaci", "limitreport-expensivefunctioncount": "Cuantia de funsionas custosa de analisador sintatical", + "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|bait|baites}}", "expandtemplates": "Despaci stensiles", "expand_templates_intro": "Esta paje spesial prende vicitesto e despaci tota stensiles en lo, en modo recorsante. Lo despaci ance funsionas suportada de analisador sintatical como {{#language:…}} e variables como {{CURRENTDAY}}. En fato, lo despaci cuasi tota cosas entre brasetas risa duple.", "expand_templates_title": "Titulo de contesto, per {{FULLPAGENAME}}, etc.:", diff --git a/languages/i18n/mk.json b/languages/i18n/mk.json index 7783806a38..605bac6c8d 100644 --- a/languages/i18n/mk.json +++ b/languages/i18n/mk.json @@ -646,8 +646,8 @@ "subject-preview": "Преглед на насловот:", "previewerrortext": "Се појави грешка при обидот да се прегледаат промените.", "blockedtitle": "Корисникот е блокиран", - "blockedtext": "'''Вашето корисничко име или IP-адреса е блокирано.'''\n\nБлокирањето е направено од страна на $1.\nДаденото образложение е ''$2''.\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Корисникот што требало да биде блокиран: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со блокирањето.\nМожете да ја искористите можноста „Е-пошта до овој корисник“ ако е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и не ви е забрането да ја користите.\nВашата сегашна IP-адреса е $3, а назнака на блокирањето гласи #$5.\nВе молиме наведете ги сите подробности прикажани погоре, во вашата евентуална реакција.", - "autoblockedtext": "Вашата IP-адреса е автоматски блокирана бидејќи била користена од страна на друг корисник, кој бил блокиран од $1.\nДаденото образложение е следново:\n\n:''$2''\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Со намера да се блокира: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со ова блокирање.\n\nИмајте предвид дека можеби нема да можете да ја искористите можноста „Е-пошта до овој корисник“ доколку не е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и ви е забрането користитење на истата.\n\nВашата IP-адреса е $3, a ID на блокирањеto е $5.\nВе молиме наведете ги овие подробности доколку реагирате на блокирањето.", + "blockedtext": "Вашето корисничко име или IP-адреса е блокирано.\n\nБлокирањето е направено од страна на $1.\nДаденото образложение е ''$2''.\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Корисникот што требало да биде блокиран: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со блокирањето.\nМожете да ја искористите можноста „{{int:emailuser}}“ ако е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и не ви е забрането да ја користите.\nВашата сегашна IP-адреса е $3, а назнака на блокирањето гласи #$5.\nВе молиме наведете ги сите подробности прикажани погоре, во вашата евентуална реакција.", + "autoblockedtext": "Вашата IP-адреса е автоматски блокирана бидејќи била користена од страна на друг корисник, кој бил блокиран од $1.\nДаденото образложение е следново:\n\n:$2\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Со намера да се блокира: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со ова блокирање.\n\nИмајте предвид дека можеби нема да можете да ја искористите можноста „{{int:emailuser}}“ доколку не е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и ви е забрането користитење на истата.\n\nВашата IP-адреса е $3, a ID на блокирањеto е $5.\nВе молиме наведете ги овие подробности доколку реагирате на блокирањето.", "systemblockedtext": "Вашето корисничко име или IP-адреса е автоматски блокирано од МедијаВики.\nПонудена причина:\n\n:$2\n\n* Почеток на блокот: $8\n* Истек на блокот: $6\n* Блокот е наменет за: $7\n\nВашата тековна IP-адреса гласи $3.\nПрепишете ги сите горенаведени поединости доколку сакате да се распрашате кај надлежните во врска со блокот.", "blockednoreason": "не е наведена причина", "whitelistedittext": "Мора да сте $1 за да уредувате страници.", @@ -3995,9 +3995,9 @@ "special-characters-group-hebrew": "Хебрејски", "special-characters-group-bangla": "Бенгалски", "special-characters-group-tamil": "тамилски", - "special-characters-group-telugu": "Телугу", + "special-characters-group-telugu": "Телушки", "special-characters-group-sinhala": "Синхалски", - "special-characters-group-gujarati": "Гуџарати", + "special-characters-group-gujarati": "Гуџаратски", "special-characters-group-devanagari": "деванагари", "special-characters-group-thai": "Тајландски", "special-characters-group-lao": "Лаошки", diff --git a/languages/i18n/nl.json b/languages/i18n/nl.json index 656ef4f9a6..a412a596af 100644 --- a/languages/i18n/nl.json +++ b/languages/i18n/nl.json @@ -117,7 +117,7 @@ "tog-enotifminoredits": "Mij e-mailen bij kleine bewerkingen van pagina’s en bestanden op mijn volglijst", "tog-enotifrevealaddr": "Mijn e-mailadres weergeven in e-mailberichten", "tog-shownumberswatching": "Het aantal gebruikers weergeven dat deze pagina volgt", - "tog-oldsig": "Uw bestaande ondertekening:", + "tog-oldsig": "Uw bestaande handtekening:", "tog-fancysig": "Handtekening als wikitekst behandelen (zonder automatische koppeling)", "tog-uselivepreview": "Voorvertoning weergeven zonder de pagina opnieuw te laden", "tog-forceeditsummary": "Een melding geven bij een lege bewerkingssamenvatting", @@ -706,8 +706,8 @@ "subject-preview": "Voorvertoning van het onderwerp:", "previewerrortext": "Er is een fout opgetreden tijdens het weergeven van uw wijzigingen.", "blockedtitle": "Gebruiker is geblokkeerd", - "blockedtext": "'''Uw gebruikersaccount of IP-adres is geblokkeerd.'''\n\nDe blokkade is uitgevoerd door $1.\nDe opgegeven reden is ''$2''.\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\nU kunt geen gebruik maken van de functie \"Deze gebruiker e-mailen\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]] en het gebruik van deze functie niet geblokkeerd is.\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", - "autoblockedtext": "Uw IP-adres is automatisch geblokkeerd, omdat het gebruikt is door een andere gebruiker, die geblokkeerd is door $1.\nDe opgegeven reden is:\n\n:''$2''\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\n\nU kunt geen gebruik maken van de functie \"Deze gebruiker e-mailen\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]], en het gebruik van deze functie niet is geblokkeerd.\n\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", + "blockedtext": "'''Uw gebruikersaccount of IP-adres is geblokkeerd.'''\n\nDe blokkade is uitgevoerd door $1.\nDe opgegeven reden is ''$2''.\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\nU kunt geen gebruik maken van de functie \"{{int:emailuser}}\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]] en het gebruik van deze functie niet geblokkeerd is.\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", + "autoblockedtext": "Uw IP-adres is automatisch geblokkeerd, omdat het gebruikt is door een andere gebruiker, die geblokkeerd is door $1.\nDe opgegeven reden is:\n\n:''$2''\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\n\nU kunt geen gebruik maken van de functie \"{{ing:emailuser}}\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]], en het gebruik van deze functie niet is geblokkeerd.\n\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", "systemblockedtext": "Uw gebruikersaccount of IP-adres is automatisch geblokkeerd door MediaWiki.\nDe opgegeven reden is:\n\n:$2\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nUw huidige IP-adres is $3.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.", "blockednoreason": "geen reden opgegeven", "whitelistedittext": "U moet $1 om pagina's te bewerken.", diff --git a/languages/i18n/oc.json b/languages/i18n/oc.json index f11e4fd10d..d1dbadb970 100644 --- a/languages/i18n/oc.json +++ b/languages/i18n/oc.json @@ -738,6 +738,7 @@ "content-json-empty-object": "Objècte void", "content-json-empty-array": "Tablèu void", "duplicate-args-category": "Paginas utilizant d'arguments duplicats dins los apèls de modèl", + "duplicate-args-category-desc": "La pagina conten de cridas a patrons qu'emplagan d'arguments duplicats, coma {{foo|bar=1|bar=2}} or {{foo|bar|1=baz}}.", "expensive-parserfunction-warning": "Atencion : Aquesta pagina conten tròp d’apèls dispendioses de foncions del parser.\n\nI deurià aver mens de {{PLURAL:$2|ampèl|ampèls}}, e actualament {{PLURAL:$1|i a $1 ampèl|i a $1 ampèls}}..", "expensive-parserfunction-category": "Paginas amb tròp d’apèls dispendioses de foncions parsaires", "post-expand-template-inclusion-warning": "Atencion : Aquesta pagina conten tròp d'inclusions de modèls.\nD'unas inclusions seràn pas efectuadas.", @@ -745,6 +746,9 @@ "post-expand-template-argument-warning": "Atencion : Aquesta pagina conten al mens un paramètre de modèl que l'inclusion es renduda impossibla. Aprèp extension, aqueste auriá produit un resultat tròp long, doncas, es pas estat inclús.", "post-expand-template-argument-category": "Paginas que contenon al mens un paramètre de modèl pas evaluat", "parser-template-loop-warning": "Modèl en bocla detectat : [[$1]]", + "template-loop-category": "Paginas amb boclas de patron", + "template-loop-category-desc": "La pagina conten una bocla dins lo patron, es a dire, un patron que se sona el meteis recursivament.", + "template-loop-warning": "Attencion: Aquesta pagina sona [[:$1]. Aquò es l'encausa d'una bocla de patron (una sonada infinida resursiva).", "parser-template-recursion-depth-warning": "Limit de longor de la recursion del modèl depassat ($1)", "language-converter-depth-warning": "Limit de prigondor del convertissor de lenga depassada ($1)", "node-count-exceeded-category": "Paginas ont nombre de nosèls es depassat", @@ -982,6 +986,7 @@ "prefs-watchlist-edits": "Nombre maximal de modificacions d'afichar dins la lista de seguiment :", "prefs-watchlist-edits-max": "Nombre maximum : 1000", "prefs-watchlist-token": "Geton per la lista de seguiment :", + "prefs-watchlist-managetokens": "Administrar los getons", "prefs-misc": "Preferéncias divèrsas", "prefs-resetpass": "Modificar lo senhal", "prefs-changeemail": "Cambiar o suprimir l'adreça electronica", @@ -1000,6 +1005,7 @@ "recentchangescount": "Nombre de modificacions d'afichar per defauta dins los cambiaments recents, los istorics e los logs :", "prefs-help-recentchangescount": "Nombre maximum : 1000", "prefs-help-watchlist-token2": "Aquí la clau secreta del flux Web de vòstra lista de seguiment.\nTota persona que la coneis poirà legir vòstra lista de seguiment, doncas, la comuniquetz pas.\nSe necessari, [[Special:ResetTokens|clicatz aicí per la reïnicializar]].", + "prefs-help-tokenmanagement": "Podètz veire e tornar inicializar la clau secreta del vòstre compte que pòt accedir al flux Web de la vòstre lista de seguit. Tota persona que coneis la clau poirà legir la vòstra lista, alara la compartissètz pas", "savedprefs": "Las preferéncias son estadas salvadas.", "savedrights": "Los dreits d'utilizaire de {{GENDER:$1|$1}} son estats enregistrats.", "timezonelegend": "Fus orari :", diff --git a/languages/i18n/pt-br.json b/languages/i18n/pt-br.json index 877184cd94..7818961b91 100644 --- a/languages/i18n/pt-br.json +++ b/languages/i18n/pt-br.json @@ -617,6 +617,7 @@ "botpasswords-existing": "Senhas de robôs existentes", "botpasswords-createnew": "Crie uma nova senha de robô", "botpasswords-editexisting": "Editar uma senha de robô existente", + "botpasswords-label-needsreset": "(senha precisa ser redefinida)", "botpasswords-label-appid": "Nome do robô:", "botpasswords-label-create": "Criar", "botpasswords-label-update": "Atualizar", @@ -640,6 +641,7 @@ "botpasswords-restriction-failed": "Restrições de senha de robô evitam esta autenticação.", "botpasswords-invalid-name": "O nome de usuário especificado não contém o separador de senha de robô (\"$1\").", "botpasswords-not-exist": "O usuário \"$1\" não possui uma senha de robô \"$2\".", + "botpasswords-needs-reset": "A senha do robô de nome \"$2\" {{GENDER:$1|do usuário|da usuária}} \"$1\" deve ser redefinida.", "resetpass_forbidden": "As senhas não podem ser alteradas", "resetpass_forbidden-reason": "Senhas não podem ser alteradas: $1", "resetpass-no-info": "Você precisa estar autenticado para acessar esta página diretamente.", @@ -1111,7 +1113,7 @@ "recentchangescount": "Número de edições a apresentar por omissão nas mudanças recentes, nos historiais de páginas e nos registos:", "prefs-help-recentchangescount": "Número máximo: 1000", "prefs-help-watchlist-token2": "Esta é a senha secreta para o feed da Web com sua lista de tokens vigiados.\nQualquer pessoa que descobrir esta senha será capaz de ler sua lista, então não a compartilhe.\nSe você precisar [[Special:ResetTokens|você pode redefini-lo]].", - "prefs-help-tokenmanagement": "Você pode ver e redefinir a chave secreta para sua conta que pode acessar o feed da Web da sua lista de vigilância. Qualquer pessoa que conheça a chave poderá ler sua lista de observação, então não compartilhe.", + "prefs-help-tokenmanagement": "Pode ver e repor a chave secreta da sua conta que permite aceder ao feed da sua lista de páginas vigiadas. Qualquer pessoa que conheça a chave será capaz de ler a sua lista de páginas vigiadas, por isso não a partilhe.", "savedprefs": "As suas preferências foram salvas.", "savedrights": "Os grupos {{GENDER:$1|do usuário|da usuária}} $1 foram gravados.", "timezonelegend": "Fuso horário:", @@ -1141,7 +1143,7 @@ "prefs-custom-json": "JSON personalizado", "prefs-custom-js": "JS personalizado", "prefs-common-config": "CSS/JSON/JavaScript compartilhado por todos os temas:", - "prefs-reset-intro": "Você pode usar esta página para restaurar as suas preferências para os valores predefinidos do sítio.\nEsta ação não pode ser desfeita.", + "prefs-reset-intro": "Pode usar esta página para repor as configurações padrão das preferências.\nAs suas preferências serão modificadas para os valores predefinidos do site.\nEsta operação não pode ser desfeita.", "prefs-emailconfirm-label": "Confirmação do e-mail:", "youremail": "Seu e-mail:", "username": "Nome de {{GENDER:$1|usuário|usuária|usuário(a)}}:", @@ -1588,7 +1590,7 @@ "recentchangeslinked-feed": "Mudanças relacionadas", "recentchangeslinked-toolbox": "Mudanças relacionadas", "recentchangeslinked-title": "Mudanças relacionadas com “$1”", - "recentchangeslinked-summary": "Digite um nome de página para ver as alterações nas páginas vinculadas ou a partir dessa página. (Para ver membros de uma categoria, digite Categoria: Nome da categoria). Mudanças nas páginas em [[Special:Watchlist|lista de páginas vigiadas]] são exibidas em negrito", + "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza {{ns:category}}:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a negrito.", "recentchangeslinked-page": "Nome da página:", "recentchangeslinked-to": "Inversamente, mostrar mudanças nas páginas que contêm ligações para esta", "recentchanges-page-added-to-category": "[[:$1]]adicionada à categoria", diff --git a/languages/i18n/pt.json b/languages/i18n/pt.json index 9a67d6faef..40a8065cd2 100644 --- a/languages/i18n/pt.json +++ b/languages/i18n/pt.json @@ -76,7 +76,8 @@ "Ngl2016", "RadiX", "MokaAkashiyaPT", - "Athena in Wonderland" + "Athena in Wonderland", + "Fitoschido" ] }, "tog-underline": "Sublinhar hiperligações:", @@ -583,6 +584,7 @@ "botpasswords-existing": "Palavras-passe de robô existentes", "botpasswords-createnew": "Criar uma nova palavra-passe para robô", "botpasswords-editexisting": "Editar uma palavra-passe de robô existente", + "botpasswords-label-needsreset": "(a palavra-passe precisa ser redefinida)", "botpasswords-label-appid": "Nome do robô:", "botpasswords-label-create": "Criar", "botpasswords-label-update": "Atualizar", @@ -606,6 +608,7 @@ "botpasswords-restriction-failed": "Restrições da palavra-passe de robô impedem esta autenticação.", "botpasswords-invalid-name": "O nome de utilizador especificado não contém o separador de palavra-passe de robô (\"$1\").", "botpasswords-not-exist": "O utilizador \"$1\" não tem uma palavra-passe para o robô chamado \"$2\".", + "botpasswords-needs-reset": "A palavra-passe do robô de nome \"$2\" {{GENDER:$1|do utilizador|da utilizadora}} \"$1\" deve ser redefinida.", "resetpass_forbidden": "As palavras-passe não podem ser alteradas", "resetpass_forbidden-reason": "As palavras-passe não podem ser alteradas: $1", "resetpass-no-info": "Precisa de iniciar sessão para aceder diretamente a esta página.", @@ -701,8 +704,8 @@ "subject-preview": "Antevisão do assunto:", "previewerrortext": "Ocorreu um erro enquanto tentava antever as suas alterações.", "blockedtitle": "O utilizador está bloqueado", - "blockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados.\n\nO bloqueio foi realizado por $1.\nO motivo apresentado foi $2.\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\nNote que para utilizar a funcionalidade \"Contactar utilizador\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", - "autoblockedtext": "O seu endereço IP foi bloqueado de forma automática porque foi utilizado recentemente por outro utilizador, o qual foi bloqueado por $1.\nO motivo apresentado foi:\n\n:$2\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\n\nNote que para utilizar a funcionalidade \"Contactar utilizador\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\n\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", + "blockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados.\n\nO bloqueio foi realizado por $1.\nO motivo apresentado foi $2.\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\nNote que para utilizar a funcionalidade \"{{int:emailuser}}\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", + "autoblockedtext": "O seu endereço IP foi bloqueado de forma automática porque foi utilizado recentemente por outro utilizador, o qual foi bloqueado por $1.\nO motivo apresentado foi:\n\n:$2\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\n\nNote que para utilizar a funcionalidade \"{{int:emailuser}}\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\n\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.", "systemblockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados automaticamente pelo MediaWiki.\nO motivo fornecido é:\n\n:$2\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nO seu endereço IP atual é $3.\nInclua todos os detalhes acima em quaisquer contactos sobre este assunto, por favor.", "blockednoreason": "sem motivo especificado", "whitelistedittext": "Precisa de $1 para poder editar páginas.", @@ -1561,7 +1564,7 @@ "recentchangeslinked-feed": "Alterações relacionadas", "recentchangeslinked-toolbox": "Alterações relacionadas", "recentchangeslinked-title": "Alterações relacionadas com \"$1\"", - "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza Categoria:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a negrito.", + "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza {{ns:category}}:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a negrito.", "recentchangeslinked-page": "Nome da página:", "recentchangeslinked-to": "Inversamente, mostrar mudanças às páginas que contêm hiperligações para esta", "recentchanges-page-added-to-category": "[[:$1]] foi adicionada à categoria", diff --git a/languages/i18n/ru.json b/languages/i18n/ru.json index 99d05480ba..e4efea81c6 100644 --- a/languages/i18n/ru.json +++ b/languages/i18n/ru.json @@ -633,6 +633,7 @@ "botpasswords-existing": "Существующие пароли бота", "botpasswords-createnew": "Создать новый пароль бота", "botpasswords-editexisting": "Редактировать существующий пароль бота", + "botpasswords-label-needsreset": "(пароль должен быть сброшен)", "botpasswords-label-appid": "Название бота:", "botpasswords-label-create": "Создать", "botpasswords-label-update": "Обновить", @@ -656,6 +657,7 @@ "botpasswords-restriction-failed": "Из-за ограничений, связанных с паролем бота, вход не произведён.", "botpasswords-invalid-name": "Указанное имя участника не содержит разделителя для пароля бота («$1»).", "botpasswords-not-exist": "У участника «$1» нет пароля для бота с названием «$2».", + "botpasswords-needs-reset": "Пароль для бота «$1» {{GENDER:$2|участника|участницы}} «$2» должен быть сброшен.", "resetpass_forbidden": "Пароль не может быть изменён", "resetpass_forbidden-reason": "Пароли не могут быть изменены: $1", "resetpass-no-info": "Чтобы обращаться непосредственно к этой странице, вам следует представиться системе.", diff --git a/languages/i18n/skr-arab.json b/languages/i18n/skr-arab.json index 0ee213e1cd..d549a85241 100644 --- a/languages/i18n/skr-arab.json +++ b/languages/i18n/skr-arab.json @@ -408,7 +408,7 @@ "yourdiff": "فرق", "templatesused": "ایں ورقے تے ورتے ڳئے {{PLURAL:$1|سانچے|سانچہ}}:", "templatesusedpreview": "ایں کچے کم تے ورتے ڳئے {{PLURAL:$1|سانچے|سانچہ}}:", - "template-protected": "(بچایا گیا)", + "template-protected": "(بچایا ڳیا)", "template-semiprotected": "(نیم محفوظ)", "hiddencategories": "ایہ ورقہ {{PLURAL:$1|1 لُکے زمریاں|$1 لکا زمرہ }} وچ شامل ہے:", "permissionserrors": "خطائے اجازت", @@ -861,7 +861,7 @@ "logentry-contentmodel-change-revertlink": "واپس", "logentry-contentmodel-change-revert": "واپس", "protectlogpage": "حفاظت لاگ", - "protectedarticle": "\"[[$1]]\" بچایا گیا اے", + "protectedarticle": "\"[[$1]]\" بچایا ڳیا ہے", "modifiedarticleprotection": "«[[$1]]» دا درجہ حفاظت تبدیل کیتا", "protectcomment": "سبب:", "protectexpiry": "مُکسی:", diff --git a/languages/i18n/sl.json b/languages/i18n/sl.json index f3e9296a7c..f314ca4650 100644 --- a/languages/i18n/sl.json +++ b/languages/i18n/sl.json @@ -515,6 +515,7 @@ "botpasswords-existing": "Obstoječa gesla botov", "botpasswords-createnew": "Ustvari novo geslo bota", "botpasswords-editexisting": "Uredi obstoječe geslo bota", + "botpasswords-label-needsreset": "(geslo mora biti ponastavljeno)", "botpasswords-label-appid": "Ime bota:", "botpasswords-label-create": "Ustvari", "botpasswords-label-update": "Posodobi", @@ -538,6 +539,7 @@ "botpasswords-restriction-failed": "Omejitve gesla bota preprečujejo to prijavo.", "botpasswords-invalid-name": "Navedeno uporabniÅ¡ko ime ne vsebuje ločila za geslo bota (»$1«).", "botpasswords-not-exist": "Uporabnik »$1« nima gesla bota z imenom »$2«.", + "botpasswords-needs-reset": "Geslo bota »$2« {{GENDER:$1|uporabnika|uporabnice}} »$1« mora biti ponastavljeno.", "resetpass_forbidden": "Gesla ne morete spremeniti", "resetpass_forbidden-reason": "Gesel nismo mogli spremeniti: $1", "resetpass-no-info": "Za neposreden dostop do te strani morate biti prijavljeni.", @@ -633,8 +635,8 @@ "subject-preview": "Predogled zadeve:", "previewerrortext": "Med poskusom prikaza predogleda vaÅ¡ih sprememb je priÅ¡lo do napake.", "blockedtitle": "Uporabnik je blokiran", - "blockedtext": "'''Urejanje z vaÅ¡im uporabniÅ¡kim imenom oziroma IP-naslovom je onemogočeno.'''\n\nBlokiral vas je $1.\nPodani razlog je ''$2''.\n\n* začetek blokade: $8\n* potek blokade: $6\n* blokirani uporabnik: $7\n\nO blokiranju se lahko pogovorite z uporabnikom/-co $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].\nVedite, da lahko ukaz »PoÅ¡lji uporabniku e-pismo« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov in ta ni blokiran.\nVaÅ¡ IP-naslov je $3, Å¡tevilka blokade pa #$5.\nProsimo, vključite ju v vse morebitne poizvedbe.", - "autoblockedtext": "VaÅ¡ IP-naslov je bil samodejno blokiran, saj je bil uporabljen s strani drugega uporabnika, ki ga je blokiral $1.\nRazlog za to je bil naslednji:\n\n:''$2''\n\n* Začetek blokade: $8\n* Konec blokade: $6\n* Blokirani uporabnik: $7\n\nKontaktirate lahko $1 ali katerega od drugih [[{{MediaWiki:Grouppage-sysop}}|administratorjev]], da razpravljate o blokadi.\n\nVedite, da lahko funkcijo »{{:MediaWiki:Emailuser/sl}}« uporabljate le, če ste v svoje [[Special:Preferences|uporabniÅ¡ke nastavitve]] vnesli veljaven e-poÅ¡tni naslov, in vam njena uporaba ni bila preprečena.\n\nVaÅ¡ trenutni IP-naslov je $3, ID blokiranja pa #$5. Prosimo, vključite ta ID v vsako zastavljeno vpraÅ¡anje.", + "blockedtext": "Urejanje z vaÅ¡im uporabniÅ¡kim imenom oziroma IP-naslovom je onemogočeno.\n\nBlokiral vas je $1.\nPodani razlog je $2.\n\n* Začetek blokade: $8\n* Potek blokade: $6\n* Blokirani uporabnik: $7\n\nO blokiranju se lahko pogovorite z uporabnikom/-co $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].\nVedite, da lahko ukaz »{{int:emailuser}}« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov in ta ni blokiran.\nVaÅ¡ IP-naslov je $3, Å¡tevilka blokade pa #$5.\nProsimo, vključite ju v vse morebitne poizvedbe.", + "autoblockedtext": "VaÅ¡ IP-naslov je bil samodejno blokiran, saj je bil uporabljen s strani drugega uporabnika, ki ga je blokiral $1.\nRazlog za to je bil naslednji:\n\n:$2\n\n* Začetek blokade: $8\n* Konec blokade: $6\n* Blokirani uporabnik: $7\n\nKontaktirate lahko $1 ali katerega od drugih [[{{MediaWiki:Grouppage-sysop}}|administratorjev]], da razpravljate o blokadi.\n\nVedite, da lahko funkcijo »{{int:emailuser}}« uporabljate le, če ste v svoje [[Special:Preferences|uporabniÅ¡ke nastavitve]] vnesli veljaven e-poÅ¡tni naslov, in vam njena uporaba ni bila preprečena.\n\nVaÅ¡ trenutni IP-naslov je $3, ID blokiranja pa #$5. Prosimo, vključite ta ID v vsako zastavljeno vpraÅ¡anje.", "systemblockedtext": "VaÅ¡e uporabniÅ¡ko ime ali IP-naslov je MediaWiki samodejn blokiral.\nPodani razlog je:\n\n:$2\n\n* Začetek blokade: $8\n* Potek blokade: $6\n* Blokirani uporabnik: $7\n\nVaÅ¡ trenutni IP-naslov je $3.\nProsimo, da v svoje poizvedbe vključite vse zgornje podatke.", "blockednoreason": "razlog ni podan", "whitelistedittext": "Za urejanje strani se morate $1.", diff --git a/languages/i18n/sv.json b/languages/i18n/sv.json index 534190a536..fa0ea82e03 100644 --- a/languages/i18n/sv.json +++ b/languages/i18n/sv.json @@ -577,6 +577,7 @@ "botpasswords-existing": "Befintliga botlösenord", "botpasswords-createnew": "Skapa ett nytt botlösenord", "botpasswords-editexisting": "Redigera ett befintligt botlösenord", + "botpasswords-label-needsreset": "(lösenordet behöver Ã¥terställas)", "botpasswords-label-appid": "Botnamn:", "botpasswords-label-create": "Skapa", "botpasswords-label-update": "Uppdatera", @@ -600,6 +601,7 @@ "botpasswords-restriction-failed": "Begränsningar av botlösenord tillÃ¥ter inte denna inloggning.", "botpasswords-invalid-name": "Det angivna användarnamnet innehÃ¥ller inte separatorn för botlösenord (\"$1\").", "botpasswords-not-exist": "Användaren \"$1\" har inte ett botlösenord som är \"$2\".", + "botpasswords-needs-reset": "Botlösenordet för botnamnet \"$2\" till {{GENDER:$1|användaren}} \"$1\" mÃ¥ste Ã¥terställas.", "resetpass_forbidden": "Lösenord kan inte ändras", "resetpass_forbidden-reason": "Lösenorden kan inte ändras: $1", "resetpass-no-info": "Du mÃ¥ste vara inloggad för att komma Ã¥t den här sidan direkt.", @@ -1549,7 +1551,7 @@ "recentchangeslinked-feed": "Relaterade ändringar", "recentchangeslinked-toolbox": "Relaterade ändringar", "recentchangeslinked-title": "Ändringar relaterade till \"$1\"", - "recentchangeslinked-summary": "Ange namnet pÃ¥ en sida för att se ändringar pÃ¥ sidor som länkas till eller frÃ¥n denna sida. (För att se medlemmar i en kategori, skriv Kategori:Namnet pÃ¥ kategorin). Ändringar pÃ¥ sidor i [[Special:Watchlist|din bevakningslista]] är fetstilta.", + "recentchangeslinked-summary": "Ange namnet pÃ¥ en sida för att se ändringar pÃ¥ sidor som länkas till eller frÃ¥n denna sida. (För att se medlemmar i en kategori, skriv {{ns:category}}:Namnet pÃ¥ kategorin). Ändringar pÃ¥ sidor i [[Special:Watchlist|din bevakningslista]] är fetstilta.", "recentchangeslinked-page": "Sidnamn:", "recentchangeslinked-to": "Visa ändringar pÃ¥ sidor med länkar till den givna sidan istället", "recentchanges-page-added-to-category": "[[:$1]] lades till i kategorin", diff --git a/languages/i18n/szl.json b/languages/i18n/szl.json index d78fcd1489..2a3b8456fc 100644 --- a/languages/i18n/szl.json +++ b/languages/i18n/szl.json @@ -347,15 +347,15 @@ "welcomecreation-msg": "Uotwarli my sam lo Ćebje kůnto.\nPamjyntej coby posztalować [[Special:Preferences|preferencyji]]", "yourname": "Mjano użytkowńika:", "userlogin-yourname": "Mjano używocza", - "userlogin-yourname-ph": "Wszkryflej swoje mjano użytkowńika", + "userlogin-yourname-ph": "Wkludź swoje miano używacza", "createacct-another-username-ph": "Wszkryflej mjano użytkowńika", "yourpassword": "Hasło:", "userlogin-yourpassword": "Hasło", - "userlogin-yourpassword-ph": "Wszkryflej swoje hasło", - "createacct-yourpassword-ph": "Wszkryflej hasło", + "userlogin-yourpassword-ph": "Wkludź swoje hasło", + "createacct-yourpassword-ph": "Wkludź hasło", "yourpasswordagain": "Naszkryflej ausdruk zaś", "createacct-yourpasswordagain": "Potwjyrdź hasło", - "createacct-yourpasswordagain-ph": "Wszkryflej hasło jeszcze roz", + "createacct-yourpasswordagain-ph": "Wkludź hasło jeszcze rŏz", "userlogin-remembermypassword": "Ńy wylogůwywuj mje", "userlogin-signwithsecure": "Użyj bezpjecznygo połůnczyńa", "yourdomainname": "Twoja domyna", @@ -375,7 +375,7 @@ "userlogin-createanother": "Twůrz inksze kůnto", "createacct-emailrequired": "E-brif", "createacct-emailoptional": "E-brif (uopcjůnalne)", - "createacct-email-ph": "Wszkryflej swůj adres do e-brifa", + "createacct-email-ph": "Wkludź swojã adresã e-brifa", "createacct-another-email-ph": "Nastow e-brif", "createaccountmail": "Użyj chwilowygo hasła losowo genyrowanygo a wyślij je na wrychtowany adres e-brifa.", "createacct-realname": "Prawdźiwe imje a nazwisko (uopcjůnalńe)", diff --git a/languages/i18n/tr.json b/languages/i18n/tr.json index 0226e5c375..db9fe9667e 100644 --- a/languages/i18n/tr.json +++ b/languages/i18n/tr.json @@ -600,6 +600,7 @@ "botpasswords-existing": "Mevcut bot parolaları", "botpasswords-createnew": "Yeni bir bot parolası oluştur", "botpasswords-editexisting": "Mevcut bir bot parolasını düzenle", + "botpasswords-label-needsreset": "(parolanın sıfırlanması gerekiyor)", "botpasswords-label-appid": "Bot ismi:", "botpasswords-label-create": "Oluştur", "botpasswords-label-update": "Güncelle", @@ -621,6 +622,7 @@ "botpasswords-no-provider": "BotPasswordsSessionProvider kullanılamaz.", "botpasswords-restriction-failed": "Bot parolası kısıtlamaları bu oturum açma işlemini önlemektedir.", "botpasswords-invalid-name": "Belirtilen kullanıcı adı bot parolası ayırıcısı içermiyor (\"$1\").", + "botpasswords-needs-reset": "\"$1\" {{GENDER:$1|kullanıcısına}} ait \"$2\" adlı bot için bot parolası sıfırlanmalı.", "resetpass_forbidden": "Parolalar değiştirilememektedir", "resetpass_forbidden-reason": "Parolalar değiştirilemez: $1", "resetpass-no-info": "Bu sayfaya doğrudan erişmek için oturum açmanız gereklidir.", diff --git a/languages/i18n/zh-hans.json b/languages/i18n/zh-hans.json index 1eaf278251..c890f9a7d9 100644 --- a/languages/i18n/zh-hans.json +++ b/languages/i18n/zh-hans.json @@ -719,8 +719,8 @@ "subject-preview": "主题的预览:", "previewerrortext": "尝试预览您的更改时发生错误。", "blockedtitle": "用户被封禁", - "blockedtext": "您的用户名或IP地址已被封禁。\n\n执行封禁的管理员是$1。封禁原因是$2。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联络$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当您在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。您当前的IP地址是$3,该封禁ID是#$5。请在您做出的任何查询中包含所有上述详情。", - "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]申诉该封禁。\n\n请注意,只有当您已在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才能发送电子邮件联系管理员。\n\n您当前的IP地址为$3,该封禁ID为#$5。请在您做出的任何查询中包含所有上述详情。", + "blockedtext": "您的用户名或IP地址已被封禁。\n\n执行封禁的管理员是$1。封禁原因是$2。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联络$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当您在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“{{int:emailuser}}”功能时,才可以使用它。您当前的IP地址是$3,该封禁ID是#$5。请在您做出的任何查询中包含所有上述详情。", + "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联系$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]申诉该封禁。\n\n请注意,只有当您已在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“{{int:emailuser}}”功能时,才能发送电子邮件联系管理员。\n\n您当前的IP地址为$3,该封禁ID为#$5。请在您做出的任何查询中包含所有上述详情。", "systemblockedtext": "您的用户名或IP地址已被MediaWiki自动封禁。封禁原因:\n\n:$2\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您当前的IP地址是$3。请在您做出的任何查询中包含所有上述详情。", "blockednoreason": "未给出原因", "whitelistedittext": "请$1以编辑页面。", diff --git a/languages/i18n/zh-hant.json b/languages/i18n/zh-hant.json index 3a14a15753..deeee82112 100644 --- a/languages/i18n/zh-hant.json +++ b/languages/i18n/zh-hant.json @@ -596,6 +596,7 @@ "botpasswords-existing": "已存在機器人密碼", "botpasswords-createnew": "建立新機器人密碼", "botpasswords-editexisting": "編輯已存在的機器人密碼", + "botpasswords-label-needsreset": "(密碼需要重新設定)", "botpasswords-label-appid": "機器人名稱:", "botpasswords-label-create": "建立", "botpasswords-label-update": "更新", @@ -1065,6 +1066,7 @@ "prefs-watchlist-edits": "監視清單中顯示的變更數量上限:", "prefs-watchlist-edits-max": "數量上限:1000", "prefs-watchlist-token": "監視清單金鑰:", + "prefs-watchlist-managetokens": "管理令牌", "prefs-misc": "其他", "prefs-resetpass": "變更密碼", "prefs-changeemail": "變更或移除電子郵件地址", diff --git a/maintenance/categoryChangesAsRdf.php b/maintenance/categoryChangesAsRdf.php new file mode 100644 index 0000000000..a12cda78b4 --- /dev/null +++ b/maintenance/categoryChangesAsRdf.php @@ -0,0 +1,542 @@ +addDescription( "Generate RDF dump of category changes in a wiki." ); + + $this->setBatchSize( 200 ); + $this->addOption( 'output', "Output file (default is stdout). Will be overwritten.", false, + true, 'o' ); + $this->addOption( 'start', 'Starting timestamp (inclusive), in ISO or Mediawiki format.', + true, true, 's' ); + $this->addOption( 'end', 'Ending timestamp (exclusive), in ISO or Mediawiki format.', true, + true, 'e' ); + } + + /** + * Initialize external service classes. + */ + public function initialize() { + // SPARQL Update syntax is close to Turtle format, so we can use Turtle writer. + $this->rdfWriter = new TurtleRdfWriter(); + $this->categoriesRdf = new CategoriesRdf( $this->rdfWriter ); + } + + public function execute() { + global $wgRCMaxAge; + + $this->initialize(); + + $startTS = new MWTimestamp( $this->getOption( "start" ) ); + $endTS = new MWTimestamp( $this->getOption( "end" ) ); + $now = new MWTimestamp(); + + if ( $now->getTimestamp() - $startTS->getTimestamp() > $wgRCMaxAge ) { + $this->error( "Start timestamp too old, maximum RC age is $wgRCMaxAge!" ); + } + if ( $now->getTimestamp() - $endTS->getTimestamp() > $wgRCMaxAge ) { + $this->error( "End timestamp too old, maximum RC age is $wgRCMaxAge!" ); + } + + $this->startTS = $startTS->getTimestamp(); + $this->endTS = $endTS->getTimestamp(); + + $outFile = $this->getOption( 'output', 'php://stdout' ); + if ( $outFile === '-' ) { + $outFile = 'php://stdout'; + } + + $output = fopen( $outFile, 'wb' ); + + $this->categoriesRdf->setupPrefixes(); + $this->rdfWriter->start(); + + $prefixes = $this->getRdf(); + // We have to strip @ from prefix, since SPARQL UPDATE doesn't use them + // Also strip dot at the end. + $prefixes = preg_replace( [ '/^@/m', '/\s*[.]$/m' ], '', $prefixes ); + fwrite( $output, $prefixes ); + + $dbr = $this->getDB( DB_REPLICA, [ 'vslow' ] ); + + // Deletes go first because if the page was deleted, other changes + // do not matter. This only gets true deletes, i.e. not pages that were restored. + $this->handleDeletes( $dbr, $output ); + // Moves go before additions because if category is moved, we should not process creation + // as it would produce wrong data - because create row has old title + $this->handleMoves( $dbr, $output ); + // We need to handle restores too since delete may have happened in previous update. + $this->handleRestores( $dbr, $output ); + $this->handleAdds( $dbr, $output ); + $this->handleChanges( $dbr, $output ); + + // Update timestamp + fwrite( $output, $this->updateTS( $this->endTS ) ); + } + + /** + * Get SPARQL for updating set of categories + * @param IDatabase $dbr + * @param string[] $deleteUrls List of URIs to be deleted, with <> + * @param string[] $pages List of categories: id => title + * @param string $mark Marks which operation requests the query + * @return string SPARQL query + */ + private function getCategoriesUpdate( IDatabase $dbr, $deleteUrls, $pages, $mark ) { + if ( empty( $deleteUrls ) ) { + return ""; + } + + if ( !empty( $pages ) ) { + $this->writeParentCategories( $dbr, $pages ); + } + + return "# $mark\n" . sprintf( self::SPARQL_DELETE_INSERT, + $this->getRdf(), + implode( ' ', $deleteUrls ) ); + } + + /** + * Write data for a set of categories + * @param IDatabase $dbr + * @param string[] $pages List of categories: id => title + */ + private function writeParentCategories( IDatabase $dbr, $pages ) { + foreach ( $this->getCategoryLinksIterator( $dbr, array_keys( $pages ) ) as $row ) { + $this->categoriesRdf->writeCategoryLinkData( $pages[$row->cl_from], $row->cl_to ); + } + } + + /** + * Generate SPARQL Update code for updating dump timestamp + * @param string|int $timestamp Timestamp for last change + * @return string SPARQL Update query for timestamp. + */ + public function updateTS( $timestamp ) { + $dumpUrl = '<' . $this->categoriesRdf->getDumpURI() . '>'; + $ts = wfTimestamp( TS_ISO_8601, $timestamp ); + $tsQuery = <<mBatchSize + ); + $this->addTimestampConditions( $it, $dbr ); + $it->addJoinConditions( + [ + 'page_props' => [ + 'LEFT JOIN', [ 'pp_propname' => 'hiddencat', 'pp_page = rc_cur_id' ] + ], + 'category' => [ + 'LEFT JOIN', [ 'cat_title = rc_title' ] + ] + ] + ); + $it->setFetchColumns( array_merge( $columns, [ + 'rc_title', + 'rc_cur_id', + 'pp_propname', + 'cat_pages', + 'cat_subcats', + 'cat_files' + ] ) ); + return $it; + } + + /** + * Fetch newly created categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getNewCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 1, + ] ); + return $it; + } + + /** + * Fetch moved categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getMovedCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr, [ 'page_title', 'page_namespace' ], [ 'page' ] ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_log_type' => 'move', + 'rc_type' => RC_LOG, + ] ); + $it->addJoinConditions( [ + 'page' => [ 'INNER JOIN', 'rc_cur_id = page_id' ], + ] ); + $this->addIndex( $it ); + return $it; + } + + /** + * Fetch deleted categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getDeletedCatsIterator( IDatabase $dbr ) { + $it = new BatchRowIterator( $dbr, + 'recentchanges', + [ 'rc_timestamp' ], + $this->mBatchSize + ); + $this->addTimestampConditions( $it, $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_log_type' => 'delete', + 'rc_log_action' => 'delete', + 'rc_type' => RC_LOG, + // We will fetch ones that do not have page record. If they do, + // this means they were restored, thus restoring handler will pick it up. + 'NOT EXISTS (SELECT * FROM page WHERE page_id = rc_cur_id)', + ] ); + $this->addIndex( $it ); + $it->setFetchColumns( [ 'rc_cur_id', 'rc_title' ] ); + return $it; + } + + /** + * Fetch restored categories + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getRestoredCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_log_type' => 'delete', + 'rc_log_action' => 'restore', + 'rc_type' => RC_LOG, + // We will only fetch ones that have page record + 'EXISTS (SELECT page_id FROM page WHERE page_id = rc_cur_id)', + ] ); + $this->addIndex( $it ); + return $it; + } + + /** + * Fetch categorization changes + * @param IDatabase $dbr + * @return BatchRowIterator + */ + protected function getChangedCatsIterator( IDatabase $dbr ) { + $it = $this->setupChangesIterator( $dbr ); + $it->addConditions( [ + 'rc_namespace' => NS_CATEGORY, + 'rc_new' => 0, + 'rc_type' => [ RC_EDIT, RC_CATEGORIZE ], + ] ); + $this->addIndex( $it ); + return $it; + } + + /** + * Add timestamp limits to iterator + * @param BatchRowIterator $it Iterator + * @param IDatabase $dbr + */ + private function addTimestampConditions( BatchRowIterator $it, IDatabase $dbr ) { + $it->addConditions( [ + 'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( $this->startTS ) ), + 'rc_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( $this->endTS ) ), + ] ); + } + + /** + * Need to force index, somehow on terbium the optimizer chooses wrong one + * @param BatchRowIterator $it + */ + private function addIndex( BatchRowIterator $it ) { + $it->addOptions( [ + 'USE INDEX' => [ 'recentchanges' => 'new_name_timestamp' ] + ] ); + } + + /** + * Get iterator for links for categories. + * @param IDatabase $dbr + * @param array $ids List of page IDs + * @return Traversable + */ + protected function getCategoryLinksIterator( IDatabase $dbr, array $ids ) { + $it = new BatchRowIterator( + $dbr, + 'categorylinks', + [ 'cl_from', 'cl_to' ], + $this->mBatchSize + ); + $it->addConditions( [ + 'cl_type' => 'subcat', + 'cl_from' => $ids + ] ); + $it->setFetchColumns( [ 'cl_from', 'cl_to' ] ); + return new RecursiveIteratorIterator( $it ); + } + + /** + * Get accumulated RDF. + * @return string + */ + public function getRdf() { + return $this->rdfWriter->drain(); + } + + /** + * Handle category deletes. + * @param IDatabase $dbr + * @param resource $output File to write the output + */ + public function handleDeletes( IDatabase $dbr, $output ) { + // This only does "true" deletes - i.e. those that the page stays deleted + foreach ( $this->getDeletedCatsIterator( $dbr ) as $batch ) { + $deleteUrls = []; + foreach ( $batch as $row ) { + // This can produce duplicates, we don't care + $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>'; + $this->processed[$row->rc_cur_id] = true; + } + fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, [], "Deletes" ) ); + } + } + + /** + * Write category data to RDF. + * @param stdclass $row Database row + */ + private function writeCategoryData( $row ) { + $this->categoriesRdf->writeCategoryData( + $row->rc_title, + $row->pp_propname === 'hiddencat', + (int)$row->cat_pages - (int)$row->cat_subcats - (int)$row->cat_files, + (int)$row->cat_subcats + ); + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleMoves( IDatabase $dbr, $output ) { + foreach ( $this->getMovedCatsIterator( $dbr ) as $batch ) { + $pages = []; + $deleteUrls = []; + foreach ( $batch as $row ) { + $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>'; + + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + + if ( $row->page_namespace != NS_CATEGORY ) { + // If page was moved out of Category:, we'll just delete + continue; + } + $row->rc_title = $row->page_title; + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->page_title; + $this->processed[$row->rc_cur_id] = true; + } + + fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, $pages, "Moves" ) ); + } + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleRestores( IDatabase $dbr, $output ) { + fwrite( $output, "# Restores\n" ); + // This will only find those restores that were not deleted later. + foreach ( $this->getRestoredCatsIterator( $dbr ) as $batch ) { + $pages = []; + foreach ( $batch as $row ) { + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->rc_title; + $this->processed[$row->rc_cur_id] = true; + } + + if ( empty( $pages ) ) { + continue; + } + + $this->writeParentCategories( $dbr, $pages ); + + fwrite( $output, sprintf( self::SPARQL_INSERT, $this->getRdf() ) ); + } + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleAdds( IDatabase $dbr, $output ) { + fwrite( $output, "# Additions\n" ); + foreach ( $this->getNewCatsIterator( $dbr ) as $batch ) { + $pages = []; + foreach ( $batch as $row ) { + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->rc_title; + $this->processed[$row->rc_cur_id] = true; + } + + if ( empty( $pages ) ) { + continue; + } + + $this->writeParentCategories( $dbr, $pages ); + fwrite( $output, sprintf( self::SPARQL_INSERT, $this->getRdf() ) ); + } + } + + /** + * @param IDatabase $dbr + * @param resource $output + */ + public function handleChanges( IDatabase $dbr, $output ) { + foreach ( $this->getChangedCatsIterator( $dbr ) as $batch ) { + $pages = []; + $deleteUrls = []; + foreach ( $batch as $row ) { + if ( isset( $this->processed[$row->rc_cur_id] ) ) { + // We already captured this one before + continue; + } + $this->writeCategoryData( $row ); + $pages[$row->rc_cur_id] = $row->rc_title; + $this->processed[$row->rc_cur_id] = true; + $deleteUrls[] = '<' . $this->categoriesRdf->labelToUrl( $row->rc_title ) . '>'; + } + + fwrite( $output, $this->getCategoriesUpdate( $dbr, $deleteUrls, $pages, "Changes" ) ); + } + } +} + +$maintClass = CategoryChangesAsRdf::class; +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/package.json b/package.json index 2bc0c80d96..1f23b1a09b 100644 --- a/package.json +++ b/package.json @@ -15,18 +15,18 @@ "grunt": "1.0.1", "grunt-banana-checker": "0.6.0", "grunt-contrib-copy": "1.0.0", - "grunt-contrib-watch": "1.0.0", + "grunt-contrib-watch": "1.0.1", "grunt-eslint": "20.1.0", "grunt-jsonlint": "1.1.0", "grunt-karma": "2.0.0", "grunt-stylelint": "0.10.0", - "karma": "1.7.1", + "karma": "2.0.2", "karma-chrome-launcher": "2.2.0", "karma-firefox-launcher": "1.0.1", "karma-mocha-reporter": "2.2.5", "karma-qunit": "2.0.1", "postcss-less": "1.1.5", - "qunit": "2.5.0", + "qunit": "2.6.0", "stylelint": "9.2.0", "stylelint-config-wikimedia": "0.4.3", "wdio-junit-reporter": "0.2.0", diff --git a/resources/Resources.php b/resources/Resources.php index ea4e5eafe7..d0bc1ba623 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -2001,11 +2001,11 @@ return [ ], 'mediawiki.special.apisandbox.styles' => [ 'targets' => [ 'desktop', 'mobile' ], - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css', + 'styles' => 'resources/src/mediawiki.special.apisandbox.styles.css', ], 'mediawiki.special.apisandbox' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.css', - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.js', + 'styles' => 'resources/src/mediawiki.special.apisandbox/apisandbox.css', + 'scripts' => 'resources/src/mediawiki.special.apisandbox/apisandbox.js', 'targets' => [ 'desktop', 'mobile' ], 'dependencies' => [ 'mediawiki.api', @@ -2073,7 +2073,7 @@ return [ ], ], 'mediawiki.special.block' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.block.js', + 'scripts' => 'resources/src/mediawiki.special.block.js', 'dependencies' => [ 'oojs-ui-core', 'oojs-ui.styles.icons-editing-core', @@ -2086,7 +2086,7 @@ return [ ], ], 'mediawiki.special.changecredentials.js' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changecredentials.js', + 'scripts' => 'resources/src/mediawiki.special.changecredentials.js', 'dependencies' => [ 'mediawiki.api', 'mediawiki.htmlform.ooui' @@ -2094,18 +2094,18 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.css', + 'styles' => 'resources/src/mediawiki.special.changeslist.css', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist.enhanced' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css', + 'styles' => 'resources/src/mediawiki.special.changeslist.enhanced.css', ], 'mediawiki.special.changeslist.legend' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css', + 'styles' => 'resources/src/mediawiki.special.changeslist.legend.css', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist.legend.js' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js', + 'scripts' => 'resources/src/mediawiki.special.changeslist.legend.js', 'dependencies' => [ 'jquery.makeCollapsible', 'mediawiki.cookie', @@ -2113,20 +2113,20 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.changeslist.visitedstatus' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js', + 'scripts' => 'resources/src/mediawiki.special.changeslist.visitedstatus.js', ], 'mediawiki.special.comparepages.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less', + 'styles' => 'resources/src/mediawiki.special.comparepages.styles.less', ], 'mediawiki.special.contributions' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.contributions.js', + 'scripts' => 'resources/src/mediawiki.special.contributions.js', 'dependencies' => [ 'mediawiki.widgets.DateInputWidget', 'mediawiki.jqueryMsg', ] ], 'mediawiki.special.edittags' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.edittags.js', + 'scripts' => 'resources/src/mediawiki.special.edittags.js', 'dependencies' => [ 'jquery.chosen', 'jquery.lengthLimit', @@ -2137,38 +2137,38 @@ return [ ], ], 'mediawiki.special.edittags.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.edittags.css', + 'styles' => 'resources/src/mediawiki.special.edittags.styles.css', ], 'mediawiki.special.import' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.import.js', + 'scripts' => 'resources/src/mediawiki.special.import.js', ], 'mediawiki.special.movePage' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.movePage.js', + 'scripts' => 'resources/src/mediawiki.special.movePage.js', 'dependencies' => [ 'mediawiki.widgets.visibleLengthLimit', 'mediawiki.widgets', ], ], 'mediawiki.special.movePage.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.movePage.css', + 'styles' => 'resources/src/mediawiki.special.movePage.css', ], 'mediawiki.special.pageLanguage' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.pageLanguage.js', + 'scripts' => 'resources/src/mediawiki.special.pageLanguage.js', 'dependencies' => [ 'oojs-ui-core', ], ], 'mediawiki.special.pagesWithProp' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css', + 'styles' => 'resources/src/mediawiki.special.pagesWithProp.css', ], 'mediawiki.special.preferences' => [ 'targets' => [ 'desktop', 'mobile' ], 'scripts' => [ - 'resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.legacy.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.personalEmail.js', + 'resources/src/mediawiki.special.preferences/confirmClose.js', + 'resources/src/mediawiki.special.preferences/convertmessagebox.js', + 'resources/src/mediawiki.special.preferences/tabs.legacy.js', + 'resources/src/mediawiki.special.preferences/timezone.js', + 'resources/src/mediawiki.special.preferences/personalEmail.js', ], 'messages' => [ 'prefs-tabs-navigation-hint', @@ -2184,17 +2184,19 @@ return [ ], 'mediawiki.special.preferences.styles' => [ 'targets' => [ 'desktop', 'mobile' ], - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.legacy.css', + // legacy + 'styles' => 'resources/src/mediawiki.special.preferences.styles.css', ], 'mediawiki.special.preferences.ooui' => [ 'targets' => [ 'desktop', 'mobile' ], 'scripts' => [ - 'resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.editfont.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js', - 'resources/src/mediawiki.special/mediawiki.special.preferences.personalEmail.js', + // FIXME: This uses files already belonging to another module + 'resources/src/mediawiki.special.preferences/confirmClose.js', + 'resources/src/mediawiki.special.preferences/convertmessagebox.js', + 'resources/src/mediawiki.special.preferences.ooui/editfont.js', + 'resources/src/mediawiki.special.preferences.ooui/tabs.js', + 'resources/src/mediawiki.special.preferences/timezone.js', + 'resources/src/mediawiki.special.preferences/personalEmail.js', ], 'messages' => [ 'prefs-tabs-navigation-hint', @@ -2213,14 +2215,14 @@ return [ ], 'mediawiki.special.preferences.styles.ooui' => [ 'targets' => [ 'desktop', 'mobile' ], - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.css', + 'styles' => 'resources/src/mediawiki.special.preferences.styles.ooui.css', ], 'mediawiki.special.recentchanges' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.recentchanges.js', + 'scripts' => 'resources/src/mediawiki.special.recentchanges.js', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.revisionDelete' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.revisionDelete.js', + 'scripts' => 'resources/src/mediawiki.special.revisionDelete.js', 'messages' => [ // @todo Load this message in content language 'colon-separator', @@ -2231,8 +2233,8 @@ return [ 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.search' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.js', - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.css', + 'scripts' => 'resources/src/mediawiki.special.search/search.js', + 'styles' => 'resources/src/mediawiki.special.search/search.css', 'dependencies' => 'mediawiki.widgets.SearchInputWidget', 'messages' => [ 'powersearch-togglelabel', @@ -2241,7 +2243,7 @@ return [ ], ], 'mediawiki.special.search.commonsInterwikiWidget' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js', + 'scripts' => 'resources/src/mediawiki.special.search.commonsInterwikiWidget.js', 'dependencies' => [ 'mediawiki.api', 'mediawiki.Uri', @@ -2254,24 +2256,23 @@ return [ ], ], 'mediawiki.special.search.interwikiwidget.styles' => [ - 'styles' => 'resources/src/mediawiki.special/' - . 'mediawiki.special.search.interwikiwidget.styles.less', + 'styles' => 'resources/src/mediawiki.special.search.interwikiwidget.styles.less', 'targets' => [ 'desktop', 'mobile' ] ], 'mediawiki.special.search.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.styles.css', + 'styles' => 'resources/src/mediawiki.special.search.styles.css', 'targets' => [ 'desktop', 'mobile' ], ], 'mediawiki.special.undelete' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js', + 'scripts' => 'resources/src/mediawiki.special.undelete.js', 'dependencies' => [ 'mediawiki.widgets.visibleLengthLimit', 'mediawiki.widgets', ], ], 'mediawiki.special.unwatchedPages' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js', - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css', + 'scripts' => 'resources/src/mediawiki.special.unwatchedPages/unwatchedPages.js', + 'styles' => 'resources/src/mediawiki.special.unwatchedPages/unwatchedPages.css', 'messages' => [ 'addedwatchtext-short', 'removedwatchtext-short', @@ -2291,9 +2292,9 @@ return [ ], 'mediawiki.special.upload' => [ 'templates' => [ - 'thumbnail.html' => 'resources/src/mediawiki.special/templates/thumbnail.html', + 'thumbnail.html' => 'resources/src/mediawiki.special.upload/templates/thumbnail.html', ], - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.upload.js', + 'scripts' => 'resources/src/mediawiki.special.upload/upload.js', 'messages' => [ 'widthheight', 'size-bytes', @@ -2319,21 +2320,21 @@ return [ ], ], 'mediawiki.special.upload.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.upload.styles.css', + 'styles' => 'resources/src/mediawiki.special.upload.styles.css', ], 'mediawiki.special.userlogin.common.styles' => [ 'targets' => [ 'desktop', 'mobile' ], 'skinStyles' => [ - 'default' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.common.css', + 'default' => 'resources/src/mediawiki.special.userlogin.common.styles/userlogin.css', ], ], 'mediawiki.special.userlogin.login.styles' => [ 'styles' => [ - 'resources/src/mediawiki.special/mediawiki.special.userlogin.login.css', + 'resources/src/mediawiki.special.userlogin.login.styles/login.css', ], ], 'mediawiki.special.userlogin.signup.js' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js', + 'scripts' => 'resources/src/mediawiki.special.userlogin.signup.js', 'messages' => [ 'createacct-emailrequired', 'noname', @@ -2348,18 +2349,18 @@ return [ ], 'mediawiki.special.userlogin.signup.styles' => [ 'styles' => [ - 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css', + 'resources/src/mediawiki.special.userlogin.signup.styles/signup.css', ], ], 'mediawiki.special.userrights' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userrights.js', + 'scripts' => 'resources/src/mediawiki.special.userrights.js', 'dependencies' => [ 'mediawiki.notification.convertmessagebox', 'jquery.lengthLimit', ], ], 'mediawiki.special.watchlist' => [ - 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.js', + 'scripts' => 'resources/src/mediawiki.special.watchlist.js', 'messages' => [ 'addedwatchtext', 'addedwatchtext-talk', @@ -2380,10 +2381,10 @@ return [ ], ], 'mediawiki.special.watchlist.styles' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.css', + 'styles' => 'resources/src/mediawiki.special.watchlist.styles.css', ], 'mediawiki.special.version' => [ - 'styles' => 'resources/src/mediawiki.special/mediawiki.special.version.css', + 'styles' => 'resources/src/mediawiki.special.version.css', ], /* MediaWiki Installer */ diff --git a/resources/src/mediawiki.language/mediawiki.language.init.js b/resources/src/mediawiki.language/mediawiki.language.init.js index e5cf26e8d3..077473ba01 100644 --- a/resources/src/mediawiki.language/mediawiki.language.init.js +++ b/resources/src/mediawiki.language/mediawiki.language.init.js @@ -77,7 +77,11 @@ if ( !( langData[ langCode ] instanceof mw.Map ) ) { langData[ langCode ] = new mw.Map(); } - langData[ langCode ].set( dataKey, value ); + if ( arguments.length > 2 ) { + langData[ langCode ].set( dataKey, value ); + } else { + langData[ langCode ].set( dataKey ); + } } }; diff --git a/resources/src/mediawiki.skinning/content.parsoid.less b/resources/src/mediawiki.skinning/content.parsoid.less index 27ecb1a4c7..d880e8bebd 100644 --- a/resources/src/mediawiki.skinning/content.parsoid.less +++ b/resources/src/mediawiki.skinning/content.parsoid.less @@ -55,7 +55,7 @@ figure[ typeof*='mw:Audio' ] { &.mw-halign-right { /* @noflip */ - margin: 0.5em 0 1.3em 1.4em; + margin: 0 0 0.5em 0.5em; /* @noflip */ clear: right; /* @noflip */ @@ -64,7 +64,7 @@ figure[ typeof*='mw:Audio' ] { &.mw-halign-left { /* @noflip */ - margin: 0.5em 1.4em 1.3em 0; + margin: 0 0.5em 0.5em 0; /* @noflip */ clear: left; /* @noflip */ @@ -116,6 +116,15 @@ figure[ typeof~='mw:Audio/Frame' ] { clear: right; float: right; + &.mw-halign-left { + /* @noflip */ + margin: 0.5em 1.4em 1.3em 0; + } + &.mw-halign-right { + /* @noflip */ + margin: 0.5em 0 1.3em 1.4em; + } + > *:first-child { > img, > video { diff --git a/resources/src/mediawiki.special.apisandbox.styles.css b/resources/src/mediawiki.special.apisandbox.styles.css new file mode 100644 index 0000000000..4dc4c27ab0 --- /dev/null +++ b/resources/src/mediawiki.special.apisandbox.styles.css @@ -0,0 +1,3 @@ +.client-js .mw-apisandbox-nojs { + display: none; +} diff --git a/resources/src/mediawiki.special.apisandbox/apisandbox.css b/resources/src/mediawiki.special.apisandbox/apisandbox.css new file mode 100644 index 0000000000..fe5ac416bf --- /dev/null +++ b/resources/src/mediawiki.special.apisandbox/apisandbox.css @@ -0,0 +1,110 @@ +.mw-apisandbox-toolbar { + background: #fff; + -webkit-position: sticky; + position: sticky; + top: 0; + margin-bottom: -1px; + padding: 0.5em 0; + border-bottom: 1px solid #a2a9b1; + text-align: right; + z-index: 1; +} + +#mw-apisandbox-ui .mw-apisandbox-link { + display: none; +} + +.mw-apisandbox-popup .oo-ui-popupWidget-body > .oo-ui-widget { + vertical-align: middle; +} + +/* So DateTimeInputWidget's calendar popup works... */ +.mw-apisandbox-popup .oo-ui-popupWidget-popup, +.mw-apisandbox-popup .oo-ui-popupWidget-body { + overflow: visible; +} + +/* Display contents of the popup on a single line */ +.mw-apisandbox-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body { + display: table; +} + +.mw-apisandbox-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body > * { + display: table-cell; +} + +.mw-apisandbox-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body > .oo-ui-buttonWidget { + padding-left: 0.5em; + width: 1%; +} + +.mw-apisandbox-spacer { + display: inline-block; + height: 1px; + width: 5em; +} + +.mw-apisandbox-help-field { + border-bottom: 1px solid rgba( 0, 0, 0, 0.1 ); +} + +.mw-apisandbox-help-field:last-child { + border-bottom: 0; +} + +.mw-apisandbox-optionalWidget { + width: 100%; +} + +.mw-apisandbox-optionalWidget.oo-ui-widget-disabled { + position: relative; + z-index: 0; /* New stacking context to prevent the cover from leaking out */ +} + +.mw-apisandbox-optionalWidget-cover { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 2; + cursor: pointer; +} + +.mw-apisandbox-optionalWidget-fields { + display: table; + width: 100%; +} + +.mw-apisandbox-optionalWidget-widget, +.mw-apisandbox-optionalWidget-checkbox { + display: table-cell; + vertical-align: middle; +} + +.mw-apisandbox-optionalWidget-checkbox { + width: 1%; /* Will be expanded by content */ + white-space: nowrap; + padding-left: 0.5em; +} + +.mw-apisandbox-textInputCode .oo-ui-inputWidget-input { + font-family: monospace, monospace; + font-size: 0.8125em; + -moz-tab-size: 4; + tab-size: 4; +} + +.mw-apisandbox-widget-field .oo-ui-textInputWidget { + /* Leave at least enough space for icon, indicator, and a sliver of text */ + min-width: 6em; +} + +.apihelp-deprecated { + font-weight: bold; + color: #d33; +} + +.apihelp-deprecated-value .oo-ui-labelElement-label { + text-decoration: line-through; +} diff --git a/resources/src/mediawiki.special.apisandbox/apisandbox.js b/resources/src/mediawiki.special.apisandbox/apisandbox.js new file mode 100644 index 0000000000..523a62e75b --- /dev/null +++ b/resources/src/mediawiki.special.apisandbox/apisandbox.js @@ -0,0 +1,1864 @@ +( function ( $, mw, OO ) { + 'use strict'; + var ApiSandbox, Util, WidgetMethods, Validators, + $content, panel, booklet, oldhash, windowManager, + formatDropdown, + api = new mw.Api(), + bookletPages = [], + availableFormats = {}, + resultPage = null, + suppressErrors = true, + updatingBooklet = false, + pages = {}, + moduleInfoCache = {}, + baseRequestParams; + + /** + * A wrapper for a widget that provides an enable/disable button + * + * @class + * @private + * @constructor + * @param {OO.ui.Widget} widget + * @param {Object} [config] Configuration options + */ + function OptionalWidget( widget, config ) { + var k; + + config = config || {}; + + this.widget = widget; + this.$cover = config.$cover || + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-cover' ); + this.checkbox = new OO.ui.CheckboxInputWidget( config.checkbox ) + .on( 'change', this.onCheckboxChange, [], this ); + + OptionalWidget[ 'super' ].call( this, config ); + + // Forward most methods for convenience + for ( k in this.widget ) { + if ( $.isFunction( this.widget[ k ] ) && !this[ k ] ) { + this[ k ] = this.widget[ k ].bind( this.widget ); + } + } + + this.$cover.on( 'click', this.onOverlayClick.bind( this ) ); + + this.$element + .addClass( 'mw-apisandbox-optionalWidget' ) + .append( + this.$cover, + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-fields' ).append( + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-widget' ).append( + widget.$element + ), + $( '
' ).addClass( 'mw-apisandbox-optionalWidget-checkbox' ).append( + this.checkbox.$element + ) + ) + ); + + this.setDisabled( widget.isDisabled() ); + } + OO.inheritClass( OptionalWidget, OO.ui.Widget ); + OptionalWidget.prototype.onCheckboxChange = function ( checked ) { + this.setDisabled( !checked ); + }; + OptionalWidget.prototype.onOverlayClick = function () { + this.setDisabled( false ); + if ( $.isFunction( this.widget.focus ) ) { + this.widget.focus(); + } + }; + OptionalWidget.prototype.setDisabled = function ( disabled ) { + OptionalWidget[ 'super' ].prototype.setDisabled.call( this, disabled ); + this.widget.setDisabled( this.isDisabled() ); + this.checkbox.setSelected( !this.isDisabled() ); + this.$cover.toggle( this.isDisabled() ); + return this; + }; + + WidgetMethods = { + textInputWidget: { + getApiValue: function () { + return this.getValue(); + }, + setApiValue: function ( v ) { + if ( v === undefined ) { + v = this.paramInfo[ 'default' ]; + } + this.setValue( v ); + }, + apiCheckValid: function () { + var that = this; + return this.getValidity().then( function () { + return $.Deferred().resolve( true ).promise(); + }, function () { + return $.Deferred().resolve( false ).promise(); + } ).done( function ( ok ) { + ok = ok || suppressErrors; + that.setIcon( ok ? null : 'alert' ); + that.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + } ); + } + }, + + dateTimeInputWidget: { + getValidity: function () { + if ( !Util.apiBool( this.paramInfo.required ) || this.getApiValue() !== '' ) { + return $.Deferred().resolve().promise(); + } else { + return $.Deferred().reject().promise(); + } + } + }, + + tokenWidget: { + alertTokenError: function ( code, error ) { + windowManager.openWindow( 'errorAlert', { + title: Util.parseMsg( 'apisandbox-results-fixtoken-fail', this.paramInfo.tokentype ), + message: error, + actions: [ + { + action: 'accept', + label: OO.ui.msg( 'ooui-dialog-process-dismiss' ), + flags: 'primary' + } + ] + } ); + }, + fetchToken: function () { + this.pushPending(); + return api.getToken( this.paramInfo.tokentype ) + .done( this.setApiValue.bind( this ) ) + .fail( this.alertTokenError.bind( this ) ) + .always( this.popPending.bind( this ) ); + }, + setApiValue: function ( v ) { + WidgetMethods.textInputWidget.setApiValue.call( this, v ); + if ( v === '123ABC' ) { + this.fetchToken(); + } + } + }, + + passwordWidget: { + getApiValueForDisplay: function () { + return ''; + } + }, + + toggleSwitchWidget: { + getApiValue: function () { + return this.getValue() ? 1 : undefined; + }, + setApiValue: function ( v ) { + this.setValue( Util.apiBool( v ) ); + }, + apiCheckValid: function () { + return $.Deferred().resolve( true ).promise(); + } + }, + + dropdownWidget: { + getApiValue: function () { + var item = this.getMenu().findSelectedItem(); + return item === null ? undefined : item.getData(); + }, + setApiValue: function ( v ) { + var menu = this.getMenu(); + + if ( v === undefined ) { + v = this.paramInfo[ 'default' ]; + } + if ( v === undefined ) { + menu.selectItem(); + } else { + menu.selectItemByData( String( v ) ); + } + }, + apiCheckValid: function () { + var ok = this.getApiValue() !== undefined || suppressErrors; + this.setIcon( ok ? null : 'alert' ); + this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + return $.Deferred().resolve( ok ).promise(); + } + }, + + tagWidget: { + getApiValue: function () { + var items = this.getValue(); + if ( items.join( '' ).indexOf( '|' ) === -1 ) { + return items.join( '|' ); + } else { + return '\x1f' + items.join( '\x1f' ); + } + }, + setApiValue: function ( v ) { + if ( v === undefined || v === '' || v === '\x1f' ) { + this.setValue( [] ); + } else { + v = String( v ); + if ( v.indexOf( '\x1f' ) !== 0 ) { + this.setValue( v.split( '|' ) ); + } else { + this.setValue( v.substr( 1 ).split( '\x1f' ) ); + } + } + }, + apiCheckValid: function () { + var ok = true, + pi = this.paramInfo; + + if ( !suppressErrors ) { + ok = this.getApiValue() !== undefined && !( + pi.allspecifier !== undefined && + this.getValue().length > 1 && + this.getValue().indexOf( pi.allspecifier ) !== -1 + ); + } + + this.setIcon( ok ? null : 'alert' ); + this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + return $.Deferred().resolve( ok ).promise(); + }, + createTagItemWidget: function ( data, label ) { + var item = OO.ui.TagMultiselectWidget.prototype.createTagItemWidget.call( this, data, label ); + if ( this.paramInfo.deprecatedvalues && + this.paramInfo.deprecatedvalues.indexOf( data ) >= 0 + ) { + item.$element.addClass( 'apihelp-deprecated-value' ); + } + return item; + } + }, + + optionalWidget: { + getApiValue: function () { + return this.isDisabled() ? undefined : this.widget.getApiValue(); + }, + setApiValue: function ( v ) { + this.setDisabled( v === undefined ); + this.widget.setApiValue( v ); + }, + apiCheckValid: function () { + if ( this.isDisabled() ) { + return $.Deferred().resolve( true ).promise(); + } else { + return this.widget.apiCheckValid(); + } + } + }, + + submoduleWidget: { + single: function () { + var v = this.isDisabled() ? this.paramInfo[ 'default' ] : this.getApiValue(); + return v === undefined ? [] : [ { value: v, path: this.paramInfo.submodules[ v ] } ]; + }, + multi: function () { + var map = this.paramInfo.submodules, + v = this.isDisabled() ? this.paramInfo[ 'default' ] : this.getApiValue(); + return v === undefined || v === '' ? [] : String( v ).split( '|' ).map( function ( v ) { + return { value: v, path: map[ v ] }; + } ); + } + }, + + uploadWidget: { + getApiValueForDisplay: function () { + return '...'; + }, + getApiValue: function () { + return this.getValue(); + }, + setApiValue: function () { + // Can't, sorry. + }, + apiCheckValid: function () { + var ok = this.getValue() !== null || suppressErrors; + this.setIcon( ok ? null : 'alert' ); + this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() ); + return $.Deferred().resolve( ok ).promise(); + } + } + }; + + Validators = { + generic: function () { + return !Util.apiBool( this.paramInfo.required ) || this.getApiValue() !== ''; + } + }; + + /** + * @class mw.special.ApiSandbox.Util + * @private + */ + Util = { + /** + * Fetch API module info + * + * @param {string} module Module to fetch data for + * @return {jQuery.Promise} + */ + fetchModuleInfo: function ( module ) { + var apiPromise, + deferred = $.Deferred(); + + if ( moduleInfoCache.hasOwnProperty( module ) ) { + return deferred + .resolve( moduleInfoCache[ module ] ) + .promise( { abort: function () {} } ); + } else { + apiPromise = api.post( { + action: 'paraminfo', + modules: module, + helpformat: 'html', + uselang: mw.config.get( 'wgUserLanguage' ) + } ).done( function ( data ) { + var info; + + if ( data.warnings && data.warnings.paraminfo ) { + deferred.reject( '???', data.warnings.paraminfo[ '*' ] ); + return; + } + + info = data.paraminfo.modules; + if ( !info || info.length !== 1 || info[ 0 ].path !== module ) { + deferred.reject( '???', 'No module data returned' ); + return; + } + + moduleInfoCache[ module ] = info[ 0 ]; + deferred.resolve( info[ 0 ] ); + } ).fail( function ( code, details ) { + if ( code === 'http' ) { + details = 'HTTP error: ' + details.exception; + } else if ( details.error ) { + details = details.error.info; + } + deferred.reject( code, details ); + } ); + return deferred + .promise( { abort: apiPromise.abort } ); + } + }, + + /** + * Mark all currently-in-use tokens as bad + */ + markTokensBad: function () { + var page, subpages, i, + checkPages = [ pages.main ]; + + while ( checkPages.length ) { + page = checkPages.shift(); + + if ( page.tokenWidget ) { + api.badToken( page.tokenWidget.paramInfo.tokentype ); + } + + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + }, + + /** + * Test an API boolean + * + * @param {Mixed} value + * @return {boolean} + */ + apiBool: function ( value ) { + return value !== undefined && value !== false; + }, + + /** + * Create a widget for a parameter. + * + * @param {Object} pi Parameter info from API + * @param {Object} opts Additional options + * @return {OO.ui.Widget} + */ + createWidgetForParameter: function ( pi, opts ) { + var widget, innerWidget, finalWidget, items, $content, func, + multiModeButton = null, + multiModeInput = null, + multiModeAllowed = false; + + opts = opts || {}; + + switch ( pi.type ) { + case 'boolean': + widget = new OO.ui.ToggleSwitchWidget(); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.toggleSwitchWidget ); + pi.required = true; // Avoid wrapping in the non-required widget + break; + + case 'string': + case 'user': + if ( Util.apiBool( pi.multi ) ) { + widget = new OO.ui.TagMultiselectWidget( { + allowArbitrary: true, + allowDuplicates: Util.apiBool( pi.allowsduplicates ), + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + } else { + widget = new OO.ui.TextInputWidget( { + required: Util.apiBool( pi.required ) + } ); + } + if ( !Util.apiBool( pi.multi ) ) { + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + widget.setValidation( Validators.generic ); + } + if ( pi.tokentype ) { + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + $.extend( widget, WidgetMethods.tokenWidget ); + } + break; + + case 'text': + widget = new OO.ui.MultilineTextInputWidget( { + required: Util.apiBool( pi.required ) + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + widget.setValidation( Validators.generic ); + break; + + case 'password': + widget = new OO.ui.TextInputWidget( { + type: 'password', + required: Util.apiBool( pi.required ) + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + $.extend( widget, WidgetMethods.passwordWidget ); + widget.setValidation( Validators.generic ); + multiModeAllowed = true; + multiModeInput = widget; + break; + + case 'integer': + widget = new OO.ui.NumberInputWidget( { + required: Util.apiBool( pi.required ), + isInteger: true + } ); + widget.setIcon = widget.input.setIcon.bind( widget.input ); + widget.setIconTitle = widget.input.setIconTitle.bind( widget.input ); + widget.getValidity = widget.input.getValidity.bind( widget.input ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + if ( Util.apiBool( pi.enforcerange ) ) { + widget.setRange( pi.min || -Infinity, pi.max || Infinity ); + } + multiModeAllowed = true; + multiModeInput = widget; + break; + + case 'limit': + widget = new OO.ui.TextInputWidget( { + required: Util.apiBool( pi.required ) + } ); + widget.setValidation( function ( value ) { + var n, pi = this.paramInfo; + + if ( value === 'max' ) { + return true; + } else { + n = +value; + return !isNaN( n ) && isFinite( n ) && + Math.floor( n ) === n && + n >= pi.min && n <= pi.apiSandboxMax; + } + } ); + pi.min = pi.min || 0; + pi.apiSandboxMax = mw.config.get( 'apihighlimits' ) ? pi.highmax : pi.max; + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + multiModeAllowed = true; + multiModeInput = widget; + break; + + case 'timestamp': + widget = new mw.widgets.datetime.DateTimeInputWidget( { + formatter: { + format: '${year|0}-${month|0}-${day|0}T${hour|0}:${minute|0}:${second|0}${zone|short}' + }, + required: Util.apiBool( pi.required ), + clearable: false + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.textInputWidget ); + $.extend( widget, WidgetMethods.dateTimeInputWidget ); + multiModeAllowed = true; + break; + + case 'upload': + widget = new OO.ui.SelectFileWidget(); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.uploadWidget ); + break; + + case 'namespace': + items = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( name, ns ) { + if ( ns === '0' ) { + name = mw.message( 'blanknamespace' ).text(); + } + return new OO.ui.MenuOptionWidget( { data: ns, label: name } ); + } ).sort( function ( a, b ) { + return a.data - b.data; + } ); + if ( Util.apiBool( pi.multi ) ) { + if ( pi.allspecifier !== undefined ) { + items.unshift( new OO.ui.MenuOptionWidget( { + data: pi.allspecifier, + label: mw.message( 'apisandbox-multivalue-all-namespaces', pi.allspecifier ).text() + } ) ); + } + + widget = new OO.ui.MenuTagMultiselectWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + } else { + widget = new OO.ui.DropdownWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.dropdownWidget ); + } + break; + + default: + if ( !Array.isArray( pi.type ) ) { + throw new Error( 'Unknown parameter type ' + pi.type ); + } + + items = pi.type.map( function ( v ) { + var config = { + data: String( v ), + label: String( v ), + classes: [] + }; + if ( pi.deprecatedvalues && pi.deprecatedvalues.indexOf( v ) >= 0 ) { + config.classes.push( 'apihelp-deprecated-value' ); + } + return new OO.ui.MenuOptionWidget( config ); + } ); + if ( Util.apiBool( pi.multi ) ) { + if ( pi.allspecifier !== undefined ) { + items.unshift( new OO.ui.MenuOptionWidget( { + data: pi.allspecifier, + label: mw.message( 'apisandbox-multivalue-all-values', pi.allspecifier ).text() + } ) ); + } + + widget = new OO.ui.MenuTagMultiselectWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + if ( Util.apiBool( pi.submodules ) ) { + widget.getSubmodules = WidgetMethods.submoduleWidget.multi; + widget.on( 'change', ApiSandbox.updateUI ); + } + } else { + widget = new OO.ui.DropdownWidget( { + menu: { items: items }, + $overlay: true + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.dropdownWidget ); + if ( Util.apiBool( pi.submodules ) ) { + widget.getSubmodules = WidgetMethods.submoduleWidget.single; + widget.getMenu().on( 'select', ApiSandbox.updateUI ); + } + if ( pi.deprecatedvalues ) { + widget.getMenu().on( 'select', function ( item ) { + this.$element.toggleClass( + 'apihelp-deprecated-value', + pi.deprecatedvalues.indexOf( item.data ) >= 0 + ); + }, [], widget ); + } + } + + break; + } + + if ( Util.apiBool( pi.multi ) && multiModeAllowed ) { + innerWidget = widget; + + multiModeButton = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-add-multi' ).text() + } ); + $content = innerWidget.$element.add( multiModeButton.$element ); + + widget = new OO.ui.PopupTagMultiselectWidget( { + allowArbitrary: true, + allowDuplicates: Util.apiBool( pi.allowsduplicates ), + $overlay: true, + popup: { + classes: [ 'mw-apisandbox-popup' ], + padded: true, + $content: $content + } + } ); + widget.paramInfo = pi; + $.extend( widget, WidgetMethods.tagWidget ); + + func = function () { + if ( !innerWidget.isDisabled() ) { + innerWidget.apiCheckValid().done( function ( ok ) { + if ( ok ) { + widget.addTag( innerWidget.getApiValue() ); + innerWidget.setApiValue( undefined ); + } + } ); + return false; + } + }; + + if ( multiModeInput ) { + multiModeInput.on( 'enter', func ); + } + multiModeButton.on( 'click', func ); + } + + if ( Util.apiBool( pi.required ) || opts.nooptional ) { + finalWidget = widget; + } else { + finalWidget = new OptionalWidget( widget ); + finalWidget.paramInfo = pi; + $.extend( finalWidget, WidgetMethods.optionalWidget ); + if ( widget.getSubmodules ) { + finalWidget.getSubmodules = widget.getSubmodules.bind( widget ); + finalWidget.on( 'disable', function () { setTimeout( ApiSandbox.updateUI ); } ); + } + finalWidget.setDisabled( true ); + } + + widget.setApiValue( pi[ 'default' ] ); + + return finalWidget; + }, + + /** + * Parse an HTML string and call Util.fixupHTML() + * + * @param {string} html HTML to parse + * @return {jQuery} + */ + parseHTML: function ( html ) { + var $ret = $( $.parseHTML( html ) ); + return Util.fixupHTML( $ret ); + }, + + /** + * Parse an i18n message and call Util.fixupHTML() + * + * @param {string} key Key of message to get + * @param {...Mixed} parameters Values for $N replacements + * @return {jQuery} + */ + parseMsg: function () { + var $ret = mw.message.apply( mw.message, arguments ).parseDom(); + return Util.fixupHTML( $ret ); + }, + + /** + * Fix HTML for ApiSandbox display + * + * Fixes are: + * - Add target="_blank" to any links + * + * @param {jQuery} $html DOM to process + * @return {jQuery} + */ + fixupHTML: function ( $html ) { + $html.filter( 'a' ).add( $html.find( 'a' ) ) + .filter( '[href]:not([target])' ) + .attr( 'target', '_blank' ); + return $html; + }, + + /** + * Format a request and return a bunch of menu option widgets + * + * @param {Object} displayParams Query parameters, sanitized for display. + * @param {Object} rawParams Query parameters. You should probably use displayParams instead. + * @return {OO.ui.MenuOptionWidget[]} Each item's data should be an OO.ui.FieldLayout + */ + formatRequest: function ( displayParams, rawParams ) { + var jsonInput, + items = [ + new OO.ui.MenuOptionWidget( { + label: Util.parseMsg( 'apisandbox-request-format-url-label' ), + data: new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { + readOnly: true, + value: mw.util.wikiScript( 'api' ) + '?' + $.param( displayParams ) + } ), { + label: Util.parseMsg( 'apisandbox-request-url-label' ) + } + ) + } ), + new OO.ui.MenuOptionWidget( { + label: Util.parseMsg( 'apisandbox-request-format-json-label' ), + data: new OO.ui.FieldLayout( + jsonInput = new OO.ui.MultilineTextInputWidget( { + classes: [ 'mw-apisandbox-textInputCode' ], + readOnly: true, + autosize: true, + maxRows: 6, + value: JSON.stringify( displayParams, null, '\t' ) + } ), { + label: Util.parseMsg( 'apisandbox-request-json-label' ) + } + ).on( 'toggle', function ( visible ) { + if ( visible ) { + // Call updatePosition instead of adjustSize + // because the latter has weird caching + // behavior and the former bypasses it. + jsonInput.updatePosition(); + } + } ) + } ) + ]; + + mw.hook( 'apisandbox.formatRequest' ).fire( items, displayParams, rawParams ); + + return items; + }, + + /** + * Event handler for when formatDropdown's selection changes + */ + onFormatDropdownChange: function () { + var i, + menu = formatDropdown.getMenu(), + items = menu.getItems(), + selectedField = menu.findSelectedItem() ? menu.findSelectedItem().getData() : null; + + for ( i = 0; i < items.length; i++ ) { + items[ i ].getData().toggle( items[ i ].getData() === selectedField ); + } + } + }; + + /** + * Interface to ApiSandbox UI + * + * @class mw.special.ApiSandbox + */ + ApiSandbox = { + /** + * Initialize the UI + * + * Automatically called on $.ready() + */ + init: function () { + var $toolbar; + + $content = $( '#mw-apisandbox' ); + + windowManager = new OO.ui.WindowManager(); + $( 'body' ).append( windowManager.$element ); + windowManager.addWindows( { + errorAlert: new OO.ui.MessageDialog() + } ); + + $toolbar = $( '
' ) + .addClass( 'mw-apisandbox-toolbar' ) + .append( + new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-submit' ).text(), + flags: [ 'primary', 'progressive' ] + } ).on( 'click', ApiSandbox.sendRequest ).$element, + new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-reset' ).text(), + flags: 'destructive' + } ).on( 'click', ApiSandbox.resetUI ).$element + ); + + booklet = new OO.ui.BookletLayout( { + expanded: false, + outlined: true, + autoFocus: false + } ); + + panel = new OO.ui.PanelLayout( { + classes: [ 'mw-apisandbox-container' ], + content: [ booklet ], + expanded: false, + framed: true + } ); + + pages.main = new ApiSandbox.PageLayout( { key: 'main', path: 'main' } ); + + // Parse the current hash string + if ( !ApiSandbox.loadFromHash() ) { + ApiSandbox.updateUI(); + } + + $( window ).on( 'hashchange', ApiSandbox.loadFromHash ); + + $content + .empty() + .append( $( '

' ).append( Util.parseMsg( 'apisandbox-intro' ) ) ) + .append( + $( '

' ).attr( 'id', 'mw-apisandbox-ui' ) + .append( $toolbar ) + .append( panel.$element ) + ); + }, + + /** + * Update the current query when the page hash changes + * + * @return {boolean} Successful + */ + loadFromHash: function () { + var params, m, re, + hash = location.hash; + + if ( oldhash === hash ) { + return false; + } + oldhash = hash; + if ( hash === '' ) { + return false; + } + + // I'm surprised this doesn't seem to exist in jQuery or mw.util. + params = {}; + hash = hash.replace( /\+/g, '%20' ); + re = /([^&=#]+)=?([^&#]*)/g; + while ( ( m = re.exec( hash ) ) ) { + params[ decodeURIComponent( m[ 1 ] ) ] = decodeURIComponent( m[ 2 ] ); + } + + ApiSandbox.updateUI( params ); + return true; + }, + + /** + * Update the pages in the booklet + * + * @param {Object} [params] Optional query parameters to load + */ + updateUI: function ( params ) { + var i, page, subpages, j, removePages, + addPages = []; + + if ( !$.isPlainObject( params ) ) { + params = undefined; + } + + if ( updatingBooklet ) { + return; + } + updatingBooklet = true; + try { + if ( params !== undefined ) { + pages.main.loadQueryParams( params ); + } + addPages.push( pages.main ); + if ( resultPage !== null ) { + addPages.push( resultPage ); + } + pages.main.apiCheckValid(); + + i = 0; + while ( addPages.length ) { + page = addPages.shift(); + if ( bookletPages[ i ] !== page ) { + for ( j = i; j < bookletPages.length; j++ ) { + if ( bookletPages[ j ].getName() === page.getName() ) { + bookletPages.splice( j, 1 ); + } + } + bookletPages.splice( i, 0, page ); + booklet.addPages( [ page ], i ); + } + i++; + + if ( page.getSubpages ) { + subpages = page.getSubpages(); + for ( j = 0; j < subpages.length; j++ ) { + if ( !pages.hasOwnProperty( subpages[ j ].key ) ) { + subpages[ j ].indentLevel = page.indentLevel + 1; + pages[ subpages[ j ].key ] = new ApiSandbox.PageLayout( subpages[ j ] ); + } + if ( params !== undefined ) { + pages[ subpages[ j ].key ].loadQueryParams( params ); + } + addPages.splice( j, 0, pages[ subpages[ j ].key ] ); + pages[ subpages[ j ].key ].apiCheckValid(); + } + } + } + + if ( bookletPages.length > i ) { + removePages = bookletPages.splice( i, bookletPages.length - i ); + booklet.removePages( removePages ); + } + + if ( !booklet.getCurrentPageName() ) { + booklet.selectFirstSelectablePage(); + } + } finally { + updatingBooklet = false; + } + }, + + /** + * Reset button handler + */ + resetUI: function () { + suppressErrors = true; + pages = { + main: new ApiSandbox.PageLayout( { key: 'main', path: 'main' } ) + }; + resultPage = null; + ApiSandbox.updateUI(); + }, + + /** + * Submit button handler + * + * @param {Object} [params] Use this set of params instead of those in the form fields. + * The form fields will be updated to match. + */ + sendRequest: function ( params ) { + var page, subpages, i, query, $result, $focus, + progress, $progressText, progressLoading, + deferreds = [], + paramsAreForced = !!params, + displayParams = {}, + tokenWidgets = [], + checkPages = [ pages.main ]; + + // Blur any focused widget before submit, because + // OO.ui.ButtonWidget doesn't take focus itself (T128054) + $focus = $( '#mw-apisandbox-ui' ).find( document.activeElement ); + if ( $focus.length ) { + $focus[ 0 ].blur(); + } + + suppressErrors = false; + + // save widget state in params (or load from it if we are forced) + if ( paramsAreForced ) { + ApiSandbox.updateUI( params ); + } + params = {}; + while ( checkPages.length ) { + page = checkPages.shift(); + if ( page.tokenWidget ) { + tokenWidgets.push( page.tokenWidget ); + } + deferreds = deferreds.concat( page.apiCheckValid() ); + page.getQueryParams( params, displayParams ); + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + + if ( !paramsAreForced ) { + // forced params means we are continuing a query; the base query should be preserved + baseRequestParams = $.extend( {}, params ); + } + + $.when.apply( $, deferreds ).done( function () { + var formatItems, menu, selectedLabel, deferred, actions, errorCount; + + // Count how many times `value` occurs in `array`. + function countValues( value, array ) { + var count, i; + count = 0; + for ( i = 0; i < array.length; i++ ) { + if ( array[ i ] === value ) { + count++; + } + } + return count; + } + + errorCount = countValues( false, arguments ); + if ( errorCount > 0 ) { + actions = [ + { + action: 'accept', + label: OO.ui.msg( 'ooui-dialog-process-dismiss' ), + flags: 'primary' + } + ]; + if ( tokenWidgets.length ) { + // Check all token widgets' validity separately + deferred = $.when.apply( $, tokenWidgets.map( function ( w ) { + return w.apiCheckValid(); + } ) ); + + deferred.done( function () { + // If only the tokens are invalid, offer to fix them + var tokenErrorCount = countValues( false, arguments ); + if ( tokenErrorCount === errorCount ) { + delete actions[ 0 ].flags; + actions.push( { + action: 'fix', + label: mw.message( 'apisandbox-results-fixtoken' ).text(), + flags: 'primary' + } ); + } + } ); + } else { + deferred = $.Deferred().resolve(); + } + deferred.always( function () { + windowManager.openWindow( 'errorAlert', { + title: Util.parseMsg( 'apisandbox-submit-invalid-fields-title' ), + message: Util.parseMsg( 'apisandbox-submit-invalid-fields-message' ), + actions: actions + } ).closed.then( function ( data ) { + if ( data && data.action === 'fix' ) { + ApiSandbox.fixTokenAndResend(); + } + } ); + } ); + return; + } + + query = $.param( displayParams ); + + formatItems = Util.formatRequest( displayParams, params ); + + // Force a 'fm' format with wrappedhtml=1, if available + if ( params.format !== undefined ) { + if ( availableFormats.hasOwnProperty( params.format + 'fm' ) ) { + params.format = params.format + 'fm'; + } + if ( params.format.substr( -2 ) === 'fm' ) { + params.wrappedhtml = 1; + } + } + + progressLoading = false; + $progressText = $( '' ).text( mw.message( 'apisandbox-sending-request' ).text() ); + progress = new OO.ui.ProgressBarWidget( { + progress: false, + $content: $progressText + } ); + + $result = $( '
' ) + .append( progress.$element ); + + resultPage = page = new OO.ui.PageLayout( '|results|', { expanded: false } ); + page.setupOutlineItem = function () { + this.outlineItem.setLabel( mw.message( 'apisandbox-results' ).text() ); + }; + + if ( !formatDropdown ) { + formatDropdown = new OO.ui.DropdownWidget( { + menu: { items: [] }, + $overlay: true + } ); + formatDropdown.getMenu().on( 'select', Util.onFormatDropdownChange ); + } + + menu = formatDropdown.getMenu(); + selectedLabel = menu.findSelectedItem() ? menu.findSelectedItem().getLabel() : ''; + if ( typeof selectedLabel !== 'string' ) { + selectedLabel = selectedLabel.text(); + } + menu.clearItems().addItems( formatItems ); + menu.chooseItem( menu.getItemFromLabel( selectedLabel ) || menu.findFirstSelectableItem() ); + + // Fire the event to update field visibilities + Util.onFormatDropdownChange(); + + page.$element.empty() + .append( + new OO.ui.FieldLayout( + formatDropdown, { + label: Util.parseMsg( 'apisandbox-request-selectformat-label' ) + } + ).$element, + formatItems.map( function ( item ) { + return item.getData().$element; + } ), + $result + ); + ApiSandbox.updateUI(); + booklet.setPage( '|results|' ); + + location.href = oldhash = '#' + query; + + api.post( params, { + contentType: 'multipart/form-data', + dataType: 'text', + xhr: function () { + var xhr = new window.XMLHttpRequest(); + xhr.upload.addEventListener( 'progress', function ( e ) { + if ( !progressLoading ) { + if ( e.lengthComputable ) { + progress.setProgress( e.loaded * 100 / e.total ); + } else { + progress.setProgress( false ); + } + } + } ); + xhr.addEventListener( 'progress', function ( e ) { + if ( !progressLoading ) { + progressLoading = true; + $progressText.text( mw.message( 'apisandbox-loading-results' ).text() ); + } + if ( e.lengthComputable ) { + progress.setProgress( e.loaded * 100 / e.total ); + } else { + progress.setProgress( false ); + } + } ); + return xhr; + } + } ) + .catch( function ( code, data, result, jqXHR ) { + var deferred = $.Deferred(); + + if ( code !== 'http' ) { + // Not really an error, work around mw.Api thinking it is. + deferred.resolve( result, jqXHR ); + } else { + // Just forward it. + deferred.reject.apply( deferred, arguments ); + } + return deferred.promise(); + } ) + .then( function ( data, jqXHR ) { + var m, loadTime, button, clear, + ct = jqXHR.getResponseHeader( 'Content-Type' ), + loginSuppressed = jqXHR.getResponseHeader( 'MediaWiki-Login-Suppressed' ) || 'false'; + + $result.empty(); + if ( loginSuppressed !== 'false' ) { + $( '
' ) + .addClass( 'warning' ) + .append( Util.parseMsg( 'apisandbox-results-login-suppressed' ) ) + .appendTo( $result ); + } + if ( /^text\/mediawiki-api-prettyprint-wrapped(?:;|$)/.test( ct ) ) { + data = JSON.parse( data ); + if ( data.modules.length ) { + mw.loader.load( data.modules ); + } + if ( data.status && data.status !== 200 ) { + $( '
' ) + .addClass( 'api-pretty-header api-pretty-status' ) + .append( Util.parseMsg( 'api-format-prettyprint-status', data.status, data.statustext ) ) + .appendTo( $result ); + } + $result.append( Util.parseHTML( data.html ) ); + loadTime = data.time; + } else if ( ( m = data.match( /][\s\S]*<\/pre>/ ) ) ) { + $result.append( Util.parseHTML( m[ 0 ] ) ); + if ( ( m = data.match( /"wgBackendResponseTime":\s*(\d+)/ ) ) ) { + loadTime = parseInt( m[ 1 ], 10 ); + } + } else { + $( '
' )
+								.addClass( 'api-pretty-content' )
+								.text( data )
+								.appendTo( $result );
+						}
+						if ( paramsAreForced || data[ 'continue' ] ) {
+							$result.append(
+								$( '
' ).append( + new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-continue' ).text() + } ).on( 'click', function () { + ApiSandbox.sendRequest( $.extend( {}, baseRequestParams, data[ 'continue' ] ) ); + } ).setDisabled( !data[ 'continue' ] ).$element, + ( clear = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-continue-clear' ).text() + } ).on( 'click', function () { + ApiSandbox.updateUI( baseRequestParams ); + clear.setDisabled( true ); + booklet.setPage( '|results|' ); + } ).setDisabled( !paramsAreForced ) ).$element, + new OO.ui.PopupButtonWidget( { + $overlay: true, + framed: false, + icon: 'info', + popup: { + $content: $( '
' ).append( Util.parseMsg( 'apisandbox-continue-help' ) ), + padded: true, + width: 'auto' + } + } ).$element + ) + ); + } + if ( typeof loadTime === 'number' ) { + $result.append( + $( '
' ).append( + new OO.ui.LabelWidget( { + label: mw.message( 'apisandbox-request-time', loadTime ).text() + } ).$element + ) + ); + } + + if ( jqXHR.getResponseHeader( 'MediaWiki-API-Error' ) === 'badtoken' ) { + // Flush all saved tokens in case one of them is the bad one. + Util.markTokensBad(); + button = new OO.ui.ButtonWidget( { + label: mw.message( 'apisandbox-results-fixtoken' ).text() + } ); + button.on( 'click', ApiSandbox.fixTokenAndResend ) + .on( 'click', button.setDisabled, [ true ], button ) + .$element.appendTo( $result ); + } + }, function ( code, data ) { + var details = 'HTTP error: ' + data.exception; + $result.empty() + .append( + new OO.ui.LabelWidget( { + label: mw.message( 'apisandbox-results-error', details ).text(), + classes: [ 'error' ] + } ).$element + ); + } ); + } ); + }, + + /** + * Handler for the "Correct token and resubmit" button + * + * Used on a 'badtoken' error, it re-fetches token parameters for all + * pages and then re-submits the query. + */ + fixTokenAndResend: function () { + var page, subpages, i, k, + ok = true, + tokenWait = { dummy: true }, + checkPages = [ pages.main ], + success = function ( k ) { + delete tokenWait[ k ]; + if ( ok && $.isEmptyObject( tokenWait ) ) { + ApiSandbox.sendRequest(); + } + }, + failure = function ( k ) { + delete tokenWait[ k ]; + ok = false; + }; + + while ( checkPages.length ) { + page = checkPages.shift(); + + if ( page.tokenWidget ) { + k = page.apiModule + page.tokenWidget.paramInfo.name; + tokenWait[ k ] = page.tokenWidget.fetchToken(); + tokenWait[ k ] + .done( success.bind( page.tokenWidget, k ) ) + .fail( failure.bind( page.tokenWidget, k ) ); + } + + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + + success( 'dummy', '' ); + }, + + /** + * Reset validity indicators for all widgets + */ + updateValidityIndicators: function () { + var page, subpages, i, + checkPages = [ pages.main ]; + + while ( checkPages.length ) { + page = checkPages.shift(); + page.apiCheckValid(); + subpages = page.getSubpages(); + for ( i = 0; i < subpages.length; i++ ) { + if ( pages.hasOwnProperty( subpages[ i ].key ) ) { + checkPages.push( pages[ subpages[ i ].key ] ); + } + } + } + } + }; + + /** + * PageLayout for API modules + * + * @class + * @private + * @extends OO.ui.PageLayout + * @constructor + * @param {Object} [config] Configuration options + */ + ApiSandbox.PageLayout = function ( config ) { + config = $.extend( { prefix: '', expanded: false }, config ); + this.displayText = config.key; + this.apiModule = config.path; + this.prefix = config.prefix; + this.paramInfo = null; + this.apiIsValid = true; + this.loadFromQueryParams = null; + this.widgets = {}; + this.tokenWidget = null; + this.indentLevel = config.indentLevel ? config.indentLevel : 0; + ApiSandbox.PageLayout[ 'super' ].call( this, config.key, config ); + this.loadParamInfo(); + }; + OO.inheritClass( ApiSandbox.PageLayout, OO.ui.PageLayout ); + ApiSandbox.PageLayout.prototype.setupOutlineItem = function () { + this.outlineItem.setLevel( this.indentLevel ); + this.outlineItem.setLabel( this.displayText ); + this.outlineItem.setIcon( this.apiIsValid || suppressErrors ? null : 'alert' ); + this.outlineItem.setIconTitle( + this.apiIsValid || suppressErrors ? '' : mw.message( 'apisandbox-alert-page' ).plain() + ); + }; + + /** + * Fetch module information for this page's module, then create UI + */ + ApiSandbox.PageLayout.prototype.loadParamInfo = function () { + var dynamicFieldset, dynamicParamNameWidget, + that = this, + removeDynamicParamWidget = function ( name, layout ) { + dynamicFieldset.removeItems( [ layout ] ); + delete that.widgets[ name ]; + }, + addDynamicParamWidget = function () { + var name, layout, widget, button; + + // Check name is filled in + name = dynamicParamNameWidget.getValue().trim(); + if ( name === '' ) { + dynamicParamNameWidget.focus(); + return; + } + + if ( that.widgets[ name ] !== undefined ) { + windowManager.openWindow( 'errorAlert', { + title: Util.parseMsg( 'apisandbox-dynamic-error-exists', name ), + actions: [ + { + action: 'accept', + label: OO.ui.msg( 'ooui-dialog-process-dismiss' ), + flags: 'primary' + } + ] + } ); + return; + } + + widget = Util.createWidgetForParameter( { + name: name, + type: 'string', + 'default': '' + }, { + nooptional: true + } ); + button = new OO.ui.ButtonWidget( { + icon: 'trash', + flags: 'destructive' + } ); + layout = new OO.ui.ActionFieldLayout( + widget, + button, + { + label: name, + align: 'left' + } + ); + button.on( 'click', removeDynamicParamWidget, [ name, layout ] ); + that.widgets[ name ] = widget; + dynamicFieldset.addItems( [ layout ], dynamicFieldset.getItems().length - 1 ); + widget.focus(); + + dynamicParamNameWidget.setValue( '' ); + }; + + this.$element.empty() + .append( new OO.ui.ProgressBarWidget( { + progress: false, + text: mw.message( 'apisandbox-loading', this.displayText ).text() + } ).$element ); + + Util.fetchModuleInfo( this.apiModule ) + .done( function ( pi ) { + var prefix, i, j, descriptionContainer, widget, layoutConfig, button, widgetField, helpField, tmp, flag, count, + items = [], + deprecatedItems = [], + buttons = [], + filterFmModules = function ( v ) { + return v.substr( -2 ) !== 'fm' || + !availableFormats.hasOwnProperty( v.substr( 0, v.length - 2 ) ); + }, + widgetLabelOnClick = function () { + var f = this.getField(); + if ( $.isFunction( f.setDisabled ) ) { + f.setDisabled( false ); + } + if ( $.isFunction( f.focus ) ) { + f.focus(); + } + }; + + // This is something of a hack. We always want the 'format' and + // 'action' parameters from the main module to be specified, + // and for 'format' we also want to simplify the dropdown since + // we always send the 'fm' variant. + if ( that.apiModule === 'main' ) { + for ( i = 0; i < pi.parameters.length; i++ ) { + if ( pi.parameters[ i ].name === 'action' ) { + pi.parameters[ i ].required = true; + delete pi.parameters[ i ][ 'default' ]; + } + if ( pi.parameters[ i ].name === 'format' ) { + tmp = pi.parameters[ i ].type; + for ( j = 0; j < tmp.length; j++ ) { + availableFormats[ tmp[ j ] ] = true; + } + pi.parameters[ i ].type = tmp.filter( filterFmModules ); + pi.parameters[ i ][ 'default' ] = 'json'; + pi.parameters[ i ].required = true; + } + } + } + + // Hide the 'wrappedhtml' parameter on format modules + if ( pi.group === 'format' ) { + pi.parameters = pi.parameters.filter( function ( p ) { + return p.name !== 'wrappedhtml'; + } ); + } + + that.paramInfo = pi; + + items.push( new OO.ui.FieldLayout( + new OO.ui.Widget( {} ).toggle( false ), { + align: 'top', + label: Util.parseHTML( pi.description ) + } + ) ); + + if ( pi.helpurls.length ) { + buttons.push( new OO.ui.PopupButtonWidget( { + $overlay: true, + label: mw.message( 'apisandbox-helpurls' ).text(), + icon: 'help', + popup: { + width: 'auto', + padded: true, + $content: $( '